diff --git a/.github/workflows/appstore-build-publish.yml b/.github/workflows/appstore-build-publish.yml deleted file mode 100644 index 486a27d..0000000 --- a/.github/workflows/appstore-build-publish.yml +++ /dev/null @@ -1,89 +0,0 @@ -name: Build and Publish Astrolabe App Release - -on: - push: - tags: - - 'astrolabe-v*' - -env: - APP_NAME: astrolabe - APP_DIR: third_party/astrolabe - -jobs: - build-and-publish: - runs-on: ubuntu-latest - permissions: - contents: write - - steps: - - name: Checkout code - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - - - name: Get version from tag - id: tag - run: | - echo "TAG=${GITHUB_REF#refs/tags/astrolabe-v}" >> $GITHUB_OUTPUT - - - name: Validate version in info.xml matches tag - working-directory: ${{ env.APP_DIR }} - run: | - INFO_VERSION=$(sed -n 's/.*\(.*\)<\/version>.*/\1/p' appinfo/info.xml | tr -d '\t') - if [ "$INFO_VERSION" != "${{ steps.tag.outputs.TAG }}" ]; then - echo "Version mismatch: info.xml has $INFO_VERSION but tag is ${{ steps.tag.outputs.TAG }}" - exit 1 - fi - echo "Version validated: $INFO_VERSION" - - - name: Setup Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 - with: - node-version: 22 - - - name: Setup PHP - uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # v2 - with: - php-version: 8.1 - coverage: none - - - name: Checkout Nextcloud server (for signing) - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - with: - repository: nextcloud/server - ref: stable30 - path: server - - - name: Install dependencies and build - working-directory: ${{ env.APP_DIR }} - run: | - composer install --no-dev --optimize-autoloader - npm ci - npm run build - - - name: Setup signing certificate - run: | - mkdir -p $HOME/.nextcloud/certificates - echo "${{ secrets.APP_PRIVATE_KEY }}" > $HOME/.nextcloud/certificates/${{ env.APP_NAME }}.key - echo "${{ secrets.APP_PUBLIC_CRT }}" > $HOME/.nextcloud/certificates/${{ env.APP_NAME }}.crt - - - name: Build app store package - working-directory: ${{ env.APP_DIR }} - run: make appstore server_dir=${{ github.workspace }}/server - - - name: Create GitHub release and attach tarball - uses: svenstaro/upload-release-action@6b7fa9f267e90b50a19fef07b3596790bb941741 # v2 - with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - file: ${{ env.APP_DIR }}/build/artifacts/${{ env.APP_NAME }}.tar.gz - asset_name: ${{ env.APP_NAME }}-${{ steps.tag.outputs.TAG }}.tar.gz - tag: ${{ github.ref }} - release_name: Astrolabe ${{ steps.tag.outputs.TAG }} - prerelease: ${{ contains(steps.tag.outputs.TAG, '-alpha') || contains(steps.tag.outputs.TAG, '-beta') || contains(steps.tag.outputs.TAG, '-rc') }} - - - name: Upload to Nextcloud App Store - uses: R0Wi/nextcloud-appstore-push-action@9244bb5445776688cfe90fa1903ea8dff95b0c28 # v1.0.4 - with: - app_name: ${{ env.APP_NAME }} - appstore_token: ${{ secrets.APPSTORE_TOKEN }} - download_url: ${{ github.server_url }}/${{ github.repository }}/releases/download/${{ github.ref_name }}/${{ env.APP_NAME }}-${{ steps.tag.outputs.TAG }}.tar.gz - app_private_key: ${{ secrets.APP_PRIVATE_KEY }} - nightly: ${{ contains(steps.tag.outputs.TAG, '-alpha') || contains(steps.tag.outputs.TAG, '-beta') || contains(steps.tag.outputs.TAG, '-rc') }} diff --git a/.github/workflows/astrolabe-ci.yml b/.github/workflows/astrolabe-ci.yml deleted file mode 100644 index 8d7afd8..0000000 --- a/.github/workflows/astrolabe-ci.yml +++ /dev/null @@ -1,323 +0,0 @@ -# Consolidated CI workflow for Astrolabe Nextcloud app -# -# Runs on PRs that modify the astrolabe directory -# Based on Nextcloud app skeleton workflows -# -# SPDX-FileCopyrightText: 2025 Nextcloud MCP Server contributors -# SPDX-License-Identifier: MIT - -name: Astrolabe CI - -on: - pull_request: - paths: - - 'third_party/astrolabe/**' - - '.github/workflows/astrolabe-ci.yml' - -permissions: - contents: read - -concurrency: - group: astrolabe-ci-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -jobs: - changes: - runs-on: ubuntu-latest - permissions: - contents: read - pull-requests: read - outputs: - frontend: ${{ steps.changes.outputs.frontend }} - php: ${{ steps.changes.outputs.php }} - steps: - - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - id: changes - continue-on-error: true - with: - filters: | - frontend: - - 'third_party/astrolabe/src/**' - - 'third_party/astrolabe/package.json' - - 'third_party/astrolabe/package-lock.json' - - 'third_party/astrolabe/vite.config.js' - - 'third_party/astrolabe/**/*.js' - - 'third_party/astrolabe/**/*.ts' - - 'third_party/astrolabe/**/*.vue' - php: - - 'third_party/astrolabe/lib/**' - - 'third_party/astrolabe/appinfo/**' - - 'third_party/astrolabe/composer.json' - - 'third_party/astrolabe/psalm.xml' - - # Node.js build and lint - node-build: - runs-on: ubuntu-latest - needs: changes - if: needs.changes.outputs.frontend != 'false' - name: Node.js build - defaults: - run: - working-directory: third_party/astrolabe - steps: - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - - name: Read package.json node and npm engines version - uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3 - id: versions - with: - path: third_party/astrolabe - fallbackNode: '^20' - fallbackNpm: '^10' - - - name: Set up node ${{ steps.versions.outputs.nodeVersion }} - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 - with: - node-version: ${{ steps.versions.outputs.nodeVersion }} - - - name: Set up npm ${{ steps.versions.outputs.npmVersion }} - run: npm i -g 'npm@${{ steps.versions.outputs.npmVersion }}' - - - name: Install dependencies & build - env: - CYPRESS_INSTALL_BINARY: 0 - PUPPETEER_SKIP_DOWNLOAD: true - run: | - npm ci - npm run build --if-present - - - name: Check webpack build changes - run: | - bash -c "[[ ! \"`git status --porcelain `\" ]] || (echo 'Please recompile and commit the assets' && exit 1)" - - # ESLint - eslint: - runs-on: ubuntu-latest - needs: changes - if: needs.changes.outputs.frontend != 'false' - name: ESLint - defaults: - run: - working-directory: third_party/astrolabe - steps: - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - - name: Read package.json node and npm engines version - uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3 - id: versions - with: - path: third_party/astrolabe - fallbackNode: '^20' - fallbackNpm: '^10' - - - name: Set up node ${{ steps.versions.outputs.nodeVersion }} - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 - with: - node-version: ${{ steps.versions.outputs.nodeVersion }} - - - name: Set up npm ${{ steps.versions.outputs.npmVersion }} - run: npm i -g 'npm@${{ steps.versions.outputs.npmVersion }}' - - - name: Install dependencies - env: - CYPRESS_INSTALL_BINARY: 0 - PUPPETEER_SKIP_DOWNLOAD: true - run: npm ci - - - name: Lint - run: npm run lint - - # Stylelint - stylelint: - runs-on: ubuntu-latest - needs: changes - if: needs.changes.outputs.frontend != 'false' - name: Stylelint - defaults: - run: - working-directory: third_party/astrolabe - steps: - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - - name: Read package.json node and npm engines version - uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3 - id: versions - with: - path: third_party/astrolabe - fallbackNode: '^20' - fallbackNpm: '^10' - - - name: Set up node ${{ steps.versions.outputs.nodeVersion }} - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 - with: - node-version: ${{ steps.versions.outputs.nodeVersion }} - - - name: Set up npm ${{ steps.versions.outputs.npmVersion }} - run: npm i -g 'npm@${{ steps.versions.outputs.npmVersion }}' - - - name: Install dependencies - env: - CYPRESS_INSTALL_BINARY: 0 - PUPPETEER_SKIP_DOWNLOAD: true - run: npm ci - - - name: Lint - run: npm run stylelint - - # PHP Code Style - php-cs: - runs-on: ubuntu-latest - needs: changes - if: needs.changes.outputs.php != 'false' - name: PHP CS Fixer - defaults: - run: - working-directory: third_party/astrolabe - steps: - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - - name: Get php version - id: versions - uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1 - with: - filename: third_party/astrolabe/appinfo/info.xml - - - name: Set up php${{ steps.versions.outputs.php-min }} - uses: shivammathur/setup-php@cf4cade2721270509d5b1c766ab3549210a39a2a # v2.33.0 - with: - php-version: ${{ steps.versions.outputs.php-min }} - extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite - coverage: none - ini-file: development - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Install dependencies - run: | - composer remove nextcloud/ocp --dev || true - composer i - - - name: Lint - run: composer run cs:check || ( echo 'Please run `composer run cs:fix` to format your code' && exit 1 ) - - # Psalm Static Analysis - psalm: - runs-on: ubuntu-latest - needs: changes - if: needs.changes.outputs.php != 'false' - name: Psalm - defaults: - run: - working-directory: third_party/astrolabe - steps: - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - - name: Get php version - id: versions - uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1 - with: - filename: third_party/astrolabe/appinfo/info.xml - - - name: Set up php${{ steps.versions.outputs.php-min }} - uses: shivammathur/setup-php@cf4cade2721270509d5b1c766ab3549210a39a2a # v2.33.0 - with: - php-version: ${{ steps.versions.outputs.php-min }} - extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite - coverage: none - ini-file: development - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Install dependencies - run: | - composer remove nextcloud/ocp --dev || true - composer i - - - name: Get OCP version matrix - id: ocp-versions - uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1 - with: - filename: third_party/astrolabe/appinfo/info.xml - - - name: Install OCP for static analysis - run: | - # Get first OCP version from matrix - OCP_VERSION=$(echo '${{ steps.ocp-versions.outputs.ocp-matrix }}' | jq -r '.include[0]."ocp-version"') - composer require --dev "nextcloud/ocp:$OCP_VERSION" --ignore-platform-reqs --with-dependencies - - - name: Run Psalm - run: composer run psalm -- --threads=1 --monochrome --no-progress --output-format=github - - # PHPUnit Tests - phpunit: - runs-on: ubuntu-latest - needs: changes - if: needs.changes.outputs.php != 'false' - defaults: - run: - working-directory: third_party/astrolabe - - strategy: - matrix: - php-versions: ['8.1', '8.2', '8.3'] - - name: PHPUnit (PHP ${{ matrix.php-versions }}) - - steps: - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - - name: Set up PHP ${{ matrix.php-versions }} - uses: shivammathur/setup-php@cf4cade2721270509d5b1c766ab3549210a39a2a # v2.33.0 - with: - php-version: ${{ matrix.php-versions }} - extensions: ctype, curl, dom, gd, iconv, intl, json, mbstring, openssl, posix, sqlite, xml, zip - coverage: none - ini-file: development - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Install dependencies - run: | - composer remove nextcloud/ocp --dev || true - composer i - - - name: Get OCP version matrix - id: ocp-versions - uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1 - with: - filename: third_party/astrolabe/appinfo/info.xml - - - name: Install OCP for testing - run: | - OCP_VERSION=$(echo '${{ steps.ocp-versions.outputs.ocp-matrix }}' | jq -r '.include[0]."ocp-version"') - composer require --dev "nextcloud/ocp:$OCP_VERSION" --ignore-platform-reqs --with-dependencies - - - name: Run PHPUnit - run: composer run test:unit - - # Summary job - summary: - permissions: - contents: none - runs-on: ubuntu-latest - needs: [changes, node-build, eslint, stylelint, php-cs, psalm, phpunit] - if: always() - name: astrolabe-ci-summary - steps: - - name: Summary status - run: | - if ${{ needs.changes.outputs.frontend != 'false' && (needs.node-build.result != 'success' || needs.eslint.result != 'success' || needs.stylelint.result != 'success') }}; then - echo "Frontend checks failed" - exit 1 - fi - if ${{ needs.changes.outputs.php != 'false' && (needs.php-cs.result != 'success' || needs.psalm.result != 'success' || needs.phpunit.result != 'success') }}; then - echo "PHP checks failed" - exit 1 - fi - echo "All checks passed" diff --git a/.github/workflows/bump-version.yml b/.github/workflows/bump-version.yml index a92373b..6015efd 100644 --- a/.github/workflows/bump-version.yml +++ b/.github/workflows/bump-version.yml @@ -83,9 +83,9 @@ jobs: commit_range="${last_mcp_tag}..HEAD" fi - # Count conventional commits that are NOT scoped to helm or astrolabe + # Count conventional commits that are NOT scoped to helm mcp_commit_count=$(git log "$commit_range" --oneline --grep="^(feat|fix|docs|refactor|perf|test|build|ci|chore)" -E | \ - { grep -v "(helm)" || true; } | { grep -v "(astrolabe)" || true; } | wc -l) + { grep -v "(helm)" || true; } | wc -l) MCP_BUMPED=false if [ "$mcp_commit_count" -gt 0 ]; then @@ -115,14 +115,6 @@ jobs: BUMPED_COMPONENTS="$BUMPED_COMPONENTS helm" fi - # Bump Astrolabe (scope: astrolabe) - echo "Checking Astrolabe for version bump..." - if has_commits_since_tag "astrolabe-v" "(feat|fix|docs|refactor|perf|test|build|ci|chore)\(astrolabe\)(!)?:"; then - echo "Bumping Astrolabe version..." - ./scripts/bump-astrolabe.sh - BUMPED_COMPONENTS="$BUMPED_COMPONENTS astrolabe" - fi - # Output summary if [ -z "$BUMPED_COMPONENTS" ]; then echo "No components required version bumps" @@ -158,10 +150,6 @@ jobs: tag=$(git tag --sort=-creatordate | grep -E '^nextcloud-mcp-server-' | head -n 1) echo "- **Helm Chart**: \`$tag\`" >> $GITHUB_STEP_SUMMARY ;; - astrolabe) - tag=$(git tag --sort=-creatordate | grep -E '^astrolabe-v' | head -n 1) - echo "- **Astrolabe**: \`$tag\`" >> $GITHUB_STEP_SUMMARY - ;; esac done diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3e9a681..7dd9cce 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -48,23 +48,6 @@ jobs: ###### Required to build OIDC App ###### - ###### Required to build Astrolabe App ###### - - - name: Set up Node.js for Astrolabe - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 - with: - node-version: '20' - - - name: Build Astrolabe app - run: | - cd third_party/astrolabe - composer install --no-dev --optimize-autoloader - npm ci - npm run build - - ###### Required to build Astrolabe App ###### - - - name: Run docker compose uses: hoverkraft-tech/compose-action@4894d2492015c1774ee5a13a95b1072093087ec3 # v2.5.0 with: diff --git a/.gitmodules b/.gitmodules index 6dc5078..768b7a1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "third_party/notes"] path = third_party/notes url = https://github.com/cbcoutinho/notes +[submodule "third_party/astrolabe"] + path = third_party/astrolabe + url = git@github.com:cbcoutinho/astrolabe.git diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 463962b..984cd39 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ ## Version Management -This monorepo uses commitizen for version management with **independent versioning** for three components: +This monorepo uses commitizen for version management with **independent versioning** for two components: ### Components @@ -10,7 +10,8 @@ This monorepo uses commitizen for version management with **independent versioni |-----------|-------|--------------|-------------| | MCP Server | `mcp` or none | `./scripts/bump-mcp.sh` | `v0.54.0` | | Helm Chart | `helm` | `./scripts/bump-helm.sh` | `nextcloud-mcp-server-0.54.0` | -| Astrolabe App | `astrolabe` | `./scripts/bump-astrolabe.sh` | `astrolabe-v0.2.0` | + +> **Note:** The Astrolabe Nextcloud app has been moved to its own repository at [cbcoutinho/astrolabe](https://github.com/cbcoutinho/astrolabe). ### Commit Message Format @@ -24,10 +25,6 @@ fix(mcp): resolve authentication bug # Helm chart changes feat(helm): add resource limits docs(helm): update values documentation - -# Astrolabe app changes -feat(astrolabe): add dark mode toggle -fix(astrolabe): resolve search UI bug ``` **Unscoped commits** default to the MCP server: @@ -40,7 +37,6 @@ feat: add new feature # → MCP server (v0.54.0) #### 1. Make Changes with Scoped Commits ```bash -git commit -m "feat(astrolabe): add dark mode toggle" git commit -m "feat(helm): add ingress annotations" git commit -m "feat(mcp): add calendar sync" ``` @@ -58,10 +54,6 @@ git commit -m "feat(mcp): add calendar sync" # → Creates tag: nextcloud-mcp-server-0.54.0 # → Updates: Chart.yaml:version -# Bump Astrolabe (reads commits with scope=astrolabe) -./scripts/bump-astrolabe.sh -# → Creates tag: astrolabe-v0.2.0 -# → Updates: info.xml, package.json ``` #### 3. Push Tags @@ -76,7 +68,6 @@ Each component maintains its own `CHANGELOG.md`: - **MCP Server**: `CHANGELOG.md` (root) - includes `feat(mcp):` and unscoped commits - **Helm Chart**: `charts/nextcloud-mcp-server/CHANGELOG.md` - includes `feat(helm):` only -- **Astrolabe**: `third_party/astrolabe/CHANGELOG.md` - includes `feat(astrolabe):` only ### Manual Version Bumps @@ -101,7 +92,6 @@ uv run cz --config .cz.toml bump --increment MINOR - **MCP Server**: Follows PEP 440, `major_version_zero = true` (0.x.x for pre-1.0) - **Helm Chart**: Follows PEP 440, starts at 0.53.0 (continues from current) -- **Astrolabe**: Follows PEP 440, `major_version_zero = true` (0.x.x for alpha/beta) ### Chart.yaml Version vs appVersion diff --git a/app-hooks/post-installation/20-install-astrolabe-app.sh b/app-hooks/post-installation/20-install-astrolabe-app.sh index b472447..3e532b8 100755 --- a/app-hooks/post-installation/20-install-astrolabe-app.sh +++ b/app-hooks/post-installation/20-install-astrolabe-app.sh @@ -2,35 +2,17 @@ set -euox pipefail -echo "Installing Astrolabe app for testing..." +echo "Installing Astrolabe app from app store..." -# Check if development astrolabe app is mounted at /opt/apps/astrolabe -if [ -d /opt/apps/astrolabe ]; then - echo "Development astrolabe app found at /opt/apps/astrolabe" - - # Remove any existing astrolabe app in custom_apps (from app store or old symlink) - if [ -e /var/www/html/custom_apps/astrolabe ]; then - echo "Removing existing astrolabe in custom_apps..." - rm -rf /var/www/html/custom_apps/astrolabe - fi - - # Create symlink from custom_apps to the mounted development version - # Per Nextcloud docs: apps outside server root need symlinks in server root - echo "Creating symlink: custom_apps/astrolabe -> /opt/apps/astrolabe" - ln -sf /opt/apps/astrolabe /var/www/html/custom_apps/astrolabe - - echo "Enabling astrolabe app from /opt/apps (development mode via symlink)" - php /var/www/html/occ app:enable astrolabe -elif [ -d /var/www/html/custom_apps/astrolabe ]; then +if [ -d /var/www/html/custom_apps/astrolabe ]; then echo "astrolabe app directory found in custom_apps (already installed)" php /var/www/html/occ app:enable astrolabe else - echo "astrolabe app not found, installing from app store..." php /var/www/html/occ app:install astrolabe php /var/www/html/occ app:enable astrolabe fi -echo "✓ Astrolabe app installed successfully" +echo "Astrolabe app installed successfully" echo "" echo "Note: MCP server configuration is managed dynamically during tests" echo " to support testing multiple MCP server deployments." diff --git a/docker-compose.yml b/docker-compose.yml index 4c153ce..9ae77eb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -37,7 +37,6 @@ services: # Mount OIDC development directory outside /var/www/html to avoid rsync conflicts # The post-installation hook will register /opt/apps as an additional app directory #- ./third_party:/opt/apps:ro - - ./third_party/astrolabe:/opt/apps/astrolabe:ro environment: - NEXTCLOUD_TRUSTED_DOMAINS=app - NEXTCLOUD_ADMIN_USER=admin diff --git a/scripts/bump-astrolabe.sh b/scripts/bump-astrolabe.sh deleted file mode 100755 index b3aefaa..0000000 --- a/scripts/bump-astrolabe.sh +++ /dev/null @@ -1,90 +0,0 @@ -#!/bin/bash -# Bump Astrolabe app version -set -euo pipefail - -# Parse optional --increment flag -INCREMENT="" -while [[ $# -gt 0 ]]; do - case $1 in - --increment) - INCREMENT="$2" - shift 2 - ;; - *) - echo "❌ Error: Unknown option: $1" >&2 - echo "Usage: $0 [--increment PATCH|MINOR|MAJOR]" >&2 - exit 1 - ;; - esac -done - -# Validate dependencies -command -v uv >/dev/null 2>&1 || { - echo "❌ Error: uv not found" >&2 - echo " Install from https://docs.astral.sh/uv/" >&2 - exit 1 -} - -# Validate Astrolabe directory exists -if [ ! -d "third_party/astrolabe" ]; then - echo "❌ Error: Must run from repository root (third_party/astrolabe not found)" >&2 - exit 1 -fi - -cd third_party/astrolabe - -# Validate required files exist -if [ ! -f "appinfo/info.xml" ]; then - echo "❌ Error: appinfo/info.xml not found" >&2 - exit 1 -fi - -if [ ! -f "package.json" ]; then - echo "❌ Error: package.json not found" >&2 - exit 1 -fi - -echo "Bumping Astrolabe version..." -if [ -n "$INCREMENT" ]; then - echo " Forcing $INCREMENT bump" -fi - -# Build commitizen command -CZ_CMD="uv run cz --config .cz.toml bump --yes" -if [ -n "$INCREMENT" ]; then - CZ_CMD="$CZ_CMD --increment $INCREMENT" -fi - -# Run commitizen bump and capture output -if ! output=$($CZ_CMD 2>&1); then - cd ../.. - - # Check if this is the expected "no commits to bump" case - if echo "$output" | grep -q "\[NO_COMMITS_TO_BUMP\]"; then - echo "ℹ️ No commits eligible for version bump" >&2 - echo "$output" >&2 - exit 0 - fi - - # Otherwise, this is an actual error - echo "❌ Error: Version bump failed" >&2 - echo "$output" >&2 - echo "" >&2 - echo "Common causes:" >&2 - echo " - No commits with scope 'astrolabe' since last version" >&2 - echo " - No conventional commits found (use feat(astrolabe):, fix(astrolabe):, etc.)" >&2 - echo " - Git working directory not clean" >&2 - exit 1 -fi - -echo "$output" -echo "" -echo "✓ Astrolabe version bumped successfully" -echo " Updated: appinfo/info.xml, package.json" -echo " Tag format: astrolabe-v\${version}" -echo "" -echo "Next steps:" -echo " cd ../.." -echo " git push --follow-tags" - -cd ../.. diff --git a/third_party/astrolabe b/third_party/astrolabe new file mode 160000 index 0000000..c079a70 --- /dev/null +++ b/third_party/astrolabe @@ -0,0 +1 @@ +Subproject commit c079a70af883329d677d492340166ff68ca4437b diff --git a/third_party/astrolabe/.cz.toml b/third_party/astrolabe/.cz.toml deleted file mode 100644 index 4aabc36..0000000 --- a/third_party/astrolabe/.cz.toml +++ /dev/null @@ -1,25 +0,0 @@ -[tool.commitizen] -name = "cz_conventional_commits" -version = "0.10.1" -tag_format = "astrolabe-v$version" -version_scheme = "semver" -update_changelog_on_bump = true -major_version_zero = true - -# Update Astrolabe-specific files only -version_files = [ - "appinfo/info.xml:", - "package.json:version" -] - -# Ignore tags from other components -ignored_tag_formats = [ - "v*", # MCP server tags - "nextcloud-mcp-server-*", # Helm chart tags -] - -# Filter commits by scope -[tool.commitizen.customize] -changelog_pattern = "^(feat|fix|docs|refactor|perf|test|build|ci|chore)\\(astrolabe\\)(!)?:" -schema_pattern = "^(feat|fix|docs|refactor|perf|test|build|ci|chore)\\(astrolabe\\)(!)?:\\s.+" -message_template = "{{change_type}}(astrolabe): {{message}}" diff --git a/third_party/astrolabe/.eslintrc.cjs b/third_party/astrolabe/.eslintrc.cjs deleted file mode 100644 index 9175db9..0000000 --- a/third_party/astrolabe/.eslintrc.cjs +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - extends: [ - '@nextcloud', - ], - rules: { - 'jsdoc/require-jsdoc': 'off', - 'vue/first-attribute-linebreak': 'off', - }, -} diff --git a/third_party/astrolabe/.gitignore b/third_party/astrolabe/.gitignore deleted file mode 100644 index 9039f45..0000000 --- a/third_party/astrolabe/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -/.idea/ -/*.iml - -/vendor/ -/vendor-bin/*/vendor/ - -/.php-cs-fixer.cache -/tests/.phpunit.cache - -dist/ -build/ -node_modules/ -js/ -css/ -.phpunit.cache/ diff --git a/third_party/astrolabe/.nvmrc b/third_party/astrolabe/.nvmrc deleted file mode 100644 index 209e3ef..0000000 --- a/third_party/astrolabe/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -20 diff --git a/third_party/astrolabe/.php-cs-fixer.dist.php b/third_party/astrolabe/.php-cs-fixer.dist.php deleted file mode 100644 index 91fc1d9..0000000 --- a/third_party/astrolabe/.php-cs-fixer.dist.php +++ /dev/null @@ -1,19 +0,0 @@ -getFinder() - ->notPath('build') - ->notPath('l10n') - ->notPath('node_modules') - ->notPath('src') - ->notPath('vendor') - ->in(__DIR__); - -return $config; diff --git a/third_party/astrolabe/CHANGELOG.md b/third_party/astrolabe/CHANGELOG.md deleted file mode 100644 index fc4a6e9..0000000 --- a/third_party/astrolabe/CHANGELOG.md +++ /dev/null @@ -1,573 +0,0 @@ -# Changelog - Astrolabe - -All notable changes to the Astrolabe Nextcloud app will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - - -### Added - -- Initial alpha release -- Semantic search across Notes, Files, Calendar, Deck, and Contacts -- Integration with Nextcloud Unified Search -- Personal settings UI for MCP server configuration -- Admin settings for global MCP server URL -- OAuth PKCE authentication flow -- Vector visualization of semantic relationships -- Hybrid search combining semantic and keyword matching -- Background content indexing -- Support for Nextcloud 30-32 - -### Notes - -- This is an alpha release intended for early adopters and testing -- Requires external MCP server deployment -- See documentation for setup: https://github.com/cbcoutinho/nextcloud-mcp-server - -## astrolabe-v0.10.1 (2026-02-03) - -### Fix - -- **helm**: add backward compatibility for legacy persistence configs - -## astrolabe-v0.10.0 (2026-01-28) - -### Feat - -- **astrolabe**: add background token refresh job - -### Fix - -- **astrolabe**: add pagination and psalm fixes for token refresh -- **astrolabe**: add locking to prevent token refresh race condition -- **astrolabe**: add issued_at to on-demand token refresh - -## astrolabe-v0.9.0 (2026-01-26) - -### Feat - -- **scripts**: add database query helpers for development - -### Fix - -- **astrolabe**: resolve Psalm type errors in PDF preview code -- **astrolabe**: fix Psalm baseline and ESLint import order -- **astrolabe**: load pdfjs-dist externally to fix PDF viewer -- **astrolabe**: improve error messages for authorization issues -- **astrolabe**: rename OAuthController and fix app password check -- **tests**: improve Astrolabe integration test reliability -- **astrolabe**: update Plotly title attributes for v3 compatibility -- **deps**: update dependency plotly.js-dist-min to v3 - -### Refactor - -- **api**: split management.py into domain-focused modules -- **astrolabe**: replace client-side PDF.js with server-side PyMuPDF rendering - -## astrolabe-v0.8.3 (2026-01-17) - -### Fix - -- **astrolabe**: improve token refresh error handling and validation -- **astrolabe**: delete stale tokens when refresh fails -- **astrolabe**: resolve CI failures for code quality checks -- **astrolabe**: use internal URL for OAuth token refresh - -### Refactor - -- **astrolabe**: add PHP property types to fix Psalm errors -- **astrolabe**: upgrade to @nextcloud/vue 9.3.3 API - -## astrolabe-v0.8.2 (2026-01-16) - -### Fix - -- **astrolabe**: Address reviewer feedback for hybrid mode -- **astrolabe**: Fix NcSelect options and CSS loading -- **astrolabe**: fix OAuth flow and settings UI for hybrid mode -- **api**: return OIDC config in hybrid mode for Astrolabe OAuth flow - -## astrolabe-v0.8.1 (2026-01-15) - -### Fix - -- **astrolabe**: address review feedback for Vue 3 bindings -- **astrolabe**: update Vue component bindings for Vue 3 compatibility -- **ci**: bump helm chart version when MCP appVersion changes - -## astrolabe-v0.8.0 (2026-01-15) - -### Feat - -- Add rate limiting and extract helpers for app password endpoints - -### Fix - -- **astrolabe**: define appName and appVersion for @nextcloud/vue -- Add missing annotations for deck remove/unassign operations -- **auth**: Store app passwords locally for multi-user BasicAuth background sync -- **deck**: use correct endpoint for reorder_card to fix cross-stack moves -- **deck**: Always preserve fields in update_card for partial updates - -### Refactor - -- Use get_settings() for vector sync enabled check -- Extract storage helper and improve PHP error handling - -## astrolabe-v0.7.2 (2025-12-30) - -### Fix - -- **astrolabe**: Fix CSS loading for Nextcloud apps - -## astrolabe-v0.7.1 (2025-12-30) - -### Fix - -- **astrolabe**: Fix revoke access button HTTP method mismatch -- **oauth**: Enable browser OAuth routes for Management API in hybrid mode -- **mcp**: Move all imports to the top of modules - -## astrolabe-v0.7.0 (2025-12-26) - -### Feat - -- Remove URL rewriting in favor of proper nextcloud config -- **helm**: migrate to new environment variable naming convention -- Migrate to vue 3 -- **astrolabe**: upgrade to Vue 3 and @nextcloud/vue 9 -- **helm**: add support for multi-user BasicAuth mode - -### Fix - -- **tests**: Add singleton reset fixture to prevent anyio.WouldBlock errors -- **tests**: Fix integration test failures in qdrant, sampling, and rag tests -- **auth**: Skip issuer validation for management API tokens -- Use settings.enable_offline_access for env var consolidation -- Add required config.py attributes -- **docker**: remove overwritehost to fix container-to-container DCR -- **deps**: update dependency @nextcloud/vue to v9 -- **deps**: update dependency vue to v3 -- **helm**: set OIDC client env vars when using existingSecret -- **helm**: trigger chart release workflow on helm chart tags -- **helm**: address PR #447 reviewer feedback -- **helm**: include MCP server version bumps in changelog pattern - -### Refactor - -- **auth**: Decouple BasicAuth and OAuth authentication strategies - -## astrolabe-v0.6.0 (2025-12-22) - -### Feat - -- **config**: enable DCR for multi-user BasicAuth with offline access -- **astrolabe**: implement app password provisioning for multi-user background sync -- **config**: consolidate configuration with smart dependency resolution (ADR-021) - -## astrolabe-v0.5.0 (2025-12-20) - -### Feat - -- **auth**: add multi-user BasicAuth pass-through mode -- **astrolabe**: add dynamic MCP server configuration for testing - -### Fix - -- **config**: address reviewer feedback - -### Refactor - -- **config**: centralize configuration validation and simplify startup - -## astrolabe-v0.4.4 (2025-12-20) - -### Fix - -- **astrolabe**: screenshots in info.xml - -## astrolabe-v0.4.3 (2025-12-19) - -### Fix - -- **astrolabe**: screenshots in info.xml - -## astrolabe-v0.4.2 (2025-12-19) - -### Fix - -- **astrolabe**: Update screenshots -- **ci**: skip existing Helm chart releases to prevent duplicate release errors - -## astrolabe-v0.4.1 (2025-12-19) - -## astrolabe-v0.4.0 (2025-12-19) - -### Feat - -- **ci**: add --increment flag to bump scripts for manual version control - -## astrolabe-v0.3.2 (2025-12-19) - -### Fix - -- **astrolabe**: add contents:write permission to appstore workflow - -## astrolabe-v0.3.1 (2025-12-19) - -### Fix - -- **astrolabe**: update commitizen pattern to properly update info.xml version - -## astrolabe-v0.3.0 (2025-12-19) - -### Fix - -- **astrolabe**: prevent workflow failure when only helm/astrolabe commits exist -- **astrolabe**: info.xml - -## astrolabe-v0.2.1 (2025-12-19) - -### BREAKING CHANGE - -- MCP server now bumps for ANY conventional commit except -those explicitly scoped to helm or astrolabe. - -### Fix - -- **ci**: push all tags explicitly in bump workflow -- **ci**: make MCP server default bump target for all non-scoped commits -- **ci**: restrict docker build to MCP server tags only -- **ci**: correct appstore-push-action version to v1.0.4 - -## astrolabe-v0.2.0 (2025-12-19) - -### BREAKING CHANGE - -- Search algorithms now require Qdrant to be populated. -Vector sync must be enabled and documents indexed for search to work. -- All OAuth deployments must be reconfigured to specify -resource URIs (NEXTCLOUD_MCP_SERVER_URL and NEXTCLOUD_RESOURCE_URI) and -choose between multi-audience or token exchange mode. -- FASTMCP_-prefixed env vars have been replaced by CLI -arguments. Refer to the README for updated usage. - -### Feat - -- **ci**: implement monorepo-aware version bumping workflow -- **astrolabe**: add Nextcloud App Store deployment automation -- configure commitizen monorepo with independent versioning -- add Alembic database migration system -- make chunk modal title clickable link to documents -- add native Plotly hover styling for clickable points -- add click interactivity to Plotly 3D scatter chart -- improve chunk viewer with fixed navigation and markdown rendering -- **astrolabe**: enable multi-select for document types and refactor PDF viewer -- **auth**: implement refresh token rotation for Nextcloud OIDC -- **astrolabe**: enhance unified search and add webhook management -- **astrolabe**: add webhook management UI to admin settings -- **astrolabe**: add OAuth token refresh and webhook presets -- **search**: add file_path metadata and chunk offsets to search results -- **astrolabe**: use proper icons and thumbnails in unified search -- **astrolabe**: add admin search settings and enhanced UI -- **astrolabe**: add unified search provider with clickable file links -- **astrolabe**: add 3D PCA visualization for semantic search -- **astrolabe**: add Nextcloud PHP app for MCP server management -- **vector-sync**: enable background sync in OAuth mode -- **vector**: add Deck card vector search with visualization support -- **vector-viz**: add news_item support for links and chunk expansion -- add MCP tool annotations for enhanced UX -- **news**: add Nextcloud News app integration -- Add tag management methods to WebDAV client -- Add OpenAI provider support for embeddings and generation -- Add Smithery CLI deployment support -- Implement ADR-016 Smithery stateless deployment mode -- Add context expansion to semantic search with chunk overlap removal -- Use Ollama native batch API in embed_batch() -- Implement Qdrant placeholder state management -- Switch files to use numeric IDs with file_path resolution -- Implement per-chunk vector visualization with context expansion -- Improve vector visualization with static assets and fixes -- Redesign UI to match Nextcloud ecosystem aesthetic -- Replace custom document chunker with LangChain MarkdownTextSplitter -- **viz**: Add dual-score display and improve UI controls -- add configurable fusion algorithms for BM25 hybrid search -- add chunk position tracking to vector indexing and search -- add vector viz template and chunk context endpoint -- add unified provider architecture with Amazon Bedrock support -- add concurrent uploads and --force flag to upload command -- implement RAG evaluation framework with CLI tooling -- Add OpenTelemetry tracing to @instrument_tool decorator -- Implement BM25 hybrid search with native Qdrant RRF fusion -- Normalize hybrid search RRF scores to 0-1 range -- Enhance vector visualization UI and parallelize search verification -- Add Vector Viz tab to app home page -- Add vector visualization pane with multi-select document types -- Implement custom PCA to remove sklearn dependency -- Add multi-document Protocol with cross-app search support -- Update nc_semantic_search tool with algorithm selection -- Implement unified search algorithm module -- Enable SSE transport for mcp service and update test fixtures -- Complete Phase 5 - Instrument all 93 MCP tools -- Add instrumentation decorator and apply to notes tools (Phase 5) -- Add OAuth token and database metrics (Phases 3-4) -- Add metrics instrumentation for queue, health, and database operations -- Add Grafana dashboard and vector sync metric instrumentation -- **ollama**: Pull model on startup if not available in ollama -- add dynamic vector sync status updates with htmx polling -- add webhook management UI and BeforeNodeDeletedEvent support -- validate Nextcloud webhook schemas and document findings -- skip tracing for health and metrics endpoints -- **helm**: Add document chunking configuration -- **vector**: Add configurable chunk size and overlap for document embedding -- **vector**: Support multiple embedding models with auto-generated collection names -- **helm**: Add observability support with ServiceMonitor and Grafana dashboard -- **observability**: Add comprehensive monitoring with Prometheus and OpenTelemetry -- **helm**: add Qdrant local mode support with three deployment options [skip ci] -- add Qdrant local mode support with in-memory and persistent storage -- implement ADR-009 - refactor semantic search to use generic semantic:read scope -- implement MCP sampling for semantic search RAG (ADR-008) -- add optional vector database and semantic search to helm chart -- add vector sync processing status to /user/page endpoint -- implement semantic search tool and fix vector sync issues (ADR-007 Phase 3) -- implement vector sync scanner and processor (ADR-007 Phase 2) -- add real elicitation integration test with python-sdk MCP client -- unify session architecture and enhance login status visibility -- Implement ADR-005 unified token verifier to eliminate token passthrough vulnerability -- add scope protection to OAuth provisioning tools -- enable authorization services for token exchange in Keycloak -- implement scope-based audience mapping and RFC 9728 support -- integrate token exchange into MCP server application -- implement RFC 8693 Standard Token Exchange for Keycloak -- Add userinfo route/page -- add browser-based user info page with separate OAuth flow -- Implement ADR-004 Progressive Consent foundation (partial) -- Complete ADR-004 Progressive Consent OAuth flows implementation -- Implement ADR-004 Progressive Consent foundation components -- Implement ADR-004 Hybrid Flow with comprehensive integration tests -- Auto-configure impersonation role in Keycloak realm import -- Implement dual-tier token exchange (Standard V2 + Legacy V1 impersonation) -- Add Keycloak external IdP integration with custom scopes -- Implement RFC 8693 token exchange for Keycloak (ADR-002 Tier 2) -- Add Keycloak OAuth provider support with refresh token storage -- **server**: Add /live & /health endpoints -- Initialize helm chart -- Add text processing background worker for telling client about progress -- **auth**: Add support for client registration deletion -- Split read/write scopes into app:read/write scopes -- Enable token introspection for opaque tokens -- **server**: Add support for custom OIDC scopes and permissions via JWTs -- Initialize JWT-scoped tools -- **caldav**: Add support for tasks -- **webdav**: Add search and list favorite response tools -- **cookbook**: Add full Cookbook app support with 13 tools and 2 resources -- Add Groups API client -- add sharing API client and server tools -- **server**: Experimental support for OAuth2/OIDC authentication -- **users**: Initialize user API client -- **server**: Add support for `streamable-http` transport type -- Add WebDAV resource copy functionality -- Add WebDAV resource move/rename functionality -- **deck**: Add support for stack, cards, labels -- **deck**: Initialize Deck app client/server -- **cli**: Replace `mcp run` with click CLI and runtime options -- **client**: Preserve fields when modifying contacts/calendar resources -- **server**: Add structured output to all tool/resource output -- **contacts**: Initialize Contacts App -- **calendar**: add comprehensive Calendar app support via CalDAV protocol -- Update webdav client create_directory method to handle recursive directories -- **webdav**: add complete file system support -- Add TablesClient and associated tools -- Switch to using async client -- **notes**: Add append to note functionality - -### Fix - -- **ci**: improve versioning and error handling -- **ci**: address critical workflow and validation issues -- **astrolabe**: address code review feedback -- **security**: address critical security issues from PR #401 code review -- **oauth**: enable PKCE for all clients and add token_broker to oauth_context -- **astrolabe**: revert invalid files_pdfviewer URL for file links -- resolve type checking warnings for CI -- move Alembic to package submodule for Docker compatibility -- update unified search results to match chunk viz display -- **astrolabe**: handle OAuth refresh token rotation -- address critical code review issues (4 fixes) -- resolve CI linting issues for Astroglobe -- **news**: revert get_item() to use get_items() + filter -- Disable DNS rebinding protection for containerized deployments -- **deps**: update dependency mcp to >=1.23,<1.24 -- address PR review feedback -- Update lockfile -- Revert mcp version <1.23 -- resolve all type checking errors (8 errors fixed) -- **deps**: update dependency mcp to >=1.23,<1.24 -- **deps**: update dependency pillow to v12 -- Add rate limit retry logic to OpenAI provider -- Increase MCP sampling timeout to 5 minutes for slower LLMs -- Share vector sync state with FastMCP session lifespan via module singleton -- Share vector sync state with FastMCP session lifespan via module singleton -- Use WebDAV for tag creation and add LLM-as-a-judge for RAG tests -- **smithery**: Enable JSON response format for scanner compatibility -- **smithery**: Add JSON Schema metadata to mcp-config endpoint -- **smithery**: Use container runtime pattern for config discovery -- Add Smithery lifespan and auth mode detection -- Use alpha_composite for proper RGBA highlight blending -- Remove pymupdf.layout.activate() to fix page_chunks behavior -- Centralize PDF processing and generate separate images per chunk -- Set is_placeholder=False in processor to fix search filtering -- Increase placeholder staleness threshold to 5x scan interval -- Add placeholder staleness check to prevent duplicate processing -- Use empty SparseVector instead of None for placeholders -- Return empty array instead of null for query_coords when no results -- Align PDF text extraction between indexing and context expansion -- Update models and viz to use int-only doc_id -- Reconstruct full content for notes to match indexed offsets -- Add async/await, PDF metadata, and type safety fixes -- **deps**: update dependency mcp to >=1.22,<1.23 -- Improve 3D plot rendering with explicit dimensions and window resize support -- Preserve 3D plot camera and improve documentation -- Preserve 3D plot camera position and fix CSS loading -- prevent infinite loop in DocumentChunker with position tracking -- Relax SearchResult validation to support DBSF fusion scores > 1.0 -- suppress Starlette middleware type warnings in ty checker -- download qrels from BEIR ZIP instead of HuggingFace -- Handle named vectors in visualization and semantic search -- Update vizApp to use bm25_hybrid algorithm and remove deprecated weights -- Update viz routes to use BM25 hybrid search after refactor -- Reorder tabs and fix viz pane session access -- Use NEXTCLOUD_OIDC_CLIENT_ID/SECRET env vars consistently -- return all notes when search query is empty -- Move grafana_folder from labels to annotations -- add dynamic dimension detection for Ollama embedding models -- improve webapp tab UI with CSS Grid and viewport-filling container -- add retry logic for ETag conflicts in category change test -- optimize Notes API pagination with pruneBefore parameter -- Support in-memory Qdrant for CI testing -- **helm**: Set default strategy to Recreate -- **observability**: isolate metrics endpoint to dedicated port -- **readiness**: Only check external Qdrant in network mode -- **vector**: Handle missing 'modified' field in notes gracefully -- **ci**: Use helm dependency build instead of update to use Chart.lock -- **helm**: update Qdrant dependency condition to match new mode structure -- **ci**: add Helm repository setup to chart release workflow -- implement deletion grace period and vector sync status tool -- remove unnecessary urllib3<2.0 constraint -- integrate vector sync tasks with Starlette lifespan for streamable-http -- **deps**: update dependency mcp to >=1.21,<1.22 -- Consolidate OAuth callbacks and implement PKCE for all flows -- Implement proper OAuth resource parameters and PRM-based discovery -- Simplify token verifier to be RFC 7519 compliant -- Use Keycloak client ID for NEXTCLOUD_RESOURCE_URI in token exchange -- Correct OAuth token audience validation for multi-audience mode -- **deps**: update dependency mcp to >=1.20,<1.21 -- add missing await for get_nextcloud_client in capabilities resource -- use valid Fernet encryption keys in token exchange tests -- accept resource URL in token audience for Nextcloud JWT tokens -- remove token-exchange-nextcloud scope and accept tokens without audience -- move audience mapper from scope to nextcloud-mcp-server client -- move token-exchange-nextcloud from default to optional scopes -- restructure routes to prevent SessionAuthBackend from interfering with FastMCP OAuth -- allow OAuth Bearer tokens on /mcp endpoint by excluding from session auth -- correct OAuth token audience validation using RFC 8707 resource parameter -- remove remaining references to deleted oauth_callback and oauth_token -- remove Hybrid Flow, make Progressive Consent default (ADR-004) -- browser OAuth userinfo endpoint and refresh token rotation -- make ENABLE_PROGRESSIVE_CONSENT consistently opt-in (default false) -- make provisioning checks opt-in (default false) -- Disable Progressive Consent for mcp-oauth to enable Hybrid Flow tests -- Complete Keycloak external IdP integration with all tests passing -- Complete Keycloak external IdP integration with all tests passing -- Update DCR token_type tests for OIDC app changes -- **helm**: Remove image tag overide -- **helm**: Update helm chart with extraArgs -- Update helm chart variables -- **helm**: Update helm version with release -- **helm**: Update helm version with release -- **helm**: Update helm version with release -- **helm**: Update helm version with release -- Trigger release -- Add support for RFC 7592 client registration and deletion -- Update webdav models for proper serialization -- **deps**: update dependency mcp to >=1.19,<1.20 -- Add CORS middleware to allow browser-based clients like MCP Inspector -- Use occ-created OAuth clients with allowed_scopes for all tests -- Separate OAuth fixtures for opaque vs JWT tokens -- **caldav**: Fix caldav search() due to missing todos -- **caldav**: Check that calendar exists after creation to avoid race condition -- **caldav**: Properly parse datetimes as vDDDTypes -- Increase HTTP client timeout to 30s -- Handle RequestError in mcp tools -- **deps**: update dependency mcp to >=1.18,<1.19 -- **deps**: update dependency pillow to v12 -- **oauth**: Remove the option to force_register new clients -- Update user/groups API to OCS v2 -- **deps**: update dependency mcp to >=1.17,<1.18 -- **deps**: update dependency mcp to >=1.16,<1.17 -- **deps**: update dependency mcp to >=1.15,<1.16 -- **docker**: Provide --host 0.0.0.0 in default docker image -- **deps**: update dependency mcp to >=1.13,<1.14 -- **server**: Replace ErrorResponses with standard McpErrors -- **notes**: Include ETags in responses to avoid accidently updates -- **notes**: Remove note contents from responses to reduce token usage -- **model**: Serialize timestamps in RFC3339 format -- **client**: Use paging to fetch all notes -- **client**: Strip cookies from responses to avoid falsely raising CSRF errors -- **calendar**: Fix iCalendar date vs datetime format -- **calendar**: Remove try/except in calendar API -- apply ruff formatting to pass CI checks -- **calendar**: address PR feedback from maintainer -- apply ruff formatting to test_webdav_operations.py -- **deps**: update dependency mcp to >=1.10,<1.11 -- update tests -- Commitizen release process -- Do not update dependencies when running in Dockerfile -- Configure logging -- Limit search results to notes with score > 0.5 -- Install deps before checking service -- **deps**: update dependency mcp to >=1.9,<1.10 - -### Refactor - -- **astrolabe**: extract PDF viewer to dedicated component -- **astrolabe**: reframe UI as semantic search service -- **news**: simplify vector sync to fetch all items -- Move background tasks to server lifespan and deprecate SSE transport -- Simplify PDF text extraction with single to_markdown call -- migrate asyncio to anyio for consistent structured concurrency -- replace httpx client with NextcloudClient in upload command -- Optimize Nextcloud access verification with centralized filtering -- Make all search algorithms query Qdrant payload, not Nextcloud -- move webapp from /user/page to /app -- consolidate database storage for webhooks and OAuth tokens -- simplify OpenTelemetry tracing configuration -- migrate vector sync from asyncio.Queue to anyio memory object streams -- update to Qdrant query_points API and fix Playwright Keycloak login -- Eliminate duplicate validation logic in UnifiedTokenVerifier -- integrate token exchange into unified get_client() pattern -- Remove NEXTCLOUD_OIDC_CLIENT_STORAGE environment variable -- Remove unnecessary user_oidc patch - CORSMiddleware patch is sufficient -- Unify OAuth configuration to be provider-agnostic -- Transform document parsing into pluggable processor architecture -- Update JWT client to use DCR, re-enable tool filtering -- Migrate from internal CalendarClient to caldav library -- Unify logging & remove factory deployment -- Add tools for all resources to enable tool-only workflows -- Add `http` to --transport option -- Use _make_request where available -- **calendar**: optimize logging for production readiness -- Modularize NC and Notes app client - -### Perf - -- **deck**: optimize card lookup by storing board_id/stack_id in metadata -- **news**: use direct API endpoint for get_item() -- Optimize vector viz search performance -- Optimize PDF processing with parallel extraction and single-render highlights -- Eliminate double-fetching in semantic search sampling -- fix vector viz search performance and visual encoding -- make note deletion concurrent in upload --force -- Exclude vector-sync status polling from distributed tracing -- **notes**: Improve notes search performance using async iterators diff --git a/third_party/astrolabe/CODE_OF_CONDUCT.md b/third_party/astrolabe/CODE_OF_CONDUCT.md deleted file mode 100644 index d906007..0000000 --- a/third_party/astrolabe/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,9 +0,0 @@ -In the Nextcloud community, participants from all over the world come together to create Free Software for a free internet. This is made possible by the support, hard work and enthusiasm of thousands of people, including those who create and use Nextcloud software. - -Our code of conduct offers some guidance to ensure Nextcloud participants can cooperate effectively in a positive and inspiring atmosphere, and to explain how together we can strengthen and support each other. - -The Code of Conduct is shared by all contributors and users who engage with the Nextcloud team and its community services. It presents a summary of the shared values and “common sense” thinking in our community. - -You can find our full code of conduct on our website: https://nextcloud.com/code-of-conduct/ - -Please, keep our CoC in mind when you contribute! That way, everyone can be a part of our community in a productive, positive, creative and fun way. diff --git a/third_party/astrolabe/LICENSE b/third_party/astrolabe/LICENSE deleted file mode 100644 index be3f7b2..0000000 --- a/third_party/astrolabe/LICENSE +++ /dev/null @@ -1,661 +0,0 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU Affero General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU Affero General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU Affero General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU Affero General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see -. diff --git a/third_party/astrolabe/Makefile b/third_party/astrolabe/Makefile deleted file mode 100644 index f96e6e0..0000000 --- a/third_party/astrolabe/Makefile +++ /dev/null @@ -1,101 +0,0 @@ -# Nextcloud App Store Release Makefile for Astrolabe -# -# Based on: https://nextcloudappstore.readthedocs.io/en/latest/developer.html - -app_name=astrolabe -project_dir=$(CURDIR) -build_dir=$(project_dir)/build -appstore_dir=$(build_dir)/artifacts -package_name=$(appstore_dir)/$(app_name) -cert_dir=$(HOME)/.nextcloud/certificates - -# Nextcloud server path (configurable via environment variable) -server_dir?=../../server -occ=$(server_dir)/occ - -# Signing -private_key=$(cert_dir)/$(app_name).key -certificate=$(cert_dir)/$(app_name).crt -sign_cmd=php $(occ) integrity:sign-app --privateKey=$(private_key) --certificate=$(certificate) - -# Clean build artifacts -.PHONY: clean -clean: - rm -rf $(build_dir) - -# Validate required dependencies -.PHONY: validate-deps -validate-deps: - @command -v composer >/dev/null 2>&1 || { echo "Error: composer not found. Install from https://getcomposer.org/"; exit 1; } - @command -v npm >/dev/null 2>&1 || { echo "Error: npm not found. Install Node.js from https://nodejs.org/"; exit 1; } - @command -v php >/dev/null 2>&1 || { echo "Error: php not found. Install PHP 8.1 or higher."; exit 1; } - @echo "✓ All dependencies found" - -# Install PHP and Node dependencies -.PHONY: install-deps -install-deps: validate-deps - composer install --no-dev --optimize-autoloader - npm ci - -# Build production frontend assets -.PHONY: build-frontend -build-frontend: - npm run build - -# Run all linters -.PHONY: lint -lint: - composer lint - composer cs:check - npm run lint - npm run stylelint - -# Assemble app files into build directory (exclude dev files) -.PHONY: assemble -assemble: clean install-deps build-frontend - mkdir -p $(package_name) - # Copy app files - rsync -av \ - --exclude='.git*' \ - --exclude='build/' \ - --exclude='tests/' \ - --exclude='node_modules/' \ - --exclude='*.log' \ - --exclude='.github/' \ - --exclude='composer.json' \ - --exclude='composer.lock' \ - --exclude='package.json' \ - --exclude='package-lock.json' \ - --exclude='vite.config.js' \ - --exclude='.eslintrc.js' \ - --exclude='.php-cs-fixer.*' \ - --exclude='psalm.xml' \ - --exclude='*.iml' \ - --exclude='.idea' \ - --exclude='src/' \ - ./ $(package_name)/ - -# Validate signing prerequisites -.PHONY: validate-signing -validate-signing: - @test -f $(occ) || { echo "Error: Nextcloud server not found at $(server_dir)"; echo "Set server_dir variable: make appstore server_dir=/path/to/server"; exit 1; } - @test -f $(private_key) || { echo "Error: Private key not found at $(private_key)"; exit 1; } - @test -f $(certificate) || { echo "Error: Certificate not found at $(certificate)"; exit 1; } - @echo "✓ Signing prerequisites validated" - -# Create signed release tarball for App Store -.PHONY: appstore -appstore: assemble validate-signing - # Sign the app - $(sign_cmd) --path=$(package_name) - # Create tarball - cd $(appstore_dir) && \ - tar -czf $(app_name).tar.gz $(app_name) - # Show package info - @echo "=========================================" - @echo "App package created:" - @echo " $(appstore_dir)/$(app_name).tar.gz" - @echo "" - @echo "Signature:" - @cat $(package_name)/appinfo/signature.json | head -n 5 - @echo "=========================================" diff --git a/third_party/astrolabe/README.md b/third_party/astrolabe/README.md deleted file mode 100644 index 2346267..0000000 --- a/third_party/astrolabe/README.md +++ /dev/null @@ -1,223 +0,0 @@ -# Astrolabe: The Intelligence Layer for Nextcloud - -Your Nextcloud instance is more than just a bucket for files—it is a galaxy of ideas, projects, and knowledge. But until now, you've been navigating it in the dark, relying on exact filenames and rigid keywords. - -**It's time to turn the lights on.** - -Astrolabe is a fully integrated Nextcloud application that transforms your server into a semantic intelligence engine. It doesn't just store your data; it **maps it, understands it, and connects it** to the AI future. - ---- - -## What You Can Do - -### 🔍 Search That Actually Understands - -Forget clunky external tools. Astrolabe registers as a **native Nextcloud Search Provider**. - -- **Seamless**: Lives right in the standard Nextcloud search bar you already use -- **Semantic**: Type "marketing strategy for the winter launch" and Astrolabe finds the relevant PDFs, chat logs, and text files—even if those exact words never appear in the document -- **Intelligent**: It finds the **concept**, not just the string - -### 🌌 Visualize Your Data Universe - -Data shouldn't just be a list; it should be a landscape. Astrolabe includes a dedicated dashboard that visualizes your document chunks as a **3D PCA Vector Plot**. - -- **See the Connections**: View your data as a constellation of points in 3D space -- **Explore Clusters**: Visually identify how your documents relate to one another -- **True "Astroglobe" Experience**: Rotate, zoom, and fly through your semantic universe just like navigators once studied the stars - -### 🤖 Power Your AI Agents - -Astrolabe isn't just for humans; it's for your AI agents, too. It acts as a bridge, running a **Model Context Protocol (MCP) Server** directly from your Nextcloud. - -- **Bring Your Own Brain**: Connect external AI clients (like Claude Desktop or Cursor) to your private data -- **Agentic Workflows**: Enable LLMs to "sample" your files, read content, and perform complex reasoning tasks using your Nextcloud data as the source of truth -- **Private & Secure**: Your data never leaves your infrastructure - ---- - -## Installation - -### From App Store (Recommended) - -1. Open **Apps** in your Nextcloud -2. Search for **"Astrolabe"** -3. Click **"Download and enable"** - -### Manual Installation - -```bash -# Clone into your Nextcloud apps directory -cd /path/to/nextcloud/apps -git clone https://github.com/cbcoutinho/nextcloud-mcp-server.git -cd nextcloud-mcp-server/third_party/astrolabe - -# Install dependencies -composer install - -# Enable the app -php /path/to/nextcloud/occ app:enable astrolabe -``` - ---- - -## Quick Start - -### 1. Configure the MCP Server URL - -Add this to your Nextcloud `config/config.php`: - -```php -'mcp_server_url' => 'http://localhost:8000', -``` - -### 2. Start the MCP Server - -The MCP server handles semantic search and AI agent connections. See the [MCP Server Installation Guide](https://github.com/cbcoutinho/nextcloud-mcp-server/blob/master/docs/installation.md) for details. - -Quick start with Docker: - -```bash -docker run -p 127.0.0.1:8000:8000 --env-file .env --rm \ - ghcr.io/cbcoutinho/nextcloud-mcp-server:latest --oauth -``` - -### 3. Authorize Access - -1. Go to **Settings → Personal → Astrolabe** -2. Click **"Authorize Access"** -3. Sign in to your identity provider -4. Approve the requested permissions - -That's it! You can now use semantic search and explore your data universe. - ---- - -## Features - -### Personal Settings - -Located in: **Settings → Personal → Astrolabe** - -- **Semantic Search Dashboard**: Interactive 3D visualization of your document chunks -- **OAuth Authorization**: Authorize Nextcloud to access the MCP server on your behalf -- **Session Information**: View connection status and authentication details -- **Connection Management**: Revoke access or disconnect when needed - -### Admin Settings - -Located in: **Settings → Administration → Astrolabe** - -- **Server Status**: Monitor MCP server health and version -- **Vector Sync Metrics**: See how many documents are indexed, processing rates, and sync status -- **Configuration Validation**: Verify server URL and connectivity -- **Feature Availability**: Check which capabilities are enabled - -### Unified Search Integration - -Astrolabe integrates directly with Nextcloud's **Unified Search**: - -- Available in the top search bar across all Nextcloud pages -- Returns semantic matches ranked by relevance -- Shows excerpts from matching documents -- Links directly to source files in Nextcloud - ---- - -## Use Cases - -### For Individuals - -- **Research**: Find all notes related to a project, even if they use different terminology -- **Organization**: Discover forgotten documents related to your current work -- **Exploration**: Visualize how your knowledge connects and evolves over time - -### For Teams - -- **Knowledge Discovery**: Surface institutional knowledge that would otherwise stay buried -- **Collaboration**: Find team members working on similar problems -- **Documentation**: Locate relevant documentation without knowing exact titles - -### For Developers - -- **AI Integration**: Connect Claude Desktop, Cursor, or other MCP clients to Nextcloud -- **RAG Workflows**: Build retrieval-augmented generation pipelines on your private data -- **Custom Agents**: Use the MCP protocol to create specialized workflows - ---- - -## Requirements - -- **Nextcloud**: Version 30 or later -- **MCP Server**: Running instance (Docker recommended) -- **Identity Provider**: OAuth provider supporting PKCE (Nextcloud OIDC Login or Keycloak) -- **Vector Sync**: Optional but recommended for semantic search (see [configuration guide](https://github.com/cbcoutinho/nextcloud-mcp-server/blob/master/docs/configuration.md)) - ---- - -## Documentation - -### User Guides - -- [MCP Server Installation](https://github.com/cbcoutinho/nextcloud-mcp-server/blob/master/docs/installation.md) -- [Configuration Guide](https://github.com/cbcoutinho/nextcloud-mcp-server/blob/master/docs/configuration.md) -- [OAuth Setup](https://github.com/cbcoutinho/nextcloud-mcp-server/blob/master/docs/oauth-setup.md) - -### Technical Details - -- [ADR-018: Nextcloud PHP App Architecture](https://github.com/cbcoutinho/nextcloud-mcp-server/blob/master/docs/ADR-018-nextcloud-php-app-for-settings-ui.md) -- [OAuth PKCE Flow Details](https://github.com/cbcoutinho/nextcloud-mcp-server/blob/master/docs/ADR-004-progressive-consent.md) -- [Vector Sync Architecture](https://github.com/cbcoutinho/nextcloud-mcp-server/blob/master/docs/ADR-002-vector-sync-authentication.md) - -### Troubleshooting - -**Cannot connect to MCP server:** -- Verify `mcp_server_url` in `config.php` -- Check MCP server is running: `curl http://localhost:8000/health` -- Review logs: `tail -f data/nextcloud.log` - -**Authorization fails:** -- Ensure MCP server is in OAuth mode -- Verify identity provider is accessible -- Check browser console for errors - -**Semantic search returns no results:** -- Verify vector sync is enabled and running -- Check indexing status in Admin settings -- Allow time for initial indexing to complete - -For more help, see the [Troubleshooting Guide](https://github.com/cbcoutinho/nextcloud-mcp-server/blob/master/docs/troubleshooting.md). - ---- - -## Contributing - -We welcome contributions! Here's how to get started: - -1. Fork the [nextcloud-mcp-server repository](https://github.com/cbcoutinho/nextcloud-mcp-server) -2. Create a feature branch: `git checkout -b feature/your-feature` -3. Make your changes in `third_party/astrolabe/` -4. Test thoroughly with a local Nextcloud instance -5. Submit a pull request - -See [CONTRIBUTING.md](https://github.com/cbcoutinho/nextcloud-mcp-server/blob/master/CONTRIBUTING.md) for detailed guidelines. - ---- - -## License - -AGPL-3.0 - ---- - -## About - -**Astrolabe** is developed as part of the [Nextcloud MCP Server](https://github.com/cbcoutinho/nextcloud-mcp-server) project, bringing the power of semantic search and AI integration to Nextcloud. - -**Author**: Chris Coutinho - ---- - -**Your Data. Mapped. Visualized. Connected.** - -Install Astrolabe for Nextcloud. diff --git a/third_party/astrolabe/appinfo/info.xml b/third_party/astrolabe/appinfo/info.xml deleted file mode 100644 index 76de198..0000000 --- a/third_party/astrolabe/appinfo/info.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - astrolabe - Astrolabe - AI-powered semantic search across your Nextcloud - - 0.10.1 - agpl - Chris Coutinho - Astrolabe - ai - https://github.com/cbcoutinho/nextcloud-mcp-server/issues - https://github.com/cbcoutinho/nextcloud-mcp-server - https://github.com/cbcoutinho/nextcloud-mcp-server/blob/master/third_party/astrolabe/screenshots/02-semantic-search-with-plot.png?raw=1 - https://github.com/cbcoutinho/nextcloud-mcp-server/blob/master/third_party/astrolabe/screenshots/01-unified-search-astrolabe.png?raw=1 - https://github.com/cbcoutinho/nextcloud-mcp-server/blob/master/third_party/astrolabe/screenshots/03-chunk-viewer-open.png?raw=1 - - - - - OCA\Astrolabe\Settings\Personal - OCA\Astrolabe\Settings\PersonalSection - OCA\Astrolabe\Settings\Admin - OCA\Astrolabe\Settings\AdminSection - - - - astrolabe - Astrolabe - astrolabe.page.index - app.svg - link - - - - OCA\Astrolabe\BackgroundJob\RefreshUserTokens - - diff --git a/third_party/astrolabe/appinfo/routes.php b/third_party/astrolabe/appinfo/routes.php deleted file mode 100644 index 35d0c8d..0000000 --- a/third_party/astrolabe/appinfo/routes.php +++ /dev/null @@ -1,115 +0,0 @@ - [ - // OAuth routes - [ - 'name' => 'oauth#initiateOAuth', - 'url' => '/oauth/authorize', - 'verb' => 'GET', - ], - [ - 'name' => 'oauth#oauthCallback', - 'url' => '/oauth/callback', - 'verb' => 'GET', - ], - [ - 'name' => 'oauth#disconnect', - 'url' => '/oauth/disconnect', - 'verb' => 'POST', - ], - - // API routes (form handlers) - [ - 'name' => 'api#revokeAccess', - 'url' => '/api/revoke', - 'verb' => 'POST', - ], - - // Background sync credentials routes - [ - 'name' => 'credentials#storeAppPassword', - 'url' => '/api/v1/background-sync/credentials', - 'verb' => 'POST', - ], - [ - 'name' => 'credentials#getCredentials', - 'url' => '/api/v1/background-sync/credentials/{userId}', - 'verb' => 'GET', - ], - [ - 'name' => 'credentials#deleteCredentials', - 'url' => '/api/v1/background-sync/credentials/revoke', - 'verb' => 'POST', - ], - [ - 'name' => 'credentials#getStatus', - 'url' => '/api/v1/background-sync/status', - 'verb' => 'GET', - ], - - // Vector search API routes - [ - 'name' => 'api#search', - 'url' => '/api/search', - 'verb' => 'GET', - ], - [ - 'name' => 'api#vectorStatus', - 'url' => '/api/vector-status', - 'verb' => 'GET', - ], - [ - 'name' => 'api#chunkContext', - 'url' => '/api/chunk-context', - 'verb' => 'GET', - ], - [ - 'name' => 'api#pdfPreview', - 'url' => '/api/pdf-preview', - 'verb' => 'GET', - ], - - // Admin settings routes - [ - 'name' => 'api#serverStatus', - 'url' => '/api/admin/server-status', - 'verb' => 'GET', - ], - [ - 'name' => 'api#adminVectorStatus', - 'url' => '/api/admin/vector-status', - 'verb' => 'GET', - ], - [ - 'name' => 'api#saveSearchSettings', - 'url' => '/api/admin/search-settings', - 'verb' => 'POST', - ], - - // Webhook management routes (admin only) - [ - 'name' => 'api#getWebhookPresets', - 'url' => '/api/admin/webhooks/presets', - 'verb' => 'GET', - ], - [ - 'name' => 'api#enableWebhookPreset', - 'url' => '/api/admin/webhooks/presets/{presetId}/enable', - 'verb' => 'POST', - ], - [ - 'name' => 'api#disableWebhookPreset', - 'url' => '/api/admin/webhooks/presets/{presetId}/disable', - 'verb' => 'POST', - ], - ], -]; diff --git a/third_party/astrolabe/composer.json b/third_party/astrolabe/composer.json deleted file mode 100644 index 91969c1..0000000 --- a/third_party/astrolabe/composer.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "name": "nextcloud/astrolabe", - "description": "This app provides a management UI for the Nextcloud MCP Server", - "license": "AGPL-3.0-or-later", - "authors": [ - { - "name": "Chris Coutinho", - "email": "chris@coutinho.io", - "homepage": "https://github.com/cbcoutinho" - } - ], - "autoload": { - "psr-4": { - "OCA\\Astrolabe\\": "lib/" - } - }, - "autoload-dev": { - "psr-4": { - "OCP\\": "vendor/nextcloud/ocp/OCP/" - } - }, - "scripts": { - "post-install-cmd": [ - "@composer bin all install --ansi" - ], - "post-update-cmd": [ - "@composer bin all install --ansi" - ], - "lint": "find . -name \\*.php -not -path './vendor/*' -not -path './vendor-bin/*' -not -path './build/*' -print0 | xargs -0 -n1 php -l", - "cs:check": "php-cs-fixer fix --dry-run --diff", - "cs:fix": "php-cs-fixer fix", - "psalm": "psalm --threads=1 --no-cache", - "test:unit": "./vendor/bin/phpunit -c tests/unit/phpunit.xml --colors=always", - "openapi": "generate-spec", - "rector": "rector && composer cs:fix" - }, - "require": { - "bamarni/composer-bin-plugin": "^1.8", - "php": "^8.1" - }, - "require-dev": { - "doctrine/dbal": "^3.8", - "nextcloud/ocp": "dev-stable30", - "phpunit/phpunit": "^10.0", - "roave/security-advisories": "dev-latest" - }, - "config": { - "allow-plugins": { - "bamarni/composer-bin-plugin": true - }, - "optimize-autoloader": true, - "sort-packages": true, - "platform": { - "php": "8.1" - } - } -} diff --git a/third_party/astrolabe/composer.lock b/third_party/astrolabe/composer.lock deleted file mode 100644 index c0f062e..0000000 --- a/third_party/astrolabe/composer.lock +++ /dev/null @@ -1,3305 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "e6ea5a770c578a5d7694602bb2618cef", - "packages": [ - { - "name": "bamarni/composer-bin-plugin", - "version": "1.8.3", - "source": { - "type": "git", - "url": "https://github.com/bamarni/composer-bin-plugin.git", - "reference": "e7ef9e012667327516c24e5fad9903a3bc91389d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/bamarni/composer-bin-plugin/zipball/e7ef9e012667327516c24e5fad9903a3bc91389d", - "reference": "e7ef9e012667327516c24e5fad9903a3bc91389d", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^2.0", - "php": "^7.2.5 || ^8.0" - }, - "require-dev": { - "composer/composer": "^2.0", - "ext-json": "*", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", - "phpunit/phpunit": "^8.5 || ^9.6 || ^10.0", - "symfony/console": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0", - "symfony/finder": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0", - "symfony/process": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0" - }, - "type": "composer-plugin", - "extra": { - "class": "Bamarni\\Composer\\Bin\\BamarniBinPlugin" - }, - "autoload": { - "psr-4": { - "Bamarni\\Composer\\Bin\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "No conflicts for your bin dependencies", - "keywords": [ - "composer", - "conflict", - "dependency", - "executable", - "isolation", - "tool" - ], - "support": { - "issues": "https://github.com/bamarni/composer-bin-plugin/issues", - "source": "https://github.com/bamarni/composer-bin-plugin/tree/1.8.3" - }, - "time": "2025-11-24T19:20:55+00:00" - } - ], - "packages-dev": [ - { - "name": "doctrine/dbal", - "version": "3.10.4", - "source": { - "type": "git", - "url": "https://github.com/doctrine/dbal.git", - "reference": "63a46cb5aa6f60991186cc98c1d1b50c09311868" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/63a46cb5aa6f60991186cc98c1d1b50c09311868", - "reference": "63a46cb5aa6f60991186cc98c1d1b50c09311868", - "shasum": "" - }, - "require": { - "composer-runtime-api": "^2", - "doctrine/deprecations": "^0.5.3|^1", - "doctrine/event-manager": "^1|^2", - "php": "^7.4 || ^8.0", - "psr/cache": "^1|^2|^3", - "psr/log": "^1|^2|^3" - }, - "conflict": { - "doctrine/cache": "< 1.11" - }, - "require-dev": { - "doctrine/cache": "^1.11|^2.0", - "doctrine/coding-standard": "14.0.0", - "fig/log-test": "^1", - "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "2.1.30", - "phpstan/phpstan-strict-rules": "^2", - "phpunit/phpunit": "9.6.29", - "slevomat/coding-standard": "8.24.0", - "squizlabs/php_codesniffer": "4.0.0", - "symfony/cache": "^5.4|^6.0|^7.0|^8.0", - "symfony/console": "^4.4|^5.4|^6.0|^7.0|^8.0" - }, - "suggest": { - "symfony/console": "For helpful console commands such as SQL execution and import of files." - }, - "bin": [ - "bin/doctrine-dbal" - ], - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\DBAL\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - } - ], - "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.", - "homepage": "https://www.doctrine-project.org/projects/dbal.html", - "keywords": [ - "abstraction", - "database", - "db2", - "dbal", - "mariadb", - "mssql", - "mysql", - "oci8", - "oracle", - "pdo", - "pgsql", - "postgresql", - "queryobject", - "sasql", - "sql", - "sqlite", - "sqlserver", - "sqlsrv" - ], - "support": { - "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.10.4" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdbal", - "type": "tidelift" - } - ], - "time": "2025-11-29T10:46:08+00:00" - }, - { - "name": "doctrine/deprecations", - "version": "1.1.5", - "source": { - "type": "git", - "url": "https://github.com/doctrine/deprecations.git", - "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", - "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "phpunit/phpunit": "<=7.5 || >=13" - }, - "require-dev": { - "doctrine/coding-standard": "^9 || ^12 || ^13", - "phpstan/phpstan": "1.4.10 || 2.1.11", - "phpstan/phpstan-phpunit": "^1.0 || ^2", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12", - "psr/log": "^1 || ^2 || ^3" - }, - "suggest": { - "psr/log": "Allows logging deprecations via PSR-3 logger implementation" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Deprecations\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", - "homepage": "https://www.doctrine-project.org/", - "support": { - "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.5" - }, - "time": "2025-04-07T20:06:18+00:00" - }, - { - "name": "doctrine/event-manager", - "version": "2.1.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/event-manager.git", - "reference": "c07799fcf5ad362050960a0fd068dded40b1e312" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/event-manager/zipball/c07799fcf5ad362050960a0fd068dded40b1e312", - "reference": "c07799fcf5ad362050960a0fd068dded40b1e312", - "shasum": "" - }, - "require": { - "php": "^8.1" - }, - "conflict": { - "doctrine/common": "<2.9" - }, - "require-dev": { - "doctrine/coding-standard": "^14", - "phpdocumentor/guides-cli": "^1.4", - "phpstan/phpstan": "^2.1.32", - "phpunit/phpunit": "^10.5.58" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", - "homepage": "https://www.doctrine-project.org/projects/event-manager.html", - "keywords": [ - "event", - "event dispatcher", - "event manager", - "event system", - "events" - ], - "support": { - "issues": "https://github.com/doctrine/event-manager/issues", - "source": "https://github.com/doctrine/event-manager/tree/2.1.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fevent-manager", - "type": "tidelift" - } - ], - "time": "2026-01-17T22:40:21+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.13.4", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", - "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3 <3.2.2" - }, - "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpspec/prophecy": "^1.10", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" - }, - "type": "library", - "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2025-08-01T08:46:24+00:00" - }, - { - "name": "nextcloud/ocp", - "version": "dev-stable30", - "source": { - "type": "git", - "url": "https://github.com/nextcloud-deps/ocp.git", - "reference": "d93fc10fea3db4b4896e37db312fae685cff54c4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/d93fc10fea3db4b4896e37db312fae685cff54c4", - "reference": "d93fc10fea3db4b4896e37db312fae685cff54c4", - "shasum": "" - }, - "require": { - "php": "~8.0 || ~8.1 || ~8.2 || ~8.3", - "psr/clock": "^1.0", - "psr/container": "^2.0.2", - "psr/event-dispatcher": "^1.0", - "psr/log": "^2.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-stable30": "30.0.0-dev" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "AGPL-3.0-or-later" - ], - "authors": [ - { - "name": "Christoph Wurst", - "email": "christoph@winzerhof-wurst.at" - } - ], - "description": "Composer package containing Nextcloud's public API (classes, interfaces)", - "support": { - "issues": "https://github.com/nextcloud-deps/ocp/issues", - "source": "https://github.com/nextcloud-deps/ocp/tree/stable30" - }, - "time": "2025-12-02T00:53:40+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v5.7.0", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "ext-json": "*", - "ext-tokenizer": "*", - "php": ">=7.4" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" - }, - "time": "2025-12-06T11:56:16+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "54750ef60c58e43759730615a392c31c80e23176" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", - "reference": "54750ef60c58e43759730615a392c31c80e23176", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2024-03-03T12:33:53+00:00" - }, - { - "name": "phar-io/version", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" - }, - "time": "2022-02-21T01:04:05+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "10.1.16", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "7e308268858ed6baedc8704a304727d20bc07c77" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", - "reference": "7e308268858ed6baedc8704a304727d20bc07c77", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^4.19.1 || ^5.1.0", - "php": ">=8.1", - "phpunit/php-file-iterator": "^4.1.0", - "phpunit/php-text-template": "^3.0.1", - "sebastian/code-unit-reverse-lookup": "^3.0.0", - "sebastian/complexity": "^3.2.0", - "sebastian/environment": "^6.1.0", - "sebastian/lines-of-code": "^2.0.2", - "sebastian/version": "^4.0.1", - "theseer/tokenizer": "^1.2.3" - }, - "require-dev": { - "phpunit/phpunit": "^10.1" - }, - "suggest": { - "ext-pcov": "PHP extension that provides line coverage", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "10.1.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-08-22T04:31:57+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "4.1.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-08-31T06:24:48+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "4.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^10.0" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:56:09+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "3.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-08-31T14:07:24+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "6.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:57:52+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "10.5.63", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "33198268dad71e926626b618f3ec3966661e4d90" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/33198268dad71e926626b618f3ec3966661e4d90", - "reference": "33198268dad71e926626b618f3ec3966661e4d90", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.13.4", - "phar-io/manifest": "^2.0.4", - "phar-io/version": "^3.2.1", - "php": ">=8.1", - "phpunit/php-code-coverage": "^10.1.16", - "phpunit/php-file-iterator": "^4.1.0", - "phpunit/php-invoker": "^4.0.0", - "phpunit/php-text-template": "^3.0.1", - "phpunit/php-timer": "^6.0.0", - "sebastian/cli-parser": "^2.0.1", - "sebastian/code-unit": "^2.0.0", - "sebastian/comparator": "^5.0.5", - "sebastian/diff": "^5.1.1", - "sebastian/environment": "^6.1.0", - "sebastian/exporter": "^5.1.4", - "sebastian/global-state": "^6.0.2", - "sebastian/object-enumerator": "^5.0.0", - "sebastian/recursion-context": "^5.0.1", - "sebastian/type": "^4.0.0", - "sebastian/version": "^4.0.1" - }, - "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "10.5-dev" - } - }, - "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.63" - }, - "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", - "type": "tidelift" - } - ], - "time": "2026-01-27T05:48:37+00:00" - }, - { - "name": "psr/cache", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ], - "support": { - "source": "https://github.com/php-fig/cache/tree/3.0.0" - }, - "time": "2021-02-03T23:26:27+00:00" - }, - { - "name": "psr/clock", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/clock.git", - "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", - "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", - "shasum": "" - }, - "require": { - "php": "^7.0 || ^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Psr\\Clock\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for reading the clock.", - "homepage": "https://github.com/php-fig/clock", - "keywords": [ - "clock", - "now", - "psr", - "psr-20", - "time" - ], - "support": { - "issues": "https://github.com/php-fig/clock/issues", - "source": "https://github.com/php-fig/clock/tree/1.0.0" - }, - "time": "2022-11-25T14:36:26+00:00" - }, - { - "name": "psr/container", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" - }, - "time": "2021-11-05T16:47:00+00:00" - }, - { - "name": "psr/event-dispatcher", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/event-dispatcher.git", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", - "shasum": "" - }, - "require": { - "php": ">=7.2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\EventDispatcher\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Standard interfaces for event handling.", - "keywords": [ - "events", - "psr", - "psr-14" - ], - "support": { - "issues": "https://github.com/php-fig/event-dispatcher/issues", - "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" - }, - "time": "2019-01-08T18:20:26+00:00" - }, - { - "name": "psr/log", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/ef29f6d262798707a9edd554e2b82517ef3a9376", - "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/2.0.0" - }, - "time": "2021-07-14T16:41:46+00:00" - }, - { - "name": "roave/security-advisories", - "version": "dev-latest", - "source": { - "type": "git", - "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "1553067758ae7f3df13df7c7e232c62d928e1d23" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/1553067758ae7f3df13df7c7e232c62d928e1d23", - "reference": "1553067758ae7f3df13df7c7e232c62d928e1d23", - "shasum": "" - }, - "conflict": { - "3f/pygmentize": "<1.2", - "adaptcms/adaptcms": "<=1.3", - "admidio/admidio": "<=4.3.16", - "adodb/adodb-php": "<=5.22.9", - "aheinze/cockpit": "<2.2", - "aimeos/ai-admin-graphql": ">=2022.04.1,<2022.10.10|>=2023.04.1,<2023.10.6|>=2024.04.1,<2024.07.2", - "aimeos/ai-admin-jsonadm": "<2020.10.13|>=2021.04.1,<2021.10.6|>=2022.04.1,<2022.10.3|>=2023.04.1,<2023.10.4|==2024.04.1", - "aimeos/ai-client-html": ">=2020.04.1,<2020.10.27|>=2021.04.1,<2021.10.22|>=2022.04.1,<2022.10.13|>=2023.04.1,<2023.10.15|>=2024.04.1,<2024.04.7", - "aimeos/ai-cms-grapesjs": ">=2021.04.1,<2021.10.8|>=2022.04.1,<2022.10.9|>=2023.04.1,<2023.10.15|>=2024.04.1,<2024.10.8|>=2025.04.1,<2025.10.2", - "aimeos/ai-controller-frontend": "<2020.10.15|>=2021.04.1,<2021.10.8|>=2022.04.1,<2022.10.8|>=2023.04.1,<2023.10.9|==2024.04.1", - "aimeos/aimeos-core": ">=2022.04.1,<2022.10.17|>=2023.04.1,<2023.10.17|>=2024.04.1,<2024.04.7", - "aimeos/aimeos-typo3": "<19.10.12|>=20,<20.10.5", - "airesvsg/acf-to-rest-api": "<=3.1", - "akaunting/akaunting": "<2.1.13", - "akeneo/pim-community-dev": "<5.0.119|>=6,<6.0.53", - "alextselegidis/easyappointments": "<1.5.2.0-beta1", - "alexusmai/laravel-file-manager": "<=3.3.1", - "alt-design/alt-redirect": "<1.6.4", - "alterphp/easyadmin-extension-bundle": ">=1.2,<1.2.11|>=1.3,<1.3.1", - "amazing/media2click": ">=1,<1.3.3", - "ameos/ameos_tarteaucitron": "<1.2.23", - "amphp/artax": "<1.0.6|>=2,<2.0.6", - "amphp/http": "<=1.7.2|>=2,<=2.1", - "amphp/http-client": ">=4,<4.4", - "anchorcms/anchor-cms": "<=0.12.7", - "andreapollastri/cipi": "<=3.1.15", - "andrewhaine/silverstripe-form-capture": ">=0.2,<=0.2.3|>=1,<1.0.2|>=2,<2.2.5", - "aoe/restler": "<1.7.1", - "apache-solr-for-typo3/solr": "<2.8.3", - "apereo/phpcas": "<1.6", - "api-platform/core": "<3.4.17|>=4,<4.0.22|>=4.1,<4.1.5", - "api-platform/graphql": "<3.4.17|>=4,<4.0.22|>=4.1,<4.1.5", - "appwrite/server-ce": "<=1.2.1", - "arc/web": "<3", - "area17/twill": "<1.2.5|>=2,<2.5.3", - "artesaos/seotools": "<0.17.2", - "asymmetricrypt/asymmetricrypt": "<9.9.99", - "athlon1600/php-proxy": "<=5.1", - "athlon1600/php-proxy-app": "<=3", - "athlon1600/youtube-downloader": "<=4", - "austintoddj/canvas": "<=3.4.2", - "auth0/auth0-php": ">=3.3,<=8.16", - "auth0/login": "<=7.18", - "auth0/symfony": "<=5.4.1", - "auth0/wordpress": "<=5.3", - "automad/automad": "<2.0.0.0-alpha5", - "automattic/jetpack": "<9.8", - "awesome-support/awesome-support": "<=6.0.7", - "aws/aws-sdk-php": "<3.288.1", - "azuracast/azuracast": "<=0.23.1", - "b13/seo_basics": "<0.8.2", - "backdrop/backdrop": "<=1.32", - "backpack/crud": "<3.4.9", - "backpack/filemanager": "<2.0.2|>=3,<3.0.9", - "bacula-web/bacula-web": "<9.7.1", - "badaso/core": "<=2.9.11", - "bagisto/bagisto": "<=2.3.7", - "barrelstrength/sprout-base-email": "<1.2.7", - "barrelstrength/sprout-forms": "<3.9", - "barryvdh/laravel-translation-manager": "<0.6.8", - "barzahlen/barzahlen-php": "<2.0.1", - "baserproject/basercms": "<=5.1.1", - "bassjobsen/bootstrap-3-typeahead": ">4.0.2", - "bbpress/bbpress": "<2.6.5", - "bcit-ci/codeigniter": "<3.1.3", - "bcosca/fatfree": "<3.7.2", - "bedita/bedita": "<4", - "bednee/cooluri": "<1.0.30", - "bigfork/silverstripe-form-capture": ">=3,<3.1.1", - "billz/raspap-webgui": "<3.3.6", - "binarytorch/larecipe": "<2.8.1", - "bk2k/bootstrap-package": ">=7.1,<7.1.2|>=8,<8.0.8|>=9,<9.0.4|>=9.1,<9.1.3|>=10,<10.0.10|>=11,<11.0.3", - "blueimp/jquery-file-upload": "==6.4.4", - "bmarshall511/wordpress_zero_spam": "<5.2.13", - "bolt/bolt": "<3.7.2", - "bolt/core": "<=4.2", - "born05/craft-twofactorauthentication": "<3.3.4", - "bottelet/flarepoint": "<2.2.1", - "bref/bref": "<2.1.17", - "brightlocal/phpwhois": "<=4.2.5", - "brotkrueml/codehighlight": "<2.7", - "brotkrueml/schema": "<1.13.1|>=2,<2.5.1", - "brotkrueml/typo3-matomo-integration": "<1.3.2", - "buddypress/buddypress": "<7.2.1", - "bugsnag/bugsnag-laravel": ">=2,<2.0.2", - "bvbmedia/multishop": "<2.0.39", - "bytefury/crater": "<6.0.2", - "cachethq/cachet": "<2.5.1", - "cakephp/cakephp": "<3.10.3|>=4,<4.0.10|>=4.1,<4.1.4|>=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10", - "cakephp/database": ">=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10", - "cardgate/magento2": "<2.0.33", - "cardgate/woocommerce": "<=3.1.15", - "cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4", - "cart2quote/module-quotation-encoded": ">=4.1.6,<=4.4.5|>=5,<5.4.4", - "cartalyst/sentry": "<=2.1.6", - "catfan/medoo": "<1.7.5", - "causal/oidc": "<4", - "cecil/cecil": "<7.47.1", - "centreon/centreon": "<22.10.15", - "cesnet/simplesamlphp-module-proxystatistics": "<3.1", - "chriskacerguis/codeigniter-restserver": "<=2.7.1", - "chrome-php/chrome": "<1.14", - "civicrm/civicrm-core": ">=4.2,<4.2.9|>=4.3,<4.3.3", - "ckeditor/ckeditor": "<4.25", - "clickstorm/cs-seo": ">=6,<6.8|>=7,<7.5|>=8,<8.4|>=9,<9.3", - "co-stack/fal_sftp": "<0.2.6", - "cockpit-hq/cockpit": "<2.11.4", - "code16/sharp": "<9.11.1", - "codeception/codeception": "<3.1.3|>=4,<4.1.22", - "codeigniter/framework": "<3.1.10", - "codeigniter4/framework": "<4.6.2", - "codeigniter4/shield": "<1.0.0.0-beta8", - "codiad/codiad": "<=2.8.4", - "codingms/additional-tca": ">=1.7,<1.15.17|>=1.16,<1.16.9", - "codingms/modules": "<4.3.11|>=5,<5.7.4|>=6,<6.4.2|>=7,<7.5.5", - "commerceteam/commerce": ">=0.9.6,<0.9.9", - "components/jquery": ">=1.0.3,<3.5", - "composer/composer": "<1.10.27|>=2,<2.2.24|>=2.3,<2.7.7", - "concrete5/concrete5": "<9.4.3", - "concrete5/core": "<8.5.8|>=9,<9.1", - "contao-components/mediaelement": ">=2.14.2,<2.21.1", - "contao/comments-bundle": ">=2,<4.13.40|>=5.0.0.0-RC1-dev,<5.3.4", - "contao/contao": ">=3,<3.5.37|>=4,<4.4.56|>=4.5,<4.13.56|>=5,<5.3.38|>=5.4.0.0-RC1-dev,<5.6.1", - "contao/core": "<3.5.39", - "contao/core-bundle": "<4.13.57|>=5,<5.3.42|>=5.4,<5.6.5", - "contao/listing-bundle": ">=3,<=3.5.30|>=4,<4.4.8", - "contao/managed-edition": "<=1.5", - "corveda/phpsandbox": "<1.3.5", - "cosenary/instagram": "<=2.3", - "couleurcitron/tarteaucitron-wp": "<0.3", - "craftcms/cms": "<=4.16.5|>=5,<=5.8.6", - "croogo/croogo": "<4", - "cuyz/valinor": "<0.12", - "czim/file-handling": "<1.5|>=2,<2.3", - "czproject/git-php": "<4.0.3", - "damienharper/auditor-bundle": "<5.2.6", - "dapphp/securimage": "<3.6.6", - "darylldoyle/safe-svg": "<1.9.10", - "datadog/dd-trace": ">=0.30,<0.30.2", - "datahihi1/tiny-env": "<1.0.3|>=1.0.9,<1.0.11", - "datatables/datatables": "<1.10.10", - "david-garcia/phpwhois": "<=4.3.1", - "dbrisinajumi/d2files": "<1", - "dcat/laravel-admin": "<=2.1.3|==2.2.0.0-beta|==2.2.2.0-beta", - "derhansen/fe_change_pwd": "<2.0.5|>=3,<3.0.3", - "derhansen/sf_event_mgt": "<4.3.1|>=5,<5.1.1|>=7,<7.4", - "desperado/xml-bundle": "<=0.1.7", - "dev-lancer/minecraft-motd-parser": "<=1.0.5", - "devcode-it/openstamanager": "<=2.9.4", - "devgroup/dotplant": "<2020.09.14-dev", - "digimix/wp-svg-upload": "<=1", - "directmailteam/direct-mail": "<6.0.3|>=7,<7.0.3|>=8,<9.5.2", - "dl/yag": "<3.0.1", - "dmk/webkitpdf": "<1.1.4", - "dnadesign/silverstripe-elemental": "<5.3.12", - "doctrine/annotations": "<1.2.7", - "doctrine/cache": ">=1,<1.3.2|>=1.4,<1.4.2", - "doctrine/common": "<2.4.3|>=2.5,<2.5.1", - "doctrine/dbal": ">=2,<2.0.8|>=2.1,<2.1.2|>=3,<3.1.4", - "doctrine/doctrine-bundle": "<1.5.2", - "doctrine/doctrine-module": "<0.7.2", - "doctrine/mongodb-odm": "<1.0.2", - "doctrine/mongodb-odm-bundle": "<3.0.1", - "doctrine/orm": ">=1,<1.2.4|>=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4", - "dolibarr/dolibarr": "<21.0.3", - "dompdf/dompdf": "<2.0.4", - "doublethreedigital/guest-entries": "<3.1.2", - "drupal-pattern-lab/unified-twig-extensions": "<=0.1", - "drupal/access_code": "<2.0.5", - "drupal/acquia_dam": "<1.1.5", - "drupal/admin_audit_trail": "<1.0.5", - "drupal/ai": "<1.0.5", - "drupal/alogin": "<2.0.6", - "drupal/cache_utility": "<1.2.1", - "drupal/civictheme": "<1.12", - "drupal/commerce_alphabank_redirect": "<1.0.3", - "drupal/commerce_eurobank_redirect": "<2.1.1", - "drupal/config_split": "<1.10|>=2,<2.0.2", - "drupal/core": ">=6,<6.38|>=7,<7.102|>=8,<10.4.9|>=10.5,<10.5.6|>=11,<11.1.9|>=11.2,<11.2.8", - "drupal/core-recommended": ">=7,<7.102|>=8,<10.2.11|>=10.3,<10.3.9|>=11,<11.0.8", - "drupal/currency": "<3.5", - "drupal/drupal": ">=5,<5.11|>=6,<6.38|>=7,<7.102|>=8,<10.2.11|>=10.3,<10.3.9|>=11,<11.0.8", - "drupal/email_tfa": "<2.0.6", - "drupal/formatter_suite": "<2.1", - "drupal/gdpr": "<3.0.1|>=3.1,<3.1.2", - "drupal/google_tag": "<1.8|>=2,<2.0.8", - "drupal/ignition": "<1.0.4", - "drupal/json_field": "<1.5", - "drupal/lightgallery": "<1.6", - "drupal/link_field_display_mode_formatter": "<1.6", - "drupal/matomo": "<1.24", - "drupal/oauth2_client": "<4.1.3", - "drupal/oauth2_server": "<2.1", - "drupal/obfuscate": "<2.0.1", - "drupal/plausible_tracking": "<1.0.2", - "drupal/quick_node_block": "<2", - "drupal/rapidoc_elements_field_formatter": "<1.0.1", - "drupal/reverse_proxy_header": "<1.1.2", - "drupal/simple_multistep": "<2", - "drupal/simple_oauth": ">=6,<6.0.7", - "drupal/spamspan": "<3.2.1", - "drupal/tfa": "<1.10", - "drupal/umami_analytics": "<1.0.1", - "duncanmcclean/guest-entries": "<3.1.2", - "dweeves/magmi": "<=0.7.24", - "ec-cube/ec-cube": "<2.4.4|>=2.11,<=2.17.1|>=3,<=3.0.18.0-patch4|>=4,<=4.1.2", - "ecodev/newsletter": "<=4", - "ectouch/ectouch": "<=2.7.2", - "egroupware/egroupware": "<23.1.20240624", - "elefant/cms": "<2.0.7", - "elgg/elgg": "<3.3.24|>=4,<4.0.5", - "elijaa/phpmemcacheadmin": "<=1.3", - "elmsln/haxcms": "<11.0.14", - "encore/laravel-admin": "<=1.8.19", - "endroid/qr-code-bundle": "<3.4.2", - "enhavo/enhavo-app": "<=0.13.1", - "enshrined/svg-sanitize": "<0.22", - "erusev/parsedown": "<1.7.2", - "ether/logs": "<3.0.4", - "evolutioncms/evolution": "<=3.2.3", - "exceedone/exment": "<4.4.3|>=5,<5.0.3", - "exceedone/laravel-admin": "<2.2.3|==3", - "ezsystems/demobundle": ">=5.4,<5.4.6.1-dev", - "ezsystems/ez-support-tools": ">=2.2,<2.2.3", - "ezsystems/ezdemo-ls-extension": ">=5.4,<5.4.2.1-dev", - "ezsystems/ezfind-ls": ">=5.3,<5.3.6.1-dev|>=5.4,<5.4.11.1-dev|>=2017.12,<2017.12.0.1-dev", - "ezsystems/ezplatform": "<=1.13.6|>=2,<=2.5.24", - "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6|>=1.5,<1.5.29|>=2.3,<2.3.39|>=3.3,<3.3.39", - "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2.1|>=5,<5.0.1|>=5.1,<5.1.1|>=5.3.0.0-beta1,<5.3.5", - "ezsystems/ezplatform-graphql": ">=1.0.0.0-RC1-dev,<1.0.13|>=2.0.0.0-beta1,<2.3.12", - "ezsystems/ezplatform-http-cache": "<2.3.16", - "ezsystems/ezplatform-kernel": "<1.2.5.1-dev|>=1.3,<1.3.35", - "ezsystems/ezplatform-rest": ">=1.2,<=1.2.2|>=1.3,<1.3.8", - "ezsystems/ezplatform-richtext": ">=2.3,<2.3.26|>=3.3,<3.3.40", - "ezsystems/ezplatform-solr-search-engine": ">=1.7,<1.7.12|>=2,<2.0.2|>=3.3,<3.3.15", - "ezsystems/ezplatform-user": ">=1,<1.0.1", - "ezsystems/ezpublish-kernel": "<6.13.8.2-dev|>=7,<7.5.31", - "ezsystems/ezpublish-legacy": "<=2017.12.7.3|>=2018.6,<=2019.03.5.1", - "ezsystems/platform-ui-assets-bundle": ">=4.2,<4.2.3", - "ezsystems/repository-forms": ">=2.3,<2.3.2.1-dev|>=2.5,<2.5.15", - "ezyang/htmlpurifier": "<=4.2", - "facade/ignition": "<1.16.15|>=2,<2.4.2|>=2.5,<2.5.2", - "facturascripts/facturascripts": "<=2022.08", - "fastly/magento2": "<1.2.26", - "feehi/cms": "<=2.1.1", - "feehi/feehicms": "<=2.1.1", - "fenom/fenom": "<=2.12.1", - "filament/actions": ">=3.2,<3.2.123", - "filament/filament": ">=4,<4.3.1", - "filament/infolists": ">=3,<3.2.115", - "filament/tables": ">=3,<3.2.115", - "filegator/filegator": "<7.8", - "filp/whoops": "<2.1.13", - "fineuploader/php-traditional-server": "<=1.2.2", - "firebase/php-jwt": "<6", - "fisharebest/webtrees": "<=2.1.18", - "fixpunkt/fp-masterquiz": "<2.2.1|>=3,<3.5.2", - "fixpunkt/fp-newsletter": "<1.1.1|>=1.2,<2.1.2|>=2.2,<3.2.6", - "flarum/core": "<1.8.10", - "flarum/flarum": "<0.1.0.0-beta8", - "flarum/framework": "<1.8.10", - "flarum/mentions": "<1.6.3", - "flarum/sticky": ">=0.1.0.0-beta14,<=0.1.0.0-beta15", - "flarum/tags": "<=0.1.0.0-beta13", - "floriangaerber/magnesium": "<0.3.1", - "fluidtypo3/vhs": "<5.1.1", - "fof/byobu": ">=0.3.0.0-beta2,<1.1.7", - "fof/pretty-mail": "<=1.1.2", - "fof/upload": "<1.2.3", - "foodcoopshop/foodcoopshop": ">=3.2,<3.6.1", - "fooman/tcpdf": "<6.2.22", - "forkcms/forkcms": "<5.11.1", - "fossar/tcpdf-parser": "<6.2.22", - "francoisjacquet/rosariosis": "<=11.5.1", - "frappant/frp-form-answers": "<3.1.2|>=4,<4.0.2", - "friendsofsymfony/oauth2-php": "<1.3", - "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", - "friendsofsymfony/user-bundle": ">=1,<1.3.5", - "friendsofsymfony1/swiftmailer": ">=4,<5.4.13|>=6,<6.2.5", - "friendsofsymfony1/symfony1": ">=1.1,<1.5.19", - "friendsoftypo3/mediace": ">=7.6.2,<7.6.5", - "friendsoftypo3/openid": ">=4.5,<4.5.31|>=4.7,<4.7.16|>=6,<6.0.11|>=6.1,<6.1.6", - "froala/wysiwyg-editor": "<=4.3", - "froxlor/froxlor": "<=2.2.5", - "frozennode/administrator": "<=5.0.12", - "fuel/core": "<1.8.1", - "funadmin/funadmin": "<=5.0.2", - "gaoming13/wechat-php-sdk": "<=1.10.2", - "genix/cms": "<=1.1.11", - "georgringer/news": "<1.3.3", - "geshi/geshi": "<=1.0.9.1", - "getformwork/formwork": "<2.2", - "getgrav/grav": "<1.11.0.0-beta1", - "getkirby/cms": "<3.9.8.3-dev|>=3.10,<3.10.1.2-dev|>=4,<4.7.1|>=5,<5.1.4", - "getkirby/kirby": "<3.9.8.3-dev|>=3.10,<3.10.1.2-dev|>=4,<4.7.1", - "getkirby/panel": "<2.5.14", - "getkirby/starterkit": "<=3.7.0.2", - "gilacms/gila": "<=1.15.4", - "gleez/cms": "<=1.3|==2", - "globalpayments/php-sdk": "<2", - "goalgorilla/open_social": "<12.3.11|>=12.4,<12.4.10|>=13.0.0.0-alpha1,<13.0.0.0-alpha11", - "gogentooss/samlbase": "<1.2.7", - "google/protobuf": "<3.4", - "gos/web-socket-bundle": "<1.10.4|>=2,<2.6.1|>=3,<3.3", - "gp247/core": "<1.1.24", - "gree/jose": "<2.2.1", - "gregwar/rst": "<1.0.3", - "grumpydictator/firefly-iii": "<6.1.17", - "gugoan/economizzer": "<=0.9.0.0-beta1", - "guzzlehttp/guzzle": "<6.5.8|>=7,<7.4.5", - "guzzlehttp/oauth-subscriber": "<0.8.1", - "guzzlehttp/psr7": "<1.9.1|>=2,<2.4.5", - "haffner/jh_captcha": "<=2.1.3|>=3,<=3.0.2", - "handcraftedinthealps/goodby-csv": "<1.4.3", - "harvesthq/chosen": "<1.8.7", - "helloxz/imgurl": "<=2.31", - "hhxsv5/laravel-s": "<3.7.36", - "hillelcoren/invoice-ninja": "<5.3.35", - "himiklab/yii2-jqgrid-widget": "<1.0.8", - "hjue/justwriting": "<=1", - "hov/jobfair": "<1.0.13|>=2,<2.0.2", - "httpsoft/http-message": "<1.0.12", - "hyn/multi-tenant": ">=5.6,<5.7.2", - "ibexa/admin-ui": ">=4.2,<4.2.3|>=4.6,<4.6.25|>=5,<5.0.3", - "ibexa/admin-ui-assets": ">=4.6.0.0-alpha1,<4.6.21", - "ibexa/core": ">=4,<4.0.7|>=4.1,<4.1.4|>=4.2,<4.2.3|>=4.5,<4.5.6|>=4.6,<4.6.2", - "ibexa/fieldtype-richtext": ">=4.6,<4.6.25|>=5,<5.0.3", - "ibexa/graphql": ">=2.5,<2.5.31|>=3.3,<3.3.28|>=4.2,<4.2.3", - "ibexa/http-cache": ">=4.6,<4.6.14", - "ibexa/post-install": "<1.0.16|>=4.6,<4.6.14", - "ibexa/solr": ">=4.5,<4.5.4", - "ibexa/user": ">=4,<4.4.3|>=5,<5.0.4", - "icecoder/icecoder": "<=8.1", - "idno/known": "<=1.3.1", - "ilicmiljan/secure-props": ">=1.2,<1.2.2", - "illuminate/auth": "<5.5.10", - "illuminate/cookie": ">=4,<=4.0.11|>=4.1,<6.18.31|>=7,<7.22.4", - "illuminate/database": "<6.20.26|>=7,<7.30.5|>=8,<8.40", - "illuminate/encryption": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.40|>=5.6,<5.6.15", - "illuminate/view": "<6.20.42|>=7,<7.30.6|>=8,<8.75", - "imdbphp/imdbphp": "<=5.1.1", - "impresscms/impresscms": "<=1.4.5", - "impresspages/impresspages": "<1.0.13", - "in2code/femanager": "<6.4.2|>=7,<7.5.3|>=8,<8.3.1", - "in2code/ipandlanguageredirect": "<5.1.2", - "in2code/lux": "<17.6.1|>=18,<24.0.2", - "in2code/powermail": "<7.5.1|>=8,<8.5.1|>=9,<10.9.1|>=11,<12.5.3|==13", - "innologi/typo3-appointments": "<2.0.6", - "intelliants/subrion": "<4.2.2", - "inter-mediator/inter-mediator": "==5.5", - "ipl/web": "<0.10.1", - "islandora/crayfish": "<4.1", - "islandora/islandora": ">=2,<2.4.1", - "ivankristianto/phpwhois": "<=4.3", - "jackalope/jackalope-doctrine-dbal": "<1.7.4", - "jambagecom/div2007": "<0.10.2", - "james-heinrich/getid3": "<1.9.21", - "james-heinrich/phpthumb": "<=1.7.23", - "jasig/phpcas": "<1.3.3", - "jbartels/wec-map": "<3.0.3", - "jcbrand/converse.js": "<3.3.3", - "joelbutcher/socialstream": "<5.6|>=6,<6.2", - "johnbillion/wp-crontrol": "<1.16.2|>=1.17,<1.19.2", - "joomla/application": "<1.0.13", - "joomla/archive": "<1.1.12|>=2,<2.0.1", - "joomla/database": ">=1,<2.2|>=3,<3.4", - "joomla/filesystem": "<1.6.2|>=2,<2.0.1", - "joomla/filter": "<2.0.6|>=3,<3.0.5|==4", - "joomla/framework": "<1.5.7|>=2.5.4,<=3.8.12", - "joomla/input": ">=2,<2.0.2", - "joomla/joomla-cms": "<3.9.12|>=4,<4.4.13|>=5,<5.2.6", - "joomla/joomla-platform": "<1.5.4", - "joomla/session": "<1.3.1", - "joyqi/hyper-down": "<=2.4.27", - "jsdecena/laracom": "<2.0.9", - "jsmitty12/phpwhois": "<5.1", - "juzaweb/cms": "<=3.4.2", - "jweiland/events2": "<8.3.8|>=9,<9.0.6", - "jweiland/kk-downloader": "<1.2.2", - "kazist/phpwhois": "<=4.2.6", - "kelvinmo/simplexrd": "<3.1.1", - "kevinpapst/kimai2": "<1.16.7", - "khodakhah/nodcms": "<=3", - "kimai/kimai": "<=2.20.1", - "kitodo/presentation": "<3.2.3|>=3.3,<3.3.4", - "klaviyo/magento2-extension": ">=1,<3", - "knplabs/knp-snappy": "<=1.4.2", - "kohana/core": "<3.3.3", - "koillection/koillection": "<1.6.12", - "krayin/laravel-crm": "<=1.3", - "kreait/firebase-php": ">=3.2,<3.8.1", - "kumbiaphp/kumbiapp": "<=1.1.1", - "la-haute-societe/tcpdf": "<6.2.22", - "laminas/laminas-diactoros": "<2.18.1|==2.19|==2.20|==2.21|==2.22|==2.23|>=2.24,<2.24.2|>=2.25,<2.25.2", - "laminas/laminas-form": "<2.17.1|>=3,<3.0.2|>=3.1,<3.1.1", - "laminas/laminas-http": "<2.14.2", - "lara-zeus/artemis": ">=1,<=1.0.6", - "lara-zeus/dynamic-dashboard": ">=3,<=3.0.1", - "laravel/fortify": "<1.11.1", - "laravel/framework": "<10.48.29|>=11,<11.44.1|>=12,<12.1.1", - "laravel/laravel": ">=5.4,<5.4.22", - "laravel/pulse": "<1.3.1", - "laravel/reverb": "<1.4", - "laravel/socialite": ">=1,<2.0.10", - "latte/latte": "<2.10.8", - "lavalite/cms": "<=9|==10.1", - "lavitto/typo3-form-to-database": "<2.2.5|>=3,<3.2.2|>=4,<4.2.3|>=5,<5.0.2", - "lcobucci/jwt": ">=3.4,<3.4.6|>=4,<4.0.4|>=4.1,<4.1.5", - "league/commonmark": "<2.7", - "league/flysystem": "<1.1.4|>=2,<2.1.1", - "league/oauth2-server": ">=8.3.2,<8.4.2|>=8.5,<8.5.3", - "leantime/leantime": "<3.3", - "lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3", - "libreform/libreform": ">=2,<=2.0.8", - "librenms/librenms": "<25.11", - "liftkit/database": "<2.13.2", - "lightsaml/lightsaml": "<1.3.5", - "limesurvey/limesurvey": "<6.5.12", - "livehelperchat/livehelperchat": "<=3.91", - "livewire/livewire": "<2.12.7|>=3.0.0.0-beta1,<3.6.4", - "livewire/volt": "<1.7", - "lms/routes": "<2.1.1", - "localizationteam/l10nmgr": "<7.4|>=8,<8.7|>=9,<9.2", - "lomkit/laravel-rest-api": "<2.13", - "luracast/restler": "<3.1", - "luyadev/yii-helpers": "<1.2.1", - "macropay-solutions/laravel-crud-wizard-free": "<3.4.17", - "maestroerror/php-heic-to-jpg": "<1.0.5", - "magento/community-edition": "<2.4.6.0-patch13|>=2.4.7.0-beta1,<2.4.7.0-patch8|>=2.4.8.0-beta1,<2.4.8.0-patch3|>=2.4.9.0-alpha1,<2.4.9.0-alpha3|==2.4.9", - "magento/core": "<=1.9.4.5", - "magento/magento1ce": "<1.9.4.3-dev", - "magento/magento1ee": ">=1,<1.14.4.3-dev", - "magento/product-community-edition": "<2.4.4.0-patch9|>=2.4.5,<2.4.5.0-patch8|>=2.4.6,<2.4.6.0-patch6|>=2.4.7,<2.4.7.0-patch1", - "magento/project-community-edition": "<=2.0.2", - "magneto/core": "<1.9.4.4-dev", - "mahocommerce/maho": "<25.9", - "maikuolan/phpmussel": ">=1,<1.6", - "mainwp/mainwp": "<=4.4.3.3", - "manogi/nova-tiptap": "<=3.2.6", - "mantisbt/mantisbt": "<2.27.2", - "marcwillmann/turn": "<0.3.3", - "marshmallow/nova-tiptap": "<5.7", - "matomo/matomo": "<1.11", - "matyhtf/framework": "<3.0.6", - "mautic/core": "<5.2.9|>=6,<6.0.7", - "mautic/core-lib": ">=1.0.0.0-beta,<4.4.13|>=5.0.0.0-alpha,<5.1.1", - "mautic/grapes-js-builder-bundle": ">=4,<4.4.18|>=5,<5.2.9|>=6,<6.0.7", - "maximebf/debugbar": "<1.19", - "mdanter/ecc": "<2", - "mediawiki/abuse-filter": "<1.39.9|>=1.40,<1.41.3|>=1.42,<1.42.2", - "mediawiki/cargo": "<3.8.3", - "mediawiki/core": "<1.39.5|==1.40", - "mediawiki/data-transfer": ">=1.39,<1.39.11|>=1.41,<1.41.3|>=1.42,<1.42.2", - "mediawiki/matomo": "<2.4.3", - "mediawiki/semantic-media-wiki": "<4.0.2", - "mehrwert/phpmyadmin": "<3.2", - "melisplatform/melis-asset-manager": "<5.0.1", - "melisplatform/melis-cms": "<5.3.4", - "melisplatform/melis-cms-slider": "<5.3.1", - "melisplatform/melis-core": "<5.3.11", - "melisplatform/melis-front": "<5.0.1", - "mezzio/mezzio-swoole": "<3.7|>=4,<4.3", - "mgallegos/laravel-jqgrid": "<=1.3", - "microsoft/microsoft-graph": ">=1.16,<1.109.1|>=2,<2.0.1", - "microsoft/microsoft-graph-beta": "<2.0.1", - "microsoft/microsoft-graph-core": "<2.0.2", - "microweber/microweber": "<=2.0.19", - "mikehaertl/php-shellcommand": "<1.6.1", - "mineadmin/mineadmin": "<=3.0.9", - "miniorange/miniorange-saml": "<1.4.3", - "mittwald/typo3_forum": "<1.2.1", - "mobiledetect/mobiledetectlib": "<2.8.32", - "modx/revolution": "<=3.1", - "mojo42/jirafeau": "<4.4", - "mongodb/mongodb": ">=1,<1.9.2", - "mongodb/mongodb-extension": "<1.21.2", - "monolog/monolog": ">=1.8,<1.12", - "moodle/moodle": "<4.4.11|>=4.5.0.0-beta,<4.5.7|>=5.0.0.0-beta,<5.0.3", - "moonshine/moonshine": "<=3.12.5", - "mos/cimage": "<0.7.19", - "movim/moxl": ">=0.8,<=0.10", - "movingbytes/social-network": "<=1.2.1", - "mpdf/mpdf": "<=7.1.7", - "munkireport/comment": "<4", - "munkireport/managedinstalls": "<2.6", - "munkireport/munki_facts": "<1.5", - "munkireport/reportdata": "<3.5", - "munkireport/softwareupdate": "<1.6", - "mustache/mustache": ">=2,<2.14.1", - "mwdelaney/wp-enable-svg": "<=0.2", - "namshi/jose": "<2.2", - "nasirkhan/laravel-starter": "<11.11", - "nategood/httpful": "<1", - "neoan3-apps/template": "<1.1.1", - "neorazorx/facturascripts": "<2022.04", - "neos/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", - "neos/form": ">=1.2,<4.3.3|>=5,<5.0.9|>=5.1,<5.1.3", - "neos/media-browser": "<7.3.19|>=8,<8.0.16|>=8.1,<8.1.11|>=8.2,<8.2.11|>=8.3,<8.3.9", - "neos/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<5.3.10|>=7,<7.0.9|>=7.1,<7.1.7|>=7.2,<7.2.6|>=7.3,<7.3.4|>=8,<8.0.2", - "neos/swiftmailer": "<5.4.5", - "nesbot/carbon": "<2.72.6|>=3,<3.8.4", - "netcarver/textile": "<=4.1.2", - "netgen/tagsbundle": ">=3.4,<3.4.11|>=4,<4.0.15", - "nette/application": ">=2,<2.0.19|>=2.1,<2.1.13|>=2.2,<2.2.10|>=2.3,<2.3.14|>=2.4,<2.4.16|>=3,<3.0.6", - "nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13", - "neuron-core/neuron-ai": "<=2.8.11", - "nilsteampassnet/teampass": "<3.1.3.1-dev", - "nitsan/ns-backup": "<13.0.1", - "nonfiction/nterchange": "<4.1.1", - "notrinos/notrinos-erp": "<=0.7", - "noumo/easyii": "<=0.9", - "novaksolutions/infusionsoft-php-sdk": "<1", - "novosga/novosga": "<=2.2.12", - "nukeviet/nukeviet": "<4.5.02", - "nyholm/psr7": "<1.6.1", - "nystudio107/craft-seomatic": "<3.4.12", - "nzedb/nzedb": "<0.8", - "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1", - "october/backend": "<1.1.2", - "october/cms": "<1.0.469|==1.0.469|==1.0.471|==1.1.1", - "october/october": "<3.7.5", - "october/rain": "<1.0.472|>=1.1,<1.1.2", - "october/system": "<3.7.5", - "oliverklee/phpunit": "<3.5.15", - "omeka/omeka-s": "<4.0.3", - "onelogin/php-saml": "<2.21.1|>=3,<3.8.1|>=4,<4.3.1", - "oneup/uploader-bundle": ">=1,<1.9.3|>=2,<2.1.5", - "open-web-analytics/open-web-analytics": "<1.8.1", - "opencart/opencart": ">=0", - "openid/php-openid": "<2.3", - "openmage/magento-lts": "<20.16", - "opensolutions/vimbadmin": "<=3.0.15", - "opensource-workshop/connect-cms": "<1.8.7|>=2,<2.4.7", - "orchid/platform": ">=8,<14.43", - "oro/calendar-bundle": ">=4.2,<=4.2.6|>=5,<=5.0.6|>=5.1,<5.1.1", - "oro/commerce": ">=4.1,<5.0.11|>=5.1,<5.1.1", - "oro/crm": ">=1.7,<1.7.4|>=3.1,<4.1.17|>=4.2,<4.2.7", - "oro/crm-call-bundle": ">=4.2,<=4.2.5|>=5,<5.0.4|>=5.1,<5.1.1", - "oro/customer-portal": ">=4.1,<=4.1.13|>=4.2,<=4.2.10|>=5,<=5.0.11|>=5.1,<=5.1.3", - "oro/platform": ">=1.7,<1.7.4|>=3.1,<3.1.29|>=4.1,<4.1.17|>=4.2,<=4.2.10|>=5,<=5.0.12|>=5.1,<=5.1.3", - "oveleon/contao-cookiebar": "<1.16.3|>=2,<2.1.3", - "oxid-esales/oxideshop-ce": "<=7.0.5", - "oxid-esales/paymorrow-module": ">=1,<1.0.2|>=2,<2.0.1", - "packbackbooks/lti-1-3-php-library": "<5", - "padraic/humbug_get_contents": "<1.1.2", - "pagarme/pagarme-php": "<3", - "pagekit/pagekit": "<=1.0.18", - "paragonie/ecc": "<2.0.1", - "paragonie/random_compat": "<2", - "passbolt/passbolt_api": "<4.6.2", - "paypal/adaptivepayments-sdk-php": "<=3.9.2", - "paypal/invoice-sdk-php": "<=3.9", - "paypal/merchant-sdk-php": "<3.12", - "paypal/permissions-sdk-php": "<=3.9.1", - "pear/archive_tar": "<1.4.14", - "pear/auth": "<1.2.4", - "pear/crypt_gpg": "<1.6.7", - "pear/http_request2": "<2.7", - "pear/pear": "<=1.10.1", - "pegasus/google-for-jobs": "<1.5.1|>=2,<2.1.1", - "personnummer/personnummer": "<3.0.2", - "phanan/koel": "<5.1.4", - "phenx/php-svg-lib": "<0.5.2", - "php-censor/php-censor": "<2.0.13|>=2.1,<2.1.5", - "php-mod/curl": "<2.3.2", - "phpbb/phpbb": "<3.3.11", - "phpems/phpems": ">=6,<=6.1.3", - "phpfastcache/phpfastcache": "<6.1.5|>=7,<7.1.2|>=8,<8.0.7", - "phpmailer/phpmailer": "<6.5", - "phpmussel/phpmussel": ">=1,<1.6", - "phpmyadmin/phpmyadmin": "<5.2.2", - "phpmyfaq/phpmyfaq": "<=4.0.13", - "phpoffice/common": "<0.2.9", - "phpoffice/math": "<=0.2", - "phpoffice/phpexcel": "<=1.8.2", - "phpoffice/phpspreadsheet": "<1.30|>=2,<2.1.12|>=2.2,<2.4|>=3,<3.10|>=4,<5", - "phppgadmin/phppgadmin": "<=7.13", - "phpseclib/phpseclib": "<2.0.47|>=3,<3.0.36", - "phpservermon/phpservermon": "<3.6", - "phpsysinfo/phpsysinfo": "<3.4.3", - "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5.0.10,<5.6.3", - "phpwhois/phpwhois": "<=4.2.5", - "phpxmlrpc/extras": "<0.6.1", - "phpxmlrpc/phpxmlrpc": "<4.9.2", - "pi/pi": "<=2.5", - "pimcore/admin-ui-classic-bundle": "<1.7.6", - "pimcore/customer-management-framework-bundle": "<4.2.1", - "pimcore/data-hub": "<1.2.4", - "pimcore/data-importer": "<1.8.9|>=1.9,<1.9.3", - "pimcore/demo": "<10.3", - "pimcore/ecommerce-framework-bundle": "<1.0.10", - "pimcore/perspective-editor": "<1.5.1", - "pimcore/pimcore": "<11.5.4", - "piwik/piwik": "<1.11", - "pixelfed/pixelfed": "<0.12.5", - "plotly/plotly.js": "<2.25.2", - "pocketmine/bedrock-protocol": "<8.0.2", - "pocketmine/pocketmine-mp": "<5.32.1", - "pocketmine/raklib": ">=0.14,<0.14.6|>=0.15,<0.15.1", - "pressbooks/pressbooks": "<5.18", - "prestashop/autoupgrade": ">=4,<4.10.1", - "prestashop/blockreassurance": "<=5.1.3", - "prestashop/blockwishlist": ">=2,<2.1.1", - "prestashop/contactform": ">=1.0.1,<4.3", - "prestashop/gamification": "<2.3.2", - "prestashop/prestashop": "<8.2.3", - "prestashop/productcomments": "<5.0.2", - "prestashop/ps_checkout": "<4.4.1|>=5,<5.0.5", - "prestashop/ps_contactinfo": "<=3.3.2", - "prestashop/ps_emailsubscription": "<2.6.1", - "prestashop/ps_facetedsearch": "<3.4.1", - "prestashop/ps_linklist": "<3.1", - "privatebin/privatebin": "<1.4|>=1.5,<1.7.4|>=1.7.7,<2.0.3", - "processwire/processwire": "<=3.0.246", - "propel/propel": ">=2.0.0.0-alpha1,<=2.0.0.0-alpha7", - "propel/propel1": ">=1,<=1.7.1", - "pterodactyl/panel": "<=1.11.10", - "ptheofan/yii2-statemachine": ">=2.0.0.0-RC1-dev,<=2", - "ptrofimov/beanstalk_console": "<1.7.14", - "pubnub/pubnub": "<6.1", - "punktde/pt_extbase": "<1.5.1", - "pusher/pusher-php-server": "<2.2.1", - "pwweb/laravel-core": "<=0.3.6.0-beta", - "pxlrbt/filament-excel": "<1.1.14|>=2.0.0.0-alpha,<2.3.3", - "pyrocms/pyrocms": "<=3.9.1", - "qcubed/qcubed": "<=3.1.1", - "quickapps/cms": "<=2.0.0.0-beta2", - "rainlab/blog-plugin": "<1.4.1", - "rainlab/debugbar-plugin": "<3.1", - "rainlab/user-plugin": "<=1.4.5", - "rankmath/seo-by-rank-math": "<=1.0.95", - "rap2hpoutre/laravel-log-viewer": "<0.13", - "react/http": ">=0.7,<1.9", - "really-simple-plugins/complianz-gdpr": "<6.4.2", - "redaxo/source": "<5.20.1", - "remdex/livehelperchat": "<4.29", - "renolit/reint-downloadmanager": "<4.0.2|>=5,<5.0.1", - "reportico-web/reportico": "<=8.1", - "rhukster/dom-sanitizer": "<1.0.7", - "rmccue/requests": ">=1.6,<1.8", - "robrichards/xmlseclibs": "<=3.1.3", - "roots/soil": "<4.1", - "roundcube/roundcubemail": "<1.5.10|>=1.6,<1.6.11", - "rudloff/alltube": "<3.0.3", - "rudloff/rtmpdump-bin": "<=2.3.1", - "s-cart/core": "<=9.0.5", - "s-cart/s-cart": "<6.9", - "sabberworm/php-css-parser": ">=1,<1.0.1|>=2,<2.0.1|>=3,<3.0.1|>=4,<4.0.1|>=5,<5.0.9|>=5.1,<5.1.3|>=5.2,<5.2.1|>=6,<6.0.2|>=7,<7.0.4|>=8,<8.0.1|>=8.1,<8.1.1|>=8.2,<8.2.1|>=8.3,<8.3.1", - "sabre/dav": ">=1.6,<1.7.11|>=1.8,<1.8.9", - "samwilson/unlinked-wikibase": "<1.42", - "scheb/two-factor-bundle": "<3.26|>=4,<4.11", - "sensiolabs/connect": "<4.2.3", - "serluck/phpwhois": "<=4.2.6", - "setasign/fpdi": "<2.6.4", - "sfroemken/url_redirect": "<=1.2.1", - "sheng/yiicms": "<1.2.1", - "shopware/core": "<6.6.10.9-dev|>=6.7,<6.7.4.1-dev", - "shopware/platform": "<6.6.10.7-dev|>=6.7,<6.7.3.1-dev", - "shopware/production": "<=6.3.5.2", - "shopware/shopware": "<=5.7.17|>=6.4.6,<6.6.10.10-dev|>=6.7,<6.7.5.1-dev", - "shopware/storefront": "<6.6.10.10-dev|>=6.7,<6.7.5.1-dev", - "shopxo/shopxo": "<=6.4", - "showdoc/showdoc": "<2.10.4", - "shuchkin/simplexlsx": ">=1.0.12,<1.1.13", - "silverstripe-australia/advancedreports": ">=1,<=2", - "silverstripe/admin": "<1.13.19|>=2,<2.1.8", - "silverstripe/assets": ">=1,<1.11.1", - "silverstripe/cms": "<4.11.3", - "silverstripe/comments": ">=1.3,<3.1.1", - "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", - "silverstripe/framework": "<5.3.23", - "silverstripe/graphql": ">=2,<2.0.5|>=3,<3.8.2|>=4,<4.3.7|>=5,<5.1.3", - "silverstripe/hybridsessions": ">=1,<2.4.1|>=2.5,<2.5.1", - "silverstripe/recipe-cms": ">=4.5,<4.5.3", - "silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1", - "silverstripe/reports": "<5.2.3", - "silverstripe/restfulserver": ">=1,<1.0.9|>=2,<2.0.4|>=2.1,<2.1.2", - "silverstripe/silverstripe-omnipay": "<2.5.2|>=3,<3.0.2|>=3.1,<3.1.4|>=3.2,<3.2.1", - "silverstripe/subsites": ">=2,<2.6.1", - "silverstripe/taxonomy": ">=1.3,<1.3.1|>=2,<2.0.1", - "silverstripe/userforms": "<3|>=5,<5.4.2", - "silverstripe/versioned-admin": ">=1,<1.11.1", - "simogeo/filemanager": "<=2.5", - "simple-updates/phpwhois": "<=1", - "simplesamlphp/saml2": "<=4.16.15|>=5.0.0.0-alpha1,<=5.0.0.0-alpha19", - "simplesamlphp/saml2-legacy": "<=4.16.15", - "simplesamlphp/simplesamlphp": "<1.18.6", - "simplesamlphp/simplesamlphp-module-infocard": "<1.0.1", - "simplesamlphp/simplesamlphp-module-openid": "<1", - "simplesamlphp/simplesamlphp-module-openidprovider": "<0.9", - "simplesamlphp/xml-common": "<1.20", - "simplesamlphp/xml-security": "==1.6.11", - "simplito/elliptic-php": "<1.0.6", - "sitegeist/fluid-components": "<3.5", - "sjbr/sr-feuser-register": "<2.6.2|>=5.1,<12.5", - "sjbr/sr-freecap": "<2.4.6|>=2.5,<2.5.3", - "sjbr/static-info-tables": "<2.3.1", - "slim/psr7": "<1.4.1|>=1.5,<1.5.1|>=1.6,<1.6.1", - "slim/slim": "<2.6", - "slub/slub-events": "<3.0.3", - "smarty/smarty": "<4.5.3|>=5,<5.1.1", - "snipe/snipe-it": "<=8.3.4", - "socalnick/scn-social-auth": "<1.15.2", - "socialiteproviders/steam": "<1.1", - "solspace/craft-freeform": ">=5,<5.10.16", - "soosyze/soosyze": "<=2", - "spatie/browsershot": "<5.0.5", - "spatie/image-optimizer": "<1.7.3", - "spencer14420/sp-php-email-handler": "<1", - "spipu/html2pdf": "<5.2.8", - "spiral/roadrunner": "<2025.1", - "spoon/library": "<1.4.1", - "spoonity/tcpdf": "<6.2.22", - "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", - "ssddanbrown/bookstack": "<24.05.1", - "starcitizentools/citizen-skin": ">=1.9.4,<3.9", - "starcitizentools/short-description": ">=4,<4.0.1", - "starcitizentools/tabber-neue": ">=1.9.1,<2.7.2|>=3,<3.1.1", - "starcitizenwiki/embedvideo": "<=4", - "statamic/cms": "<=5.22", - "stormpath/sdk": "<9.9.99", - "studio-42/elfinder": "<=2.1.64", - "studiomitte/friendlycaptcha": "<0.1.4", - "subhh/libconnect": "<7.0.8|>=8,<8.1", - "sukohi/surpass": "<1", - "sulu/form-bundle": ">=2,<2.5.3", - "sulu/sulu": "<1.6.44|>=2,<2.5.25|>=2.6,<2.6.9|>=3.0.0.0-alpha1,<3.0.0.0-alpha3", - "sumocoders/framework-user-bundle": "<1.4", - "superbig/craft-audit": "<3.0.2", - "svewap/a21glossary": "<=0.4.10", - "swag/paypal": "<5.4.4", - "swiftmailer/swiftmailer": "<6.2.5", - "swiftyedit/swiftyedit": "<1.2", - "sylius/admin-bundle": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2", - "sylius/grid": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1", - "sylius/grid-bundle": "<1.10.1", - "sylius/paypal-plugin": "<1.6.2|>=1.7,<1.7.2|>=2,<2.0.2", - "sylius/resource-bundle": ">=1,<1.3.14|>=1.4,<1.4.7|>=1.5,<1.5.2|>=1.6,<1.6.4", - "sylius/sylius": "<1.12.19|>=1.13.0.0-alpha1,<1.13.4", - "symbiote/silverstripe-multivaluefield": ">=3,<3.1", - "symbiote/silverstripe-queuedjobs": ">=3,<3.0.2|>=3.1,<3.1.4|>=4,<4.0.7|>=4.1,<4.1.2|>=4.2,<4.2.4|>=4.3,<4.3.3|>=4.4,<4.4.3|>=4.5,<4.5.1|>=4.6,<4.6.4", - "symbiote/silverstripe-seed": "<6.0.3", - "symbiote/silverstripe-versionedfiles": "<=2.0.3", - "symfont/process": ">=0", - "symfony/cache": ">=3.1,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8", - "symfony/dependency-injection": ">=2,<2.0.17|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", - "symfony/error-handler": ">=4.4,<4.4.4|>=5,<5.0.4", - "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", - "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7|>=5.3.14,<5.3.15|>=5.4.3,<5.4.4|>=6.0.3,<6.0.4", - "symfony/http-client": ">=4.3,<5.4.47|>=6,<6.4.15|>=7,<7.1.8", - "symfony/http-foundation": "<5.4.50|>=6,<6.4.29|>=7,<7.3.7", - "symfony/http-kernel": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.2.6", - "symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", - "symfony/maker-bundle": ">=1.27,<1.29.2|>=1.30,<1.31.1", - "symfony/mime": ">=4.3,<4.3.8", - "symfony/phpunit-bridge": ">=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", - "symfony/polyfill": ">=1,<1.10", - "symfony/polyfill-php55": ">=1,<1.10", - "symfony/process": "<5.4.46|>=6,<6.4.14|>=7,<7.1.7", - "symfony/proxy-manager-bridge": ">=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", - "symfony/routing": ">=2,<2.0.19", - "symfony/runtime": ">=5.3,<5.4.46|>=6,<6.4.14|>=7,<7.1.7", - "symfony/security": ">=2,<2.7.51|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.8", - "symfony/security-bundle": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.4.10|>=7,<7.0.10|>=7.1,<7.1.3", - "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.9", - "symfony/security-csrf": ">=2.4,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", - "symfony/security-guard": ">=2.8,<3.4.48|>=4,<4.4.23|>=5,<5.2.8", - "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7|>=5.1,<5.2.8|>=5.3,<5.4.47|>=6,<6.4.15|>=7,<7.1.8", - "symfony/serializer": ">=2,<2.0.11|>=4.1,<4.4.35|>=5,<5.3.12", - "symfony/symfony": "<5.4.50|>=6,<6.4.29|>=7,<7.3.7", - "symfony/translation": ">=2,<2.0.17", - "symfony/twig-bridge": ">=2,<4.4.51|>=5,<5.4.31|>=6,<6.3.8", - "symfony/ux-autocomplete": "<2.11.2", - "symfony/ux-live-component": "<2.25.1", - "symfony/ux-twig-component": "<2.25.1", - "symfony/validator": "<5.4.43|>=6,<6.4.11|>=7,<7.1.4", - "symfony/var-exporter": ">=4.2,<4.2.12|>=4.3,<4.3.8", - "symfony/web-profiler-bundle": ">=2,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4", - "symfony/webhook": ">=6.3,<6.3.8", - "symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7|>=2.2.0.0-beta1,<2.2.0.0-beta2", - "symphonycms/symphony-2": "<2.6.4", - "t3/dce": "<0.11.5|>=2.2,<2.6.2", - "t3g/svg-sanitizer": "<1.0.3", - "t3s/content-consent": "<1.0.3|>=2,<2.0.2", - "tastyigniter/tastyigniter": "<4", - "tcg/voyager": "<=1.8", - "tecnickcom/tc-lib-pdf-font": "<2.6.4", - "tecnickcom/tcpdf": "<6.8", - "terminal42/contao-tablelookupwizard": "<3.3.5", - "thelia/backoffice-default-template": ">=2.1,<2.1.2", - "thelia/thelia": ">=2.1,<2.1.3", - "theonedemon/phpwhois": "<=4.2.5", - "thinkcmf/thinkcmf": "<6.0.8", - "thorsten/phpmyfaq": "<=4.0.13", - "tikiwiki/tiki-manager": "<=17.1", - "timber/timber": ">=0.16.6,<1.23.1|>=1.24,<1.24.1|>=2,<2.1", - "tinymce/tinymce": "<7.2", - "tinymighty/wiki-seo": "<1.2.2", - "titon/framework": "<9.9.99", - "tltneon/lgsl": "<7", - "tobiasbg/tablepress": "<=2.0.0.0-RC1", - "topthink/framework": "<6.0.17|>=6.1,<=8.0.4", - "topthink/think": "<=6.1.1", - "topthink/thinkphp": "<=3.2.3|>=6.1.3,<=8.0.4", - "torrentpier/torrentpier": "<=2.8.8", - "tpwd/ke_search": "<4.0.3|>=4.1,<4.6.6|>=5,<5.0.2", - "tribalsystems/zenario": "<=9.7.61188", - "truckersmp/phpwhois": "<=4.3.1", - "ttskch/pagination-service-provider": "<1", - "twbs/bootstrap": "<3.4.1|>=4,<4.3.1", - "twig/twig": "<3.11.2|>=3.12,<3.14.1|>=3.16,<3.19", - "typo3/cms": "<9.5.29|>=10,<10.4.35|>=11,<11.5.23|>=12,<12.2", - "typo3/cms-backend": "<4.1.14|>=4.2,<4.2.15|>=4.3,<4.3.7|>=4.4,<4.4.4|>=7,<=7.6.50|>=8,<=8.7.39|>=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", - "typo3/cms-belog": ">=10,<=10.4.47|>=11,<=11.5.41|>=12,<=12.4.24|>=13,<=13.4.2", - "typo3/cms-beuser": ">=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", - "typo3/cms-core": "<=8.7.56|>=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", - "typo3/cms-dashboard": ">=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", - "typo3/cms-extbase": "<6.2.24|>=7,<7.6.8|==8.1.1", - "typo3/cms-extensionmanager": ">=10,<=10.4.47|>=11,<=11.5.41|>=12,<=12.4.24|>=13,<=13.4.2", - "typo3/cms-felogin": ">=4.2,<4.2.3", - "typo3/cms-fluid": "<4.3.4|>=4.4,<4.4.1", - "typo3/cms-form": ">=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.47|>=11,<=11.5.41|>=12,<=12.4.24|>=13,<=13.4.2", - "typo3/cms-frontend": "<4.3.9|>=4.4,<4.4.5", - "typo3/cms-indexed-search": ">=10,<=10.4.47|>=11,<=11.5.41|>=12,<=12.4.24|>=13,<=13.4.2", - "typo3/cms-install": "<4.1.14|>=4.2,<4.2.16|>=4.3,<4.3.9|>=4.4,<4.4.5|>=12.2,<12.4.8|==13.4.2", - "typo3/cms-lowlevel": ">=11,<=11.5.41", - "typo3/cms-recordlist": ">=11,<11.5.48", - "typo3/cms-recycler": ">=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", - "typo3/cms-rte-ckeditor": ">=9.5,<9.5.42|>=10,<10.4.39|>=11,<11.5.30", - "typo3/cms-scheduler": ">=11,<=11.5.41", - "typo3/cms-setup": ">=9,<=9.5.50|>=10,<=10.4.49|>=11,<=11.5.43|>=12,<=12.4.30|>=13,<=13.4.11", - "typo3/cms-webhooks": ">=12,<=12.4.30|>=13,<=13.4.11", - "typo3/cms-workspaces": ">=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", - "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", - "typo3/html-sanitizer": ">=1,<=1.5.2|>=2,<=2.1.3", - "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.3.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<3.3.23|>=4,<4.0.17|>=4.1,<4.1.16|>=4.2,<4.2.12|>=4.3,<4.3.3", - "typo3/phar-stream-wrapper": ">=1,<2.1.1|>=3,<3.1.1", - "typo3/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", - "typo3fluid/fluid": ">=2,<2.0.8|>=2.1,<2.1.7|>=2.2,<2.2.4|>=2.3,<2.3.7|>=2.4,<2.4.4|>=2.5,<2.5.11|>=2.6,<2.6.10", - "ua-parser/uap-php": "<3.8", - "uasoft-indonesia/badaso": "<=2.9.7", - "unisharp/laravel-filemanager": "<2.9.1", - "universal-omega/dynamic-page-list3": "<3.6.4", - "unopim/unopim": "<=0.3", - "userfrosting/userfrosting": ">=0.3.1,<4.6.3", - "usmanhalalit/pixie": "<1.0.3|>=2,<2.0.2", - "uvdesk/community-skeleton": "<=1.1.1", - "uvdesk/core-framework": "<=1.1.1", - "vanilla/safecurl": "<0.9.2", - "verbb/comments": "<1.5.5", - "verbb/formie": "<=2.1.43", - "verbb/image-resizer": "<2.0.9", - "verbb/knock-knock": "<1.2.8", - "verot/class.upload.php": "<=2.1.6", - "vertexvaar/falsftp": "<0.2.6", - "villagedefrance/opencart-overclocked": "<=1.11.1", - "vova07/yii2-fileapi-widget": "<0.1.9", - "vrana/adminer": "<=4.8.1", - "vufind/vufind": ">=2,<9.1.1", - "waldhacker/hcaptcha": "<2.1.2", - "wallabag/tcpdf": "<6.2.22", - "wallabag/wallabag": "<2.6.11", - "wanglelecc/laracms": "<=1.0.3", - "wapplersystems/a21glossary": "<=0.4.10", - "web-auth/webauthn-framework": ">=3.3,<3.3.4|>=4.5,<4.9", - "web-auth/webauthn-lib": ">=4.5,<4.9", - "web-feet/coastercms": "==5.5", - "web-tp3/wec_map": "<3.0.3", - "webbuilders-group/silverstripe-kapost-bridge": "<0.4", - "webcoast/deferred-image-processing": "<1.0.2", - "webklex/laravel-imap": "<5.3", - "webklex/php-imap": "<5.3", - "webpa/webpa": "<3.1.2", - "webreinvent/vaahcms": "<=2.3.1", - "wikibase/wikibase": "<=1.39.3", - "wikimedia/parsoid": "<0.12.2", - "willdurand/js-translation-bundle": "<2.1.1", - "winter/wn-backend-module": "<1.2.4", - "winter/wn-cms-module": "<1.0.476|>=1.1,<1.1.11|>=1.2,<1.2.7", - "winter/wn-dusk-plugin": "<2.1", - "winter/wn-system-module": "<1.2.4", - "wintercms/winter": "<=1.2.3", - "wireui/wireui": "<1.19.3|>=2,<2.1.3", - "woocommerce/woocommerce": "<6.6|>=8.8,<8.8.5|>=8.9,<8.9.3", - "wp-cli/wp-cli": ">=0.12,<2.5", - "wp-graphql/wp-graphql": "<=1.14.5", - "wp-premium/gravityforms": "<2.4.21", - "wpanel/wpanel4-cms": "<=4.3.1", - "wpcloud/wp-stateless": "<3.2", - "wpglobus/wpglobus": "<=1.9.6", - "wwbn/avideo": "<14.3", - "xataface/xataface": "<3", - "xpressengine/xpressengine": "<3.0.15", - "yab/quarx": "<2.4.5", - "yeswiki/yeswiki": "<=4.5.4", - "yetiforce/yetiforce-crm": "<6.5", - "yidashi/yii2cmf": "<=2", - "yii2mod/yii2-cms": "<1.9.2", - "yiisoft/yii": "<1.1.31", - "yiisoft/yii2": "<2.0.52", - "yiisoft/yii2-authclient": "<2.2.15", - "yiisoft/yii2-bootstrap": "<2.0.4", - "yiisoft/yii2-dev": "<=2.0.45", - "yiisoft/yii2-elasticsearch": "<2.0.5", - "yiisoft/yii2-gii": "<=2.2.4", - "yiisoft/yii2-jui": "<2.0.4", - "yiisoft/yii2-redis": "<2.0.20", - "yikesinc/yikes-inc-easy-mailchimp-extender": "<6.8.6", - "yoast-seo-for-typo3/yoast_seo": "<7.2.3", - "yourls/yourls": "<=1.8.2", - "yuan1994/tpadmin": "<=1.3.12", - "yungifez/skuul": "<=2.6.5", - "z-push/z-push-dev": "<2.7.6", - "zencart/zencart": "<=1.5.7.0-beta", - "zendesk/zendesk_api_client_php": "<2.2.11", - "zendframework/zend-cache": ">=2.4,<2.4.8|>=2.5,<2.5.3", - "zendframework/zend-captcha": ">=2,<2.4.9|>=2.5,<2.5.2", - "zendframework/zend-crypt": ">=2,<2.4.9|>=2.5,<2.5.2", - "zendframework/zend-db": "<2.2.10|>=2.3,<2.3.5", - "zendframework/zend-developer-tools": ">=1.2.2,<1.2.3", - "zendframework/zend-diactoros": "<1.8.4", - "zendframework/zend-feed": "<2.10.3", - "zendframework/zend-form": ">=2,<2.2.7|>=2.3,<2.3.1", - "zendframework/zend-http": "<2.8.1", - "zendframework/zend-json": ">=2.1,<2.1.6|>=2.2,<2.2.6", - "zendframework/zend-ldap": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.8|>=2.3,<2.3.3", - "zendframework/zend-mail": "<2.4.11|>=2.5,<2.7.2", - "zendframework/zend-navigation": ">=2,<2.2.7|>=2.3,<2.3.1", - "zendframework/zend-session": ">=2,<2.2.9|>=2.3,<2.3.4", - "zendframework/zend-validator": ">=2.3,<2.3.6", - "zendframework/zend-view": ">=2,<2.2.7|>=2.3,<2.3.1", - "zendframework/zend-xmlrpc": ">=2.1,<2.1.6|>=2.2,<2.2.6", - "zendframework/zendframework": "<=3", - "zendframework/zendframework1": "<1.12.20", - "zendframework/zendopenid": "<2.0.2", - "zendframework/zendrest": "<2.0.2", - "zendframework/zendservice-amazon": "<2.0.3", - "zendframework/zendservice-api": "<1", - "zendframework/zendservice-audioscrobbler": "<2.0.2", - "zendframework/zendservice-nirvanix": "<2.0.2", - "zendframework/zendservice-slideshare": "<2.0.2", - "zendframework/zendservice-technorati": "<2.0.2", - "zendframework/zendservice-windowsazure": "<2.0.2", - "zendframework/zendxml": ">=1,<1.0.1", - "zenstruck/collection": "<0.2.1", - "zetacomponents/mail": "<1.8.2", - "zf-commons/zfc-user": "<1.2.2", - "zfcampus/zf-apigility-doctrine": ">=1,<1.0.3", - "zfr/zfr-oauth2-server-module": "<0.1.2", - "zoujingli/thinkadmin": "<=6.1.53" - }, - "default-branch": true, - "type": "metapackage", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "role": "maintainer" - }, - { - "name": "Ilya Tribusean", - "email": "slash3b@gmail.com", - "role": "maintainer" - } - ], - "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", - "keywords": [ - "dev" - ], - "support": { - "issues": "https://github.com/Roave/SecurityAdvisories/issues", - "source": "https://github.com/Roave/SecurityAdvisories/tree/latest" - }, - "funding": [ - { - "url": "https://github.com/Ocramius", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/roave/security-advisories", - "type": "tidelift" - } - ], - "time": "2025-12-12T23:06:01+00:00" - }, - { - "name": "sebastian/cli-parser", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", - "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", - "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-02T07:12:49+00:00" - }, - { - "name": "sebastian/code-unit", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:58:43+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:59:15+00:00" - }, - { - "name": "sebastian/comparator", - "version": "5.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "55dfef806eb7dfeb6e7a6935601fef866f8ca48d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55dfef806eb7dfeb6e7a6935601fef866f8ca48d", - "reference": "55dfef806eb7dfeb6e7a6935601fef866f8ca48d", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/diff": "^5.0", - "sebastian/exporter": "^5.0" - }, - "require-dev": { - "phpunit/phpunit": "^10.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", - "type": "tidelift" - } - ], - "time": "2026-01-24T09:25:16+00:00" - }, - { - "name": "sebastian/complexity", - "version": "3.2.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "68ff824baeae169ec9f2137158ee529584553799" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", - "reference": "68ff824baeae169ec9f2137158ee529584553799", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "security": "https://github.com/sebastianbergmann/complexity/security/policy", - "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-12-21T08:37:17+00:00" - }, - { - "name": "sebastian/diff", - "version": "5.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0", - "symfony/process": "^6.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-02T07:15:17+00:00" - }, - { - "name": "sebastian/environment", - "version": "6.1.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", - "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "https://github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-23T08:47:14+00:00" - }, - { - "name": "sebastian/exporter", - "version": "5.1.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "0735b90f4da94969541dac1da743446e276defa6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/0735b90f4da94969541dac1da743446e276defa6", - "reference": "0735b90f4da94969541dac1da743446e276defa6", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/recursion-context": "^5.0" - }, - "require-dev": { - "phpunit/phpunit": "^10.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", - "type": "tidelift" - } - ], - "time": "2025-09-24T06:09:11+00:00" - }, - { - "name": "sebastian/global-state", - "version": "6.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", - "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" - }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "https://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-02T07:19:19+00:00" - }, - { - "name": "sebastian/lines-of-code", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-12-21T08:38:20+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "5.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T07:08:32+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T07:06:18+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "5.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "47e34210757a2f37a97dcd207d032e1b01e64c7a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/47e34210757a2f37a97dcd207d032e1b01e64c7a", - "reference": "47e34210757a2f37a97dcd207d032e1b01e64c7a", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "https://github.com/sebastianbergmann/recursion-context", - "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", - "type": "tidelift" - } - ], - "time": "2025-08-10T07:50:56+00:00" - }, - { - "name": "sebastian/type", - "version": "4.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", - "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T07:10:45+00:00" - }, - { - "name": "sebastian/version", - "version": "4.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-07T11:34:05+00:00" - }, - { - "name": "theseer/tokenizer", - "version": "1.3.1", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", - "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.3.1" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2025-11-17T20:03:58+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": { - "nextcloud/ocp": 20, - "roave/security-advisories": 20 - }, - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": "^8.1" - }, - "platform-dev": {}, - "platform-overrides": { - "php": "8.1" - }, - "plugin-api-version": "2.9.0" -} diff --git a/third_party/astrolabe/img/app-dark.svg b/third_party/astrolabe/img/app-dark.svg deleted file mode 100644 index 0edff66..0000000 --- a/third_party/astrolabe/img/app-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/third_party/astrolabe/img/app.svg b/third_party/astrolabe/img/app.svg deleted file mode 100644 index 498850e..0000000 --- a/third_party/astrolabe/img/app.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/third_party/astrolabe/lib/AppInfo/Application.php b/third_party/astrolabe/lib/AppInfo/Application.php deleted file mode 100644 index 75aed93..0000000 --- a/third_party/astrolabe/lib/AppInfo/Application.php +++ /dev/null @@ -1,45 +0,0 @@ -registerSearchProvider(SemanticSearchProvider::class); - - // Register declarative admin settings - $context->registerDeclarativeSettings(AstrolabeAdminSettings::class); - - // Register event listeners for declarative settings - $context->registerEventListener( - DeclarativeSettingsGetValueEvent::class, - AstrolabeAdminSettingsListener::class - ); - $context->registerEventListener( - DeclarativeSettingsSetValueEvent::class, - AstrolabeAdminSettingsListener::class - ); - } - - public function boot(IBootContext $context): void { - } -} diff --git a/third_party/astrolabe/lib/BackgroundJob/RefreshUserTokens.php b/third_party/astrolabe/lib/BackgroundJob/RefreshUserTokens.php deleted file mode 100644 index 7c3c3a0..0000000 --- a/third_party/astrolabe/lib/BackgroundJob/RefreshUserTokens.php +++ /dev/null @@ -1,207 +0,0 @@ -setInterval(self::JOB_INTERVAL_SECONDS); - $this->setTimeSensitivity(IJob::TIME_INSENSITIVE); - } - - protected function run(mixed $argument): void { - $this->logger->info('RefreshUserTokens: Starting background token refresh'); - - $refreshed = 0; - $failed = 0; - $skipped = 0; - $offset = 0; - $totalUsers = 0; - - // Process users in batches to prevent memory issues on large installations - do { - $userIds = $this->tokenStorage->getAllUsersWithTokens(self::BATCH_SIZE, $offset); - $batchCount = count($userIds); - $totalUsers += $batchCount; - - foreach ($userIds as $userId) { - $result = $this->refreshUserTokenIfNeeded($userId); - match ($result) { - 'refreshed' => $refreshed++, - 'failed' => $failed++, - 'skipped' => $skipped++, - }; - } - - $offset += self::BATCH_SIZE; - } while ($batchCount === self::BATCH_SIZE); - - $this->logger->info("RefreshUserTokens: Complete - total=$totalUsers, refreshed=$refreshed, failed=$failed, skipped=$skipped"); - } - - /** - * Refresh a user's token if it's nearing expiration. - * - * Calculates the refresh threshold based on the token's actual lifetime, - * refreshing when less than 50% of the lifetime remains. - * - * Uses locking to prevent race conditions with on-demand refresh in - * getAccessToken(). If lock cannot be acquired, skips this user since - * on-demand refresh is already handling it. - * - * @return string 'refreshed', 'failed', or 'skipped' - */ - private function refreshUserTokenIfNeeded(string $userId): string { - $token = $this->tokenStorage->getUserToken($userId); - - if ($token === null) { - return 'skipped'; - } - - $expiresAt = (int)($token['expires_at'] ?? 0); - $issuedAt = isset($token['issued_at']) ? (int)$token['issued_at'] : null; - $timeRemaining = $expiresAt - time(); - - // Calculate token lifetime from stored data or use default - if ($issuedAt !== null) { - $tokenLifetime = $expiresAt - $issuedAt; - } else { - // Fallback: use default lifetime assumption - $tokenLifetime = self::DEFAULT_TOKEN_LIFETIME_SECONDS; - } - - // Calculate threshold: refresh when 50% of lifetime remains - $threshold = max( - (int)($tokenLifetime * self::REFRESH_AT_REMAINING_PERCENT), - self::MIN_THRESHOLD_SECONDS - ); - - if ($timeRemaining > $threshold) { - // Token still has plenty of time, skip - return 'skipped'; - } - - // Token is expiring soon, attempt refresh with lock - try { - return $this->tokenStorage->withTokenLock($userId, function () use ($userId) { - // Re-check token after acquiring lock (double-check pattern) - // Another process may have refreshed while we waited for lock - $currentToken = $this->tokenStorage->getUserToken($userId); - - if ($currentToken === null) { - return 'skipped'; - } - - // Recalculate threshold with current token data - $currentExpiresAt = (int)($currentToken['expires_at'] ?? 0); - $currentIssuedAt = isset($currentToken['issued_at']) ? (int)$currentToken['issued_at'] : null; - $currentTimeRemaining = $currentExpiresAt - time(); - - if ($currentIssuedAt !== null) { - $currentTokenLifetime = $currentExpiresAt - $currentIssuedAt; - } else { - $currentTokenLifetime = self::DEFAULT_TOKEN_LIFETIME_SECONDS; - } - - $currentThreshold = max( - (int)($currentTokenLifetime * self::REFRESH_AT_REMAINING_PERCENT), - self::MIN_THRESHOLD_SECONDS - ); - - if ($currentTimeRemaining > $currentThreshold) { - // Token was refreshed by another process while we waited - $this->logger->debug("RefreshUserTokens: Token already refreshed for user $userId while waiting for lock"); - return 'skipped'; - } - - // Still needs refresh, proceed - if (!isset($currentToken['refresh_token'])) { - $this->logger->warning("RefreshUserTokens: User $userId has no refresh token"); - return 'failed'; - } - - $this->logger->debug("RefreshUserTokens: Refreshing token for user $userId (remaining={$currentTimeRemaining}s, threshold={$currentThreshold}s)"); - - /** @var string $refreshToken */ - $refreshToken = $currentToken['refresh_token']; - $newTokenData = $this->tokenRefresher->refreshAccessToken($refreshToken); - - if ($newTokenData === null) { - $this->logger->warning("RefreshUserTokens: Refresh returned null for user $userId"); - // Don't delete token here - let on-demand refresh handle cleanup - return 'failed'; - } - - // Calculate new expiration and store issued_at for future calculations - $expiresIn = (int)($newTokenData['expires_in'] ?? self::DEFAULT_TOKEN_LIFETIME_SECONDS); - $now = time(); - - /** @var string $accessToken */ - $accessToken = $newTokenData['access_token']; - /** @var string $newRefreshToken */ - $newRefreshToken = $newTokenData['refresh_token'] ?? $refreshToken; - - $this->tokenStorage->storeUserToken( - $userId, - $accessToken, - $newRefreshToken, - $now + $expiresIn, - $now // issued_at - ); - - $this->logger->debug("RefreshUserTokens: Successfully refreshed token for user $userId"); - return 'refreshed'; - }); - } catch (LockedException $e) { - // Lock held by on-demand refresh - expected, not an error - $this->logger->debug("RefreshUserTokens: Lock held for user $userId, skipping"); - return 'skipped'; - } catch (\Exception $e) { - $this->logger->error("RefreshUserTokens: Failed to refresh for user $userId: " . $e->getMessage()); - return 'failed'; - } - } -} diff --git a/third_party/astrolabe/lib/Controller/ApiController.php b/third_party/astrolabe/lib/Controller/ApiController.php deleted file mode 100644 index 91535a3..0000000 --- a/third_party/astrolabe/lib/Controller/ApiController.php +++ /dev/null @@ -1,854 +0,0 @@ -client = $client; - $this->userSession = $userSession; - $this->urlGenerator = $urlGenerator; - $this->logger = $logger; - $this->tokenStorage = $tokenStorage; - $this->config = $config; - $this->tokenRefresher = $tokenRefresher; - } - - /** - * Revoke user's background access (delete refresh token). - * - * Called from personal settings form POST. - * Redirects back to personal settings after completion. - * - * @return RedirectResponse - */ - #[NoAdminRequired] - public function revokeAccess(): RedirectResponse { - $user = $this->userSession->getUser(); - if (!$user) { - // Should not happen (NoAdminRequired ensures user is logged in) - $this->logger->error('Revoke access called without authenticated user'); - return new RedirectResponse( - $this->urlGenerator->linkToRoute('settings.PersonalSettings.index', ['section' => 'astrolabe']) - ); - } - - $userId = $user->getUID(); - - // Get user's OAuth token - $token = $this->tokenStorage->getUserToken($userId); - if (!$token) { - $this->logger->error("Cannot revoke access: No token found for user $userId"); - return new RedirectResponse( - $this->urlGenerator->linkToRoute('settings.PersonalSettings.index', ['section' => 'astrolabe']) - ); - } - - $accessToken = $token['access_token']; - - // Call MCP server API to revoke access - $result = $this->client->revokeUserAccess($userId, $accessToken); - - if (isset($result['error'])) { - $this->logger->error("Failed to revoke access for user $userId", [ - 'error' => $result['error'] - ]); - // TODO: Add flash message/notification for user feedback - } else { - $this->logger->info("Successfully revoked background access for user $userId"); - - // Delete local OAuth tokens from Nextcloud config - // This ensures hasBackgroundAccess() returns false on next page load - $this->tokenStorage->deleteUserToken($userId); - $this->logger->debug("Deleted local OAuth tokens for user $userId"); - - // TODO: Add success flash message/notification - } - - // Redirect back to personal settings - return new RedirectResponse( - $this->urlGenerator->linkToRoute('settings.PersonalSettings.index', ['section' => 'astrolabe']) - ); - } - - /** - * Execute semantic search via MCP server. - * - * AJAX endpoint for vector search UI in app page. - * Uses user's OAuth token for authentication. - * - * @param string $query Search query - * @param string $algorithm Search algorithm (semantic, bm25, hybrid) - * @param int $limit Number of results (max 50) - * @param string $doc_types Comma-separated document types (e.g., "note,file") - * @param string $include_pca Whether to include PCA coordinates for visualization - * @return JSONResponse - */ - #[NoAdminRequired] - public function search( - string $query = '', - string $algorithm = 'hybrid', - int $limit = 10, - string $doc_types = '', - string $include_pca = 'true', - ): JSONResponse { - if (empty($query)) { - return new JSONResponse([ - 'success' => false, - 'error' => 'Missing required parameter: query' - ], Http::STATUS_BAD_REQUEST); - } - - // Get current user - $user = $this->userSession->getUser(); - if (!$user) { - return new JSONResponse([ - 'success' => false, - 'error' => 'User not authenticated' - ], Http::STATUS_UNAUTHORIZED); - } - - $userId = $user->getUID(); - - // Create refresh callback that calls IdP directly - /** @return array{access_token: string, refresh_token: string, expires_in: int}|null */ - $refreshCallback = function (string $refreshToken): ?array { - $newTokenData = $this->tokenRefresher->refreshAccessToken($refreshToken); - - if ($newTokenData === null) { - return null; - } - - return [ - 'access_token' => $newTokenData['access_token'], - 'refresh_token' => $newTokenData['refresh_token'] ?? $refreshToken, - 'expires_in' => $newTokenData['expires_in'] ?? 3600, - ]; - }; - - // Get user's OAuth token for MCP server with automatic refresh - $accessToken = $this->tokenStorage->getAccessToken($userId, $refreshCallback); - if ($accessToken === null) { - return new JSONResponse([ - 'success' => false, - 'error' => 'MCP server authorization required. Please authorize the app first.' - ], Http::STATUS_UNAUTHORIZED); - } - - // Validate algorithm - $validAlgorithms = ['semantic', 'bm25', 'hybrid']; - if (!in_array($algorithm, $validAlgorithms)) { - $algorithm = 'hybrid'; - } - - // Enforce limit bounds - $limit = max(1, min($limit, 50)); - - // Parse doc_types filter - $docTypesArray = null; - if (!empty($doc_types)) { - $validDocTypes = ['note', 'file', 'deck_card', 'calendar', 'contact', 'news_item']; - $docTypesArray = array_filter( - explode(',', $doc_types), - fn ($t) => in_array(trim($t), $validDocTypes) - ); - $docTypesArray = array_map('trim', $docTypesArray); - if (empty($docTypesArray)) { - $docTypesArray = null; - } - } - - // Parse include_pca (string "true"/"false" from query params) - $includePcaBool = in_array(strtolower($include_pca), ['true', '1', 'yes'], true); - - // Execute search via MCP server with OAuth token - $result = $this->client->search($query, $algorithm, $limit, $includePcaBool, $docTypesArray, $accessToken); - - if (isset($result['error'])) { - return new JSONResponse([ - 'success' => false, - 'error' => $result['error'] - ], Http::STATUS_INTERNAL_SERVER_ERROR); - } - - $response = [ - 'success' => true, - 'results' => $result['results'] ?? [], - 'algorithm_used' => $result['algorithm_used'] ?? $algorithm, - 'total_documents' => $result['total_documents'] ?? 0, - ]; - - // Include PCA visualization coordinates if requested and available - if ($includePcaBool) { - $response['coordinates_3d'] = $result['coordinates_3d'] ?? []; - $response['query_coords'] = $result['query_coords'] ?? []; - if (isset($result['pca_variance'])) { - $response['pca_variance'] = $result['pca_variance']; - } - } - - return new JSONResponse($response); - } - - /** - * Get vector sync status from MCP server. - * - * AJAX endpoint for status refresh in personal settings. - * - * @return JSONResponse - */ - #[NoAdminRequired] - public function vectorStatus(): JSONResponse { - $status = $this->client->getVectorSyncStatus(); - - if (isset($status['error'])) { - return new JSONResponse([ - 'success' => false, - 'error' => $status['error'] - ], Http::STATUS_INTERNAL_SERVER_ERROR); - } - - return new JSONResponse([ - 'success' => true, - 'status' => $status - ]); - } - - /** - * Get MCP server status. - * - * Admin-only endpoint for admin settings page. - * Returns server version, uptime, and vector sync availability. - * - * @return JSONResponse - */ - public function serverStatus(): JSONResponse { - $status = $this->client->getStatus(); - - // Validate that status is an array before accessing - if (!is_array($status)) { - return new JSONResponse([ - 'success' => false, - 'error' => 'Invalid response from MCP server' - ], Http::STATUS_INTERNAL_SERVER_ERROR); - } - - if (isset($status['error'])) { - return new JSONResponse([ - 'success' => false, - 'error' => $status['error'] - ], Http::STATUS_INTERNAL_SERVER_ERROR); - } - - return new JSONResponse([ - 'success' => true, - 'status' => $status - ]); - } - - /** - * Get vector sync status for admin. - * - * Admin-only endpoint for admin settings page. - * Returns indexing metrics and sync status. - * - * @return JSONResponse - */ - public function adminVectorStatus(): JSONResponse { - $status = $this->client->getVectorSyncStatus(); - - // Validate that status is an array before accessing - if (!is_array($status)) { - return new JSONResponse([ - 'success' => false, - 'error' => 'Invalid response from MCP server' - ], Http::STATUS_INTERNAL_SERVER_ERROR); - } - - if (isset($status['error'])) { - return new JSONResponse([ - 'success' => false, - 'error' => $status['error'] - ], Http::STATUS_INTERNAL_SERVER_ERROR); - } - - return new JSONResponse([ - 'success' => true, - 'status' => $status - ]); - } - - /** - * Save admin search settings. - * - * Admin-only endpoint to configure AI Search provider parameters. - * - * @return JSONResponse - */ - public function saveSearchSettings(): JSONResponse { - // Parse JSON body - $input = file_get_contents('php://input'); - $data = json_decode($input, true); - - if ($data === null) { - return new JSONResponse([ - 'success' => false, - 'error' => 'Invalid JSON body' - ], Http::STATUS_BAD_REQUEST); - } - - // Validate and save algorithm - $validAlgorithms = ['hybrid', 'semantic', 'bm25']; - $algorithm = $data['algorithm'] ?? AdminSettings::DEFAULT_SEARCH_ALGORITHM; - if (!in_array($algorithm, $validAlgorithms)) { - $algorithm = AdminSettings::DEFAULT_SEARCH_ALGORITHM; - } - $this->config->setAppValue( - $this->appName, - AdminSettings::SETTING_SEARCH_ALGORITHM, - $algorithm - ); - - // Validate and save fusion method - $validFusions = ['rrf', 'dbsf']; - $fusion = $data['fusion'] ?? AdminSettings::DEFAULT_SEARCH_FUSION; - if (!in_array($fusion, $validFusions)) { - $fusion = AdminSettings::DEFAULT_SEARCH_FUSION; - } - $this->config->setAppValue( - $this->appName, - AdminSettings::SETTING_SEARCH_FUSION, - $fusion - ); - - // Validate and save score threshold (0-100) - $scoreThreshold = (int)($data['scoreThreshold'] ?? AdminSettings::DEFAULT_SEARCH_SCORE_THRESHOLD); - $scoreThreshold = max(0, min(100, $scoreThreshold)); - $this->config->setAppValue( - $this->appName, - AdminSettings::SETTING_SEARCH_SCORE_THRESHOLD, - (string)$scoreThreshold - ); - - // Validate and save limit (5-100) - $limit = (int)($data['limit'] ?? AdminSettings::DEFAULT_SEARCH_LIMIT); - $limit = max(5, min(100, $limit)); - $this->config->setAppValue( - $this->appName, - AdminSettings::SETTING_SEARCH_LIMIT, - (string)$limit - ); - - $this->logger->info('Admin search settings saved', [ - 'algorithm' => $algorithm, - 'fusion' => $fusion, - 'scoreThreshold' => $scoreThreshold, - 'limit' => $limit, - ]); - - return new JSONResponse([ - 'success' => true, - 'settings' => [ - 'algorithm' => $algorithm, - 'fusion' => $fusion, - 'scoreThreshold' => $scoreThreshold, - 'limit' => $limit, - ] - ]); - } - - /** - * Get available webhook presets. - * - * Admin-only endpoint that lists webhook presets filtered by installed apps. - * - * @return JSONResponse - */ - public function getWebhookPresets(): JSONResponse { - // Get admin's OAuth token for API calls - $user = $this->userSession->getUser(); - if (!$user) { - return new JSONResponse([ - 'success' => false, - 'error' => 'User not authenticated' - ], Http::STATUS_UNAUTHORIZED); - } - - $userId = $user->getUID(); - - // Create refresh callback - /** @return array{access_token: string, refresh_token: string, expires_in: int}|null */ - $refreshCallback = function (string $refreshToken): ?array { - $newTokenData = $this->tokenRefresher->refreshAccessToken($refreshToken); - - if ($newTokenData === null) { - return null; - } - - return [ - 'access_token' => $newTokenData['access_token'], - 'refresh_token' => $newTokenData['refresh_token'] ?? $refreshToken, - 'expires_in' => $newTokenData['expires_in'] ?? 3600, - ]; - }; - - // Get access token with automatic refresh - $accessToken = $this->tokenStorage->getAccessToken($userId, $refreshCallback); - if ($accessToken === null) { - return new JSONResponse([ - 'success' => false, - 'error' => 'MCP server authorization required' - ], Http::STATUS_UNAUTHORIZED); - } - - // Get installed apps to filter presets - $installedAppsResult = $this->client->getInstalledApps($accessToken); - if (isset($installedAppsResult['error'])) { - return new JSONResponse([ - 'success' => false, - 'error' => $installedAppsResult['error'] - ], Http::STATUS_INTERNAL_SERVER_ERROR); - } - - $installedApps = $installedAppsResult['apps'] ?? []; - - // Get registered webhooks to check preset status - $webhooksResult = $this->client->listWebhooks($accessToken); - if (isset($webhooksResult['error'])) { - return new JSONResponse([ - 'success' => false, - 'error' => $webhooksResult['error'] - ], Http::STATUS_INTERNAL_SERVER_ERROR); - } - - $registeredWebhooks = $webhooksResult['webhooks'] ?? []; - - // Filter presets by installed apps - $presets = WebhookPresets::filterPresetsByInstalledApps($installedApps); - - // Add enabled status to each preset - // IMPORTANT: Match both event type AND filter to avoid false positives - // (e.g., Notes and Files both use FILE_EVENT_* but with different filters) - $presetsWithStatus = []; - foreach ($presets as $presetId => $preset) { - // Check if all events for this preset are registered with matching filters - $allEventsRegistered = true; - foreach ($preset['events'] as $presetEvent) { - $eventMatched = false; - foreach ($registeredWebhooks as $webhook) { - // Match event type - if ($webhook['event'] !== $presetEvent['event']) { - continue; - } - - // Match filter (both must have filter or both must not have filter) - $presetFilter = !empty($presetEvent['filter']) ? $presetEvent['filter'] : null; - $webhookFilter = !empty($webhook['eventFilter']) ? $webhook['eventFilter'] : null; - - // Compare filters (use json_encode for deep comparison) - if (json_encode($presetFilter) === json_encode($webhookFilter)) { - $eventMatched = true; - break; - } - } - - if (!$eventMatched) { - $allEventsRegistered = false; - break; - } - } - - $presetsWithStatus[$presetId] = array_merge($preset, [ - 'enabled' => $allEventsRegistered - ]); - } - - return new JSONResponse([ - 'success' => true, - 'presets' => $presetsWithStatus - ]); - } - - /** - * Enable a webhook preset. - * - * Admin-only endpoint that registers all webhooks for a preset. - * - * @param string $presetId Preset ID to enable - * @return JSONResponse - */ - public function enableWebhookPreset(string $presetId): JSONResponse { - // Get admin's OAuth token - $user = $this->userSession->getUser(); - if (!$user) { - return new JSONResponse([ - 'success' => false, - 'error' => 'User not authenticated' - ], Http::STATUS_UNAUTHORIZED); - } - - $userId = $user->getUID(); - - // Create refresh callback - /** @return array{access_token: string, refresh_token: string, expires_in: int}|null */ - $refreshCallback = function (string $refreshToken): ?array { - $newTokenData = $this->tokenRefresher->refreshAccessToken($refreshToken); - - if ($newTokenData === null) { - return null; - } - - return [ - 'access_token' => $newTokenData['access_token'], - 'refresh_token' => $newTokenData['refresh_token'] ?? $refreshToken, - 'expires_in' => $newTokenData['expires_in'] ?? 3600, - ]; - }; - - // Get access token with automatic refresh - $accessToken = $this->tokenStorage->getAccessToken($userId, $refreshCallback); - if ($accessToken === null) { - return new JSONResponse([ - 'success' => false, - 'error' => 'MCP server authorization required' - ], Http::STATUS_UNAUTHORIZED); - } - - // Get preset configuration - $preset = WebhookPresets::getPreset($presetId); - if ($preset === null) { - return new JSONResponse([ - 'success' => false, - 'error' => "Unknown preset: $presetId" - ], Http::STATUS_BAD_REQUEST); - } - - // Get MCP server URL for webhook callback URI - $mcpServerUrl = $this->client->getServerUrl(); - $callbackUri = $mcpServerUrl . '/api/v1/webhooks/callback'; - - // Register each event in the preset - $registered = []; - $errors = []; - foreach ($preset['events'] as $eventConfig) { - $result = $this->client->createWebhook( - $eventConfig['event'], - $callbackUri, - !empty($eventConfig['filter']) ? $eventConfig['filter'] : null, - $accessToken - ); - - if (isset($result['error'])) { - $errors[] = [ - 'event' => $eventConfig['event'], - 'error' => $result['error'] - ]; - } else { - $registered[] = $result; - } - } - - if (!empty($errors)) { - return new JSONResponse([ - 'success' => false, - 'error' => 'Failed to register some webhooks', - 'registered' => $registered, - 'errors' => $errors - ], Http::STATUS_INTERNAL_SERVER_ERROR); - } - - $this->logger->info("Enabled webhook preset $presetId for user $userId", [ - 'preset_id' => $presetId, - 'webhooks_registered' => count($registered) - ]); - - return new JSONResponse([ - 'success' => true, - 'message' => "Enabled {$preset['name']}", - 'webhooks' => $registered - ]); - } - - /** - * Disable a webhook preset. - * - * Admin-only endpoint that deletes all webhooks for a preset. - * - * @param string $presetId Preset ID to disable - * @return JSONResponse - */ - public function disableWebhookPreset(string $presetId): JSONResponse { - // Get admin's OAuth token - $user = $this->userSession->getUser(); - if (!$user) { - return new JSONResponse([ - 'success' => false, - 'error' => 'User not authenticated' - ], Http::STATUS_UNAUTHORIZED); - } - - $userId = $user->getUID(); - - // Create refresh callback - /** @return array{access_token: string, refresh_token: string, expires_in: int}|null */ - $refreshCallback = function (string $refreshToken): ?array { - $newTokenData = $this->tokenRefresher->refreshAccessToken($refreshToken); - - if ($newTokenData === null) { - return null; - } - - return [ - 'access_token' => $newTokenData['access_token'], - 'refresh_token' => $newTokenData['refresh_token'] ?? $refreshToken, - 'expires_in' => $newTokenData['expires_in'] ?? 3600, - ]; - }; - - // Get access token with automatic refresh - $accessToken = $this->tokenStorage->getAccessToken($userId, $refreshCallback); - if ($accessToken === null) { - return new JSONResponse([ - 'success' => false, - 'error' => 'MCP server authorization required' - ], Http::STATUS_UNAUTHORIZED); - } - - // Get preset configuration - $preset = WebhookPresets::getPreset($presetId); - if ($preset === null) { - return new JSONResponse([ - 'success' => false, - 'error' => "Unknown preset: $presetId" - ], Http::STATUS_BAD_REQUEST); - } - - // Get all registered webhooks - $webhooksResult = $this->client->listWebhooks($accessToken); - if (isset($webhooksResult['error'])) { - return new JSONResponse([ - 'success' => false, - 'error' => $webhooksResult['error'] - ], Http::STATUS_INTERNAL_SERVER_ERROR); - } - - $registeredWebhooks = $webhooksResult['webhooks'] ?? []; - - // Find webhooks that match this preset's events AND filters - // IMPORTANT: Must match both event type AND filter to avoid deleting - // webhooks from other presets (e.g., Notes vs Files both use FILE_EVENT_*) - $webhooksToDelete = []; - foreach ($registeredWebhooks as $webhook) { - // Check if this webhook matches any event in the preset - foreach ($preset['events'] as $presetEvent) { - // Match event type - if ($webhook['event'] !== $presetEvent['event']) { - continue; - } - - // Match filter (both must have filter or both must not have filter) - $presetFilter = !empty($presetEvent['filter']) ? $presetEvent['filter'] : null; - $webhookFilter = !empty($webhook['eventFilter']) ? $webhook['eventFilter'] : null; - - // Compare filters (use json_encode for deep comparison) - if (json_encode($presetFilter) === json_encode($webhookFilter)) { - $webhooksToDelete[] = $webhook; - break; // This webhook matches, no need to check other preset events - } - } - } - - // Delete each matching webhook - $deleted = []; - $errors = []; - foreach ($webhooksToDelete as $webhook) { - $result = $this->client->deleteWebhook($webhook['id'], $accessToken); - - if (isset($result['error'])) { - $errors[] = [ - 'webhook_id' => $webhook['id'], - 'event' => $webhook['event'], - 'error' => $result['error'] - ]; - } else { - $deleted[] = $webhook['id']; - } - } - - if (!empty($errors)) { - return new JSONResponse([ - 'success' => false, - 'error' => 'Failed to delete some webhooks', - 'deleted' => $deleted, - 'errors' => $errors - ], Http::STATUS_INTERNAL_SERVER_ERROR); - } - - $this->logger->info("Disabled webhook preset $presetId for user $userId", [ - 'preset_id' => $presetId, - 'webhooks_deleted' => count($deleted) - ]); - - return new JSONResponse([ - 'success' => true, - 'message' => "Disabled {$preset['name']}", - 'deleted' => $deleted - ]); - } - - /** - * Get chunk context for visualization. - * - * @param string $doc_type Document type - * @param string $doc_id Document ID - * @param int $start Start offset - * @param int $end End offset - * @return JSONResponse - */ - #[NoAdminRequired] - public function chunkContext( - string $doc_type, - string $doc_id, - int $start, - int $end, - ): JSONResponse { - $user = $this->userSession->getUser(); - if (!$user) { - return new JSONResponse(['error' => 'User not authenticated'], Http::STATUS_UNAUTHORIZED); - } - - $userId = $user->getUID(); - - // Create refresh callback - /** @return array{access_token: string, refresh_token: string, expires_in: int}|null */ - $refreshCallback = function (string $refreshToken): ?array { - $newTokenData = $this->tokenRefresher->refreshAccessToken($refreshToken); - - if ($newTokenData === null) { - return null; - } - - return [ - 'access_token' => $newTokenData['access_token'], - 'refresh_token' => $newTokenData['refresh_token'] ?? $refreshToken, - 'expires_in' => $newTokenData['expires_in'] ?? 3600, - ]; - }; - - // Get user's OAuth token for MCP server with automatic refresh - $accessToken = $this->tokenStorage->getAccessToken($userId, $refreshCallback); - if ($accessToken === null) { - return new JSONResponse([ - 'success' => false, - 'error' => 'MCP server authorization required.' - ], Http::STATUS_UNAUTHORIZED); - } - - $result = $this->client->getChunkContext($doc_type, $doc_id, $start, $end, $accessToken); - - if (isset($result['error'])) { - return new JSONResponse(['success' => false, 'error' => $result['error']], Http::STATUS_INTERNAL_SERVER_ERROR); - } - - return new JSONResponse($result); - } - - /** - * Get PDF page preview (server-side rendered). - * - * AJAX endpoint for PDF viewer in semantic search UI. - * Uses server-side PyMuPDF rendering to avoid CSP/worker issues. - * - * @param string $file_path WebDAV path to PDF file - * @param int $page Page number (1-indexed, default: 1) - * @param float $scale Zoom factor (default: 2.0) - * @return JSONResponse - */ - #[NoAdminRequired] - public function pdfPreview( - string $file_path, - int $page = 1, - float $scale = 2.0, - ): JSONResponse { - $user = $this->userSession->getUser(); - if (!$user) { - return new JSONResponse(['success' => false, 'error' => 'User not authenticated'], Http::STATUS_UNAUTHORIZED); - } - - $userId = $user->getUID(); - - // Create refresh callback - /** @return array{access_token: string, refresh_token: string, expires_in: int}|null */ - $refreshCallback = function (string $refreshToken): ?array { - $newTokenData = $this->tokenRefresher->refreshAccessToken($refreshToken); - - if ($newTokenData === null) { - return null; - } - - return [ - 'access_token' => $newTokenData['access_token'], - 'refresh_token' => $newTokenData['refresh_token'] ?? $refreshToken, - 'expires_in' => $newTokenData['expires_in'] ?? 3600, - ]; - }; - - // Get user's OAuth token for MCP server with automatic refresh - $accessToken = $this->tokenStorage->getAccessToken($userId, $refreshCallback); - if ($accessToken === null) { - return new JSONResponse([ - 'success' => false, - 'error' => 'MCP server authorization required.' - ], Http::STATUS_UNAUTHORIZED); - } - - $result = $this->client->getPdfPreview($file_path, $page, $scale, $accessToken); - - if (isset($result['error'])) { - return new JSONResponse(['success' => false, 'error' => $result['error']], Http::STATUS_INTERNAL_SERVER_ERROR); - } - - return new JSONResponse($result); - } -} diff --git a/third_party/astrolabe/lib/Controller/CredentialsController.php b/third_party/astrolabe/lib/Controller/CredentialsController.php deleted file mode 100644 index 4d414a2..0000000 --- a/third_party/astrolabe/lib/Controller/CredentialsController.php +++ /dev/null @@ -1,324 +0,0 @@ -tokenStorage = $tokenStorage; - $this->userSession = $userSession; - $this->logger = $logger; - $this->config = $config; - $this->client = $client; - $this->httpClientService = $httpClientService; - $this->urlGenerator = $urlGenerator; - } - - /** - * Store app password for background sync. - * - * Validates the app password by making a test request to Nextcloud, - * then stores it encrypted if valid. - * - * @param string $appPassword Nextcloud app password - * @return JSONResponse - */ - #[NoAdminRequired] - public function storeAppPassword(string $appPassword): JSONResponse { - $user = $this->userSession->getUser(); - if (!$user) { - $this->logger->error('storeAppPassword called without authenticated user'); - return new JSONResponse([ - 'success' => false, - 'error' => 'User not authenticated' - ], Http::STATUS_UNAUTHORIZED); - } - - $userId = $user->getUID(); - - // Validate app password format (xxxxx-xxxxx-xxxxx-xxxxx-xxxxx) - if (!preg_match('/^[a-zA-Z0-9]{5}-[a-zA-Z0-9]{5}-[a-zA-Z0-9]{5}-[a-zA-Z0-9]{5}-[a-zA-Z0-9]{5}$/', $appPassword)) { - $this->logger->warning("Invalid app password format for user: $userId"); - return new JSONResponse([ - 'success' => false, - 'error' => 'Invalid app password format' - ], Http::STATUS_BAD_REQUEST); - } - - // Validate app password with Nextcloud - $isValid = $this->validateAppPassword($userId, $appPassword); - - if (!$isValid) { - $this->logger->warning("App password validation failed for user: $userId"); - return new JSONResponse([ - 'success' => false, - 'error' => 'Invalid app password. Please check the password and try again.' - ], Http::STATUS_UNAUTHORIZED); - } - - // Store encrypted app password locally in Nextcloud - try { - $this->tokenStorage->storeBackgroundSyncPassword($userId, $appPassword); - $this->logger->info("Stored app password locally for user: $userId"); - } catch (\Exception $e) { - $this->logger->error("Failed to store app password locally for user $userId", [ - 'error' => $e->getMessage() - ]); - return new JSONResponse([ - 'success' => false, - 'error' => 'Failed to save app password locally' - ], Http::STATUS_INTERNAL_SERVER_ERROR); - } - - // Send app password to MCP server for background sync - // Get MCP server URL from system config (set in config.php) - $mcpServerUrl = $this->config->getSystemValue('mcp_server_url', ''); - if (empty($mcpServerUrl)) { - $this->logger->warning('MCP server URL not configured, app password stored locally only'); - return new JSONResponse([ - 'success' => true, - 'partial_success' => true, - 'local_storage' => true, - 'mcp_sync' => false, - 'message' => 'App password saved locally (MCP server not configured)' - ], Http::STATUS_OK); - } - - try { - $httpClient = $this->httpClientService->newClient(); - - // Send to MCP server with BasicAuth (user proves ownership of password) - $mcpEndpoint = rtrim($mcpServerUrl, '/') . '/api/v1/users/' . urlencode($userId) . '/app-password'; - - $this->logger->debug("Sending app password to MCP server: $mcpEndpoint"); - - $response = $httpClient->post($mcpEndpoint, [ - 'auth' => [$userId, $appPassword], - 'headers' => [ - 'Content-Type' => 'application/json', - 'Accept' => 'application/json', - ], - 'timeout' => 10, - ]); - - $statusCode = $response->getStatusCode(); - $body = json_decode($response->getBody(), true); - - if ($statusCode === 200 && ($body['success'] ?? false)) { - $this->logger->info("Successfully provisioned app password to MCP server for user: $userId"); - return new JSONResponse([ - 'success' => true, - 'partial_success' => false, - 'local_storage' => true, - 'mcp_sync' => true, - 'message' => 'App password saved successfully' - ], Http::STATUS_OK); - } else { - $error = $body['error'] ?? 'Unknown error'; - $this->logger->error("MCP server rejected app password for user $userId: $error"); - // Return partial success since it was stored locally but MCP sync failed - return new JSONResponse([ - 'success' => true, - 'partial_success' => true, - 'local_storage' => true, - 'mcp_sync' => false, - 'message' => 'App password saved locally (MCP server sync failed)', - 'mcp_error' => $error - ], Http::STATUS_OK); - } - } catch (\Exception $e) { - $this->logger->error("Failed to send app password to MCP server for user $userId", [ - 'error' => $e->getMessage() - ]); - // Return partial success since it was stored locally but MCP was unreachable - return new JSONResponse([ - 'success' => true, - 'partial_success' => true, - 'local_storage' => true, - 'mcp_sync' => false, - 'message' => 'App password saved locally (MCP server unreachable)', - 'mcp_error' => $e->getMessage() - ], Http::STATUS_OK); - } - } - - /** - * Validate app password by making a test request to Nextcloud. - * - * @param string $userId User ID - * @param string $appPassword App password to validate - * @return bool True if valid, false otherwise - */ - private function validateAppPassword(string $userId, string $appPassword): bool { - try { - // Use 127.0.0.1 for internal validation (we're running inside Nextcloud container) - // Using IP address instead of 'localhost' to avoid Nextcloud's overwrite.cli.url rewriting - // getAbsoluteURL() returns the external URL which isn't accessible from inside the container - $baseUrl = 'http://127.0.0.1'; - - // Make a test request to Nextcloud API with BasicAuth - // Using OCS API user endpoint as a lightweight test - $testUrl = $baseUrl . '/ocs/v1.php/cloud/user?format=json'; - - $this->logger->debug("Validating app password for user: $userId against $testUrl"); - - // Use Nextcloud's HTTP client - $httpClient = $this->httpClientService->newClient(); - - $response = $httpClient->get($testUrl, [ - 'auth' => [$userId, $appPassword], - 'headers' => [ - 'OCS-APIRequest' => 'true', - 'Accept' => 'application/json', - ], - 'timeout' => 10, - ]); - - $statusCode = $response->getStatusCode(); - - // Success is 200 OK - if ($statusCode === 200) { - $this->logger->debug("App password validation successful for user: $userId"); - return true; - } - - $this->logger->warning("App password validation failed for user: $userId (HTTP $statusCode)"); - return false; - } catch (\Exception $e) { - $this->logger->error("Exception during app password validation for user $userId", [ - 'error' => $e->getMessage() - ]); - return false; - } - } - - /** - * Get background sync credentials status for the current user. - * - * @return JSONResponse - */ - #[NoAdminRequired] - public function getStatus(): JSONResponse { - $user = $this->userSession->getUser(); - if (!$user) { - return new JSONResponse([ - 'success' => false, - 'error' => 'User not authenticated' - ], Http::STATUS_UNAUTHORIZED); - } - - $userId = $user->getUID(); - - $hasAccess = $this->tokenStorage->hasBackgroundSyncAccess($userId); - $syncType = $this->tokenStorage->getBackgroundSyncType($userId); - $provisionedAt = $this->tokenStorage->getBackgroundSyncProvisionedAt($userId); - - return new JSONResponse([ - 'success' => true, - 'has_background_access' => $hasAccess, - 'sync_type' => $syncType, - 'provisioned_at' => $provisionedAt, - ], Http::STATUS_OK); - } - - /** - * Get credentials for a specific user (admin only). - * - * Note: This does NOT return the actual password, only metadata. - * - * @param string $userId User ID to check - * @return JSONResponse - */ - public function getCredentials(string $userId): JSONResponse { - // This endpoint should only be accessible by admins - // For now, just return metadata (not actual credentials) - $hasAccess = $this->tokenStorage->hasBackgroundSyncAccess($userId); - $syncType = $this->tokenStorage->getBackgroundSyncType($userId); - $provisionedAt = $this->tokenStorage->getBackgroundSyncProvisionedAt($userId); - - return new JSONResponse([ - 'success' => true, - 'user_id' => $userId, - 'has_background_access' => $hasAccess, - 'sync_type' => $syncType, - 'provisioned_at' => $provisionedAt, - ], Http::STATUS_OK); - } - - /** - * Delete background sync credentials for the current user. - * - * @return JSONResponse - */ - #[NoAdminRequired] - public function deleteCredentials(): JSONResponse { - $user = $this->userSession->getUser(); - if (!$user) { - return new JSONResponse([ - 'success' => false, - 'error' => 'User not authenticated' - ], Http::STATUS_UNAUTHORIZED); - } - - $userId = $user->getUID(); - - try { - // Delete both OAuth tokens and app password (if any exist) - $this->tokenStorage->deleteUserToken($userId); - $this->tokenStorage->deleteBackgroundSyncPassword($userId); - - $this->logger->info("Deleted background sync credentials for user: $userId"); - - return new JSONResponse([ - 'success' => true, - 'message' => 'Credentials deleted successfully' - ], Http::STATUS_OK); - } catch (\Exception $e) { - $this->logger->error("Failed to delete credentials for user $userId", [ - 'error' => $e->getMessage() - ]); - return new JSONResponse([ - 'success' => false, - 'error' => 'Failed to delete credentials' - ], Http::STATUS_INTERNAL_SERVER_ERROR); - } - } -} diff --git a/third_party/astrolabe/lib/Controller/OauthController.php b/third_party/astrolabe/lib/Controller/OauthController.php deleted file mode 100644 index 6172335..0000000 --- a/third_party/astrolabe/lib/Controller/OauthController.php +++ /dev/null @@ -1,550 +0,0 @@ -config = $config; - $this->session = $session; - $this->userSession = $userSession; - $this->urlGenerator = $urlGenerator; - $this->tokenStorage = $tokenStorage; - $this->logger = $logger; - $this->l = $l; - $this->httpClient = $clientService->newClient(); - $this->client = $client; - } - - /** - * Initiate OAuth authorization flow. - * - * Always generates PKCE code verifier and challenge (RFC 9207). - * Stores state and code verifier in session, then redirects user to IdP authorization endpoint. - * - * @return RedirectResponse|TemplateResponse - */ - #[NoAdminRequired] - #[NoCSRFRequired] - public function initiateOAuth() { - $this->logger->info('initiateOAuth called'); - - $user = $this->userSession->getUser(); - if (!$user) { - $this->logger->error('initiateOAuth: User not authenticated'); - return new TemplateResponse( - 'astrolabe', - 'settings/error', - ['error' => $this->l->t('User not authenticated')] - ); - } - - $this->logger->info('initiateOAuth: User authenticated: ' . $user->getUID()); - - try { - // Get MCP server configuration - $mcpServerUrl = $this->config->getSystemValue('mcp_server_url', ''); - if (empty($mcpServerUrl)) { - throw new \Exception('MCP server URL not configured'); - } - - // Always generate PKCE values (RFC 9207: PKCE recommended for all clients) - $codeVerifier = bin2hex(random_bytes(32)); - $codeChallenge = $this->base64UrlEncode(hash('sha256', $codeVerifier, true)); - - // Check if confidential client secret is also configured - $clientSecret = $this->config->getSystemValue('astrolabe_client_secret', ''); - $isConfidentialClient = !empty($clientSecret); - - if ($isConfidentialClient) { - $this->logger->info('Using confidential client mode with PKCE and client secret'); - } else { - $this->logger->info('Using public client mode with PKCE only'); - } - - // Generate state for CSRF protection - $state = bin2hex(random_bytes(16)); - - // Store values in session - $this->session->set('mcp_oauth_code_verifier', $codeVerifier); - $this->session->set('mcp_oauth_state', $state); - $this->session->set('mcp_oauth_user_id', $user->getUID()); - - // Build OAuth authorization URL - $authUrl = $this->buildAuthorizationUrl( - $mcpServerUrl, - $state, - $codeChallenge - ); - - $this->logger->info('Initiating OAuth flow for user: ' . $user->getUID()); - - return new RedirectResponse($authUrl); - } catch (\Exception $e) { - $this->logger->error('Failed to initiate OAuth flow', [ - 'error' => $e->getMessage() - ]); - - return new TemplateResponse( - 'astrolabe', - 'settings/error', - ['error' => $this->l->t('Failed to initiate OAuth: %s', [$e->getMessage()])] - ); - } - } - - /** - * Handle OAuth callback after user authorization. - * - * Validates state, exchanges authorization code for access token using PKCE, - * and stores tokens for the user. - * - * @param string $code Authorization code - * @param string $state State parameter for CSRF protection - * @param string|null $error Error from IdP - * @param string|null $error_description Error description from IdP - * @return RedirectResponse - */ - #[NoAdminRequired] - #[NoCSRFRequired] - public function oauthCallback( - string $code = '', - string $state = '', - ?string $error = null, - ?string $error_description = null, - ): RedirectResponse { - try { - // Check for errors from IdP - if ($error) { - throw new \Exception("OAuth error: $error - " . ($error_description ?? '')); - } - - // Validate state to prevent CSRF - $storedState = $this->session->get('mcp_oauth_state'); - if (empty($storedState) || $state !== $storedState) { - throw new \Exception('Invalid state parameter (CSRF protection)'); - } - - // Get stored PKCE verifier (always required) - $codeVerifier = $this->session->get('mcp_oauth_code_verifier'); - if (empty($codeVerifier)) { - throw new \Exception('PKCE code verifier not found in session'); - } - - // Get user ID from session - $userId = $this->session->get('mcp_oauth_user_id'); - if (empty($userId)) { - throw new \Exception('User ID not found in session'); - } - - // Get MCP server configuration - $mcpServerUrl = $this->config->getSystemValue('mcp_server_url', ''); - if (empty($mcpServerUrl)) { - throw new \Exception('MCP server URL not configured'); - } - - // Exchange authorization code for tokens - $tokenData = $this->exchangeCodeForToken( - $mcpServerUrl, - $code, - $codeVerifier - ); - - // Store tokens for user - $this->tokenStorage->storeUserToken( - $userId, - $tokenData['access_token'], - $tokenData['refresh_token'] ?? '', - time() + ($tokenData['expires_in'] ?? 3600) - ); - - // Clean up session - $this->session->remove('mcp_oauth_code_verifier'); - $this->session->remove('mcp_oauth_state'); - $this->session->remove('mcp_oauth_user_id'); - - $this->logger->info("OAuth flow completed successfully for user: $userId"); - - // Redirect back to personal settings - return new RedirectResponse( - $this->urlGenerator->linkToRoute('settings.PersonalSettings.index', ['section' => 'astrolabe']) - ); - } catch (\Exception $e) { - $this->logger->error('OAuth callback failed', [ - 'error' => $e->getMessage() - ]); - - // Clean up session - $this->session->remove('mcp_oauth_code_verifier'); - $this->session->remove('mcp_oauth_state'); - $this->session->remove('mcp_oauth_user_id'); - - // Redirect to settings with error - return new RedirectResponse( - $this->urlGenerator->linkToRoute('settings.PersonalSettings.index', [ - 'section' => 'astrolabe', - 'error' => urlencode($e->getMessage()) - ]) - ); - } - } - - /** - * Disconnect user's MCP OAuth tokens. - * - * Deletes stored tokens from Nextcloud. Note: Does not revoke tokens on IdP side. - * - * @return RedirectResponse - */ - #[NoAdminRequired] - public function disconnect(): RedirectResponse { - $user = $this->userSession->getUser(); - if (!$user) { - return new RedirectResponse( - $this->urlGenerator->linkToRoute('settings.PersonalSettings.index', ['section' => 'astrolabe']) - ); - } - - $userId = $user->getUID(); - - try { - $this->tokenStorage->deleteUserToken($userId); - $this->logger->info("Disconnected MCP OAuth for user: $userId"); - } catch (\Exception $e) { - $this->logger->error("Failed to disconnect MCP OAuth for user $userId", [ - 'error' => $e->getMessage() - ]); - } - - return new RedirectResponse( - $this->urlGenerator->linkToRoute('settings.PersonalSettings.index', ['section' => 'astrolabe']) - ); - } - - /** - * Build OAuth authorization URL. - * - * Queries MCP server for IdP configuration, then performs OIDC discovery - * to find the authorization endpoint. Supports both Nextcloud OIDC and - * external IdPs like Keycloak. - * - * Always uses PKCE (RFC 9207 recommends PKCE for all clients). - * - * @param string $mcpServerUrl Base URL of MCP server - * @param string $state CSRF state parameter - * @param string $codeChallenge PKCE code challenge - * @return string Authorization URL - * @throws \Exception if OIDC discovery fails - */ - private function buildAuthorizationUrl( - string $mcpServerUrl, - string $state, - string $codeChallenge, - ): string { - // First, query MCP server to discover which IdP it's configured to use - $this->logger->info('buildAuthorizationUrl: Starting', [ - 'mcp_server_url' => $mcpServerUrl, - ]); - - try { - $statusUrl = $mcpServerUrl . '/api/v1/status'; - $this->logger->info('buildAuthorizationUrl: Fetching MCP server status', [ - 'url' => $statusUrl, - ]); - - $statusResponse = $this->httpClient->get($statusUrl); - $statusData = json_decode($statusResponse->getBody(), true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new \RuntimeException('Invalid JSON in status response: ' . json_last_error_msg()); - } - - $this->logger->info('buildAuthorizationUrl: MCP server status received', [ - 'auth_mode' => $statusData['auth_mode'] ?? 'unknown', - 'has_oidc' => isset($statusData['oidc']), - 'oidc_discovery_url' => $statusData['oidc']['discovery_url'] ?? 'not_set', - ]); - - } catch (\Exception $e) { - $this->logger->error('buildAuthorizationUrl: Failed to fetch MCP server status', [ - 'url' => $mcpServerUrl . '/api/v1/status', - 'error' => $e->getMessage(), - 'trace' => $e->getTraceAsString(), - ]); - throw new \Exception('Cannot connect to MCP server: ' . $e->getMessage()); - } - - // Determine OIDC discovery URL - // Priority: 1) MCP server's configured discovery URL, 2) Nextcloud OIDC app - if (isset($statusData['oidc']['discovery_url'])) { - // MCP server has external IdP configured (e.g., Keycloak) - $discoveryUrl = $statusData['oidc']['discovery_url']; - $this->logger->info('Using IdP from MCP server configuration', [ - 'discovery_url' => $discoveryUrl, - ]); - } else { - // Fall back to Nextcloud's OIDC app - // Use internal localhost URL for HTTP request (accessible from inside container) - // We'll transform the returned URLs to external format after discovery - $discoveryUrl = 'http://localhost/.well-known/openid-configuration'; - $internalBaseUrl = 'http://localhost'; - - $this->logger->info('Using Nextcloud OIDC app as IdP (internal request)', [ - 'discovery_url' => $discoveryUrl, - ]); - } - - // Perform OIDC discovery - $this->logger->info('buildAuthorizationUrl: Starting OIDC discovery', [ - 'discovery_url' => $discoveryUrl, - ]); - - try { - $response = $this->httpClient->get($discoveryUrl); - $responseBody = $response->getBody(); - $this->logger->info('buildAuthorizationUrl: Got OIDC discovery response', [ - 'status_code' => $response->getStatusCode(), - 'body_length' => strlen($responseBody), - ]); - - $discovery = json_decode($responseBody, true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new \RuntimeException('Invalid JSON in OIDC discovery: ' . json_last_error_msg()); - } - - if (!isset($discovery['authorization_endpoint'])) { - throw new \RuntimeException('Missing authorization_endpoint in OIDC discovery'); - } - - $authEndpoint = $discovery['authorization_endpoint']; - - // Transform internal URL to external URL if using Nextcloud OIDC app - // The discovery was done via internal http://localhost but browsers need - // the external URL (e.g., http://localhost:8080) - if (isset($internalBaseUrl)) { - $externalBaseUrl = $this->urlGenerator->getAbsoluteURL('/'); - $externalBaseUrl = rtrim($externalBaseUrl, '/'); - $authEndpoint = str_replace($internalBaseUrl, $externalBaseUrl, $authEndpoint); - } - - $this->logger->info('buildAuthorizationUrl: OIDC discovery succeeded', [ - 'auth_endpoint' => $authEndpoint, - 'token_endpoint' => $discovery['token_endpoint'] ?? 'not_set', - ]); - - } catch (\Exception $e) { - $this->logger->error('buildAuthorizationUrl: OIDC discovery failed', [ - 'discovery_url' => $discoveryUrl, - 'error' => $e->getMessage(), - 'trace' => $e->getTraceAsString(), - ]); - throw new \Exception('Failed to discover OAuth endpoints: ' . $e->getMessage()); - } - - // Build callback URL - $redirectUri = $this->urlGenerator->linkToRouteAbsolute( - 'astrolabe.oauth.oauthCallback' - ); - - // Get public MCP server URL for token audience (RFC 8707 Resource Indicator) - // Use public URL that clients/browsers see, not internal Docker URL - $mcpServerPublicUrl = $this->config->getSystemValue('mcp_server_public_url', $mcpServerUrl); - - // Build authorization URL parameters - $params = [ - 'client_id' => $this->client->getClientId(), - 'redirect_uri' => $redirectUri, - 'response_type' => 'code', - 'scope' => 'openid profile email offline_access', // Request MCP scopes - 'state' => $state, - 'resource' => $mcpServerPublicUrl, // RFC 8707 Resource Indicator - request token with MCP server audience - ]; - - // Add PKCE parameters (always required per RFC 9207) - $params['code_challenge'] = $codeChallenge; - $params['code_challenge_method'] = 'S256'; - - return $authEndpoint . '?' . http_build_query($params); - } - - /** - * Exchange authorization code for access token. - * - * Always uses PKCE code_verifier (RFC 9207). - * For confidential clients: Also includes client_secret for additional security. - * For public clients: Uses PKCE code_verifier only. - * - * Queries MCP server for IdP configuration, then performs OIDC discovery - * to find the token endpoint. Supports both Nextcloud OIDC and external IdPs. - * - * @param string $mcpServerUrl Base URL of MCP server - * @param string $code Authorization code - * @param string $codeVerifier PKCE code verifier - * @return array Token data containing access_token, refresh_token, expires_in - * @throws \Exception on HTTP or token error - */ - private function exchangeCodeForToken( - string $mcpServerUrl, - string $code, - string $codeVerifier, - ): array { - // Query MCP server to discover which IdP it's configured to use - try { - $statusResponse = $this->httpClient->get($mcpServerUrl . '/api/v1/status'); - $statusData = json_decode($statusResponse->getBody(), true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new \RuntimeException('Invalid status response from MCP server'); - } - - } catch (\Exception $e) { - $this->logger->error('Failed to fetch MCP server status during token exchange', [ - 'error' => $e->getMessage(), - ]); - throw new \Exception('Cannot connect to MCP server: ' . $e->getMessage()); - } - - // Determine OIDC discovery URL and token endpoint - $useInternalNextcloud = !isset($statusData['oidc']['discovery_url']); - - if (!$useInternalNextcloud) { - // External IdP configured - use discovery - $discoveryUrl = $statusData['oidc']['discovery_url']; - - try { - $response = $this->httpClient->get($discoveryUrl); - $discovery = json_decode($response->getBody(), true); - - if (json_last_error() !== JSON_ERROR_NONE || !isset($discovery['token_endpoint'])) { - throw new \RuntimeException('Invalid OIDC discovery response'); - } - - $tokenEndpoint = $discovery['token_endpoint']; - - } catch (\Exception $e) { - $this->logger->error('OIDC discovery failed during token exchange', [ - 'discovery_url' => $discoveryUrl, - 'error' => $e->getMessage(), - ]); - throw new \Exception('Failed to discover token endpoint: ' . $e->getMessage()); - } - } else { - // Nextcloud's OIDC app - use internal URL directly (no HTTP request needed) - // This avoids network issues when overwritehost includes external port - $tokenEndpoint = 'http://localhost/apps/oidc/token'; - } - - $redirectUri = $this->urlGenerator->linkToRouteAbsolute( - 'astrolabe.oauth.oauthCallback' - ); - - // Build token request parameters - $postData = [ - 'grant_type' => 'authorization_code', - 'code' => $code, - 'redirect_uri' => $redirectUri, - 'client_id' => $this->client->getClientId(), - ]; - - // Always include PKCE code verifier (RFC 9207) - $postData['code_verifier'] = $codeVerifier; - - // Also include client secret if configured (defense in depth for confidential clients) - $clientSecret = $this->config->getSystemValue('astrolabe_client_secret', ''); - if (!empty($clientSecret)) { - $postData['client_secret'] = $clientSecret; - $this->logger->info('Using PKCE with client secret for token exchange'); - } else { - $this->logger->info('Using PKCE only for token exchange'); - } - - // Use Nextcloud's HTTP client for token request - try { - $response = $this->httpClient->post($tokenEndpoint, [ - 'body' => http_build_query($postData), - 'headers' => [ - 'Content-Type' => 'application/x-www-form-urlencoded', - 'Accept' => 'application/json', - ], - ]); - - $tokenData = json_decode($response->getBody(), true); - - if (json_last_error() !== JSON_ERROR_NONE || !isset($tokenData['access_token'])) { - throw new \RuntimeException('Invalid token response from server'); - } - - return $tokenData; - - } catch (\Exception $e) { - $this->logger->error('Token exchange failed', [ - 'error' => $e->getMessage(), - 'token_endpoint' => $tokenEndpoint, - ]); - throw new \Exception('Token exchange failed: ' . $e->getMessage()); - } - } - - /** - * Base64 URL-safe encoding (for PKCE). - * - * @param string $data Data to encode - * @return string Base64 URL-encoded string - */ - private function base64UrlEncode(string $data): string { - return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); - } -} diff --git a/third_party/astrolabe/lib/Controller/PageController.php b/third_party/astrolabe/lib/Controller/PageController.php deleted file mode 100644 index 998fc1d..0000000 --- a/third_party/astrolabe/lib/Controller/PageController.php +++ /dev/null @@ -1,29 +0,0 @@ - - */ -class AstrolabeAdminSettingsListener implements IEventListener { - public function __construct( - private IConfig $config, - private LoggerInterface $logger, - ) { - } - - public function handle(Event $event): void { - if (!$event instanceof DeclarativeSettingsGetValueEvent && !$event instanceof DeclarativeSettingsSetValueEvent) { - return; - } - - if ($event->getApp() !== Application::APP_ID) { - return; - } - - if ($event->getFormId() !== 'astrolabe-admin-settings') { - return; - } - - if ($event instanceof DeclarativeSettingsGetValueEvent) { - $this->handleGetValue($event); - } elseif ($event instanceof DeclarativeSettingsSetValueEvent) { - $this->handleSetValue($event); - } - } - - private function handleGetValue(DeclarativeSettingsGetValueEvent $event): void { - $fieldId = $event->getFieldId(); - - // Map field IDs to system config keys - $value = match($fieldId) { - 'mcp_server_url' => $this->config->getSystemValue('mcp_server_url', ''), - 'mcp_server_api_key' => '****', // Never leak the API key on read - 'astrolabe_client_id' => $this->config->getSystemValue('astrolabe_client_id', ''), - 'astrolabe_client_secret' => '****', // Never leak the secret on read - default => null, - }; - - if ($value !== null) { - $event->setValue($value); - } - } - - private function handleSetValue(DeclarativeSettingsSetValueEvent $event): void { - $fieldId = $event->getFieldId(); - $value = $event->getValue(); - - // Only save if value is not empty (allow clearing by setting to empty string) - // For password fields, if the value is '****', don't update (user didn't change it) - if ($fieldId === 'mcp_server_api_key' && $value === '****') { - $event->stopPropagation(); - return; - } - if ($fieldId === 'astrolabe_client_secret' && $value === '****') { - $event->stopPropagation(); - return; - } - - try { - match($fieldId) { - 'mcp_server_url' => $this->config->setSystemValue('mcp_server_url', (string)$value), - 'mcp_server_api_key' => $this->config->setSystemValue('mcp_server_api_key', (string)$value), - 'astrolabe_client_id' => $this->config->setSystemValue('astrolabe_client_id', (string)$value), - 'astrolabe_client_secret' => $this->config->setSystemValue('astrolabe_client_secret', (string)$value), - default => null, - }; - - $this->logger->info('Astrolabe admin setting updated', [ - 'field' => $fieldId, - 'app' => Application::APP_ID, - ]); - } catch (\Exception $e) { - $this->logger->error('Failed to update Astrolabe admin setting', [ - 'field' => $fieldId, - 'error' => $e->getMessage(), - 'app' => Application::APP_ID, - ]); - throw $e; - } - - $event->stopPropagation(); - } -} diff --git a/third_party/astrolabe/lib/Search/SemanticSearchProvider.php b/third_party/astrolabe/lib/Search/SemanticSearchProvider.php deleted file mode 100644 index bdcb2f0..0000000 --- a/third_party/astrolabe/lib/Search/SemanticSearchProvider.php +++ /dev/null @@ -1,349 +0,0 @@ -l10n->t('Astrolabe'); - } - - /** - * Order in search results. Lower = higher priority. - * Use negative value when user is in our app's context. - */ - public function getOrder(string $route, array $routeParameters): int { - if (str_contains($route, Application::APP_ID)) { - return -1; // Prioritize when in Astrolabe app - } - return 40; // Above most apps, below files/mail - } - - /** - * Execute semantic search via MCP server. - * - * SECURITY: Results are filtered server-side to only include documents - * owned by the searching user. User identity comes from OAuth token. - */ - public function search(IUser $user, ISearchQuery $query): SearchResult { - $term = $query->getTerm(); - $limit = $query->getLimit(); - $cursor = $query->getCursor(); - - // Skip empty queries - if (empty(trim($term))) { - return SearchResult::complete($this->getName(), []); - } - - $userId = $user->getUID(); - - // Create refresh callback matching ApiController pattern - /** @return array{access_token: string, refresh_token: string, expires_in: int}|null */ - $refreshCallback = function (string $refreshToken): ?array { - $newTokenData = $this->tokenRefresher->refreshAccessToken($refreshToken); - - if ($newTokenData === null) { - return null; - } - - return [ - 'access_token' => $newTokenData['access_token'], - 'refresh_token' => $newTokenData['refresh_token'] ?? $refreshToken, - 'expires_in' => $newTokenData['expires_in'] ?? 3600, - ]; - }; - - // Get OAuth token for user with automatic refresh - $accessToken = $this->tokenStorage->getAccessToken($userId, $refreshCallback); - if ($accessToken === null) { - // User hasn't authorized the app yet - return empty results - $this->logger->debug('No OAuth token for user in semantic search', [ - 'user_id' => $userId, - ]); - return SearchResult::complete($this->getName(), []); - } - - // Check if MCP server is available and vector sync enabled - $status = $this->client->getStatus(); - if (!empty($status['error']) || !($status['vector_sync_enabled'] ?? false)) { - $this->logger->debug('MCP server not available or vector sync disabled', [ - 'status' => $status, - ]); - return SearchResult::complete($this->getName(), []); - } - - // Load admin search settings - $algorithm = $this->config->getAppValue( - Application::APP_ID, - AdminSettings::SETTING_SEARCH_ALGORITHM, - AdminSettings::DEFAULT_SEARCH_ALGORITHM - ); - $fusion = $this->config->getAppValue( - Application::APP_ID, - AdminSettings::SETTING_SEARCH_FUSION, - AdminSettings::DEFAULT_SEARCH_FUSION - ); - $scoreThreshold = (int)$this->config->getAppValue( - Application::APP_ID, - AdminSettings::SETTING_SEARCH_SCORE_THRESHOLD, - (string)AdminSettings::DEFAULT_SEARCH_SCORE_THRESHOLD - ); - $configuredLimit = (int)$this->config->getAppValue( - Application::APP_ID, - AdminSettings::SETTING_SEARCH_LIMIT, - (string)AdminSettings::DEFAULT_SEARCH_LIMIT - ); - - // Use configured limit if query limit is higher - $effectiveLimit = min($limit, $configuredLimit); - - // Calculate offset from cursor - $offset = $cursor ? (int)$cursor : 0; - - // Execute semantic search with OAuth token and admin settings - // Server extracts user_id from token - results filtered to that user's documents - $results = $this->client->searchForUnifiedSearch( - query: $term, - token: $accessToken, - limit: $effectiveLimit, - offset: $offset, - algorithm: $algorithm, - fusion: $fusion, - scoreThreshold: $scoreThreshold / 100.0, // Convert percentage to 0-1 range - ); - - if (!empty($results['error'])) { - $this->logger->warning('Semantic search failed', [ - 'error' => $results['error'], - 'query' => $term, - ]); - return SearchResult::complete($this->getName(), []); - } - - // Transform results to SearchResultEntry objects - $entries = []; - foreach ($results['results'] ?? [] as $result) { - $entries[] = $this->transformResult($result); - } - - // Return paginated if more results might exist - $totalFound = $results['total_found'] ?? count($entries); - if (count($entries) >= $effectiveLimit && $totalFound > $offset + $effectiveLimit) { - return SearchResult::paginated( - $this->getName(), - $entries, - (string)($offset + $effectiveLimit) - ); - } - - return SearchResult::complete($this->getName(), $entries); - } - - /** - * Transform MCP search result to Nextcloud SearchResultEntry. - */ - private function transformResult(array $result): SearchResultEntry { - $docType = $result['doc_type'] ?? 'unknown'; - $title = $result['title'] ?? $this->l10n->t('Untitled'); - $score = $result['score'] ?? 0; - $id = isset($result['id']) ? (string)$result['id'] : null; - $mimeType = $result['mime_type'] ?? null; - - // Build resource URL based on document type - $resourceUrl = $this->buildResourceUrl($result); - - // Get icon and thumbnail based on document type - [$thumbnailUrl, $iconClass] = $this->getIconAndThumbnail($docType, $id, $mimeType); - - // Build metadata string with chunk and page info - $metadataParts = []; - - // Chunk info (always available) - if (isset($result['chunk_index']) && isset($result['total_chunks'])) { - $chunkNum = $result['chunk_index'] + 1; // Convert 0-based to 1-based - $metadataParts[] = sprintf('Chunk %d/%d', $chunkNum, $result['total_chunks']); - } - - // Page info for PDFs - if (!empty($result['page_number']) && !empty($result['page_count'])) { - $metadataParts[] = sprintf('Page %d/%d', $result['page_number'], $result['page_count']); - } - - // Combine metadata parts - $metadata = !empty($metadataParts) ? implode(' · ', $metadataParts) : ''; - - // Subline shows only chunk/page metadata (no excerpt, consistent with chunk viz) - $subline = $metadata ?: sprintf( - '%s · %d%% %s', - $this->getDocTypeLabel($docType), - (int)($score * 100), - $this->l10n->t('relevant') - ); - - return new SearchResultEntry( - $thumbnailUrl, - $title, - $subline, - $resourceUrl, - $iconClass, - false // not rounded - ); - } - - /** - * Build URL to navigate to Astrolabe with chunk viewer. - * - * Links to Astrolabe app with query parameters that trigger the chunk modal, - * allowing users to preview the chunk before navigating to the full document. - */ - private function buildResourceUrl(array $result): string { - // Build base URL to Astrolabe app - $baseUrl = $this->urlGenerator->linkToRoute(Application::APP_ID . '.page.index'); - - // Extract chunk parameters - $docType = $result['doc_type'] ?? 'unknown'; - $id = $result['id'] ?? null; - $chunkStart = $result['chunk_start_offset'] ?? null; - $chunkEnd = $result['chunk_end_offset'] ?? null; - - // If we have chunk information, build URL with parameters - if ($id !== null && $chunkStart !== null && $chunkEnd !== null) { - $params = [ - 'doc_type' => $docType, - 'doc_id' => $id, - 'chunk_start' => $chunkStart, - 'chunk_end' => $chunkEnd, - ]; - - // Add optional metadata - if (isset($result['title'])) { - $params['title'] = $result['title']; - } - if (isset($result['path'])) { - $params['path'] = $result['path']; - } - if (isset($result['page_number'])) { - $params['page_number'] = $result['page_number']; - } - if (isset($result['board_id'])) { - $params['board_id'] = $result['board_id']; - } - - // Encode parameters for URL - $queryString = http_build_query($params); - return $baseUrl . '?' . $queryString; - } - - // Fallback to base URL if no chunk information - return $baseUrl; - } - - /** - * Get icon and thumbnail for document type. - * - * Returns [thumbnailUrl, iconClass] tuple. - * For files, uses mimetype-specific icons and preview thumbnails when available. - * For other document types, uses appropriate icon classes. - * - * @return array{string, string} [thumbnailUrl, iconClass] - */ - private function getIconAndThumbnail(string $docType, ?string $id, ?string $mimeType): array { - if ($docType === 'file' && $id !== null && $mimeType !== null) { - // For files, check if preview is supported - $thumbnailUrl = ''; - if ($this->previewManager->isMimeSupported($mimeType)) { - $thumbnailUrl = $this->urlGenerator->linkToRouteAbsolute( - 'core.Preview.getPreviewByFileId', - ['x' => 32, 'y' => 32, 'fileId' => $id] - ); - } - - // Get mimetype-specific icon class - $iconClass = $mimeType === FileInfo::MIMETYPE_FOLDER - ? 'icon-folder' - : $this->mimeTypeDetector->mimeTypeIcon($mimeType); - - return [$thumbnailUrl, $iconClass]; - } - - // For non-file document types, use icon classes - $iconClass = match ($docType) { - 'note' => 'icon-notes', - 'deck_card' => 'icon-deck', - 'calendar', 'calendar_event' => 'icon-calendar', - 'news_item' => 'icon-rss', - 'contact' => 'icon-contacts', - default => 'icon-file', - }; - - return ['', $iconClass]; - } - - /** - * Get human-readable label for document type. - */ - private function getDocTypeLabel(string $docType): string { - return match ($docType) { - 'note' => $this->l10n->t('Note'), - 'file' => $this->l10n->t('File'), - 'deck_card' => $this->l10n->t('Deck Card'), - 'calendar', 'calendar_event' => $this->l10n->t('Calendar'), - 'news_item' => $this->l10n->t('News'), - 'contact' => $this->l10n->t('Contact'), - default => $this->l10n->t('Document'), - }; - } - -} diff --git a/third_party/astrolabe/lib/Service/IdpTokenRefresher.php b/third_party/astrolabe/lib/Service/IdpTokenRefresher.php deleted file mode 100644 index 682e105..0000000 --- a/third_party/astrolabe/lib/Service/IdpTokenRefresher.php +++ /dev/null @@ -1,220 +0,0 @@ -config = $config; - $this->httpClient = $clientService->newClient(); - $this->logger = $logger; - $this->mcpServerClient = $mcpServerClient; - } - - /** - * Get Nextcloud base URL for constructing internal OIDC endpoint URLs. - * - * IMPORTANT: This is for INTERNAL server-to-server requests (PHP to local Apache), - * NOT for external client URLs. We must use the internal container URL, not the - * external URL that browsers see. - * - * Configuration priority: - * 1. astrolabe_internal_url - Explicit internal URL (for custom container setups) - * 2. http://localhost - Default for Docker containers (web server on port 80) - * - * NOTE: We intentionally DO NOT use overwrite.cli.url here because: - * - overwrite.cli.url is the EXTERNAL URL (e.g., http://localhost:8080) - * - External URLs are not accessible from inside the container - * - This method is for internal HTTP requests to the local web server - * - * @return string Base URL for internal requests (e.g., "http://localhost") - */ - private function getNextcloudBaseUrl(): string { - // Check for explicit internal URL config (for custom container setups) - $internalUrl = $this->config->getSystemValue('astrolabe_internal_url', ''); - if (!is_string($internalUrl)) { - $internalUrl = ''; - } - if (!empty($internalUrl)) { - // Validate URL format - if (!filter_var($internalUrl, FILTER_VALIDATE_URL)) { - $this->logger->warning('Invalid astrolabe_internal_url format, using default', [ - 'configured_url' => $internalUrl, - ]); - return 'http://localhost'; - } - // Warn if it looks like an external URL (common misconfiguration) - if (preg_match('/:\d{4,5}$/', $internalUrl)) { - $this->logger->warning('astrolabe_internal_url appears to use external port mapping', [ - 'configured_url' => $internalUrl, - 'hint' => 'Internal URLs should use port 80, not mapped ports like :8080', - ]); - } - return rtrim($internalUrl, '/'); - } - - // Default: container environment with web server on localhost:80 - // This works because PHP runs inside the same container as Apache - return 'http://localhost'; - } - - /** - * Refresh access token using refresh token. - * - * Calls IdP's token endpoint directly (NOT MCP server). - * - * @param string $refreshToken The refresh token - * @return array|null New token data or null on failure - */ - public function refreshAccessToken(string $refreshToken): ?array { - // Check if confidential client secret is configured - $clientSecret = $this->config->getSystemValue('astrolabe_client_secret', ''); - - if (empty($clientSecret)) { - $this->logger->warning('Cannot refresh: no client secret configured. Confidential client required for token refresh.'); - return null; - } - - try { - // Get MCP server URL - $mcpServerUrl = $this->config->getSystemValue('mcp_server_url', ''); - if (empty($mcpServerUrl)) { - throw new \Exception('MCP server URL not configured'); - } - - // Query MCP server to discover which IdP it's configured to use - $statusResponse = $this->httpClient->get($mcpServerUrl . '/api/v1/status'); - $statusData = json_decode($statusResponse->getBody(), true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new \RuntimeException('Invalid status response from MCP server'); - } - - // Determine OIDC discovery URL and token endpoint - $useInternalNextcloud = !isset($statusData['oidc']['discovery_url']); - - if (!$useInternalNextcloud) { - // External IdP configured - use OIDC discovery - $discoveryUrl = $statusData['oidc']['discovery_url']; - - $this->logger->debug('IdpTokenRefresher: Using external IdP', [ - 'discovery_url' => $discoveryUrl, - ]); - - $discoveryResponse = $this->httpClient->get($discoveryUrl); - $discovery = json_decode($discoveryResponse->getBody(), true); - - if (json_last_error() !== JSON_ERROR_NONE || !isset($discovery['token_endpoint'])) { - throw new \RuntimeException('Invalid OIDC discovery response'); - } - - $tokenEndpoint = $discovery['token_endpoint']; - } else { - // Nextcloud's OIDC app - use internal URL - $tokenEndpoint = $this->getNextcloudBaseUrl() . '/apps/oidc/token'; - - $this->logger->debug('IdpTokenRefresher: Using Nextcloud OIDC app', [ - 'token_endpoint' => $tokenEndpoint, - ]); - } - - // Call IdP's token endpoint with refresh_token grant - $postData = [ - 'grant_type' => 'refresh_token', - 'refresh_token' => $refreshToken, - 'client_id' => $this->mcpServerClient->getClientId(), - 'client_secret' => $clientSecret, - ]; - - $this->logger->info('IdpTokenRefresher: Requesting token refresh'); - - $response = $this->httpClient->post($tokenEndpoint, [ - 'body' => http_build_query($postData), - 'headers' => [ - 'Content-Type' => 'application/x-www-form-urlencoded', - 'Accept' => 'application/json', - ], - ]); - - $tokenData = json_decode($response->getBody(), true); - - if (json_last_error() !== JSON_ERROR_NONE || !isset($tokenData['access_token'])) { - throw new \RuntimeException('Invalid token response from IdP'); - } - - // Validate refresh_token is present (required for token rotation) - if (!isset($tokenData['refresh_token'])) { - $this->logger->error( - 'IdpTokenRefresher: No refresh token in response - token rotation will fail', - [ - 'has_access_token' => isset($tokenData['access_token']), - 'response_keys' => array_keys($tokenData), - ] - ); - return null; - } - - $this->logger->info('IdpTokenRefresher: Token refresh successful'); - - return $tokenData; - - } catch (\OCP\Http\Client\LocalServerException $e) { - // Network/connection error - may be transient - $this->logger->warning('IdpTokenRefresher: Network error during refresh', [ - 'error' => $e->getMessage(), - ]); - return null; - } catch (\Exception $e) { - $statusCode = null; - if (method_exists($e, 'getCode')) { - $statusCode = $e->getCode(); - } - - // Log with appropriate level based on error type - if ($statusCode === 401 || $statusCode === 403) { - // Auth error - token is invalid, should be deleted - $this->logger->error('IdpTokenRefresher: Auth error - token invalid', [ - 'status_code' => $statusCode, - 'error' => $e->getMessage(), - ]); - } elseif ($statusCode >= 500) { - // Server error - may be transient - $this->logger->warning('IdpTokenRefresher: Server error during refresh', [ - 'status_code' => $statusCode, - 'error' => $e->getMessage(), - ]); - } else { - $this->logger->error('IdpTokenRefresher: Token refresh failed', [ - 'status_code' => $statusCode, - 'error' => $e->getMessage(), - ]); - } - return null; - } - } -} diff --git a/third_party/astrolabe/lib/Service/McpServerClient.php b/third_party/astrolabe/lib/Service/McpServerClient.php deleted file mode 100644 index 73225b8..0000000 --- a/third_party/astrolabe/lib/Service/McpServerClient.php +++ /dev/null @@ -1,666 +0,0 @@ -httpClient = $clientService->newClient(); - $this->config = $config; - $this->logger = $logger; - - // Get MCP server configuration from Nextcloud config - $baseUrl = $this->config->getSystemValue('mcp_server_url', 'http://localhost:8000'); - $this->baseUrl = is_string($baseUrl) ? $baseUrl : 'http://localhost:8000'; - } - - /** - * Get server status (version, auth mode, features). - * - * Public endpoint - no authentication required. - * - * @return array{ - * version?: string, - * auth_mode?: string, - * vector_sync_enabled?: bool, - * uptime_seconds?: int, - * management_api_version?: string, - * error?: string - * } - */ - public function getStatus(): array { - try { - $response = $this->httpClient->get($this->baseUrl . '/api/v1/status'); - $data = json_decode($response->getBody(), true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new \RuntimeException('Invalid JSON response from server'); - } - - return $data; - } catch (\Exception $e) { - $this->logger->error('Failed to get MCP server status', [ - 'error' => $e->getMessage(), - 'server_url' => $this->baseUrl, - ]); - return ['error' => $e->getMessage()]; - } - } - - /** - * Get user session details. - * - * Requires authentication via OAuth bearer token. - * - * @param string $userId The user ID to query - * @param string $token OAuth bearer token - * @return array{ - * session_id?: string, - * background_access_granted?: bool, - * background_access_details?: array, - * idp_profile?: array, - * error?: string - * } - */ - public function getUserSession(string $userId, string $token): array { - try { - $response = $this->httpClient->get( - $this->baseUrl . '/api/v1/users/' . urlencode($userId) . '/session', - [ - 'headers' => [ - 'Authorization' => 'Bearer ' . $token - ] - ] - ); - $data = json_decode($response->getBody(), true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new \RuntimeException('Invalid JSON response from server'); - } - - return $data; - } catch (\Exception $e) { - $this->logger->error("Failed to get session for user $userId", [ - 'error' => $e->getMessage(), - 'user_id' => $userId, - ]); - return ['error' => $e->getMessage()]; - } - } - - /** - * Revoke user's background access (delete refresh token). - * - * Requires authentication via OAuth bearer token. - * - * @param string $userId The user ID whose access to revoke - * @param string $token OAuth bearer token - * @return array{success?: bool, message?: string, error?: string} - */ - public function revokeUserAccess(string $userId, string $token): array { - try { - $response = $this->httpClient->post( - $this->baseUrl . '/api/v1/users/' . urlencode($userId) . '/revoke', - [ - 'headers' => [ - 'Authorization' => 'Bearer ' . $token - ] - ] - ); - $data = json_decode($response->getBody(), true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new \RuntimeException('Invalid JSON response from server'); - } - - return $data; - } catch (\Exception $e) { - $this->logger->error("Failed to revoke access for user $userId", [ - 'error' => $e->getMessage(), - 'user_id' => $userId, - ]); - return ['error' => $e->getMessage()]; - } - } - - /** - * Get vector sync status (indexing metrics). - * - * Public endpoint - no authentication required. - * Only available if VECTOR_SYNC_ENABLED=true on server. - * - * @return array{ - * status?: string, - * indexed_documents?: int, - * pending_documents?: int, - * last_sync_time?: string, - * documents_per_second?: float, - * errors_24h?: int, - * error?: string - * } - */ - public function getVectorSyncStatus(): array { - try { - $response = $this->httpClient->get($this->baseUrl . '/api/v1/vector-sync/status'); - $data = json_decode($response->getBody(), true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new \RuntimeException('Invalid JSON response from server'); - } - - return $data; - } catch (\Exception $e) { - $this->logger->error('Failed to get vector sync status', [ - 'error' => $e->getMessage(), - ]); - return ['error' => $e->getMessage()]; - } - } - - /** - * Execute semantic search for vector visualization. - * - * Requires OAuth bearer token for user-filtered search. - * Only available if VECTOR_SYNC_ENABLED=true on server. - * - * @param string $query Search query string - * @param string $algorithm Search algorithm: "semantic", "bm25", or "hybrid" - * @param int $limit Number of results (max 50) - * @param bool $includePca Whether to include PCA coordinates for 2D plot - * @param array|null $docTypes Document types to filter (e.g., ['note', 'file']) - * @param string|null $token OAuth bearer token for authentication - * @return array{ - * results?: array, - * pca_coordinates?: array, - * algorithm_used?: string, - * total_documents?: int, - * error?: string - * } - */ - public function search( - string $query, - string $algorithm = 'hybrid', - int $limit = 10, - bool $includePca = true, - ?array $docTypes = null, - ?string $token = null, - ): array { - try { - $requestBody = [ - 'query' => $query, - 'algorithm' => $algorithm, - 'limit' => min($limit, 50), // Enforce max limit - 'include_pca' => $includePca, - ]; - - // Add doc_types filter if specified - if ($docTypes !== null && count($docTypes) > 0) { - $requestBody['doc_types'] = $docTypes; - } - - $options = ['json' => $requestBody]; - - // Add authorization header if token provided - if ($token !== null) { - $options['headers'] = [ - 'Authorization' => 'Bearer ' . $token - ]; - } - - $response = $this->httpClient->post( - $this->baseUrl . '/api/v1/vector-viz/search', - $options - ); - $data = json_decode($response->getBody(), true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new \RuntimeException('Invalid JSON response from server'); - } - - return $data; - } catch (\Exception $e) { - $this->logger->error('Failed to execute search', [ - 'error' => $e->getMessage(), - 'query' => $query, - 'algorithm' => $algorithm, - ]); - return ['error' => $e->getMessage()]; - } - } - - /** - * Execute semantic search for Nextcloud Unified Search. - * - * Simplified search method specifically for the unified search provider. - * Uses OAuth bearer token for authentication and user-scoped filtering. - * - * @param string $query Search query string - * @param string $token OAuth bearer token for authentication - * @param int $limit Maximum number of results (default: 20) - * @param int $offset Pagination offset (default: 0) - * @param string $algorithm Search algorithm: hybrid, semantic, or bm25 (default: hybrid) - * @param string $fusion Fusion method for hybrid: rrf or dbsf (default: rrf) - * @param float $scoreThreshold Minimum score threshold 0-1 (default: 0) - * @return array{ - * results?: array, - * total_found?: int, - * algorithm_used?: string, - * error?: string - * } - */ - public function searchForUnifiedSearch( - string $query, - string $token, - int $limit = 20, - int $offset = 0, - string $algorithm = 'hybrid', - string $fusion = 'rrf', - float $scoreThreshold = 0.0, - ): array { - try { - $response = $this->httpClient->post( - $this->baseUrl . '/api/v1/search', - [ - 'headers' => [ - 'Authorization' => 'Bearer ' . $token, - 'Content-Type' => 'application/json', - ], - 'json' => [ - 'query' => $query, - 'algorithm' => $algorithm, - 'fusion' => $fusion, - 'score_threshold' => $scoreThreshold, - 'limit' => min($limit, 100), - 'offset' => $offset, - 'include_pca' => false, - 'include_chunks' => true, - ] - ] - ); - $data = json_decode($response->getBody(), true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new \RuntimeException('Invalid JSON response from server'); - } - - return $data; - } catch (\Exception $e) { - $this->logger->error('Unified search failed', [ - 'error' => $e->getMessage(), - 'query' => $query, - ]); - return ['error' => $e->getMessage()]; - } - } - - /** - * Check if the MCP server is reachable and API key is valid. - * - * @return bool True if server is reachable and healthy - */ - public function isServerReachable(): bool { - $status = $this->getStatus(); - return !isset($status['error']); - } - - /** - * Get the configured MCP server internal URL (for API calls). - * - * @return string The internal base URL - */ - public function getServerUrl(): string { - return $this->baseUrl; - } - - /** - * Get the public MCP server URL (for display, OAuth audience). - * - * Falls back to internal URL if public URL not configured. - * - * @return string The public URL users/browsers see - */ - public function getPublicServerUrl(): string { - return $this->config->getSystemValue('mcp_server_public_url', $this->baseUrl); - } - - /** - * Get the OAuth client ID from system config. - * - * The Astrolabe app has its own OAuth client (separate from MCP server's client). - * Client ID must be configured in config.php for OAuth functionality to work. - * - * @return string OAuth client ID or empty string if not configured - */ - public function getClientId(): string { - $clientId = $this->config->getSystemValue('astrolabe_client_id', ''); - - if (empty($clientId)) { - $this->logger->warning('astrolabe_client_id is not configured in config.php - OAuth functionality will not work'); - return ''; - } - - $this->logger->debug('Using client ID from system config: ' . substr($clientId, 0, 8) . '...'); - return $clientId; - } - - /** - * List all registered webhooks for a user. - * - * Requires OAuth bearer token for authentication. - * - * @param string $token OAuth bearer token - * @return array{ - * webhooks?: array, - * error?: string - * } - */ - public function listWebhooks(string $token): array { - try { - $response = $this->httpClient->get( - $this->baseUrl . '/api/v1/webhooks', - [ - 'headers' => [ - 'Authorization' => 'Bearer ' . $token - ] - ] - ); - $data = json_decode($response->getBody(), true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new \RuntimeException('Invalid JSON response from server'); - } - - return $data; - } catch (\Exception $e) { - $this->logger->error('Failed to list webhooks', [ - 'error' => $e->getMessage(), - ]); - return ['error' => $e->getMessage()]; - } - } - - /** - * Create a new webhook registration. - * - * Requires OAuth bearer token for authentication. - * - * @param string $event Event type (e.g., "\\OCA\\Files::postCreate") - * @param string $uri Callback URI for webhook notifications - * @param array|null $eventFilter Optional event filter parameters - * @param string $token OAuth bearer token - * @return array{ - * id?: int, - * event?: string, - * uri?: string, - * event_filter?: array, - * enabled?: bool, - * error?: string - * } - */ - public function createWebhook( - string $event, - string $uri, - ?array $eventFilter, - string $token, - ): array { - try { - $requestBody = [ - 'event' => $event, - 'uri' => $uri, - ]; - - if ($eventFilter !== null) { - $requestBody['event_filter'] = $eventFilter; - } - - $response = $this->httpClient->post( - $this->baseUrl . '/api/v1/webhooks', - [ - 'headers' => [ - 'Authorization' => 'Bearer ' . $token, - 'Content-Type' => 'application/json', - ], - 'json' => $requestBody - ] - ); - $data = json_decode($response->getBody(), true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new \RuntimeException('Invalid JSON response from server'); - } - - return $data; - } catch (\Exception $e) { - $this->logger->error('Failed to create webhook', [ - 'error' => $e->getMessage(), - 'event' => $event, - ]); - return ['error' => $e->getMessage()]; - } - } - - /** - * Delete a webhook registration. - * - * Requires OAuth bearer token for authentication. - * - * @param int $webhookId Webhook ID to delete - * @param string $token OAuth bearer token - * @return array{success?: bool, error?: string} - */ - public function deleteWebhook(int $webhookId, string $token): array { - try { - $response = $this->httpClient->delete( - $this->baseUrl . '/api/v1/webhooks/' . $webhookId, - [ - 'headers' => [ - 'Authorization' => 'Bearer ' . $token - ] - ] - ); - - // Successful DELETE may return 204 No Content - if ($response->getStatusCode() === 204) { - return ['success' => true]; - } - - $data = json_decode($response->getBody(), true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new \RuntimeException('Invalid JSON response from server'); - } - - return $data; - } catch (\Exception $e) { - $this->logger->error('Failed to delete webhook', [ - 'error' => $e->getMessage(), - 'webhook_id' => $webhookId, - ]); - return ['error' => $e->getMessage()]; - } - } - - /** - * Get list of installed Nextcloud apps. - * - * Used to filter webhook presets based on available apps. - * Requires OAuth bearer token for authentication. - * - * @param string $token OAuth bearer token - * @return array{ - * apps?: array, - * error?: string - * } - */ - public function getInstalledApps(string $token): array { - try { - $response = $this->httpClient->get( - $this->baseUrl . '/api/v1/apps', - [ - 'headers' => [ - 'Authorization' => 'Bearer ' . $token - ] - ] - ); - $data = json_decode($response->getBody(), true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new \RuntimeException('Invalid JSON response from server'); - } - - return $data; - } catch (\Exception $e) { - $this->logger->error('Failed to get installed apps', [ - 'error' => $e->getMessage(), - ]); - return ['error' => $e->getMessage()]; - } - } - - /** - * Get chunk context (text, surrounding context, page image). - * - * Requires OAuth bearer token for authentication. - * - * @param string $docType Document type - * @param string $docId Document ID - * @param int $start Start offset - * @param int $end End offset - * @param string $token OAuth bearer token - * @return array - */ - public function getChunkContext( - string $docType, - string $docId, - int $start, - int $end, - string $token, - ): array { - try { - $response = $this->httpClient->get( - $this->baseUrl . '/api/v1/chunk-context', - [ - 'headers' => [ - 'Authorization' => 'Bearer ' . $token - ], - 'query' => [ - 'doc_type' => $docType, - 'doc_id' => $docId, - 'start' => $start, - 'end' => $end, - 'context' => 500 - ] - ] - ); - $data = json_decode($response->getBody(), true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new \RuntimeException('Invalid JSON response from server'); - } - - return $data; - } catch (\Exception $e) { - $this->logger->error('Failed to get chunk context', [ - 'error' => $e->getMessage(), - 'doc_type' => $docType, - 'doc_id' => $docId, - ]); - return ['error' => $e->getMessage()]; - } - } - - /** - * Get PDF page preview (server-side rendered). - * - * Renders a PDF page to PNG using PyMuPDF on the server. - * This avoids client-side PDF.js issues with CSP and ES private fields. - * - * Requires OAuth bearer token for authentication. - * - * @param string $filePath WebDAV path to PDF file - * @param int $page Page number (1-indexed) - * @param float $scale Zoom factor (default: 2.0) - * @param string $token OAuth bearer token - * @return array{ - * success?: bool, - * image?: string, - * page_number?: int, - * total_pages?: int, - * error?: string - * } - */ - public function getPdfPreview( - string $filePath, - int $page, - float $scale, - string $token, - ): array { - try { - $response = $this->httpClient->get( - $this->baseUrl . '/api/v1/pdf-preview', - [ - 'headers' => [ - 'Authorization' => 'Bearer ' . $token - ], - 'query' => [ - 'file_path' => $filePath, - 'page' => $page, - 'scale' => $scale, - ] - ] - ); - /** @var array{success?: bool, image?: string, page_number?: int, total_pages?: int, error?: string} $data */ - $data = json_decode((string)$response->getBody(), true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new \RuntimeException('Invalid JSON response from server'); - } - - return $data; - } catch (\Exception $e) { - $this->logger->error('Failed to get PDF preview', [ - 'error' => $e->getMessage(), - 'file_path' => $filePath, - 'page' => $page, - ]); - return ['error' => $e->getMessage()]; - } - } -} diff --git a/third_party/astrolabe/lib/Service/McpTokenStorage.php b/third_party/astrolabe/lib/Service/McpTokenStorage.php deleted file mode 100644 index 15d0973..0000000 --- a/third_party/astrolabe/lib/Service/McpTokenStorage.php +++ /dev/null @@ -1,519 +0,0 @@ -config = $config; - $this->crypto = $crypto; - $this->db = $db; - $this->logger = $logger; - $this->lockingProvider = $lockingProvider; - } - - /** - * Store MCP OAuth tokens for a user. - * - * Tokens are encrypted before storage to protect user credentials. - * - * @param string $userId User ID - * @param string $accessToken OAuth access token - * @param string $refreshToken OAuth refresh token - * @param int $expiresAt Unix timestamp when token expires - * @param int|null $issuedAt Unix timestamp when token was issued (for lifetime calculation) - */ - public function storeUserToken( - string $userId, - string $accessToken, - string $refreshToken, - int $expiresAt, - ?int $issuedAt = null, - ): void { - try { - $tokenData = [ - 'access_token' => $accessToken, - 'refresh_token' => $refreshToken, - 'expires_at' => $expiresAt, - 'issued_at' => $issuedAt ?? time(), - ]; - - // Encrypt token data before storage - $encrypted = $this->crypto->encrypt(json_encode($tokenData)); - - // Store in user preferences - $this->config->setUserValue( - $userId, - 'astrolabe', - 'oauth_tokens', - $encrypted - ); - - $this->logger->info("Stored MCP OAuth tokens for user: $userId"); - } catch (\Exception $e) { - $this->logger->error("Failed to store MCP tokens for user $userId", [ - 'error' => $e->getMessage() - ]); - throw $e; - } - } - - /** - * Get MCP OAuth tokens for a user. - * - * @param string $userId User ID - * @return array|null Token data array with keys: access_token, refresh_token, expires_at - */ - public function getUserToken(string $userId): ?array { - try { - $encrypted = $this->config->getUserValue( - $userId, - 'astrolabe', - 'oauth_tokens', - '' - ); - - if (empty($encrypted)) { - return null; - } - - // Decrypt and parse token data - $decrypted = $this->crypto->decrypt($encrypted); - $tokenData = json_decode($decrypted, true); - - if (!$tokenData || !isset($tokenData['access_token'])) { - $this->logger->warning("Invalid token data for user: $userId"); - return null; - } - - return $tokenData; - } catch (\Exception $e) { - $this->logger->error("Failed to retrieve MCP tokens for user $userId", [ - 'error' => $e->getMessage() - ]); - return null; - } - } - - /** - * Check if a token is expired or about to expire. - * - * Uses TOKEN_EXPIRY_BUFFER_SECONDS buffer to refresh tokens before they actually expire. - * - * @param array $token Token data array - * @return bool True if expired or about to expire - */ - public function isExpired(array $token): bool { - if (!isset($token['expires_at'])) { - return true; - } - - // Expire early to avoid race conditions - return time() >= ($token['expires_at'] - self::TOKEN_EXPIRY_BUFFER_SECONDS); - } - - /** - * Get the lock path for a user's token refresh operation. - * - * @param string $userId User ID - * @return string Lock path - */ - private function getTokenRefreshLockPath(string $userId): string { - return 'astrolabe/oauth/tokens/' . $userId; - } - - /** - * Execute callback while holding exclusive lock on user's token. - * - * Prevents race conditions between background job and on-demand token refresh. - * - * Note: Lock TTL is configured at the Nextcloud server level (default: 3600s). - * If a process crashes while holding the lock, it will auto-expire after the TTL. - * The ILockingProvider interface does not support per-call timeouts. - * - * @template T - * @param string $userId User ID - * @param callable(): T $callback - * @return T - * @throws LockedException If lock cannot be acquired - */ - public function withTokenLock(string $userId, callable $callback): mixed { - $lockPath = $this->getTokenRefreshLockPath($userId); - - $this->lockingProvider->acquireLock($lockPath, ILockingProvider::LOCK_EXCLUSIVE); - try { - return $callback(); - } finally { - $this->lockingProvider->releaseLock($lockPath, ILockingProvider::LOCK_EXCLUSIVE); - } - } - - /** - * Delete stored tokens for a user. - * - * Used when user disconnects or revokes access. - * - * @param string $userId User ID - */ - public function deleteUserToken(string $userId): void { - try { - $this->config->deleteUserValue( - $userId, - 'astrolabe', - 'oauth_tokens' - ); - - $this->logger->info("Deleted MCP OAuth tokens for user: $userId"); - } catch (\Exception $e) { - $this->logger->error("Failed to delete MCP tokens for user $userId", [ - 'error' => $e->getMessage() - ]); - throw $e; - } - } - - /** - * Get user IDs that have OAuth tokens stored. - * - * Queries oc_preferences directly since IConfig doesn't support - * listing all users with a specific key set. - * - * @param int $limit Maximum users to return (0 = no limit, for backward compatibility) - * @param int $offset Starting offset for pagination - * @return list Array of user IDs - */ - public function getAllUsersWithTokens(int $limit = 0, int $offset = 0): array { - $qb = $this->db->getQueryBuilder(); - $qb->select('userid') - ->from('preferences') - ->where($qb->expr()->eq('appid', $qb->createNamedParameter('astrolabe'))) - ->andWhere($qb->expr()->eq('configkey', $qb->createNamedParameter('oauth_tokens'))); - - if ($limit > 0) { - $qb->setMaxResults($limit); - } - if ($offset > 0) { - $qb->setFirstResult($offset); - } - - $result = $qb->executeQuery(); - /** @var list $userIds */ - $userIds = []; - /** @psalm-suppress MixedAssignment - IResult::fetch() returns mixed */ - while (($row = $result->fetch()) !== false) { - if (is_array($row) && isset($row['userid']) && is_string($row['userid'])) { - $userIds[] = $row['userid']; - } - } - $result->closeCursor(); - - return $userIds; - } - - /** - * Get the access token for a user, handling expiration and refresh. - * - * This is a convenience method that combines token retrieval, - * expiration checking, and automatic refresh if needed. - * - * Uses double-check locking pattern to prevent race conditions between - * background job and on-demand refresh while minimizing lock contention. - * - * @param string $userId User ID - * @param callable|null $refreshCallback Callback to refresh token if expired - * Should accept (refreshToken) and return new token data - * @return string|null Access token, or null if not available - */ - public function getAccessToken(string $userId, ?callable $refreshCallback = null): ?string { - // Quick check without lock (optimization) - $token = $this->getUserToken($userId); - - if (!$token) { - return null; - } - - // If not expired, return immediately without lock - if (!$this->isExpired($token)) { - return $token['access_token']; - } - - // Token expired - acquire lock for refresh - try { - /** - * @return string|null - * @psalm-suppress MixedInferredReturnType - */ - return $this->withTokenLock($userId, function () use ($userId, $refreshCallback): ?string { - // Re-check after acquiring lock (double-check pattern) - // Another process may have refreshed while we waited for the lock - $currentToken = $this->getUserToken($userId); - - if ($currentToken === null) { - return null; - } - - // Check if another process already refreshed the token - if (!$this->isExpired($currentToken)) { - $this->logger->debug("Token already refreshed for user $userId while waiting for lock"); - /** @var string */ - return $currentToken['access_token']; - } - - // Still expired, perform refresh - if ($refreshCallback && isset($currentToken['refresh_token'])) { - try { - /** @var string $refreshToken */ - $refreshToken = $currentToken['refresh_token']; - $newTokenData = $refreshCallback($refreshToken); - - if ($newTokenData && isset($newTokenData['access_token'])) { - // Store refreshed token - // Use new refresh token if provided (rotation), otherwise keep old one - $now = time(); - /** @var string $accessToken */ - $accessToken = $newTokenData['access_token']; - /** @var string $newRefreshToken */ - $newRefreshToken = $newTokenData['refresh_token'] ?? $refreshToken; - $expiresIn = (int)($newTokenData['expires_in'] ?? 3600); - - $this->storeUserToken( - $userId, - $accessToken, - $newRefreshToken, - $now + $expiresIn, - $now // issued_at for accurate lifetime calculation - ); - - return $accessToken; - } - } catch (\Exception $e) { - $this->logger->error("Failed to refresh token for user $userId", [ - 'error' => $e->getMessage() - ]); - // Delete stale token to prevent repeated refresh attempts - $this->deleteUserToken($userId); - return null; - } - - // Refresh callback returned null or invalid data - delete stale token - $this->deleteUserToken($userId); - $this->logger->info("Deleted stale token for user $userId after refresh failure"); - return null; - } - - // Token expired and no refresh callback available - delete stale token - $this->deleteUserToken($userId); - $this->logger->info("Token expired for user $userId, no refresh available"); - return null; - }); - } catch (LockedException $e) { - // Could not acquire lock - another process is refreshing - // Return stale token rather than failing - caller can retry if needed - $this->logger->warning("Could not acquire token lock for user $userId, returning stale token"); - /** @var string|null $staleToken */ - $staleToken = $token['access_token'] ?? null; - return $staleToken; - } - } - - /** - * Store app password for background sync. - * - * App passwords are encrypted before storage and used as an alternative - * to OAuth refresh tokens for background sync operations. - * - * @param string $userId User ID - * @param string $appPassword Nextcloud app password - */ - public function storeBackgroundSyncPassword( - string $userId, - string $appPassword, - ): void { - try { - // Encrypt app password before storage - $encrypted = $this->crypto->encrypt($appPassword); - - // Store in user preferences - $this->config->setUserValue( - $userId, - 'astrolabe', - 'background_sync_password', - $encrypted - ); - - // Mark credential type - $this->config->setUserValue( - $userId, - 'astrolabe', - 'background_sync_type', - 'app_password' - ); - - // Store provisioned timestamp - $this->config->setUserValue( - $userId, - 'astrolabe', - 'background_sync_provisioned_at', - (string)time() - ); - - $this->logger->info("Stored background sync app password for user: $userId"); - } catch (\Exception $e) { - $this->logger->error("Failed to store app password for user $userId", [ - 'error' => $e->getMessage() - ]); - throw $e; - } - } - - /** - * Get app password for background sync. - * - * @param string $userId User ID - * @return string|null Decrypted app password, or null if not set - */ - public function getBackgroundSyncPassword(string $userId): ?string { - try { - $encrypted = $this->config->getUserValue( - $userId, - 'astrolabe', - 'background_sync_password', - '' - ); - - if (empty($encrypted)) { - return null; - } - - // Decrypt app password - return $this->crypto->decrypt($encrypted); - } catch (\Exception $e) { - $this->logger->error("Failed to retrieve app password for user $userId", [ - 'error' => $e->getMessage() - ]); - return null; - } - } - - /** - * Delete background sync app password for a user. - * - * @param string $userId User ID - */ - public function deleteBackgroundSyncPassword(string $userId): void { - try { - $this->config->deleteUserValue( - $userId, - 'astrolabe', - 'background_sync_password' - ); - - $this->config->deleteUserValue( - $userId, - 'astrolabe', - 'background_sync_type' - ); - - $this->config->deleteUserValue( - $userId, - 'astrolabe', - 'background_sync_provisioned_at' - ); - - $this->logger->info("Deleted background sync app password for user: $userId"); - } catch (\Exception $e) { - $this->logger->error("Failed to delete app password for user $userId", [ - 'error' => $e->getMessage() - ]); - throw $e; - } - } - - /** - * Check if user has provisioned background sync access. - * - * Returns true if either OAuth tokens or app password is configured. - * - * @param string $userId User ID - * @return bool True if background sync is provisioned - */ - public function hasBackgroundSyncAccess(string $userId): bool { - // Check for OAuth tokens - $oauthToken = $this->getUserToken($userId); - if ($oauthToken !== null) { - return true; - } - - // Check for app password - $appPassword = $this->getBackgroundSyncPassword($userId); - return $appPassword !== null; - } - - /** - * Get background sync credential type for a user. - * - * @param string $userId User ID - * @return string|null 'oauth' or 'app_password', or null if not provisioned - */ - public function getBackgroundSyncType(string $userId): ?string { - $type = $this->config->getUserValue( - $userId, - 'astrolabe', - 'background_sync_type', - '' - ); - - // Fallback to OAuth if tokens exist but type not set - if (empty($type) && $this->getUserToken($userId) !== null) { - return 'oauth'; - } - - return empty($type) ? null : $type; - } - - /** - * Get background sync provisioned timestamp for a user. - * - * @param string $userId User ID - * @return int|null Unix timestamp, or null if not provisioned - */ - public function getBackgroundSyncProvisionedAt(string $userId): ?int { - $timestamp = $this->config->getUserValue( - $userId, - 'astrolabe', - 'background_sync_provisioned_at', - '' - ); - - return empty($timestamp) ? null : (int)$timestamp; - } -} diff --git a/third_party/astrolabe/lib/Service/WebhookPresets.php b/third_party/astrolabe/lib/Service/WebhookPresets.php deleted file mode 100644 index f24d089..0000000 --- a/third_party/astrolabe/lib/Service/WebhookPresets.php +++ /dev/null @@ -1,188 +0,0 @@ - - * }> - */ - public static function getPresets(): array { - return [ - 'notes_sync' => [ - 'name' => 'Notes Sync', - 'description' => 'Real-time synchronization for Notes app (create, update, delete)', - 'app' => 'notes', - 'events' => [ - [ - 'event' => self::FILE_EVENT_CREATED, - 'filter' => ['event.node.path' => '/^\\/.*\\/files\\/Notes\\//'], - ], - [ - 'event' => self::FILE_EVENT_WRITTEN, - 'filter' => ['event.node.path' => '/^\\/.*\\/files\\/Notes\\//'], - ], - [ - 'event' => self::FILE_EVENT_DELETED, - 'filter' => ['event.node.path' => '/^\\/.*\\/files\\/Notes\\//'], - ], - ], - ], - 'calendar_sync' => [ - 'name' => 'Calendar Sync', - 'description' => 'Real-time synchronization for Calendar events (create, update, delete)', - 'app' => 'calendar', - 'events' => [ - [ - 'event' => self::CALENDAR_EVENT_CREATED, - 'filter' => [], - ], - [ - 'event' => self::CALENDAR_EVENT_UPDATED, - 'filter' => [], - ], - [ - 'event' => self::CALENDAR_EVENT_DELETED, - 'filter' => [], - ], - ], - ], - 'tables_sync' => [ - 'name' => 'Tables Sync', - 'description' => 'Real-time synchronization for Tables rows (add, update, delete)', - 'app' => 'tables', - 'events' => [ - [ - 'event' => self::TABLES_EVENT_ROW_ADDED, - 'filter' => [], - ], - [ - 'event' => self::TABLES_EVENT_ROW_UPDATED, - 'filter' => [], - ], - [ - 'event' => self::TABLES_EVENT_ROW_DELETED, - 'filter' => [], - ], - ], - ], - 'forms_sync' => [ - 'name' => 'Forms Sync', - 'description' => 'Real-time synchronization for Forms submissions', - 'app' => 'forms', - 'events' => [ - [ - 'event' => self::FORMS_EVENT_FORM_SUBMITTED, - 'filter' => [], - ], - ], - ], - 'files_sync' => [ - 'name' => 'All Files Sync', - 'description' => 'Real-time synchronization for all file operations (create, update, delete)', - 'app' => 'files', - 'events' => [ - [ - 'event' => self::FILE_EVENT_CREATED, - 'filter' => [], - ], - [ - 'event' => self::FILE_EVENT_WRITTEN, - 'filter' => [], - ], - [ - 'event' => self::FILE_EVENT_DELETED, - 'filter' => [], - ], - ], - ], - ]; - } - - /** - * Get a webhook preset by ID. - * - * @param string $presetId Preset identifier (e.g., "notes_sync", "calendar_sync") - * @return array|null Preset configuration or null if not found - */ - public static function getPreset(string $presetId): ?array { - $presets = self::getPresets(); - return $presets[$presetId] ?? null; - } - - /** - * Get list of event class names for a preset. - * - * @param string $presetId Preset identifier - * @return array List of fully qualified event class names - */ - public static function getPresetEvents(string $presetId): array { - $preset = self::getPreset($presetId); - if ($preset === null) { - return []; - } - - return array_map( - fn ($eventConfig) => $eventConfig['event'], - $preset['events'] - ); - } - - /** - * Filter webhook presets to only show those for installed apps. - * - * @param array $installedApps List of installed app names - * @return array Filtered presets - */ - public static function filterPresetsByInstalledApps(array $installedApps): array { - $filtered = []; - foreach (self::getPresets() as $presetId => $preset) { - $appName = $preset['app']; - // "files" is always available (core functionality) - if ($appName === 'files' || in_array($appName, $installedApps)) { - $filtered[$presetId] = $preset; - } - } - return $filtered; - } -} diff --git a/third_party/astrolabe/lib/Settings/Admin.php b/third_party/astrolabe/lib/Settings/Admin.php deleted file mode 100644 index bcda1c6..0000000 --- a/third_party/astrolabe/lib/Settings/Admin.php +++ /dev/null @@ -1,117 +0,0 @@ -client = $client; - $this->config = $config; - $this->initialState = $initialState; - } - - /** - * @return TemplateResponse - */ - public function getForm(): TemplateResponse { - // Get configuration from config.php (local, fast) - $serverUrl = $this->config->getSystemValue('mcp_server_url', ''); - $apiKeyConfigured = !empty($this->config->getSystemValue('mcp_server_api_key', '')); - $clientId = $this->config->getSystemValue('astrolabe_client_id', ''); - $clientIdConfigured = !empty($clientId); - $clientSecret = $this->config->getSystemValue('astrolabe_client_secret', ''); - $clientSecretConfigured = !empty($clientSecret); - - // Load search settings from app config - $searchSettings = [ - 'algorithm' => $this->config->getAppValue( - Application::APP_ID, - self::SETTING_SEARCH_ALGORITHM, - self::DEFAULT_SEARCH_ALGORITHM - ), - 'fusion' => $this->config->getAppValue( - Application::APP_ID, - self::SETTING_SEARCH_FUSION, - self::DEFAULT_SEARCH_FUSION - ), - 'scoreThreshold' => (int)$this->config->getAppValue( - Application::APP_ID, - self::SETTING_SEARCH_SCORE_THRESHOLD, - (string)self::DEFAULT_SEARCH_SCORE_THRESHOLD - ), - 'limit' => (int)$this->config->getAppValue( - Application::APP_ID, - self::SETTING_SEARCH_LIMIT, - (string)self::DEFAULT_SEARCH_LIMIT - ), - ]; - - // Provide initial state for Vue.js frontend - // MCP server data will be fetched asynchronously by Vue component - $this->initialState->provideInitialState('admin-config', [ - 'config' => [ - 'serverUrl' => $serverUrl, - 'apiKeyConfigured' => $apiKeyConfigured, - 'clientIdConfigured' => $clientIdConfigured, - 'clientSecretConfigured' => $clientSecretConfigured, - ], - 'searchSettings' => $searchSettings, - ]); - - $parameters = []; - - return new TemplateResponse( - Application::APP_ID, - 'settings/admin', - $parameters, - TemplateResponse::RENDER_AS_BLANK - ); - } - - /** - * @return string The section ID - */ - public function getSection(): string { - return 'astrolabe'; - } - - /** - * @return int Priority (lower = higher up) - */ - public function getPriority(): int { - return 10; - } -} diff --git a/third_party/astrolabe/lib/Settings/AdminSection.php b/third_party/astrolabe/lib/Settings/AdminSection.php deleted file mode 100644 index 295efee..0000000 --- a/third_party/astrolabe/lib/Settings/AdminSection.php +++ /dev/null @@ -1,52 +0,0 @@ -l = $l; - $this->urlGenerator = $urlGenerator; - } - - /** - * @return string The section ID - */ - public function getID(): string { - return 'astrolabe'; - } - - /** - * @return string The translated section name - */ - public function getName(): string { - return $this->l->t('Astrolabe'); - } - - /** - * @return int Priority (lower = higher up in list) - */ - public function getPriority(): int { - return 80; - } - - /** - * @return string Section icon (SVG or image URL) - */ - public function getIcon(): string { - return $this->urlGenerator->imagePath('astrolabe', 'app-dark.svg'); - } -} diff --git a/third_party/astrolabe/lib/Settings/AstrolabeAdminSettings.php b/third_party/astrolabe/lib/Settings/AstrolabeAdminSettings.php deleted file mode 100644 index f549f5d..0000000 --- a/third_party/astrolabe/lib/Settings/AstrolabeAdminSettings.php +++ /dev/null @@ -1,64 +0,0 @@ - 'astrolabe-admin-settings', - 'priority' => 10, - 'section_type' => DeclarativeSettingsTypes::SECTION_TYPE_ADMIN, - 'section_id' => 'astrolabe', - 'storage_type' => DeclarativeSettingsTypes::STORAGE_TYPE_EXTERNAL, - 'title' => $this->l->t('MCP Server Configuration'), - 'description' => $this->l->t('Configure the connection to your Nextcloud MCP Server'), - 'doc_url' => 'https://github.com/cbcoutinho/nextcloud-mcp-server', - - 'fields' => [ - [ - 'id' => 'mcp_server_url', - 'title' => $this->l->t('MCP Server URL'), - 'description' => $this->l->t('The base URL of your Nextcloud MCP Server instance (e.g., http://localhost:8000)'), - 'type' => DeclarativeSettingsTypes::URL, - 'placeholder' => 'http://localhost:8000', - 'default' => '', - ], - [ - 'id' => 'mcp_server_api_key', - 'title' => $this->l->t('API Key'), - 'description' => $this->l->t('Authentication key for the MCP server (leave empty if not required)'), - 'type' => DeclarativeSettingsTypes::PASSWORD, - 'placeholder' => $this->l->t('Enter API key'), - 'default' => '', - ], - [ - 'id' => 'astrolabe_client_id', - 'title' => $this->l->t('OAuth Client ID'), - 'description' => $this->l->t('The OAuth client ID for Astrolabe (required for multi-user deployments)'), - 'type' => DeclarativeSettingsTypes::TEXT, - 'placeholder' => $this->l->t('Enter OAuth client ID'), - 'default' => '', - ], - [ - 'id' => 'astrolabe_client_secret', - 'title' => $this->l->t('OAuth Client Secret'), - 'description' => $this->l->t('Optional: Client secret for OAuth. If not set, PKCE will be used as fallback.'), - 'type' => DeclarativeSettingsTypes::PASSWORD, - 'placeholder' => $this->l->t('Enter client secret (optional)'), - 'default' => '', - ], - ], - ]; - } -} diff --git a/third_party/astrolabe/lib/Settings/Personal.php b/third_party/astrolabe/lib/Settings/Personal.php deleted file mode 100644 index f6f38fd..0000000 --- a/third_party/astrolabe/lib/Settings/Personal.php +++ /dev/null @@ -1,238 +0,0 @@ -client = $client; - $this->userSession = $userSession; - $this->initialState = $initialState; - $this->tokenStorage = $tokenStorage; - $this->urlGenerator = $urlGenerator; - } - - /** - * @return TemplateResponse - */ - public function getForm(): TemplateResponse { - $user = $this->userSession->getUser(); - if (!$user) { - return new TemplateResponse(Application::APP_ID, 'settings/error', [ - 'error' => 'User not authenticated' - ], TemplateResponse::RENDER_AS_BLANK); - } - - $userId = $user->getUID(); - - // Fetch server status to determine auth mode - $serverStatus = $this->client->getStatus(); - - // Check for server connection error - if (isset($serverStatus['error'])) { - return new TemplateResponse( - Application::APP_ID, - 'settings/error', - [ - 'error' => 'Cannot connect to MCP server', - 'details' => $serverStatus['error'], - 'server_url' => $this->client->getPublicServerUrl(), - ], - TemplateResponse::RENDER_AS_BLANK - ); - } - - // Get auth mode from server (defaults to oauth if not specified) - $authMode = $serverStatus['auth_mode'] ?? 'oauth'; - $supportsAppPasswords = $serverStatus['supports_app_passwords'] ?? false; - - // Check if user has MCP OAuth token - $token = $this->tokenStorage->getUserToken($userId); - - // For multi_user_basic mode with app password support (hybrid mode) - // User needs BOTH: - // 1. OAuth token for Astrolabe→MCP API calls (stored in McpTokenStorage) - // 2. App password for MCP→Nextcloud background sync - if ($authMode === 'multi_user_basic' && $supportsAppPasswords) { - // Check both credentials - $hasOAuthToken = ($token !== null && !$this->tokenStorage->isExpired($token)); - // In hybrid mode, check specifically for app password (not general background access) - // because MCP server needs the app password for background sync - $hasAppPassword = ($this->tokenStorage->getBackgroundSyncPassword($userId) !== null); - $backgroundSyncType = $this->tokenStorage->getBackgroundSyncType($userId); - $backgroundSyncProvisionedAt = $this->tokenStorage->getBackgroundSyncProvisionedAt($userId); - - // OAuth URL for Astrolabe's own OAuth controller (NOT MCP server's browser OAuth) - $oauthUrl = $this->urlGenerator->linkToRoute('astrolabe.oauth.initiateOAuth'); - - // Consolidated template parameters (camelCase convention) - $parameters = [ - 'userId' => $userId, - 'serverUrl' => $this->client->getPublicServerUrl(), - 'serverStatus' => $serverStatus, - 'authMode' => $authMode, - 'supportsAppPasswords' => $supportsAppPasswords, - 'session' => null, // No session in hybrid mode - 'vectorSyncEnabled' => $serverStatus['vector_sync_enabled'] ?? false, - // OAuth token status (for Astrolabe→MCP API calls) - 'hasOAuthToken' => $hasOAuthToken, - 'oauthUrl' => $oauthUrl, - // App password status (for MCP→Nextcloud background sync) - 'hasBackgroundAccess' => $hasAppPassword, - 'backgroundAccessGranted' => $hasAppPassword, // Legacy alias - 'backgroundSyncType' => $backgroundSyncType, - 'backgroundSyncProvisionedAt' => $backgroundSyncProvisionedAt, - 'requesttoken' => \OCP\Util::callRegister(), - ]; - - return new TemplateResponse( - Application::APP_ID, - 'settings/personal', - $parameters, - TemplateResponse::RENDER_AS_BLANK - ); - } - // For OAuth modes, if no token or token is expired, show OAuth authorization UI - elseif (!$token || $this->tokenStorage->isExpired($token)) { - $oauthUrl = $this->urlGenerator->linkToRoute('astrolabe.oauth.initiateOAuth'); - - return new TemplateResponse( - Application::APP_ID, - 'settings/oauth-required', - [ - 'oauth_url' => $oauthUrl, - 'server_url' => $this->client->getPublicServerUrl(), - 'has_expired' => ($token !== null), // true if token exists but expired - ], - TemplateResponse::RENDER_AS_BLANK - ); - } - - // User has valid token - fetch data from MCP server - $accessToken = $token['access_token']; - - // Fetch server status (public endpoint, no token needed) - $serverStatus = $this->client->getStatus(); - - // Fetch user session data (requires token) - $userSession = $this->client->getUserSession($userId, $accessToken); - - // Check for server connection error - if (isset($serverStatus['error'])) { - return new TemplateResponse( - Application::APP_ID, - 'settings/error', - [ - 'error' => 'Cannot connect to MCP server', - 'details' => $serverStatus['error'], - 'server_url' => $this->client->getPublicServerUrl(), - ], - TemplateResponse::RENDER_AS_BLANK - ); - } - - // Check for authentication error (invalid/expired token) - if (isset($userSession['error'])) { - // Token might be invalid - delete it and show OAuth UI - $this->tokenStorage->deleteUserToken($userId); - - $oauthUrl = $this->urlGenerator->linkToRoute('astrolabe.oauth.initiateOAuth'); - - return new TemplateResponse( - Application::APP_ID, - 'settings/oauth-required', - [ - 'oauth_url' => $oauthUrl, - 'server_url' => $this->client->getPublicServerUrl(), - 'has_expired' => true, - 'error_message' => 'Your session has expired. Please sign in again.', - ], - TemplateResponse::RENDER_AS_BLANK - ); - } - - // Check background sync credential status - $hasBackgroundAccess = $this->tokenStorage->hasBackgroundSyncAccess($userId); - $backgroundSyncType = $this->tokenStorage->getBackgroundSyncType($userId); - $backgroundSyncProvisionedAt = $this->tokenStorage->getBackgroundSyncProvisionedAt($userId); - - // OAuth URL for standard OAuth mode (in case user needs to re-authorize) - $oauthUrl = $this->urlGenerator->linkToRoute('astrolabe.oauth.initiateOAuth'); - - // Provide initial state for Vue.js frontend (if needed) - $this->initialState->provideInitialState('user-data', [ - 'userId' => $userId, - 'serverStatus' => $serverStatus, - 'session' => $userSession, - ]); - - // Consolidated template parameters (camelCase convention) - $parameters = [ - 'userId' => $userId, - 'serverUrl' => $this->client->getPublicServerUrl(), - 'serverStatus' => $serverStatus, - 'session' => $userSession, - 'vectorSyncEnabled' => $serverStatus['vector_sync_enabled'] ?? false, - // OAuth status - 'hasOAuthToken' => true, - 'oauthUrl' => $oauthUrl, - // Background sync status - 'hasBackgroundAccess' => $hasBackgroundAccess, - 'backgroundAccessGranted' => $userSession['background_access_granted'] ?? false, // Legacy - 'backgroundSyncType' => $backgroundSyncType, - 'backgroundSyncProvisionedAt' => $backgroundSyncProvisionedAt, - 'requesttoken' => \OCP\Util::callRegister(), - ]; - - return new TemplateResponse( - Application::APP_ID, - 'settings/personal', - $parameters, - TemplateResponse::RENDER_AS_BLANK - ); - } - - /** - * @return string The section ID - */ - public function getSection(): string { - return 'astrolabe'; - } - - /** - * @return int Priority (lower = higher up) - */ - public function getPriority(): int { - return 50; - } -} diff --git a/third_party/astrolabe/lib/Settings/PersonalSection.php b/third_party/astrolabe/lib/Settings/PersonalSection.php deleted file mode 100644 index fd64f21..0000000 --- a/third_party/astrolabe/lib/Settings/PersonalSection.php +++ /dev/null @@ -1,52 +0,0 @@ -l = $l; - $this->urlGenerator = $urlGenerator; - } - - /** - * @return string The section ID - */ - public function getID(): string { - return 'astrolabe'; - } - - /** - * @return string The translated section name - */ - public function getName(): string { - return $this->l->t('Astrolabe'); - } - - /** - * @return int Priority (lower = higher up in list, 0-99) - */ - public function getPriority(): int { - return 80; - } - - /** - * @return string Section icon (SVG or image URL) - */ - public function getIcon(): string { - return $this->urlGenerator->imagePath('astrolabe', 'app-dark.svg'); - } -} diff --git a/third_party/astrolabe/openapi.json b/third_party/astrolabe/openapi.json deleted file mode 100644 index 3f0c242..0000000 --- a/third_party/astrolabe/openapi.json +++ /dev/null @@ -1,149 +0,0 @@ -{ - "openapi": "3.0.3", - "info": { - "title": "astrolabe", - "version": "0.0.1", - "description": "Manage the MCP Server from within Nextcloud UI", - "license": { - "name": "agpl" - } - }, - "components": { - "securitySchemes": { - "basic_auth": { - "type": "http", - "scheme": "basic" - }, - "bearer_auth": { - "type": "http", - "scheme": "bearer" - } - }, - "schemas": { - "OCSMeta": { - "type": "object", - "required": [ - "status", - "statuscode" - ], - "properties": { - "status": { - "type": "string" - }, - "statuscode": { - "type": "integer" - }, - "message": { - "type": "string" - }, - "totalitems": { - "type": "string" - }, - "itemsperpage": { - "type": "string" - } - } - } - } - }, - "paths": { - "/ocs/v2.php/apps/astrolabe/api": { - "get": { - "operationId": "api-index", - "summary": "An example API endpoint", - "tags": [ - "api" - ], - "security": [ - { - "bearer_auth": [] - }, - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "OCS-APIRequest", - "in": "header", - "description": "Required to be true for the API request to pass", - "required": true, - "schema": { - "type": "boolean", - "default": true - } - } - ], - "responses": { - "200": { - "description": "Data returned", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "401": { - "description": "Current user is not logged in", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": {} - } - } - } - } - } - } - } - } - } - } - }, - "tags": [] -} diff --git a/third_party/astrolabe/package-lock.json b/third_party/astrolabe/package-lock.json deleted file mode 100644 index 38482a7..0000000 --- a/third_party/astrolabe/package-lock.json +++ /dev/null @@ -1,10450 +0,0 @@ -{ - "name": "astrolabe", - "version": "0.10.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "astrolabe", - "version": "0.10.0", - "license": "AGPL-3.0-or-later", - "dependencies": { - "@nextcloud/axios": "^2.5.1", - "@nextcloud/dialogs": "^7.2.0", - "@nextcloud/initial-state": "^3.0.0", - "@nextcloud/l10n": "^3.1.0", - "@nextcloud/router": "^3.0.1", - "@nextcloud/vue": "^9.3.3", - "markdown-it": "^14.1.0", - "plotly.js-dist-min": "^3.0.0", - "vue": "^3.0.0", - "vue-material-design-icons": "^5.3.1" - }, - "devDependencies": { - "@nextcloud/browserslist-config": "3.1.2", - "@nextcloud/eslint-config": "8.4.2", - "@nextcloud/stylelint-config": "3.1.1", - "@vitejs/plugin-vue": "^6.0.3", - "sass-embedded": "^1.97.1", - "terser": "5.44.1", - "vite": "7.2.7" - }, - "engines": { - "node": "^22.0.0", - "npm": "^10.5.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.28.5", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.28.5", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5", - "@jridgewell/remapping": "^2.3.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/eslint-parser": { - "version": "7.28.5", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", - "eslint-visitor-keys": "^2.1.0", - "semver": "^6.3.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || >=14.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.11.0", - "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" - } - }, - "node_modules/@babel/generator": { - "version": "7.28.5", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/parser": "^7.28.5", - "@babel/types": "^7.28.5", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/compat-data": "^7.27.2", - "@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-globals": { - "version": "7.28.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.3", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.28.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.28.4", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.28.5", - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.5" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.28.4", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.27.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.28.5", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.5", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.28.5", - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bufbuild/protobuf": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.10.2.tgz", - "integrity": "sha512-uFsRXwIGyu+r6AMdz+XijIIZJYpoWeYzILt5yZ2d3mCjQrWUTVpVD9WL/jZAbvp+Ed04rOhrsk7FiTcEDseB5A==", - "dev": true, - "license": "(Apache-2.0 AND BSD-3-Clause)" - }, - "node_modules/@buttercup/fetch": { - "version": "0.2.1", - "license": "MIT", - "optionalDependencies": { - "node-fetch": "^3.3.0" - } - }, - "node_modules/@cacheable/memory": { - "version": "2.0.6", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@cacheable/utils": "^2.3.2", - "@keyv/bigmap": "^1.3.0", - "hookified": "^1.13.0", - "keyv": "^5.5.4" - } - }, - "node_modules/@cacheable/memory/node_modules/@keyv/bigmap": { - "version": "1.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "hashery": "^1.2.0", - "hookified": "^1.13.0" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "keyv": "^5.5.4" - } - }, - "node_modules/@cacheable/memory/node_modules/keyv": { - "version": "5.5.5", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@keyv/serialize": "^1.1.1" - } - }, - "node_modules/@cacheable/utils": { - "version": "2.3.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "hashery": "^1.2.0", - "keyv": "^5.5.4" - } - }, - "node_modules/@cacheable/utils/node_modules/keyv": { - "version": "5.5.5", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@keyv/serialize": "^1.1.1" - } - }, - "node_modules/@ckpack/vue-color": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@ckpack/vue-color/-/vue-color-1.6.0.tgz", - "integrity": "sha512-b9kFTKhYbNArfgP1lmnaVm0VNsWdZjqIbyHUYry7mZ+E7JeTQclbjq1+2xWn0SE3wzqRYlXmAVjECPOgteWmMQ==", - "license": "MIT", - "dependencies": { - "@ctrl/tinycolor": "^3.6.0", - "material-colors": "^1.2.6" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "vue": "^3.2.0" - } - }, - "node_modules/@csstools/css-parser-algorithms": { - "version": "3.0.5", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-tokenizer": "^3.0.4" - } - }, - "node_modules/@csstools/css-syntax-patches-for-csstree": { - "version": "1.0.21", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@csstools/css-tokenizer": { - "version": "3.0.4", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@csstools/media-query-list-parser": { - "version": "4.0.3", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4" - } - }, - "node_modules/@ctrl/tinycolor": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", - "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/@dual-bundle/import-meta-resolve": { - "version": "4.2.1", - "dev": true, - "license": "MIT", - "peer": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/JounQin" - } - }, - "node_modules/@emnapi/core": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz", - "integrity": "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@emnapi/wasi-threads": "1.1.0", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", - "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", - "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@es-joy/jsdoccomment": { - "version": "0.41.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "comment-parser": "1.4.1", - "esquery": "^1.5.0", - "jsdoc-type-pratt-parser": "~4.0.0" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.12", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.2", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.12", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@file-type/xml": { - "version": "0.4.4", - "license": "MIT", - "dependencies": { - "sax": "^1.4.1", - "strtok3": "^10.3.4" - } - }, - "node_modules/@floating-ui/core": { - "version": "1.7.3", - "license": "MIT", - "dependencies": { - "@floating-ui/utils": "^0.2.10" - } - }, - "node_modules/@floating-ui/dom": { - "version": "1.7.4", - "license": "MIT", - "dependencies": { - "@floating-ui/core": "^1.7.3", - "@floating-ui/utils": "^0.2.10" - } - }, - "node_modules/@floating-ui/utils": { - "version": "0.2.10", - "license": "MIT" - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.12", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "dev": true, - "license": "BSD-3-Clause", - "peer": true - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.11", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@keyv/serialize": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@mdi/js": { - "version": "7.4.47", - "resolved": "https://registry.npmjs.org/@mdi/js/-/js-7.4.47.tgz", - "integrity": "sha512-KPnNOtm5i2pMabqZxpUz7iQf+mfrYZyKCZ8QNz85czgEt7cuHcGorWfdzUMWYA0SD+a6Hn4FmJ+YhzzzjkTZrQ==", - "license": "Apache-2.0" - }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", - "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@tybys/wasm-util": "^0.10.0" - } - }, - "node_modules/@nextcloud/auth": { - "version": "2.5.3", - "license": "GPL-3.0-or-later", - "dependencies": { - "@nextcloud/browser-storage": "^0.5.0", - "@nextcloud/event-bus": "^3.3.2" - }, - "engines": { - "node": "^20.0.0 || ^22.0.0 || ^24.0.0" - } - }, - "node_modules/@nextcloud/axios": { - "version": "2.5.2", - "license": "GPL-3.0-or-later", - "dependencies": { - "@nextcloud/auth": "^2.5.1", - "@nextcloud/router": "^3.0.1", - "axios": "^1.12.2" - }, - "engines": { - "node": "^20.0.0 || ^22.0.0 || ^24.0.0" - } - }, - "node_modules/@nextcloud/browser-storage": { - "version": "0.5.0", - "license": "GPL-3.0-or-later", - "engines": { - "node": "^24 || ^22 || ^20" - } - }, - "node_modules/@nextcloud/browserslist-config": { - "version": "3.1.2", - "dev": true, - "license": "GPL-3.0-or-later", - "engines": { - "node": "^20 || ^22 || ^24", - "npm": ">=10.5.0" - }, - "peerDependencies": { - "browserslist": "^4.26.3" - } - }, - "node_modules/@nextcloud/capabilities": { - "version": "1.2.1", - "license": "GPL-3.0-or-later", - "dependencies": { - "@nextcloud/initial-state": "^3.0.0" - }, - "engines": { - "node": "^20.0.0 || ^22.0.0 || ^24.0.0" - } - }, - "node_modules/@nextcloud/dialogs": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@nextcloud/dialogs/-/dialogs-7.2.0.tgz", - "integrity": "sha512-seb2yYnGsP72t3aeK7WdcgfANpb/AHYc86Fz0kfzM11tvdqbs6Mz4Ja3bxccIJFXoyAp+NYS9UKpxA7bAQPywQ==", - "license": "AGPL-3.0-or-later", - "dependencies": { - "@mdi/js": "^7.4.47", - "@nextcloud/auth": "^2.5.3", - "@nextcloud/axios": "^2.5.2", - "@nextcloud/browser-storage": "^0.5.0", - "@nextcloud/event-bus": "^3.3.3", - "@nextcloud/files": "^3.12.2", - "@nextcloud/initial-state": "^3.0.0", - "@nextcloud/l10n": "^3.4.1", - "@nextcloud/paths": "^3.0.0", - "@nextcloud/router": "^3.1.0", - "@nextcloud/sharing": "^0.3.0", - "@nextcloud/vue": "^9.3.1", - "@types/toastify-js": "^1.12.4", - "@vueuse/core": "^14.1.0", - "cancelable-promise": "^4.3.1", - "p-queue": "^9.0.1", - "toastify-js": "^1.12.0", - "vue": "^3.5.25", - "webdav": "^5.8.0" - }, - "engines": { - "node": "^20 || ^22 || ^24" - } - }, - "node_modules/@nextcloud/eslint-config": { - "version": "8.4.2", - "dev": true, - "license": "AGPL-3.0-or-later", - "engines": { - "node": "^20.0.0", - "npm": "^10.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.26.9", - "@babel/eslint-parser": "^7.16.5", - "@nextcloud/eslint-plugin": "^2.2.1", - "@vue/eslint-config-typescript": "^13.0.0", - "eslint": "^8.27.0", - "eslint-config-standard": "^17.1.0", - "eslint-import-resolver-exports": "^1.0.0-beta.5", - "eslint-import-resolver-typescript": "^3.8.0", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-jsdoc": "^46.2.6", - "eslint-plugin-n": "^16.0.0", - "eslint-plugin-promise": "^6.6.0", - "eslint-plugin-vue": "^9.7.0", - "typescript": "^5.0.2" - } - }, - "node_modules/@nextcloud/eslint-plugin": { - "version": "2.2.1", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "fast-xml-parser": "^4.2.5", - "requireindex": "^1.2.0", - "semver": "^7.5.3" - }, - "engines": { - "node": "^20.0.0", - "npm": "^10.0.0" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/@nextcloud/eslint-plugin/node_modules/semver": { - "version": "7.7.3", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nextcloud/event-bus": { - "version": "3.3.3", - "license": "GPL-3.0-or-later", - "dependencies": { - "@types/semver": "^7.7.0", - "semver": "^7.7.2" - }, - "engines": { - "node": "^20 || ^22 || ^24" - } - }, - "node_modules/@nextcloud/event-bus/node_modules/semver": { - "version": "7.7.3", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nextcloud/files": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-3.12.2.tgz", - "integrity": "sha512-vBo8tf3Xh6efiF8CrEo3pKj9AtvAF6RdDGO1XKL65IxV8+UUd9Uxl2lUExHlzoDRRczCqfGfaWfRRaFhYqce5Q==", - "license": "AGPL-3.0-or-later", - "dependencies": { - "@nextcloud/auth": "^2.5.3", - "@nextcloud/capabilities": "^1.2.1", - "@nextcloud/l10n": "^3.4.1", - "@nextcloud/logger": "^3.0.3", - "@nextcloud/paths": "^3.0.0", - "@nextcloud/router": "^3.1.0", - "@nextcloud/sharing": "^0.3.0", - "cancelable-promise": "^4.3.1", - "is-svg": "^6.1.0", - "typescript-event-target": "^1.1.1", - "webdav": "^5.8.0" - }, - "engines": { - "node": "^20.0.0 || ^22.0.0 || ^24.0.0" - } - }, - "node_modules/@nextcloud/initial-state": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@nextcloud/initial-state/-/initial-state-3.0.0.tgz", - "integrity": "sha512-cV+HBdkQJGm8FxkBI5rFT/FbMNWNBvpbj6OPrg4Ae4YOOsQ15CL8InPOAw1t4XkOkQK2NEdUGQLVUz/19wXbdQ==", - "license": "GPL-3.0-or-later", - "engines": { - "node": "^20.0.0 || ^22.0.0 || ^24.0.0" - } - }, - "node_modules/@nextcloud/l10n": { - "version": "3.4.1", - "license": "GPL-3.0-or-later", - "dependencies": { - "@nextcloud/router": "^3.0.1", - "@nextcloud/typings": "^1.9.1", - "@types/escape-html": "^1.0.4", - "dompurify": "^3.2.6", - "escape-html": "^1.0.3" - }, - "engines": { - "node": "^20 || ^22 || ^24" - } - }, - "node_modules/@nextcloud/logger": { - "version": "3.0.3", - "license": "GPL-3.0-or-later", - "dependencies": { - "@nextcloud/auth": "^2.5.3" - }, - "engines": { - "node": "^20.0.0 || ^22.0.0 || ^24.0.0" - } - }, - "node_modules/@nextcloud/paths": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@nextcloud/paths/-/paths-3.0.0.tgz", - "integrity": "sha512-+sTfTkIbVUa2Ue3bkz3R7F1mhddvHPOWUxkSNg7Q5dAsimVFBaTRgiBAJmsAag3JPsxyuS8kUgeb0zdEssRdTA==", - "license": "GPL-3.0-or-later", - "engines": { - "node": "^20.0.0 || ^22.0.0 || ^24.0.0" - } - }, - "node_modules/@nextcloud/router": { - "version": "3.1.0", - "license": "GPL-3.0-or-later", - "dependencies": { - "@nextcloud/typings": "^1.10.0" - }, - "engines": { - "node": "^20.0.0 || ^22.0.0 || ^24.0.0" - } - }, - "node_modules/@nextcloud/sharing": { - "version": "0.3.0", - "license": "GPL-3.0-or-later", - "dependencies": { - "@nextcloud/initial-state": "^3.0.0", - "is-svg": "^6.1.0" - }, - "engines": { - "node": "^20.0.0 || ^22.0.0 || ^24.0.0" - }, - "optionalDependencies": { - "@nextcloud/files": "^3.12.0" - } - }, - "node_modules/@nextcloud/stylelint-config": { - "version": "3.1.1", - "dev": true, - "license": "AGPL-3.0-or-later", - "dependencies": { - "stylelint-use-logical": "^2.1.2" - }, - "engines": { - "node": "^20 || ^22 || ^24" - }, - "peerDependencies": { - "stylelint": "^16.13.2", - "stylelint-config-recommended-scss": "^15.0.1", - "stylelint-config-recommended-vue": "^1.5.0" - } - }, - "node_modules/@nextcloud/typings": { - "version": "1.10.0", - "license": "GPL-3.0-or-later", - "dependencies": { - "@types/jquery": "3.5.16" - }, - "engines": { - "node": "^20.0.0 || ^22.0.0 || ^24.0.0" - } - }, - "node_modules/@nextcloud/vue": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-9.4.0.tgz", - "integrity": "sha512-MoEbaFqFeZfTB+8d/BtgObAfzJMQ+vdidzMP/zKzx9J4cW+vgY5bciDUueY+t3f0uwSJXO3xsqXXWj9x2KihzQ==", - "license": "AGPL-3.0-or-later", - "dependencies": { - "@ckpack/vue-color": "^1.6.0", - "@floating-ui/dom": "^1.7.4", - "@nextcloud/auth": "^2.5.3", - "@nextcloud/axios": "^2.5.2", - "@nextcloud/browser-storage": "^0.5.0", - "@nextcloud/capabilities": "^1.2.1", - "@nextcloud/event-bus": "^3.3.3", - "@nextcloud/initial-state": "^3.0.0", - "@nextcloud/l10n": "^3.4.1", - "@nextcloud/logger": "^3.0.3", - "@nextcloud/router": "^3.1.0", - "@nextcloud/sharing": "^0.3.0", - "@vuepic/vue-datepicker": "^11.0.3", - "@vueuse/components": "^14.1.0", - "@vueuse/core": "^14.0.0", - "blurhash": "^2.0.5", - "clone": "^2.1.2", - "debounce": "^3.0.0", - "dompurify": "^3.3.1", - "emoji-mart-vue-fast": "^15.0.5", - "escape-html": "^1.0.3", - "floating-vue": "^5.2.2", - "focus-trap": "^7.8.0", - "linkifyjs": "^4.3.2", - "p-queue": "^9.1.0", - "rehype-external-links": "^3.0.0", - "rehype-highlight": "^7.0.2", - "rehype-react": "^8.0.0", - "remark-breaks": "^4.0.0", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.1.2", - "remark-unlink-protocols": "^1.0.0", - "splitpanes": "^4.0.4", - "striptags": "^3.2.0", - "tabbable": "^6.4.0", - "tributejs": "^5.1.3", - "ts-md5": "^2.0.1", - "unified": "^11.0.5", - "unist-builder": "^4.0.0", - "unist-util-visit": "^5.0.0", - "vue": "^3.5.18", - "vue-router": "^4.6.4", - "vue-select": "^4.0.0-beta.6" - }, - "engines": { - "node": "^20.11.0 || ^22 || ^24" - } - }, - "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { - "version": "5.1.1-v1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "eslint-scope": "5.1.1" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "dev": true, - "license": "MIT", - "peer": 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", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nolyfill/is-core-module": { - "version": "1.0.39", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12.4.0" - } - }, - "node_modules/@parcel/watcher": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", - "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "dependencies": { - "detect-libc": "^1.0.3", - "is-glob": "^4.0.3", - "micromatch": "^4.0.5", - "node-addon-api": "^7.0.0" - }, - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "@parcel/watcher-android-arm64": "2.5.1", - "@parcel/watcher-darwin-arm64": "2.5.1", - "@parcel/watcher-darwin-x64": "2.5.1", - "@parcel/watcher-freebsd-x64": "2.5.1", - "@parcel/watcher-linux-arm-glibc": "2.5.1", - "@parcel/watcher-linux-arm-musl": "2.5.1", - "@parcel/watcher-linux-arm64-glibc": "2.5.1", - "@parcel/watcher-linux-arm64-musl": "2.5.1", - "@parcel/watcher-linux-x64-glibc": "2.5.1", - "@parcel/watcher-linux-x64-musl": "2.5.1", - "@parcel/watcher-win32-arm64": "2.5.1", - "@parcel/watcher-win32-ia32": "2.5.1", - "@parcel/watcher-win32-x64": "2.5.1" - } - }, - "node_modules/@parcel/watcher-android-arm64": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", - "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "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.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", - "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "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.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", - "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "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.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", - "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "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.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", - "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "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.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", - "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "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.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", - "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "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.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", - "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "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.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", - "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "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.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", - "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "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.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", - "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "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.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", - "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "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.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", - "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.53", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.53.tgz", - "integrity": "sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", - "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", - "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", - "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", - "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", - "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", - "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", - "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", - "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", - "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", - "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", - "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", - "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", - "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", - "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", - "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.53.3", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.53.3", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", - "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", - "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", - "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", - "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", - "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rtsao/scc": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@tokenizer/token": { - "version": "0.3.0", - "license": "MIT" - }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", - "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@types/debug": { - "version": "4.1.12", - "license": "MIT", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/escape-html": { - "version": "1.0.4", - "license": "MIT" - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "license": "MIT" - }, - "node_modules/@types/estree-jsx": { - "version": "1.0.5", - "license": "MIT", - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/@types/hast": { - "version": "3.0.4", - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/jquery": { - "version": "3.5.16", - "license": "MIT", - "dependencies": { - "@types/sizzle": "*" - } - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@types/mdast": { - "version": "4.0.4", - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/ms": { - "version": "2.1.0", - "license": "MIT" - }, - "node_modules/@types/semver": { - "version": "7.7.1", - "license": "MIT" - }, - "node_modules/@types/sizzle": { - "version": "2.3.10", - "license": "MIT" - }, - "node_modules/@types/toastify-js": { - "version": "1.12.4", - "resolved": "https://registry.npmjs.org/@types/toastify-js/-/toastify-js-1.12.4.tgz", - "integrity": "sha512-zfZHU4tKffPCnZRe7pjv/eFKzTVHozKewFCKaCjZ4gFinKgJRz/t0bkZiMCXJxPhv/ZoeDGNOeRD09R0kQZ/nw==", - "license": "MIT" - }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "license": "MIT", - "optional": true - }, - "node_modules/@types/unist": { - "version": "3.0.3", - "license": "MIT" - }, - "node_modules/@types/web-bluetooth": { - "version": "0.0.21", - "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", - "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", - "license": "MIT" - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.18.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/type-utils": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "7.18.0", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.18.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "7.18.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "7.18.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.18.0", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.7.3", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "7.18.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.18.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "license": "ISC" - }, - "node_modules/@unrs/resolver-binding-android-arm-eabi": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", - "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "peer": true - }, - "node_modules/@unrs/resolver-binding-android-arm64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", - "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "peer": true - }, - "node_modules/@unrs/resolver-binding-darwin-arm64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", - "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "peer": true - }, - "node_modules/@unrs/resolver-binding-darwin-x64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", - "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "peer": true - }, - "node_modules/@unrs/resolver-binding-freebsd-x64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", - "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "peer": true - }, - "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", - "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", - "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", - "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@unrs/resolver-binding-linux-arm64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", - "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", - "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", - "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", - "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", - "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@unrs/resolver-binding-linux-x64-gnu": { - "version": "1.11.1", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@unrs/resolver-binding-linux-x64-musl": { - "version": "1.11.1", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@unrs/resolver-binding-wasm32-wasi": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", - "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.11" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", - "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "peer": true - }, - "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", - "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "peer": true - }, - "node_modules/@unrs/resolver-binding-win32-x64-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", - "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "peer": true - }, - "node_modules/@vitejs/plugin-vue": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.3.tgz", - "integrity": "sha512-TlGPkLFLVOY3T7fZrwdvKpjprR3s4fxRln0ORDo1VQ7HHyxJwTlrjKU3kpVWTlaAjIEuCTokmjkZnr8Tpc925w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rolldown/pluginutils": "1.0.0-beta.53" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "peerDependencies": { - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0", - "vue": "^3.2.25" - } - }, - "node_modules/@vue/compiler-core": { - "version": "3.5.27", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.27.tgz", - "integrity": "sha512-gnSBQjZA+//qDZen+6a2EdHqJ68Z7uybrMf3SPjEGgG4dicklwDVmMC1AeIHxtLVPT7sn6sH1KOO+tS6gwOUeQ==", - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.5", - "@vue/shared": "3.5.27", - "entities": "^7.0.0", - "estree-walker": "^2.0.2", - "source-map-js": "^1.2.1" - } - }, - "node_modules/@vue/compiler-core/node_modules/entities": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", - "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/@vue/compiler-dom": { - "version": "3.5.27", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.27.tgz", - "integrity": "sha512-oAFea8dZgCtVVVTEC7fv3T5CbZW9BxpFzGGxC79xakTr6ooeEqmRuvQydIiDAkglZEAd09LgVf1RoDnL54fu5w==", - "license": "MIT", - "dependencies": { - "@vue/compiler-core": "3.5.27", - "@vue/shared": "3.5.27" - } - }, - "node_modules/@vue/compiler-sfc": { - "version": "3.5.27", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.27.tgz", - "integrity": "sha512-sHZu9QyDPeDmN/MRoshhggVOWE5WlGFStKFwu8G52swATgSny27hJRWteKDSUUzUH+wp+bmeNbhJnEAel/auUQ==", - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.5", - "@vue/compiler-core": "3.5.27", - "@vue/compiler-dom": "3.5.27", - "@vue/compiler-ssr": "3.5.27", - "@vue/shared": "3.5.27", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.21", - "postcss": "^8.5.6", - "source-map-js": "^1.2.1" - } - }, - "node_modules/@vue/compiler-ssr": { - "version": "3.5.27", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.27.tgz", - "integrity": "sha512-Sj7h+JHt512fV1cTxKlYhg7qxBvack+BGncSpH+8vnN+KN95iPIcqB5rsbblX40XorP+ilO7VIKlkuu3Xq2vjw==", - "license": "MIT", - "dependencies": { - "@vue/compiler-dom": "3.5.27", - "@vue/shared": "3.5.27" - } - }, - "node_modules/@vue/devtools-api": { - "version": "6.6.4", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", - "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", - "license": "MIT" - }, - "node_modules/@vue/eslint-config-typescript": { - "version": "13.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@typescript-eslint/eslint-plugin": "^7.1.1", - "@typescript-eslint/parser": "^7.1.1", - "vue-eslint-parser": "^9.3.1" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "peerDependencies": { - "eslint": "^8.56.0", - "eslint-plugin-vue": "^9.0.0", - "typescript": ">=4.7.4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@vue/reactivity": { - "version": "3.5.27", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.27.tgz", - "integrity": "sha512-vvorxn2KXfJ0nBEnj4GYshSgsyMNFnIQah/wczXlsNXt+ijhugmW+PpJ2cNPe4V6jpnBcs0MhCODKllWG+nvoQ==", - "license": "MIT", - "dependencies": { - "@vue/shared": "3.5.27" - } - }, - "node_modules/@vue/runtime-core": { - "version": "3.5.27", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.27.tgz", - "integrity": "sha512-fxVuX/fzgzeMPn/CLQecWeDIFNt3gQVhxM0rW02Tvp/YmZfXQgcTXlakq7IMutuZ/+Ogbn+K0oct9J3JZfyk3A==", - "license": "MIT", - "dependencies": { - "@vue/reactivity": "3.5.27", - "@vue/shared": "3.5.27" - } - }, - "node_modules/@vue/runtime-dom": { - "version": "3.5.27", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.27.tgz", - "integrity": "sha512-/QnLslQgYqSJ5aUmb5F0z0caZPGHRB8LEAQ1s81vHFM5CBfnun63rxhvE/scVb/j3TbBuoZwkJyiLCkBluMpeg==", - "license": "MIT", - "dependencies": { - "@vue/reactivity": "3.5.27", - "@vue/runtime-core": "3.5.27", - "@vue/shared": "3.5.27", - "csstype": "^3.2.3" - } - }, - "node_modules/@vue/server-renderer": { - "version": "3.5.27", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.27.tgz", - "integrity": "sha512-qOz/5thjeP1vAFc4+BY3Nr6wxyLhpeQgAE/8dDtKo6a6xdk+L4W46HDZgNmLOBUDEkFXV3G7pRiUqxjX0/2zWA==", - "license": "MIT", - "dependencies": { - "@vue/compiler-ssr": "3.5.27", - "@vue/shared": "3.5.27" - }, - "peerDependencies": { - "vue": "3.5.27" - } - }, - "node_modules/@vue/shared": { - "version": "3.5.27", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.27.tgz", - "integrity": "sha512-dXr/3CgqXsJkZ0n9F3I4elY8wM9jMJpP3pvRG52r6m0tu/MsAFIe6JpXVGeNMd/D9F4hQynWT8Rfuj0bdm9kFQ==", - "license": "MIT" - }, - "node_modules/@vuepic/vue-datepicker": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@vuepic/vue-datepicker/-/vue-datepicker-11.0.3.tgz", - "integrity": "sha512-sb2adwqwK2PizLQOpxCYps2SwhVT6/ic2HMIOqHJXuYa6iAJZWGL5YVlS7O4aW+sk6ZyxlDURLO7kDZPL4HB/w==", - "license": "MIT", - "dependencies": { - "date-fns": "^4.1.0" - }, - "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "vue": ">=3.3.0" - } - }, - "node_modules/@vueuse/components": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@vueuse/components/-/components-14.1.0.tgz", - "integrity": "sha512-SDRJUAv3H7/PMh+KkYpq0d5KMzpKOfqx4qcV4xyN4mZOLPw8NkiWu+yDcfXwI8h1uCqhRNz2cdeaLa+IuaehFw==", - "license": "MIT", - "dependencies": { - "@vueuse/core": "14.1.0", - "@vueuse/shared": "14.1.0" - }, - "peerDependencies": { - "vue": "^3.5.0" - } - }, - "node_modules/@vueuse/core": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-14.1.0.tgz", - "integrity": "sha512-rgBinKs07hAYyPF834mDTigH7BtPqvZ3Pryuzt1SD/lg5wEcWqvwzXXYGEDb2/cP0Sj5zSvHl3WkmMELr5kfWw==", - "license": "MIT", - "dependencies": { - "@types/web-bluetooth": "^0.0.21", - "@vueuse/metadata": "14.1.0", - "@vueuse/shared": "14.1.0" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "vue": "^3.5.0" - } - }, - "node_modules/@vueuse/metadata": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-14.1.0.tgz", - "integrity": "sha512-7hK4g015rWn2PhKcZ99NyT+ZD9sbwm7SGvp7k+k+rKGWnLjS/oQozoIZzWfCewSUeBmnJkIb+CNr7Zc/EyRnnA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/@vueuse/shared": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-14.1.0.tgz", - "integrity": "sha512-EcKxtYvn6gx1F8z9J5/rsg3+lTQnvOruQd8fUecW99DCK04BkWD7z5KQ/wTAx+DazyoEE9dJt/zV8OIEQbM6kw==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "vue": "^3.5.0" - } - }, - "node_modules/acorn": { - "version": "8.15.0", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "dev": true, - "license": "MIT", - "peer": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/are-docs-informative": { - "version": "0.0.2", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "license": "Python-2.0" - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bound": "^1.0.3", - "is-array-buffer": "^3.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-includes": { - "version": "3.1.9", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.24.0", - "es-object-atoms": "^1.1.1", - "get-intrinsic": "^1.3.0", - "is-string": "^1.1.1", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.6", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-shim-unscopables": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.3", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.3", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/async-function": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "license": "MIT" - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axios": { - "version": "1.13.2", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/bail": { - "version": "2.0.2", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "license": "MIT" - }, - "node_modules/base-64": { - "version": "1.0.0", - "license": "MIT" - }, - "node_modules/baseline-browser-mapping": { - "version": "2.9.7", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, - "node_modules/blurhash": { - "version": "2.0.5", - "license": "MIT" - }, - "node_modules/boolbase": { - "version": "1.0.0", - "dev": true, - "license": "ISC", - "peer": true - }, - "node_modules/brace-expansion": { - "version": "2.0.2", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.28.1", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "peer": true, - "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-builder": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/buffer-builder/-/buffer-builder-0.2.0.tgz", - "integrity": "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==", - "dev": true, - "license": "MIT/X11" - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/builtins": { - "version": "5.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "semver": "^7.0.0" - } - }, - "node_modules/builtins/node_modules/semver": { - "version": "7.7.3", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/byte-length": { - "version": "1.0.2", - "license": "MIT" - }, - "node_modules/cacheable": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@cacheable/memory": "^2.0.6", - "@cacheable/utils": "^2.3.2", - "hookified": "^1.13.0", - "keyv": "^5.5.4", - "qified": "^0.5.2" - } - }, - "node_modules/cacheable/node_modules/keyv": { - "version": "5.5.5", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@keyv/serialize": "^1.1.1" - } - }, - "node_modules/call-bind": { - "version": "1.0.8", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "peer": 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", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cancelable-promise": { - "version": "4.3.1", - "license": "MIT" - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001760", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0", - "peer": true - }, - "node_modules/ccount": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", - "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "peer": 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/character-entities": { - "version": "2.0.2", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-html4": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", - "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-legacy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", - "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-reference-invalid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", - "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/charenc": { - "version": "0.0.2", - "license": "BSD-3-Clause", - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/clone": { - "version": "2.1.2", - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/colord": { - "version": "2.9.3", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/colorjs.io": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.5.2.tgz", - "integrity": "sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==", - "dev": true, - "license": "MIT" - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/commander": { - "version": "2.20.3", - "dev": true, - "license": "MIT" - }, - "node_modules/comment-parser": { - "version": "1.4.1", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/core-js": { - "version": "3.47.0", - "hasInstallScript": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/cosmiconfig": { - "version": "9.0.0", - "dev": true, - "license": "MIT", - "peer": 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", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypt": { - "version": "0.0.2", - "license": "BSD-3-Clause", - "engines": { - "node": "*" - } - }, - "node_modules/css-functions-list": { - "version": "3.2.3", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12 || >=16" - } - }, - "node_modules/css-tree": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "mdn-data": "2.12.2", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "license": "MIT" - }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/data-view-buffer": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-length": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/inspect-js" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/date-fns": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", - "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/kossnocorp" - } - }, - "node_modules/debounce": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-3.0.0.tgz", - "integrity": "sha512-64byRbF0/AirwbuHqB3/ZpMG9/nckDa6ZA0yd6UnaQNwbbemCOwvz2sL5sjXLHhZHADyiwLm0M5qMhltUUx+TA==", - "license": "MIT", - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/debug": { - "version": "4.4.3", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decode-named-character-reference": { - "version": "1.2.0", - "license": "MIT", - "dependencies": { - "character-entities": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/dequal": { - "version": "2.0.3", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "bin": { - "detect-libc": "bin/detect-libc.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/devlop": { - "version": "1.1.0", - "license": "MIT", - "dependencies": { - "dequal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "peer": 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", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause", - "peer": true - }, - "node_modules/domhandler": { - "version": "5.0.3", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/dompurify": { - "version": "3.3.1", - "license": "(MPL-2.0 OR Apache-2.0)", - "optionalDependencies": { - "@types/trusted-types": "^2.0.7" - } - }, - "node_modules/domutils": { - "version": "3.2.2", - "dev": true, - "license": "BSD-2-Clause", - "peer": 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", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.5.267", - "dev": true, - "license": "ISC", - "peer": true - }, - "node_modules/emoji-mart-vue-fast": { - "version": "15.0.5", - "license": "BSD-3-Clause", - "dependencies": { - "@babel/runtime": "^7.18.6", - "core-js": "^3.23.5" - }, - "peerDependencies": { - "vue": ">2.0.0" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/entities": { - "version": "4.5.0", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/error-ex": { - "version": "1.3.4", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.24.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-to-primitive": { - "version": "1.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "is-callable": "^1.2.7", - "is-date-object": "^1.0.5", - "is-symbol": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/esbuild": { - "version": "0.25.12", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "license": "MIT" - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.57.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-compat-utils": { - "version": "0.5.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "semver": "^7.5.4" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "eslint": ">=6.0.0" - } - }, - "node_modules/eslint-compat-utils/node_modules/semver": { - "version": "7.7.3", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-config-standard": { - "version": "17.1.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "eslint": "^8.0.1", - "eslint-plugin-import": "^2.25.2", - "eslint-plugin-n": "^15.0.0 || ^16.0.0 ", - "eslint-plugin-promise": "^6.0.0" - } - }, - "node_modules/eslint-import-resolver-exports": { - "version": "1.0.0-beta.5", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "resolve.exports": "^2.0.0" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-import-resolver-typescript": { - "version": "3.10.1", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "@nolyfill/is-core-module": "1.0.39", - "debug": "^4.4.0", - "get-tsconfig": "^4.10.0", - "is-bun-module": "^2.0.0", - "stable-hash": "^0.0.5", - "tinyglobby": "^0.2.13", - "unrs-resolver": "^1.6.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-import-resolver-typescript" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*", - "eslint-plugin-import-x": "*" - }, - "peerDependenciesMeta": { - "eslint-plugin-import": { - "optional": true - }, - "eslint-plugin-import-x": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils": { - "version": "2.12.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-es-x": { - "version": "7.8.0", - "dev": true, - "funding": [ - "https://github.com/sponsors/ota-meshi", - "https://opencollective.com/eslint" - ], - "license": "MIT", - "peer": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.1.2", - "@eslint-community/regexpp": "^4.11.0", - "eslint-compat-utils": "^0.5.1" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": ">=8" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.32.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.9", - "array.prototype.findlastindex": "^1.2.6", - "array.prototype.flat": "^1.3.3", - "array.prototype.flatmap": "^1.3.3", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.1", - "hasown": "^2.0.2", - "is-core-module": "^2.16.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "object.groupby": "^1.0.3", - "object.values": "^1.2.1", - "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.9", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" - } - }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.12", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-jsdoc": { - "version": "46.10.1", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "@es-joy/jsdoccomment": "~0.41.0", - "are-docs-informative": "^0.0.2", - "comment-parser": "1.4.1", - "debug": "^4.3.4", - "escape-string-regexp": "^4.0.0", - "esquery": "^1.5.0", - "is-builtin-module": "^3.2.1", - "semver": "^7.5.4", - "spdx-expression-parse": "^4.0.0" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" - } - }, - "node_modules/eslint-plugin-jsdoc/node_modules/semver": { - "version": "7.7.3", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-plugin-n": { - "version": "16.6.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "builtins": "^5.0.1", - "eslint-plugin-es-x": "^7.5.0", - "get-tsconfig": "^4.7.0", - "globals": "^13.24.0", - "ignore": "^5.2.4", - "is-builtin-module": "^3.2.1", - "is-core-module": "^2.12.1", - "minimatch": "^3.1.2", - "resolve": "^1.22.2", - "semver": "^7.5.3" - }, - "engines": { - "node": ">=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-n/node_modules/brace-expansion": { - "version": "1.1.12", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-n/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-n/node_modules/semver": { - "version": "7.7.3", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-plugin-promise": { - "version": "6.6.0", - "dev": true, - "license": "ISC", - "peer": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" - } - }, - "node_modules/eslint-plugin-vue": { - "version": "9.33.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "globals": "^13.24.0", - "natural-compare": "^1.4.0", - "nth-check": "^2.1.1", - "postcss-selector-parser": "^6.0.15", - "semver": "^7.6.3", - "vue-eslint-parser": "^9.4.3", - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": "^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" - } - }, - "node_modules/eslint-plugin-vue/node_modules/semver": { - "version": "7.7.3", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.12", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.2", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-util-is-identifier-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", - "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "license": "MIT" - }, - "node_modules/esutils": { - "version": "2.0.3", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "license": "MIT" - }, - "node_modules/extend": { - "version": "3.0.2", - "license": "MIT" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "dev": true, - "license": "MIT", - "peer": 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", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/fast-uri": { - "version": "3.1.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause", - "peer": true - }, - "node_modules/fast-xml-parser": { - "version": "4.5.3", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT", - "dependencies": { - "strnum": "^1.1.1" - }, - "bin": { - "fxparser": "src/cli/cli.js" - } - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 4.9.1" - } - }, - "node_modules/fastq": { - "version": "1.19.1", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fdir": { - "version": "6.5.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.3.3", - "dev": true, - "license": "ISC", - "peer": true - }, - "node_modules/floating-vue": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/floating-vue/-/floating-vue-5.2.2.tgz", - "integrity": "sha512-afW+h2CFafo+7Y9Lvw/xsqjaQlKLdJV7h1fCHfcYQ1C4SVMlu7OAekqWgu5d4SgvkBVU0pVpLlVsrSTBURFRkg==", - "license": "MIT", - "dependencies": { - "@floating-ui/dom": "~1.1.1", - "vue-resize": "^2.0.0-alpha.1" - }, - "peerDependencies": { - "@nuxt/kit": "^3.2.0", - "vue": "^3.2.0" - }, - "peerDependenciesMeta": { - "@nuxt/kit": { - "optional": true - } - } - }, - "node_modules/floating-vue/node_modules/@floating-ui/dom": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.1.1.tgz", - "integrity": "sha512-TpIO93+DIujg3g7SykEAGZMDtbJRrmnYRCNYSjJlvIbGhBjRSNTLVbNeDQBrzy9qDgUbiWdc7KA0uZHZ2tJmiw==", - "license": "MIT", - "dependencies": { - "@floating-ui/core": "^1.1.0" - } - }, - "node_modules/focus-trap": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.8.0.tgz", - "integrity": "sha512-/yNdlIkpWbM0ptxno3ONTuf+2g318kh2ez3KSeZN5dZ8YC6AAmgeWz+GasYYiBJPFaYcSAPeu4GfhUaChzIJXA==", - "license": "MIT", - "dependencies": { - "tabbable": "^6.4.0" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.11", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-each": { - "version": "0.3.5", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/form-data": { - "version": "4.0.5", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "license": "MIT", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "dev": true, - "license": "ISC", - "peer": 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, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.8", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "functions-have-names": "^1.2.3", - "hasown": "^2.0.2", - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "dev": true, - "license": "MIT", - "peer": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/generator-function": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-symbol-description": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-tsconfig": { - "version": "4.13.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.12", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/global-modules": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "global-prefix": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/globals": { - "version": "13.24.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalthis": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globjoin": { - "version": "0.1.4", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/gopd": { - "version": "1.2.0", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graphemer": { - "version": "1.4.0", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/has-bigints": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "dunder-proto": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hashery": { - "version": "1.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "hookified": "^1.13.0" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hast-util-is-element": { - "version": "3.0.0", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-jsx-runtime": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", - "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "hast-util-whitespace": "^3.0.0", - "mdast-util-mdx-expression": "^2.0.0", - "mdast-util-mdx-jsx": "^3.0.0", - "mdast-util-mdxjs-esm": "^2.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0", - "style-to-js": "^1.0.0", - "unist-util-position": "^5.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-text": { - "version": "4.0.2", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "hast-util-is-element": "^3.0.0", - "unist-util-find-after": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-whitespace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", - "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/highlight.js": { - "version": "11.11.1", - "license": "BSD-3-Clause", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/hookified": { - "version": "1.14.0", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/hot-patcher": { - "version": "2.0.1", - "license": "MIT" - }, - "node_modules/html-tags": { - "version": "3.3.1", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/htmlparser2": { - "version": "8.0.2", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" - } - }, - "node_modules/ignore": { - "version": "5.3.2", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 4" - } - }, - "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, - "license": "MIT" - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "dev": true, - "license": "MIT", - "peer": 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", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "dev": true, - "license": "ISC", - "peer": true - }, - "node_modules/ini": { - "version": "1.3.8", - "dev": true, - "license": "ISC", - "peer": true - }, - "node_modules/inline-style-parser": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", - "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", - "license": "MIT" - }, - "node_modules/internal-slot": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-absolute-url": { - "version": "4.0.1", - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-alphabetical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", - "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-alphanumerical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", - "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", - "license": "MIT", - "dependencies": { - "is-alphabetical": "^2.0.0", - "is-decimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.5", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/is-async-function": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "async-function": "^1.0.0", - "call-bound": "^1.0.3", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-bigints": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-boolean-object": { - "version": "1.2.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-buffer": { - "version": "1.1.6", - "license": "MIT" - }, - "node_modules/is-builtin-module": { - "version": "3.2.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "builtin-modules": "^3.3.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-bun-module": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "semver": "^7.7.1" - } - }, - "node_modules/is-bun-module/node_modules/semver": { - "version": "7.7.3", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-view": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-decimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", - "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-function": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bound": "^1.0.4", - "generator-function": "^2.0.0", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-hexadecimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", - "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-map": { - "version": "2.0.3", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "4.1.0", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regex": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "peer": 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-set": { - "version": "2.0.3", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-svg": { - "version": "6.1.0", - "license": "MIT", - "dependencies": { - "@file-type/xml": "^0.4.3" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-symbol": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bound": "^1.0.2", - "has-symbols": "^1.1.0", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.15", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.4", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "dev": true, - "license": "ISC", - "peer": true - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/js-yaml": { - "version": "4.1.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsdoc-type-pratt-parser": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/jsesc": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/json5": { - "version": "2.2.3", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/known-css-properties": { - "version": "0.37.0", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/layerr": { - "version": "3.0.0", - "license": "MIT" - }, - "node_modules/levn": { - "version": "0.4.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/linkify-it": { - "version": "5.0.0", - "license": "MIT", - "dependencies": { - "uc.micro": "^2.0.0" - } - }, - "node_modules/linkifyjs": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.3.2.tgz", - "integrity": "sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==", - "license": "MIT" - }, - "node_modules/locate-path": { - "version": "6.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/longest-streak": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", - "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/lowlight": { - "version": "3.3.0", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "devlop": "^1.0.0", - "highlight.js": "~11.11.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/magic-string": { - "version": "0.30.21", - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/markdown-it": { - "version": "14.1.0", - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", - "mdurl": "^2.0.0", - "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" - }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" - } - }, - "node_modules/material-colors": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz", - "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==", - "license": "ISC" - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/mathml-tag-names": { - "version": "2.1.3", - "dev": true, - "license": "MIT", - "peer": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/md5": { - "version": "2.3.0", - "license": "BSD-3-Clause", - "dependencies": { - "charenc": "0.0.2", - "crypt": "0.0.2", - "is-buffer": "~1.1.6" - } - }, - "node_modules/mdast-squeeze-paragraphs": { - "version": "6.0.0", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "unist-util-visit": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-find-and-replace": { - "version": "3.0.2", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "escape-string-regexp": "^5.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { - "version": "5.0.0", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mdast-util-from-markdown": { - "version": "2.0.2", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-expression": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", - "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-jsx": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", - "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "parse-entities": "^4.0.0", - "stringify-entities": "^4.0.0", - "unist-util-stringify-position": "^4.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdxjs-esm": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", - "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-newline-to-break": { - "version": "2.0.0", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-find-and-replace": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-phrasing": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", - "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-hast": { - "version": "13.2.1", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-markdown": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", - "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-string": { - "version": "4.0.0", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdn-data": { - "version": "2.12.2", - "dev": true, - "license": "CC0-1.0", - "peer": true - }, - "node_modules/mdurl": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/meow": { - "version": "13.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromark": { - "version": "4.0.2", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-core-commonmark": { - "version": "2.0.3", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-destination": "^2.0.0", - "micromark-factory-label": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-title": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-html-tag-name": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-destination": { - "version": "2.0.1", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-label": { - "version": "2.0.1", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-space": { - "version": "2.0.1", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-title": { - "version": "2.0.1", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-whitespace": { - "version": "2.0.1", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-character": { - "version": "2.1.1", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-chunked": { - "version": "2.0.1", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-classify-character": { - "version": "2.0.1", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-combine-extensions": { - "version": "2.0.1", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-chunked": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-numeric-character-reference": { - "version": "2.0.2", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-string": { - "version": "2.0.1", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-encode": { - "version": "2.0.1", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-html-tag-name": { - "version": "2.0.1", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-normalize-identifier": { - "version": "2.0.1", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-resolve-all": { - "version": "2.0.1", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.1", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-subtokenize": { - "version": "2.1.0", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-symbol": { - "version": "2.0.1", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-types": { - "version": "2.0.2", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromatch": { - "version": "4.0.8", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimatch": { - "version": "9.0.5", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "dev": true, - "license": "MIT", - "peer": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.11", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/napi-postinstall": { - "version": "0.3.4", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "napi-postinstall": "lib/cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/napi-postinstall" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/nested-property": { - "version": "4.0.0", - "license": "MIT" - }, - "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, - "license": "MIT", - "optional": true - }, - "node_modules/node-domexception": { - "version": "1.0.0", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", - "engines": { - "node": ">=10.5.0" - } - }, - "node_modules/node-fetch": { - "version": "3.3.2", - "license": "MIT", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, - "node_modules/node-releases": { - "version": "2.0.27", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.7", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0", - "has-symbols": "^1.1.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.values": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/once": { - "version": "1.4.0", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/own-keys": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "get-intrinsic": "^1.2.6", - "object-keys": "^1.1.1", - "safe-push-apply": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-queue": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.1.0.tgz", - "integrity": "sha512-O/ZPaXuQV29uSLbxWBGGZO1mCQXV2BLIwUr59JUU9SoH76mnYvtms7aafH/isNSNGwuEfP6W/4xD0/TJXxrizw==", - "license": "MIT", - "dependencies": { - "eventemitter3": "^5.0.1", - "p-timeout": "^7.0.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-timeout": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-7.0.1.tgz", - "integrity": "sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==", - "license": "MIT", - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-entities": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", - "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^2.0.0", - "character-entities-legacy": "^3.0.0", - "character-reference-invalid": "^2.0.0", - "decode-named-character-reference": "^1.0.0", - "is-alphanumerical": "^2.0.0", - "is-decimal": "^2.0.0", - "is-hexadecimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/parse-entities/node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", - "license": "MIT" - }, - "node_modules/parse-json": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "peer": 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/path-exists": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/path-posix": { - "version": "1.0.0", - "license": "ISC" - }, - "node_modules/path-type": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/plotly.js-dist-min": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/plotly.js-dist-min/-/plotly.js-dist-min-3.3.1.tgz", - "integrity": "sha512-ZxKM9DlEoEF3wBzGRPGHt6gWTJrm5N81J9AgX9UBX/Qjc9L4lRxtPBPq+RmBJWoA71j1X5Z1ouuguLkdoo88tg==", - "license": "MIT" - }, - "node_modules/possible-typed-array-names": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/postcss": { - "version": "8.5.6", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-html": { - "version": "1.8.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "htmlparser2": "^8.0.0", - "js-tokens": "^9.0.0", - "postcss": "^8.5.0", - "postcss-safe-parser": "^6.0.0" - }, - "engines": { - "node": "^12 || >=14" - } - }, - "node_modules/postcss-html/node_modules/js-tokens": { - "version": "9.0.1", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/postcss-media-query-parser": { - "version": "0.2.3", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/postcss-resolve-nested-selector": { - "version": "0.1.6", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/postcss-safe-parser": { - "version": "6.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.3.3" - } - }, - "node_modules/postcss-scss": { - "version": "4.0.9", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss-scss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12.0" - }, - "peerDependencies": { - "postcss": "^8.4.29" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/property-information": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", - "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "license": "MIT" - }, - "node_modules/punycode": { - "version": "2.3.1", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/punycode.js": { - "version": "2.3.1", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/qified": { - "version": "0.5.3", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "hookified": "^1.13.0" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/querystringify": { - "version": "2.2.0", - "license": "MIT" - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "peer": true - }, - "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, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.10", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.1", - "which-builtin-type": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.4", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/rehype-external-links": { - "version": "3.0.0", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@ungap/structured-clone": "^1.0.0", - "hast-util-is-element": "^3.0.0", - "is-absolute-url": "^4.0.0", - "space-separated-tokens": "^2.0.0", - "unist-util-visit": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-highlight": { - "version": "7.0.2", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-to-text": "^4.0.0", - "lowlight": "^3.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-react": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/rehype-react/-/rehype-react-8.0.0.tgz", - "integrity": "sha512-vzo0YxYbB2HE+36+9HWXVdxNoNDubx63r5LBzpxBGVWM8s9mdnMdbmuJBAX6TTyuGdZjZix6qU3GcSuKCIWivw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-to-jsx-runtime": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-breaks": { - "version": "4.0.0", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-newline-to-break": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-parse": { - "version": "11.0.0", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-rehype": { - "version": "11.1.2", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "mdast-util-to-hast": "^13.0.0", - "unified": "^11.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-unlink-protocols": { - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-squeeze-paragraphs": "^6.0.0", - "unist-util-visit": "^5.0.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/requireindex": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.5" - } - }, - "node_modules/requires-port": { - "version": "1.0.0", - "license": "MIT" - }, - "node_modules/resolve": { - "version": "1.22.11", - "dev": true, - "license": "MIT", - "peer": true, - "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", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/resolve.exports": { - "version": "2.0.3", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rollup": { - "version": "4.53.3", - "dev": true, - "license": "MIT", - "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.53.3", - "@rollup/rollup-android-arm64": "4.53.3", - "@rollup/rollup-darwin-arm64": "4.53.3", - "@rollup/rollup-darwin-x64": "4.53.3", - "@rollup/rollup-freebsd-arm64": "4.53.3", - "@rollup/rollup-freebsd-x64": "4.53.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", - "@rollup/rollup-linux-arm-musleabihf": "4.53.3", - "@rollup/rollup-linux-arm64-gnu": "4.53.3", - "@rollup/rollup-linux-arm64-musl": "4.53.3", - "@rollup/rollup-linux-loong64-gnu": "4.53.3", - "@rollup/rollup-linux-ppc64-gnu": "4.53.3", - "@rollup/rollup-linux-riscv64-gnu": "4.53.3", - "@rollup/rollup-linux-riscv64-musl": "4.53.3", - "@rollup/rollup-linux-s390x-gnu": "4.53.3", - "@rollup/rollup-linux-x64-gnu": "4.53.3", - "@rollup/rollup-linux-x64-musl": "4.53.3", - "@rollup/rollup-openharmony-arm64": "4.53.3", - "@rollup/rollup-win32-arm64-msvc": "4.53.3", - "@rollup/rollup-win32-ia32-msvc": "4.53.3", - "@rollup/rollup-win32-x64-gnu": "4.53.3", - "@rollup/rollup-win32-x64-msvc": "4.53.3", - "fsevents": "~2.3.2" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "peer": true, - "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==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/safe-array-concat": { - "version": "1.1.3", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "has-symbols": "^1.1.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-push-apply": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "es-errors": "^1.3.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-regex-test": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "peer": 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/sass": { - "version": "1.97.1", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.97.1.tgz", - "integrity": "sha512-uf6HoO8fy6ClsrShvMgaKUn14f2EHQLQRtpsZZLeU/Mv0Q1K5P0+x2uvH6Cub39TVVbWNSrraUhDAoFph6vh0A==", - "dev": true, - "license": "MIT", - "optional": 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-embedded": { - "version": "1.97.1", - "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.97.1.tgz", - "integrity": "sha512-wH3CbOThHYGX0bUyqFf7laLKyhVWIFc2lHynitkqMIUCtX2ixH9mQh0bN7+hkUu5BFt/SXvEMjFbkEbBMpQiSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@bufbuild/protobuf": "^2.5.0", - "buffer-builder": "^0.2.0", - "colorjs.io": "^0.5.0", - "immutable": "^5.0.2", - "rxjs": "^7.4.0", - "supports-color": "^8.1.1", - "sync-child-process": "^1.0.2", - "varint": "^6.0.0" - }, - "bin": { - "sass": "dist/bin/sass.js" - }, - "engines": { - "node": ">=16.0.0" - }, - "optionalDependencies": { - "sass-embedded-all-unknown": "1.97.1", - "sass-embedded-android-arm": "1.97.1", - "sass-embedded-android-arm64": "1.97.1", - "sass-embedded-android-riscv64": "1.97.1", - "sass-embedded-android-x64": "1.97.1", - "sass-embedded-darwin-arm64": "1.97.1", - "sass-embedded-darwin-x64": "1.97.1", - "sass-embedded-linux-arm": "1.97.1", - "sass-embedded-linux-arm64": "1.97.1", - "sass-embedded-linux-musl-arm": "1.97.1", - "sass-embedded-linux-musl-arm64": "1.97.1", - "sass-embedded-linux-musl-riscv64": "1.97.1", - "sass-embedded-linux-musl-x64": "1.97.1", - "sass-embedded-linux-riscv64": "1.97.1", - "sass-embedded-linux-x64": "1.97.1", - "sass-embedded-unknown-all": "1.97.1", - "sass-embedded-win32-arm64": "1.97.1", - "sass-embedded-win32-x64": "1.97.1" - } - }, - "node_modules/sass-embedded-all-unknown": { - "version": "1.97.1", - "resolved": "https://registry.npmjs.org/sass-embedded-all-unknown/-/sass-embedded-all-unknown-1.97.1.tgz", - "integrity": "sha512-0au5gUNibfob7W/g+ycBx74O22CL8vwHiZdEDY6J0uzMkHPiSJk//h0iRf5AUnMArFHJjFd3urIiQIaoRKYa1Q==", - "cpu": [ - "!arm", - "!arm64", - "!riscv64", - "!x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "sass": "1.97.1" - } - }, - "node_modules/sass-embedded-android-arm": { - "version": "1.97.1", - "resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.97.1.tgz", - "integrity": "sha512-B5dlv4utJ+yC8ZpBeWTHwSZPVKRlqA8pcaD0FAzeNm/DelIFgQUQtt0UwgYoAI6wDIiie5uSVpMK9l2DaCbiBQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-android-arm64": { - "version": "1.97.1", - "resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.97.1.tgz", - "integrity": "sha512-h62DmOiS2Jn87s8+8GhJcMerJnTKa1IsIa9iIKjLiqbAvBDKCGUs027RugZkM+Zx7I+vhPq86PUXBYZ9EkRxdw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-android-riscv64": { - "version": "1.97.1", - "resolved": "https://registry.npmjs.org/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.97.1.tgz", - "integrity": "sha512-tGup88vgaXPnUHEgDMujrt5rfYadvkiVjRb/45FJTx2hQFoGVbmUXz5XqUFjIIbEjQ3kAJqp86A2jy11s43UiQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-android-x64": { - "version": "1.97.1", - "resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.97.1.tgz", - "integrity": "sha512-CAzKjjzu90LZduye2O9+UGX1oScMyF5/RVOa5CxACKALeIS+3XL3LVdV47kwKPoBv5B1aFUvGLscY0CR7jBAbg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-darwin-arm64": { - "version": "1.97.1", - "resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.97.1.tgz", - "integrity": "sha512-tyDzspzh5PbqdAFGtVKUXuf0up6Lff3c1U8J7+4Y7jW6AWRBnq95vTzIIxfnNifGCTI2fW5e7GAZpYygKpNwcw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-darwin-x64": { - "version": "1.97.1", - "resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.97.1.tgz", - "integrity": "sha512-FMrRuSPI2ICt2M2SYaLbiG4yxn86D6ae+XtrRdrrBMhWprAcB7Iyu67bgRzZkipMZNIKKeTR7EUvJHgZzi5ixQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-arm": { - "version": "1.97.1", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.97.1.tgz", - "integrity": "sha512-48VxaTUApLyx1NXFdZhKqI/7FYLmz8Ju3Ki2V/p+mhn5raHgAiYeFgn8O1WGxTOh+hBb9y3FdSR5a8MNTbmKMQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-arm64": { - "version": "1.97.1", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.97.1.tgz", - "integrity": "sha512-im80gfDWRivw9Su3r3YaZmJaCATcJgu3CsCSLodPk1b1R2+X/E12zEQayvrl05EGT9PDwTtuiqKgS4ND4xjwVg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-musl-arm": { - "version": "1.97.1", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.97.1.tgz", - "integrity": "sha512-FUFs466t3PVViVOKY/60JgLLtl61Pf7OW+g5BeEfuqVcSvYUECVHeiYHtX1fT78PEVa0h9tHpM6XpWti+7WYFA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-musl-arm64": { - "version": "1.97.1", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.97.1.tgz", - "integrity": "sha512-kD35WSD9o0279Ptwid3Jnbovo1FYnuG2mayYk9z4ZI4mweXEK6vTu+tlvCE/MdF/zFKSj11qaxaH+uzXe2cO5A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-musl-riscv64": { - "version": "1.97.1", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.97.1.tgz", - "integrity": "sha512-ZgpYps5YHuhA2+KiLkPukRbS5298QObgUhPll/gm5i0LOZleKCwrFELpVPcbhsSBuxqji2uaag5OL+n3JRBVVg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-musl-x64": { - "version": "1.97.1", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.97.1.tgz", - "integrity": "sha512-wcAigOyyvZ6o1zVypWV7QLZqpOEVnlBqJr9MbpnRIm74qFTSbAEmShoh8yMXBymzuVSmEbThxAwW01/TLf62tA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-riscv64": { - "version": "1.97.1", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.97.1.tgz", - "integrity": "sha512-9j1qE1ZrLMuGb+LUmBzw93Z4TNfqlRkkxjPVZy6u5vIggeSfvGbte7eRoYBNWX6SFew/yBCL90KXIirWFSGrlQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-x64": { - "version": "1.97.1", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.97.1.tgz", - "integrity": "sha512-7nrLFYMH/UgvEgXR5JxQJ6y9N4IJmnFnYoDxN0nw0jUp+CQWQL4EJ4RqAKTGelneueRbccvt2sEyPK+X0KJ9Jg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-unknown-all": { - "version": "1.97.1", - "resolved": "https://registry.npmjs.org/sass-embedded-unknown-all/-/sass-embedded-unknown-all-1.97.1.tgz", - "integrity": "sha512-oPSeKc7vS2dx3ZJHiUhHKcyqNq0GWzAiR8zMVpPd/kVMl5ZfVyw+5HTCxxWDBGkX02lNpou27JkeBPCaneYGAQ==", - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "!android", - "!darwin", - "!linux", - "!win32" - ], - "dependencies": { - "sass": "1.97.1" - } - }, - "node_modules/sass-embedded-win32-arm64": { - "version": "1.97.1", - "resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.97.1.tgz", - "integrity": "sha512-L5j7J6CbZgHGwcfVedMVpM3z5MYeighcyZE8GF2DVmjWzZI3JtPKNY11wNTD/P9o1Uql10YPOKhGH0iWIXOT7Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-win32-x64": { - "version": "1.97.1", - "resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.97.1.tgz", - "integrity": "sha512-rfaZAKXU8cW3E7gvdafyD6YtgbEcsDeT99OEiHXRT0UGFuXT8qCOjpAwIKaOA3XXr2d8S42xx6cXcaZ1a+1fgw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded/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, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/sax": { - "version": "1.4.3", - "license": "BlueOak-1.0.0" - }, - "node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-proto": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "dunder-proto": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "peer": 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", - "dev": true, - "license": "MIT", - "peer": 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", - "dev": true, - "license": "MIT", - "peer": 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", - "dev": true, - "license": "MIT", - "peer": 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", - "dev": true, - "license": "ISC", - "peer": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/space-separated-tokens": { - "version": "2.0.2", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "dev": true, - "license": "CC-BY-3.0", - "peer": true - }, - "node_modules/spdx-expression-parse": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.22", - "dev": true, - "license": "CC0-1.0", - "peer": true - }, - "node_modules/splitpanes": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/splitpanes/-/splitpanes-4.0.4.tgz", - "integrity": "sha512-RbysugZhjbCw5fgplvk3hOXr41stahQDtZhHVkhnnJI6H4wlGDhM2kIpbehy7v92duy9GnMa8zIhHigIV1TWtg==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antoniandre" - }, - "peerDependencies": { - "vue": "^3.2.0" - } - }, - "node_modules/stable-hash": { - "version": "0.0.5", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/stop-iteration-iterator": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "es-errors": "^1.3.0", - "internal-slot": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.10", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-data-property": "^1.1.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-object-atoms": "^1.0.0", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.9", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/stringify-entities": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", - "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", - "license": "MIT", - "dependencies": { - "character-entities-html4": "^2.0.0", - "character-entities-legacy": "^3.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/striptags": { - "version": "3.2.0", - "license": "MIT" - }, - "node_modules/strnum": { - "version": "1.1.2", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT" - }, - "node_modules/strtok3": { - "version": "10.3.4", - "license": "MIT", - "dependencies": { - "@tokenizer/token": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/style-to-js": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", - "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", - "license": "MIT", - "dependencies": { - "style-to-object": "1.0.14" - } - }, - "node_modules/style-to-object": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", - "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", - "license": "MIT", - "dependencies": { - "inline-style-parser": "0.2.7" - } - }, - "node_modules/stylelint": { - "version": "16.26.1", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/stylelint" - }, - { - "type": "github", - "url": "https://github.com/sponsors/stylelint" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-syntax-patches-for-csstree": "^1.0.19", - "@csstools/css-tokenizer": "^3.0.4", - "@csstools/media-query-list-parser": "^4.0.3", - "@csstools/selector-specificity": "^5.0.0", - "@dual-bundle/import-meta-resolve": "^4.2.1", - "balanced-match": "^2.0.0", - "colord": "^2.9.3", - "cosmiconfig": "^9.0.0", - "css-functions-list": "^3.2.3", - "css-tree": "^3.1.0", - "debug": "^4.4.3", - "fast-glob": "^3.3.3", - "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^11.1.1", - "global-modules": "^2.0.0", - "globby": "^11.1.0", - "globjoin": "^0.1.4", - "html-tags": "^3.3.1", - "ignore": "^7.0.5", - "imurmurhash": "^0.1.4", - "is-plain-object": "^5.0.0", - "known-css-properties": "^0.37.0", - "mathml-tag-names": "^2.1.3", - "meow": "^13.2.0", - "micromatch": "^4.0.8", - "normalize-path": "^3.0.0", - "picocolors": "^1.1.1", - "postcss": "^8.5.6", - "postcss-resolve-nested-selector": "^0.1.6", - "postcss-safe-parser": "^7.0.1", - "postcss-selector-parser": "^7.1.0", - "postcss-value-parser": "^4.2.0", - "resolve-from": "^5.0.0", - "string-width": "^4.2.3", - "supports-hyperlinks": "^3.2.0", - "svg-tags": "^1.0.0", - "table": "^6.9.0", - "write-file-atomic": "^5.0.1" - }, - "bin": { - "stylelint": "bin/stylelint.mjs" - }, - "engines": { - "node": ">=18.12.0" - } - }, - "node_modules/stylelint-config-html": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": "^12 || >=14" - }, - "funding": { - "url": "https://github.com/sponsors/ota-meshi" - }, - "peerDependencies": { - "postcss-html": "^1.0.0", - "stylelint": ">=14.0.0" - } - }, - "node_modules/stylelint-config-recommended": { - "version": "16.0.0", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/stylelint" - }, - { - "type": "github", - "url": "https://github.com/sponsors/stylelint" - } - ], - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "stylelint": "^16.16.0" - } - }, - "node_modules/stylelint-config-recommended-scss": { - "version": "15.0.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "postcss-scss": "^4.0.9", - "stylelint-config-recommended": "^16.0.0", - "stylelint-scss": "^6.12.0" - }, - "engines": { - "node": ">=20" - }, - "peerDependencies": { - "postcss": "^8.3.3", - "stylelint": "^16.16.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - } - } - }, - "node_modules/stylelint-config-recommended-vue": { - "version": "1.6.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "semver": "^7.3.5", - "stylelint-config-html": ">=1.0.0", - "stylelint-config-recommended": ">=6.0.0" - }, - "engines": { - "node": "^12 || >=14" - }, - "funding": { - "url": "https://github.com/sponsors/ota-meshi" - }, - "peerDependencies": { - "postcss-html": "^1.0.0", - "stylelint": ">=14.0.0" - } - }, - "node_modules/stylelint-config-recommended-vue/node_modules/semver": { - "version": "7.7.3", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stylelint-scss": { - "version": "6.13.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "css-tree": "^3.0.1", - "is-plain-object": "^5.0.0", - "known-css-properties": "^0.37.0", - "mdn-data": "^2.25.0", - "postcss-media-query-parser": "^0.2.3", - "postcss-resolve-nested-selector": "^0.1.6", - "postcss-selector-parser": "^7.1.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "stylelint": "^16.8.2" - } - }, - "node_modules/stylelint-scss/node_modules/mdn-data": { - "version": "2.25.0", - "dev": true, - "license": "CC0-1.0", - "peer": true - }, - "node_modules/stylelint-scss/node_modules/postcss-selector-parser": { - "version": "7.1.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/stylelint-use-logical": { - "version": "2.1.2", - "dev": true, - "license": "CC0-1.0", - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "stylelint": ">= 11 < 17" - } - }, - "node_modules/stylelint/node_modules/@csstools/selector-specificity": { - "version": "5.0.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "peer": true, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "postcss-selector-parser": "^7.0.0" - } - }, - "node_modules/stylelint/node_modules/balanced-match": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/stylelint/node_modules/file-entry-cache": { - "version": "11.1.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "flat-cache": "^6.1.19" - } - }, - "node_modules/stylelint/node_modules/flat-cache": { - "version": "6.1.19", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "cacheable": "^2.2.0", - "flatted": "^3.3.3", - "hookified": "^1.13.0" - } - }, - "node_modules/stylelint/node_modules/ignore": { - "version": "7.0.5", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/stylelint/node_modules/postcss-safe-parser": { - "version": "7.0.1", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/stylelint/node_modules/postcss-selector-parser": { - "version": "7.1.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/stylelint/node_modules/resolve-from": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-hyperlinks": { - "version": "3.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=14.18" - }, - "funding": { - "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/svg-tags": { - "version": "1.0.0", - "dev": true, - "peer": true - }, - "node_modules/sync-child-process": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/sync-child-process/-/sync-child-process-1.0.2.tgz", - "integrity": "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "sync-message-port": "^1.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/sync-message-port": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sync-message-port/-/sync-message-port-1.1.3.tgz", - "integrity": "sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/tabbable": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", - "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", - "license": "MIT" - }, - "node_modules/table": { - "version": "6.9.0", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/table/node_modules/ajv": { - "version": "8.17.1", - "dev": true, - "license": "MIT", - "peer": 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/table/node_modules/json-schema-traverse": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/terser": { - "version": "5.44.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toastify-js": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/toastify-js/-/toastify-js-1.12.0.tgz", - "integrity": "sha512-HeMHCO9yLPvP9k0apGSdPUWrUbLnxUKNFzgUoZp1PHCLploIX/4DSQ7V8H25ef+h4iO9n0he7ImfcndnN6nDrQ==", - "license": "MIT" - }, - "node_modules/tributejs": { - "version": "5.1.3", - "license": "MIT" - }, - "node_modules/trim-lines": { - "version": "3.0.1", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/trough": { - "version": "2.2.0", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/ts-api-utils": { - "version": "1.4.3", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/ts-md5": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ts-md5/-/ts-md5-2.0.1.tgz", - "integrity": "sha512-yF35FCoEOFBzOclSkMNEUbFQZuv89KEQ+5Xz03HrMSGUGB1+r+El+JiGOFwsP4p9RFNzwlrydYoTLvPOuICl9w==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/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==", - "dev": true, - "license": "0BSD" - }, - "node_modules/type-check": { - "version": "0.4.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.15", - "reflect.getprototypeof": "^1.0.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.7", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0", - "reflect.getprototypeof": "^1.0.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "devOptional": true, - "license": "Apache-2.0", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/typescript-event-target": { - "version": "1.1.1", - "license": "MIT" - }, - "node_modules/uc.micro": { - "version": "2.1.0", - "license": "MIT" - }, - "node_modules/unbox-primitive": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bound": "^1.0.3", - "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/unified": { - "version": "11.0.5", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "bail": "^2.0.0", - "devlop": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-builder": { - "version": "4.0.0", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-find-after": { - "version": "5.0.0", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-is": { - "version": "6.0.1", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-position": { - "version": "5.0.0", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit": { - "version": "5.0.0", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents": { - "version": "6.0.2", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unrs-resolver": { - "version": "1.11.1", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "peer": true, - "dependencies": { - "napi-postinstall": "^0.3.0" - }, - "funding": { - "url": "https://opencollective.com/unrs-resolver" - }, - "optionalDependencies": { - "@unrs/resolver-binding-android-arm-eabi": "1.11.1", - "@unrs/resolver-binding-android-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-x64": "1.11.1", - "@unrs/resolver-binding-freebsd-x64": "1.11.1", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", - "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-musl": "1.11.1", - "@unrs/resolver-binding-wasm32-wasi": "1.11.1", - "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", - "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", - "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.2.2", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url-join": { - "version": "5.0.0", - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/url-parse": { - "version": "1.5.10", - "license": "MIT", - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/varint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "dev": true, - "license": "MIT" - }, - "node_modules/vfile": { - "version": "6.0.3", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-message": { - "version": "4.0.3", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vite": { - "version": "7.2.7", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.5.0", - "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", - "tinyglobby": "^0.2.15" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "lightningcss": "^1.21.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "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/vue": { - "version": "3.5.27", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.27.tgz", - "integrity": "sha512-aJ/UtoEyFySPBGarREmN4z6qNKpbEguYHMmXSiOGk69czc+zhs0NF6tEFrY8TZKAl8N/LYAkd4JHVd5E/AsSmw==", - "license": "MIT", - "dependencies": { - "@vue/compiler-dom": "3.5.27", - "@vue/compiler-sfc": "3.5.27", - "@vue/runtime-dom": "3.5.27", - "@vue/server-renderer": "3.5.27", - "@vue/shared": "3.5.27" - }, - "peerDependencies": { - "typescript": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/vue-eslint-parser": { - "version": "9.4.3", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "debug": "^4.3.4", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", - "esquery": "^1.4.0", - "lodash": "^4.17.21", - "semver": "^7.3.6" - }, - "engines": { - "node": "^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=6.0.0" - } - }, - "node_modules/vue-eslint-parser/node_modules/eslint-scope": { - "version": "7.2.2", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/vue-eslint-parser/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/vue-eslint-parser/node_modules/estraverse": { - "version": "5.3.0", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/vue-eslint-parser/node_modules/semver": { - "version": "7.7.3", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/vue-material-design-icons": { - "version": "5.3.1", - "license": "MIT" - }, - "node_modules/vue-resize": { - "version": "2.0.0-alpha.1", - "resolved": "https://registry.npmjs.org/vue-resize/-/vue-resize-2.0.0-alpha.1.tgz", - "integrity": "sha512-7+iqOueLU7uc9NrMfrzbG8hwMqchfVfSzpVlCMeJQe4pyibqyoifDNbKTZvwxZKDvGkB+PdFeKvnGZMoEb8esg==", - "license": "MIT", - "peerDependencies": { - "vue": "^3.0.0" - } - }, - "node_modules/vue-router": { - "version": "4.6.4", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.4.tgz", - "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==", - "license": "MIT", - "dependencies": { - "@vue/devtools-api": "^6.6.4" - }, - "funding": { - "url": "https://github.com/sponsors/posva" - }, - "peerDependencies": { - "vue": "^3.5.0" - } - }, - "node_modules/vue-select": { - "version": "4.0.0-beta.6", - "resolved": "https://registry.npmjs.org/vue-select/-/vue-select-4.0.0-beta.6.tgz", - "integrity": "sha512-K+zrNBSpwMPhAxYLTCl56gaMrWZGgayoWCLqe5rWwkB8aUbAUh7u6sXjIR7v4ckp2WKC7zEEUY27g6h1MRsIHw==", - "license": "MIT", - "peerDependencies": { - "vue": "3.x" - } - }, - "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/webdav": { - "version": "5.8.0", - "license": "MIT", - "dependencies": { - "@buttercup/fetch": "^0.2.1", - "base-64": "^1.0.0", - "byte-length": "^1.0.2", - "entities": "^6.0.0", - "fast-xml-parser": "^4.5.1", - "hot-patcher": "^2.0.1", - "layerr": "^3.0.0", - "md5": "^2.3.0", - "minimatch": "^9.0.5", - "nested-property": "^4.0.0", - "node-fetch": "^3.3.2", - "path-posix": "^1.0.0", - "url-join": "^5.0.0", - "url-parse": "^1.5.10" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/webdav/node_modules/entities": { - "version": "6.0.1", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/which": { - "version": "2.0.2", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "is-bigint": "^1.1.0", - "is-boolean-object": "^1.2.1", - "is-number-object": "^1.1.1", - "is-string": "^1.1.1", - "is-symbol": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "call-bound": "^1.0.2", - "function.prototype.name": "^1.1.6", - "has-tostringtag": "^1.0.2", - "is-async-function": "^2.0.0", - "is-date-object": "^1.1.0", - "is-finalizationregistry": "^1.1.0", - "is-generator-function": "^1.0.10", - "is-regex": "^1.2.1", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.1.0", - "which-collection": "^1.0.2", - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-collection": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.19", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "for-each": "^0.3.5", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "dev": true, - "license": "ISC", - "peer": true - }, - "node_modules/write-file-atomic": { - "version": "5.0.1", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/xml-name-validator": { - "version": "4.0.0", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "dev": true, - "license": "ISC", - "peer": true - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - } - } -} diff --git a/third_party/astrolabe/package.json b/third_party/astrolabe/package.json deleted file mode 100644 index 46ae04b..0000000 --- a/third_party/astrolabe/package.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "name": "astrolabe", - "version": "0.10.1", - "license": "AGPL-3.0-or-later", - "engines": { - "node": "^22.0.0", - "npm": "^10.5.0" - }, - "scripts": { - "build": "vite build", - "dev": "vite --mode development build", - "watch": "vite --mode development build --watch", - "lint": "eslint src", - "stylelint": "stylelint src/**/*.vue src/**/*.scss src/**/*.css" - }, - "type": "module", - "browserslist": [ - "extends @nextcloud/browserslist-config" - ], - "dependencies": { - "@nextcloud/axios": "^2.5.1", - "@nextcloud/dialogs": "^7.2.0", - "@nextcloud/initial-state": "^3.0.0", - "@nextcloud/l10n": "^3.1.0", - "@nextcloud/router": "^3.0.1", - "@nextcloud/vue": "^9.3.3", - "markdown-it": "^14.1.0", - "plotly.js-dist-min": "^3.0.0", - "vue": "^3.0.0", - "vue-material-design-icons": "^5.3.1" - }, - "devDependencies": { - "@nextcloud/browserslist-config": "3.1.2", - "@nextcloud/eslint-config": "8.4.2", - "@nextcloud/stylelint-config": "3.1.1", - "@vitejs/plugin-vue": "^6.0.3", - "sass-embedded": "^1.97.1", - "terser": "5.44.1", - "vite": "7.2.7" - } -} diff --git a/third_party/astrolabe/psalm-baseline.xml b/third_party/astrolabe/psalm-baseline.xml deleted file mode 100644 index b4c0207..0000000 --- a/third_party/astrolabe/psalm-baseline.xml +++ /dev/null @@ -1,488 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - getBody()]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - getBody()]]> - getBody()]]> - - - getBody()]]> - getBody()]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - getBody()]]> - getBody()]]> - getBody()]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - , - * error?: string - * }]]> - - - , - * total_found?: int, - * algorithm_used?: string, - * error?: string - * }]]> - - - - , - * error?: string - * }]]> - - - - - - - - - - - - - - - - - config->getSystemValue('mcp_server_public_url', $this->baseUrl)]]> - - - getBody()]]> - getBody()]]> - getBody()]]> - getBody()]]> - getBody()]]> - getBody()]]> - getBody()]]> - getBody()]]> - getBody()]]> - getBody()]]> - getBody()]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $eventConfig['event']]]> - - - - - - - - - ]]> - $eventConfig['event'], - $preset['events'] - )]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/third_party/astrolabe/psalm.xml b/third_party/astrolabe/psalm.xml deleted file mode 100644 index 920055b..0000000 --- a/third_party/astrolabe/psalm.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - diff --git a/third_party/astrolabe/rector.php b/third_party/astrolabe/rector.php deleted file mode 100644 index 32a7586..0000000 --- a/third_party/astrolabe/rector.php +++ /dev/null @@ -1,30 +0,0 @@ -withPaths([ - __DIR__ . '/lib', - __DIR__ . '/tests', - ]) - ->withPhpSets(php80: true) - ->withPreparedSets( - deadCode: true, - codeQuality: true, - codingStyle: true, - typeDeclarations: true, - privatization: true, - instanceOf: true, - earlyReturn: true, - strictBooleans: true, - carbon: true, - rectorPreset: true, - phpunitCodeQuality: true, - doctrineCodeQuality: true, - symfonyCodeQuality: true, - symfonyConfigs: true, - twig: true, - phpunit: true, - ); diff --git a/third_party/astrolabe/screenshots/01-unified-search-astrolabe.png b/third_party/astrolabe/screenshots/01-unified-search-astrolabe.png deleted file mode 100644 index 8058362..0000000 Binary files a/third_party/astrolabe/screenshots/01-unified-search-astrolabe.png and /dev/null differ diff --git a/third_party/astrolabe/screenshots/02-semantic-search-with-plot.png b/third_party/astrolabe/screenshots/02-semantic-search-with-plot.png deleted file mode 100644 index 3dcd386..0000000 Binary files a/third_party/astrolabe/screenshots/02-semantic-search-with-plot.png and /dev/null differ diff --git a/third_party/astrolabe/screenshots/03-chunk-viewer-open.png b/third_party/astrolabe/screenshots/03-chunk-viewer-open.png deleted file mode 100644 index 6d36e1a..0000000 Binary files a/third_party/astrolabe/screenshots/03-chunk-viewer-open.png and /dev/null differ diff --git a/third_party/astrolabe/src/App.vue b/third_party/astrolabe/src/App.vue deleted file mode 100644 index 6886cd9..0000000 --- a/third_party/astrolabe/src/App.vue +++ /dev/null @@ -1,1432 +0,0 @@ - - - - - - - diff --git a/third_party/astrolabe/src/adminSettings.js b/third_party/astrolabe/src/adminSettings.js deleted file mode 100644 index ab2feed..0000000 --- a/third_party/astrolabe/src/adminSettings.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Admin settings page Vue app for Astrolabe. - * - * Mounts the AdminSettings Vue component for async loading - * and improved UX. - */ - -import { createApp } from 'vue' -import { translate as t, translatePlural as n } from '@nextcloud/l10n' -import AdminSettings from './components/admin/AdminSettings.vue' - -const app = createApp(AdminSettings) - -// Add translation methods globally -app.config.globalProperties.t = t -app.config.globalProperties.n = n - -app.mount('#astrolabe-admin-settings') diff --git a/third_party/astrolabe/src/components/MarkdownViewer.vue b/third_party/astrolabe/src/components/MarkdownViewer.vue deleted file mode 100644 index 3c0b36a..0000000 --- a/third_party/astrolabe/src/components/MarkdownViewer.vue +++ /dev/null @@ -1,172 +0,0 @@ - - - - - diff --git a/third_party/astrolabe/src/components/PDFViewer.vue b/third_party/astrolabe/src/components/PDFViewer.vue deleted file mode 100644 index e4081a1..0000000 --- a/third_party/astrolabe/src/components/PDFViewer.vue +++ /dev/null @@ -1,183 +0,0 @@ - - - - - diff --git a/third_party/astrolabe/src/components/admin/AdminSettings.vue b/third_party/astrolabe/src/components/admin/AdminSettings.vue deleted file mode 100644 index 8c38926..0000000 --- a/third_party/astrolabe/src/components/admin/AdminSettings.vue +++ /dev/null @@ -1,695 +0,0 @@ - - - - - diff --git a/third_party/astrolabe/src/main.js b/third_party/astrolabe/src/main.js deleted file mode 100644 index f28d460..0000000 --- a/third_party/astrolabe/src/main.js +++ /dev/null @@ -1,11 +0,0 @@ -import { createApp } from 'vue' -import { translate as t, translatePlural as n } from '@nextcloud/l10n' -import App from './App.vue' - -const app = createApp(App) - -// Add translation methods globally -app.config.globalProperties.t = t -app.config.globalProperties.n = n - -app.mount('#astrolabe') diff --git a/third_party/astrolabe/src/personalSettings.js b/third_party/astrolabe/src/personalSettings.js deleted file mode 100644 index 12c1427..0000000 --- a/third_party/astrolabe/src/personalSettings.js +++ /dev/null @@ -1,124 +0,0 @@ -/** - * Personal settings page JavaScript for Astrolabe. - * - * Loads styles for the personal settings page and handles form interactions. - */ - -import './styles/settings.css' - -// Wait for DOM to be ready -document.addEventListener('DOMContentLoaded', function() { - // Helper function to show error notifications - function showError(message) { - if (typeof OC !== 'undefined' && OC.Notification) { - OC.Notification.showTemporary(message, { type: 'error' }) - } else { - alert(message) - } - } - - function showSuccess(message) { - if (typeof OC !== 'undefined' && OC.Notification) { - OC.Notification.showTemporary(message, { type: 'success' }) - } else { - alert(message) - } - } - - // App password form with error handling - const appPasswordForm = document.getElementById('mcp-app-password-form') - if (appPasswordForm) { - appPasswordForm.addEventListener('submit', async function(e) { - e.preventDefault() - const submitButton = document.getElementById('mcp-save-app-password-button') - const originalText = submitButton.textContent - - try { - submitButton.disabled = true - submitButton.textContent = t('astrolabe', 'Saving...') - - const formData = new FormData(appPasswordForm) - const response = await fetch(appPasswordForm.action, { - method: 'POST', - body: formData, - }) - - const result = await response.json() - - if (response.ok && result.success) { - showSuccess(t('astrolabe', 'Background sync access successfully provisioned!')) - setTimeout(() => window.location.reload(), 1000) - } else { - showError(result.error || t('astrolabe', 'Failed to save app password. Please check that it is valid.')) - } - } catch (error) { - console.error('App password provisioning error:', error) - showError(t('astrolabe', 'Unable to connect to server. Please check that the MCP server is running and try again.')) - } finally { - submitButton.disabled = false - submitButton.textContent = originalText - } - }) - } - - // Revoke form confirmation - const revokeForm = document.getElementById('mcp-revoke-form') - if (revokeForm) { - revokeForm.addEventListener('submit', function(e) { - if (!confirm(t('astrolabe', 'Are you sure you want to disable indexing? Your content will be removed from semantic search.'))) { - e.preventDefault() - } - }) - } - - // Disconnect form confirmation - const disconnectForm = document.getElementById('mcp-disconnect-form') - if (disconnectForm) { - disconnectForm.addEventListener('submit', function(e) { - if (!confirm(t('astrolabe', 'Are you sure you want to disconnect from Astrolabe? You will need to re-authorize to use semantic search.'))) { - e.preventDefault() - } - }) - } - - // Revoke background access form with error handling - const revokeBackgroundForm = document.getElementById('mcp-revoke-background-form') - if (revokeBackgroundForm) { - revokeBackgroundForm.addEventListener('submit', async function(e) { - e.preventDefault() - - if (!confirm(t('astrolabe', 'Are you sure you want to revoke background sync access? The MCP server will no longer be able to access your Nextcloud data for background operations.'))) { - return - } - - const submitButton = revokeBackgroundForm.querySelector('button[type="submit"]') - const originalText = submitButton.textContent - - try { - submitButton.disabled = true - submitButton.textContent = t('astrolabe', 'Revoking...') - - const formData = new FormData(revokeBackgroundForm) - const response = await fetch(revokeBackgroundForm.action, { - method: 'POST', - body: formData, - }) - - const result = await response.json() - - if (response.ok && result.success) { - showSuccess(t('astrolabe', 'Background sync access revoked successfully.')) - setTimeout(() => window.location.reload(), 1000) - } else { - showError(result.error || t('astrolabe', 'Failed to revoke background sync access.')) - } - } catch (error) { - console.error('Revoke error:', error) - showError(t('astrolabe', 'Unable to connect to server. Your access may already be revoked, or the server may be down.')) - } finally { - submitButton.disabled = false - submitButton.textContent = originalText - } - }) - } -}) diff --git a/third_party/astrolabe/src/styles/settings.css b/third_party/astrolabe/src/styles/settings.css deleted file mode 100644 index 69a2f71..0000000 --- a/third_party/astrolabe/src/styles/settings.css +++ /dev/null @@ -1,290 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - * - * Astrolabe settings styles - * Relies on Nextcloud's core .section class for layout - */ - -/* Info tables */ -.mcp-info-table { - width: 100%; - border-collapse: collapse; - margin: calc(var(--default-grid-baseline) * 3) 0; -} - -.mcp-info-table tr { - border-bottom: 1px solid var(--color-border); -} - -.mcp-info-table tr:last-child { - border-bottom: none; -} - -.mcp-info-table td { - padding: calc(var(--default-grid-baseline) * 2) 0; - vertical-align: top; -} - -.mcp-info-table td:first-child { - width: 200px; - color: var(--color-text-maxcontrast); - font-weight: 600; - padding-inline-end: calc(var(--default-grid-baseline) * 4); -} - -.mcp-info-table td:last-child { - color: var(--color-main-text); -} - -/* Status badges */ -.badge { - display: inline-flex; - align-items: center; - gap: calc(var(--default-grid-baseline) * 1.5); - padding: calc(var(--default-grid-baseline) * 1.5) calc(var(--default-grid-baseline) * 3); - border-radius: calc(var(--border-radius-element) * 1.5); - font-size: 13px; - font-weight: 600; -} - -.badge-success { - background: var(--color-success); - color: var(--color-success-text); -} - -.badge-warning { - background: var(--color-warning); - color: var(--color-warning-text); -} - -.badge-neutral { - background: var(--color-background-dark); - color: var(--color-text-maxcontrast); -} - -.badge-info { - background: var(--color-primary-element); - color: var(--color-primary-element-text); -} - -/* Input groups */ -.mcp-input-group { - display: flex; - gap: calc(var(--default-grid-baseline) * 2); - align-items: stretch; - margin-top: calc(var(--default-grid-baseline) * 2); -} - -.mcp-input-group input[type='password'], -.mcp-input-group input[type='text'] { - flex: 1; - font-family: monospace; -} - -/* Revoke/warning sections */ -.mcp-revoke-section { - margin-top: calc(var(--default-grid-baseline) * 4); - padding: calc(var(--default-grid-baseline) * 4); - background: var(--color-warning); - border-radius: var(--border-radius-element); - border-inline-start: calc(var(--default-grid-baseline)) solid var(--color-warning-text); -} - -/* Feature lists */ -.mcp-feature-list { - list-style: none; - padding: 0; - margin: calc(var(--default-grid-baseline) * 3) 0; -} - -.mcp-feature-list li { - display: flex; - gap: calc(var(--default-grid-baseline) * 3); - padding: calc(var(--default-grid-baseline) * 2) 0; - align-items: start; -} - -.mcp-feature-list .icon { - flex-shrink: 0; - width: 24px; - height: 24px; - opacity: 0.7; -} - -.mcp-feature-list div { - flex: 1; -} - -.mcp-feature-list strong { - display: block; - font-weight: 600; - margin-bottom: calc(var(--default-grid-baseline)); -} - -.mcp-feature-list p { - margin: 0; - color: var(--color-text-maxcontrast); -} - -/* Responsive tables */ -@media (max-width: 768px) { - .mcp-info-table td:first-child, - .mcp-info-table td:last-child { - display: block; - width: 100%; - } - - .mcp-info-table td:first-child { - padding-bottom: calc(var(--default-grid-baseline)); - } - - .mcp-info-table td:last-child { - padding-top: calc(var(--default-grid-baseline)); - } -} - -/* Admin settings forms */ -.mcp-settings-form { - max-width: 600px; -} - -.mcp-form-group { - margin-bottom: calc(var(--default-grid-baseline) * 5); -} - -.mcp-form-group label { - display: block; - font-weight: 600; - margin-bottom: calc(var(--default-grid-baseline) * 2); -} - -.mcp-range { - width: 100%; - margin-top: calc(var(--default-grid-baseline) * 2); - accent-color: var(--color-primary-element); -} - -.mcp-form-actions { - display: flex; - align-items: center; - gap: calc(var(--default-grid-baseline) * 4); - margin-top: calc(var(--default-grid-baseline) * 6); - padding-top: calc(var(--default-grid-baseline) * 5); - border-top: 1px solid var(--color-border); -} - -/* Webhook preset cards */ -.mcp-preset-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); - gap: calc(var(--default-grid-baseline) * 4); - margin: calc(var(--default-grid-baseline) * 4) 0; -} - -.mcp-preset-card { - background: var(--color-background-dark); - border-radius: var(--border-radius-container); - padding: calc(var(--default-grid-baseline) * 4); - border: 2px solid transparent; - transition: border-color var(--animation-slow), box-shadow var(--animation-slow); -} - -.mcp-preset-card:hover { - border-color: var(--color-border-dark); - box-shadow: 0 2px 8px var(--color-box-shadow); -} - -.mcp-preset-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: calc(var(--default-grid-baseline) * 3); -} - -.mcp-preset-header h4 { - margin: 0; - font-weight: 600; -} - -.mcp-preset-status { - padding: calc(var(--default-grid-baseline)) calc(var(--default-grid-baseline) * 2.5); - border-radius: calc(var(--border-radius-element) * 1.5); - font-size: 11px; - font-weight: 600; - text-transform: uppercase; -} - -.mcp-status-enabled { - background: var(--color-success); - color: var(--color-success-text); -} - -.mcp-status-disabled { - background: var(--color-background-darker); - color: var(--color-text-maxcontrast); -} - -.mcp-preset-description { - color: var(--color-text-maxcontrast); - margin-bottom: calc(var(--default-grid-baseline) * 3); -} - -.mcp-preset-meta { - display: flex; - justify-content: space-between; - align-items: center; - padding-top: calc(var(--default-grid-baseline) * 3); - border-top: 1px solid var(--color-border); - margin-bottom: calc(var(--default-grid-baseline) * 3); - font-size: 12px; - color: var(--color-text-maxcontrast); -} - -.mcp-preset-actions { - display: flex; - gap: calc(var(--default-grid-baseline) * 2); -} - -.mcp-preset-toggle { - flex: 1; - padding: calc(var(--default-grid-baseline) * 2) calc(var(--default-grid-baseline) * 4); - border-radius: var(--border-radius-element); - font-size: 13px; - font-weight: 600; - cursor: pointer; - transition: all var(--animation-quick); - border: none; -} - -.mcp-preset-toggle.primary { - background: var(--color-primary-element); - color: var(--color-primary-element-text); -} - -.mcp-preset-toggle.primary:hover:not(:disabled) { - background: var(--color-primary-element-hover); -} - -.mcp-preset-toggle.secondary { - background: var(--color-background-darker); - color: var(--color-main-text); - border: 1px solid var(--color-border); -} - -.mcp-preset-toggle.secondary:hover:not(:disabled) { - background: var(--color-background-hover); - border-color: var(--color-border-dark); -} - -.mcp-preset-toggle:disabled { - opacity: 0.6; - cursor: not-allowed; -} - -.mcp-loading { - text-align: center; - padding: calc(var(--default-grid-baseline) * 5); - color: var(--color-text-maxcontrast); - font-style: italic; -} diff --git a/third_party/astrolabe/stylelint.config.cjs b/third_party/astrolabe/stylelint.config.cjs deleted file mode 100644 index ff8f902..0000000 --- a/third_party/astrolabe/stylelint.config.cjs +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extends: '@nextcloud/stylelint-config', -} diff --git a/third_party/astrolabe/templates/index.php b/third_party/astrolabe/templates/index.php deleted file mode 100644 index 8059c60..0000000 --- a/third_party/astrolabe/templates/index.php +++ /dev/null @@ -1,13 +0,0 @@ - - -
diff --git a/third_party/astrolabe/templates/settings/admin.php b/third_party/astrolabe/templates/settings/admin.php deleted file mode 100644 index cbe1e79..0000000 --- a/third_party/astrolabe/templates/settings/admin.php +++ /dev/null @@ -1,15 +0,0 @@ - - -
- -
diff --git a/third_party/astrolabe/templates/settings/error.php b/third_party/astrolabe/templates/settings/error.php deleted file mode 100644 index 6f31e49..0000000 --- a/third_party/astrolabe/templates/settings/error.php +++ /dev/null @@ -1,51 +0,0 @@ - - -
-
-

- - -

- - -

t('Details:')); ?>

-

- - - -

t('Server URL:')); ?>

-

- - - -

- - -

t('Troubleshooting Steps:')); ?>

-
    -
  1. t('Verify the MCP server is running and accessible')); ?>
  2. -
  3. t('Check that mcp_server_url in config.php is correct')); ?>
  4. -
  5. t('Ensure mcp_server_api_key matches the server configuration')); ?>
  6. -
  7. t('Check firewall rules and network connectivity')); ?>
  8. -
  9. t('Review MCP server logs for errors')); ?>
  10. -
- -

- - t('View Documentation')); ?> - -

-
-
diff --git a/third_party/astrolabe/templates/settings/oauth-required.php b/third_party/astrolabe/templates/settings/oauth-required.php deleted file mode 100644 index 0443d50..0000000 --- a/third_party/astrolabe/templates/settings/oauth-required.php +++ /dev/null @@ -1,117 +0,0 @@ - - -
-

t('Astrolabe')); ?>

-

t('AI-powered semantic search across your Nextcloud content.')); ?>

-
- - -
-

t('Session Expired')); ?>

-

-
- - -
-

t('Enable Semantic Search')); ?>

- - -

- t('Your authorization has expired. Please sign in again to continue using semantic search.')); ?> -

- -

- t('To search your content by meaning, Astrolabe needs permission to index your Nextcloud data.')); ?> -

- - -

- t('What happens next?')); ?> -

- -
    -
  1. t('Sign in to confirm your identity')); ?>
  2. -
  3. t('Grant permission to index your content')); ?>
  4. -
  5. t('Your content will be indexed for semantic search')); ?>
  6. -
  7. t('Start searching with natural language')); ?>
  8. -
- -

t('Content to be Indexed')); ?>

- -
    -
  • - -
    - t('Notes & Files')); ?> -

    t('Your notes and documents will be searchable by meaning')); ?>

    -
    -
  • -
  • - -
    - t('Calendar & Tasks')); ?> -

    t('Find events and tasks with natural language queries')); ?>

    -
    -
  • -
  • - -
    - t('Deck Cards')); ?> -

    t('Search across your Deck boards and cards')); ?>

    -
    -
  • -
- - - -

- t('You can disable indexing at any time from this settings page.')); ?> -

-
- -
-

t('About Astrolabe')); ?>

- -

- t('Astrolabe enables semantic search - finding content by meaning rather than exact keywords. Ask questions like "meeting notes from last week" or "recipes with chicken" to find relevant documents.')); ?> -

- -

- t('Your content is processed to understand its meaning, enabling powerful natural language search across all your Nextcloud data.')); ?> -

- - -
diff --git a/third_party/astrolabe/templates/settings/personal.php b/third_party/astrolabe/templates/settings/personal.php deleted file mode 100644 index 9efdd7a..0000000 --- a/third_party/astrolabe/templates/settings/personal.php +++ /dev/null @@ -1,303 +0,0 @@ -getURLGenerator(); - -script('astrolabe', 'astrolabe-personalSettings'); -style('astrolabe', 'astrolabe-main'); // All CSS bundled into main -?> - -
-

t('Astrolabe')); ?>

-

t('AI-powered semantic search across your Nextcloud content. Find documents by meaning, not just keywords.')); ?>

-
- -
-

t('Service Status')); ?>

- - - - - - - - - -
t('Service URL')); ?>
t('Version')); ?>
-
- -
-

t('Background Sync Access')); ?>

- - - - -
-

- - - t('Active')); ?> - -

- - - - - - - - - - - - - - - - - - - - - - -
t('Credential Type')); ?> - - t('App Password')); ?> - - t('OAuth Refresh Token')); ?> - -
t('Provisioned At')); ?>
t('Provisioned At')); ?>
t('Indexed Content')); ?>
- -
- -
- - -

- t('This will revoke background sync access. The MCP server will no longer be able to access your Nextcloud data for background operations.')); ?> -

-
- -
- - -

- t('This will stop background indexing and remove your content from semantic search. You can re-enable it at any time.')); ?> -

-
- -
-
- - - - -

- t('To use semantic search, you need to complete two setup steps:')); ?> -

- - -
-

- - t('Complete')); ?> - - t('Required')); ?> - - t('Step 1: Authorize Search Access')); ?> -

-

- t('Authorize Astrolabe to perform searches on your behalf.')); ?> -

- - - - t('Authorize')); ?> - - -

t('Search access authorized.')); ?>

- -
- - -
-

- - t('Complete')); ?> - - t('Required')); ?> - - t('Step 2: Enable Background Indexing')); ?> -

-

- t('Provide an app password to allow background indexing of your content.')); ?> -

- -
-

- - t('Generate app password in Security settings')); ?> - -

- -
- -
- - -
-

- t('The app password will be validated and securely encrypted before storage.')); ?> -

-
-
- -

t('Background indexing enabled.')); ?>

- -
- - - -

- t('Enable background sync to allow the MCP server to access your Nextcloud data for background operations like content indexing.')); ?> -

- -
-

t('Option 1: OAuth Refresh Token (Recommended for Future)')); ?>

-

- t('When Nextcloud fully supports OAuth for app APIs. Currently waiting for upstream PR to merge.')); ?> -

- - - t('Authorize via OAuth')); ?> - -
- -
-

t('Option 2: App Password (Works Today - Recommended)')); ?>

-

- t('Generate an app password in Security settings and provide it below. This is the recommended interim solution.')); ?> -

- -
-

t('Step 1:')); ?> - - t('Generate app password in Security settings')); ?> - -

- -

t('Step 2:')); ?> t('Enter the app password below:')); ?>

- -
- -
- - -
-

- t('The app password will be validated and securely encrypted before storage.')); ?> -

-
-
-
- - -
- - -
-

t('Identity Provider Profile')); ?>

- - $value): ?> - - - - - -
- - - - - -
-
- - - -
-

t('Search Your Content')); ?>

-

t('Use natural language to search across your Notes, Files, Calendar, and Deck cards. Ask questions like "meeting notes from last week" or "recipes with chicken".')); ?>

- - - t('Open Astrolabe')); ?> - -
- -
-

t('Semantic Search')); ?>

-

- t('Semantic search is not enabled on this server. Contact your administrator to enable this feature.')); ?> -

-
- - -
-

t('Manage Connection')); ?>

-

t('You are connected to the Astrolabe service.')); ?>

- -
-
- - -

- t('This will disconnect from the Astrolabe service. You will need to re-authorize to use semantic search features.')); ?> -

-
-
-
diff --git a/third_party/astrolabe/tests/bootstrap.php b/third_party/astrolabe/tests/bootstrap.php deleted file mode 100644 index 6acece4..0000000 --- a/third_party/astrolabe/tests/bootstrap.php +++ /dev/null @@ -1,9 +0,0 @@ - - - - . - - - - ../appinfo - ../lib - - - diff --git a/third_party/astrolabe/tests/unit/BackgroundJob/RefreshUserTokensTest.php b/third_party/astrolabe/tests/unit/BackgroundJob/RefreshUserTokensTest.php deleted file mode 100644 index d467841..0000000 --- a/third_party/astrolabe/tests/unit/BackgroundJob/RefreshUserTokensTest.php +++ /dev/null @@ -1,635 +0,0 @@ -timeFactory = $this->createMock(ITimeFactory::class); - $this->tokenStorage = $this->createMock(McpTokenStorage::class); - $this->tokenRefresher = $this->createMock(IdpTokenRefresher::class); - $this->logger = $this->createMock(LoggerInterface::class); - - $this->job = new RefreshUserTokens( - $this->timeFactory, - $this->tokenStorage, - $this->tokenRefresher, - $this->logger - ); - } - - /** - * Set up default withTokenLock behavior that executes the callback. - * Call this in tests that need the lock to succeed. - */ - private function setupDefaultLockBehavior(): void { - $this->tokenStorage->method('withTokenLock') - ->willReturnCallback(fn ($userId, $callback) => $callback()); - } - - // ========================================================================= - // Constructor Tests - // ========================================================================= - - public function testConstructorSetsInterval(): void { - // Use reflection to access the protected interval property - $reflection = new \ReflectionClass($this->job); - $property = $reflection->getProperty('interval'); - $property->setAccessible(true); - - $this->assertEquals(900, $property->getValue($this->job)); - } - - // ========================================================================= - // run() Method Tests - // ========================================================================= - - public function testRunWithNoUsers(): void { - $this->tokenStorage->method('getAllUsersWithTokens') - ->willReturn([]); - - $this->logger->expects($this->exactly(2)) - ->method('info') - ->willReturnCallback(function (string $message) { - static $callCount = 0; - $callCount++; - if ($callCount === 1) { - $this->assertStringContainsString('Starting', $message); - } else { - $this->assertStringContainsString('total=0', $message); - $this->assertStringContainsString('refreshed=0, failed=0, skipped=0', $message); - } - }); - - // Call run() via reflection since it's protected - $this->invokeRun(); - } - - public function testRunWithMultipleUsersAndMixedResults(): void { - $this->setupDefaultLockBehavior(); - - $this->tokenStorage->method('getAllUsersWithTokens') - ->willReturn(['alice', 'bob', 'charlie']); - - // Alice: token with plenty of time (skipped) - // Bob: token near expiry with refresh token (refreshed) - // Charlie: token near expiry without refresh token (failed) - $this->tokenStorage->method('getUserToken') - ->willReturnCallback(function (string $userId) { - $now = time(); - return match ($userId) { - 'alice' => [ - 'access_token' => 'alice-token', - 'refresh_token' => 'alice-refresh', - 'expires_at' => $now + 3600, // 1 hour remaining (>50% of default lifetime) - 'issued_at' => $now, - ], - 'bob' => [ - 'access_token' => 'bob-token', - 'refresh_token' => 'bob-refresh', - 'expires_at' => $now + 100, // ~100s remaining (<50% of default lifetime) - 'issued_at' => $now - 3500, - ], - 'charlie' => [ - 'access_token' => 'charlie-token', - // No refresh_token - 'expires_at' => $now + 100, - 'issued_at' => $now - 3500, - ], - default => null, - }; - }); - - // Bob's refresh should succeed - $this->tokenRefresher->method('refreshAccessToken') - ->with('bob-refresh') - ->willReturn([ - 'access_token' => 'bob-new-token', - 'refresh_token' => 'bob-new-refresh', - 'expires_in' => 3600, - ]); - - $this->tokenStorage->expects($this->once()) - ->method('storeUserToken') - ->with( - 'bob', - 'bob-new-token', - 'bob-new-refresh', - $this->anything(), - $this->anything() - ); - - $this->logger->expects($this->exactly(2)) - ->method('info') - ->willReturnCallback(function (string $message) { - static $callCount = 0; - $callCount++; - if ($callCount === 2) { - $this->assertStringContainsString('total=3', $message); - $this->assertStringContainsString('refreshed=1, failed=1, skipped=1', $message); - } - }); - - $this->invokeRun(); - } - - public function testRunProcessesUsersInBatches(): void { - $this->setupDefaultLockBehavior(); - - // Simulate 150 users processed in 2 batches (100 + 50) - $batch1 = array_map(fn ($i) => "user{$i}", range(1, 100)); - $batch2 = array_map(fn ($i) => "user{$i}", range(101, 150)); - - $callCount = 0; - $this->tokenStorage->method('getAllUsersWithTokens') - ->willReturnCallback(function (int $limit, int $offset) use (&$callCount, $batch1, $batch2) { - $callCount++; - // First call: offset 0, return 100 users (full batch) - if ($offset === 0) { - $this->assertEquals(100, $limit); - return $batch1; - } - // Second call: offset 100, return 50 users (partial batch = last) - if ($offset === 100) { - $this->assertEquals(100, $limit); - return $batch2; - } - // Should not be called again - $this->fail("Unexpected getAllUsersWithTokens call with offset $offset"); - }); - - // All tokens have plenty of time (all skipped) - $this->tokenStorage->method('getUserToken') - ->willReturnCallback(function (string $userId) { - $now = time(); - return [ - 'access_token' => "{$userId}-token", - 'refresh_token' => "{$userId}-refresh", - 'expires_at' => $now + 3600, - 'issued_at' => $now, - ]; - }); - - $this->tokenRefresher->expects($this->never()) - ->method('refreshAccessToken'); - - $this->logger->expects($this->exactly(2)) - ->method('info') - ->willReturnCallback(function (string $message) { - static $infoCallCount = 0; - $infoCallCount++; - if ($infoCallCount === 2) { - $this->assertStringContainsString('total=150', $message); - $this->assertStringContainsString('refreshed=0, failed=0, skipped=150', $message); - } - }); - - $this->invokeRun(); - - // Verify getAllUsersWithTokens was called exactly twice (2 batches) - $this->assertEquals(2, $callCount); - } - - // ========================================================================= - // refreshUserTokenIfNeeded() Tests - // ========================================================================= - - public function testRefreshSkippedWhenTokenHasPlentyOfTime(): void { - $now = time(); - $this->tokenStorage->method('getUserToken') - ->with('testuser') - ->willReturn([ - 'access_token' => 'valid-token', - 'refresh_token' => 'refresh-token', - 'expires_at' => $now + 3600, // 1 hour remaining - 'issued_at' => $now, - ]); - - $this->tokenRefresher->expects($this->never()) - ->method('refreshAccessToken'); - - $result = $this->invokeRefreshUserTokenIfNeeded('testuser'); - - $this->assertEquals('skipped', $result); - } - - public function testRefreshTriggeredWhenTokenNearExpiry(): void { - $this->setupDefaultLockBehavior(); - - $now = time(); - $this->tokenStorage->method('getUserToken') - ->with('testuser') - ->willReturn([ - 'access_token' => 'expiring-token', - 'refresh_token' => 'refresh-token', - 'expires_at' => $now + 300, // 5 min remaining (< 50% of 3600s) - 'issued_at' => $now - 3300, // Issued 55 min ago - ]); - - $this->tokenRefresher->expects($this->once()) - ->method('refreshAccessToken') - ->with('refresh-token') - ->willReturn([ - 'access_token' => 'new-token', - 'refresh_token' => 'new-refresh-token', - 'expires_in' => 3600, - ]); - - $this->tokenStorage->expects($this->once()) - ->method('storeUserToken'); - - $result = $this->invokeRefreshUserTokenIfNeeded('testuser'); - - $this->assertEquals('refreshed', $result); - } - - public function testRefreshFailsWhenNoRefreshToken(): void { - $this->setupDefaultLockBehavior(); - - $now = time(); - $this->tokenStorage->method('getUserToken') - ->with('testuser') - ->willReturn([ - 'access_token' => 'expiring-token', - // No refresh_token - 'expires_at' => $now + 100, - 'issued_at' => $now - 3500, - ]); - - $this->logger->expects($this->once()) - ->method('warning') - ->with($this->stringContains('no refresh token')); - - $this->tokenRefresher->expects($this->never()) - ->method('refreshAccessToken'); - - $result = $this->invokeRefreshUserTokenIfNeeded('testuser'); - - $this->assertEquals('failed', $result); - } - - public function testRefreshFailsWhenRefresherReturnsNull(): void { - $this->setupDefaultLockBehavior(); - - $now = time(); - $this->tokenStorage->method('getUserToken') - ->with('testuser') - ->willReturn([ - 'access_token' => 'expiring-token', - 'refresh_token' => 'invalid-refresh', - 'expires_at' => $now + 100, - 'issued_at' => $now - 3500, - ]); - - $this->tokenRefresher->expects($this->once()) - ->method('refreshAccessToken') - ->with('invalid-refresh') - ->willReturn(null); - - $this->logger->expects($this->once()) - ->method('warning') - ->with($this->stringContains('Refresh returned null')); - - // Should NOT delete token - let on-demand refresh handle cleanup - $this->tokenStorage->expects($this->never()) - ->method('deleteUserToken'); - - $result = $this->invokeRefreshUserTokenIfNeeded('testuser'); - - $this->assertEquals('failed', $result); - } - - public function testRefreshUsesIssuedAtForLifetimeCalculation(): void { - $this->setupDefaultLockBehavior(); - - $now = time(); - // Token with custom lifetime: issued 50 min ago, expires in 10 min (total 60 min) - // 10/60 = 16.7% remaining, which is < 50%, so should refresh - $this->tokenStorage->method('getUserToken') - ->with('testuser') - ->willReturn([ - 'access_token' => 'token', - 'refresh_token' => 'refresh', - 'expires_at' => $now + 600, // 10 min remaining - 'issued_at' => $now - 3000, // 50 min ago, total lifetime 60 min - ]); - - $this->tokenRefresher->expects($this->once()) - ->method('refreshAccessToken') - ->willReturn([ - 'access_token' => 'new-token', - 'refresh_token' => 'new-refresh', - 'expires_in' => 3600, - ]); - - $result = $this->invokeRefreshUserTokenIfNeeded('testuser'); - - $this->assertEquals('refreshed', $result); - } - - public function testRefreshUsesDefaultLifetimeWhenNoIssuedAt(): void { - $this->setupDefaultLockBehavior(); - - $now = time(); - // Token without issued_at, uses default 3600s lifetime - // 300s remaining / 3600s = 8.3% remaining, which is < 50%, so should refresh - $this->tokenStorage->method('getUserToken') - ->with('testuser') - ->willReturn([ - 'access_token' => 'token', - 'refresh_token' => 'refresh', - 'expires_at' => $now + 300, // 5 min remaining - // No issued_at - ]); - - $this->tokenRefresher->expects($this->once()) - ->method('refreshAccessToken') - ->willReturn([ - 'access_token' => 'new-token', - 'refresh_token' => 'new-refresh', - 'expires_in' => 3600, - ]); - - $result = $this->invokeRefreshUserTokenIfNeeded('testuser'); - - $this->assertEquals('refreshed', $result); - } - - public function testRefreshStoresNewTokenWithIssuedAt(): void { - $this->setupDefaultLockBehavior(); - - $now = time(); - $this->tokenStorage->method('getUserToken') - ->with('testuser') - ->willReturn([ - 'access_token' => 'old-token', - 'refresh_token' => 'old-refresh', - 'expires_at' => $now + 100, - 'issued_at' => $now - 3500, - ]); - - $this->tokenRefresher->expects($this->once()) - ->method('refreshAccessToken') - ->willReturn([ - 'access_token' => 'new-token', - 'refresh_token' => 'new-refresh', - 'expires_in' => 3600, - ]); - - // Verify storeUserToken is called with issued_at parameter - $this->tokenStorage->expects($this->once()) - ->method('storeUserToken') - ->with( - 'testuser', - 'new-token', - 'new-refresh', - $this->greaterThan($now), // expires_at = now + 3600 - $this->greaterThanOrEqual($now) // issued_at = now - ); - - $result = $this->invokeRefreshUserTokenIfNeeded('testuser'); - - $this->assertEquals('refreshed', $result); - } - - public function testRefreshKeepsOldRefreshTokenIfNotRotated(): void { - $this->setupDefaultLockBehavior(); - - $now = time(); - $this->tokenStorage->method('getUserToken') - ->with('testuser') - ->willReturn([ - 'access_token' => 'old-token', - 'refresh_token' => 'original-refresh', - 'expires_at' => $now + 100, - 'issued_at' => $now - 3500, - ]); - - // IdP returns new access token but no new refresh token (no rotation) - $this->tokenRefresher->expects($this->once()) - ->method('refreshAccessToken') - ->willReturn([ - 'access_token' => 'new-token', - // No refresh_token in response - 'expires_in' => 3600, - ]); - - // Should use the original refresh token - $this->tokenStorage->expects($this->once()) - ->method('storeUserToken') - ->with( - 'testuser', - 'new-token', - 'original-refresh', // Original refresh token preserved - $this->anything(), - $this->anything() - ); - - $result = $this->invokeRefreshUserTokenIfNeeded('testuser'); - - $this->assertEquals('refreshed', $result); - } - - public function testRefreshHandlesException(): void { - $this->setupDefaultLockBehavior(); - - $now = time(); - $this->tokenStorage->method('getUserToken') - ->with('testuser') - ->willReturn([ - 'access_token' => 'token', - 'refresh_token' => 'refresh', - 'expires_at' => $now + 100, - 'issued_at' => $now - 3500, - ]); - - $this->tokenRefresher->expects($this->once()) - ->method('refreshAccessToken') - ->willThrowException(new \Exception('Network error')); - - $this->logger->expects($this->once()) - ->method('error') - ->with($this->stringContains('Failed to refresh')); - - $result = $this->invokeRefreshUserTokenIfNeeded('testuser'); - - $this->assertEquals('failed', $result); - } - - public function testRefreshSkippedWhenNoToken(): void { - $this->tokenStorage->method('getUserToken') - ->with('testuser') - ->willReturn(null); - - $this->tokenRefresher->expects($this->never()) - ->method('refreshAccessToken'); - - $result = $this->invokeRefreshUserTokenIfNeeded('testuser'); - - $this->assertEquals('skipped', $result); - } - - // ========================================================================= - // Locking Tests - // ========================================================================= - - public function testRefreshSkippedWhenLockCannotBeAcquired(): void { - $now = time(); - $this->tokenStorage->method('getUserToken') - ->with('testuser') - ->willReturn([ - 'access_token' => 'expiring-token', - 'refresh_token' => 'refresh-token', - 'expires_at' => $now + 100, // ~100s remaining (< 50% of default) - 'issued_at' => $now - 3500, - ]); - - // Lock acquisition fails (on-demand refresh is holding it) - $this->tokenStorage->expects($this->once()) - ->method('withTokenLock') - ->willThrowException(new LockedException('astrolabe/oauth/tokens/testuser')); - - // Token refresher should NOT be called when lock fails - $this->tokenRefresher->expects($this->never()) - ->method('refreshAccessToken'); - - $this->logger->expects($this->once()) - ->method('debug') - ->with($this->stringContains('Lock held for user testuser')); - - $result = $this->invokeRefreshUserTokenIfNeeded('testuser'); - - $this->assertEquals('skipped', $result); - } - - public function testRefreshUsesLockForTokenRefresh(): void { - $now = time(); - $this->tokenStorage->method('getUserToken') - ->with('testuser') - ->willReturn([ - 'access_token' => 'expiring-token', - 'refresh_token' => 'refresh-token', - 'expires_at' => $now + 100, - 'issued_at' => $now - 3500, - ]); - - // withTokenLock is called and executes the callback - $this->tokenStorage->expects($this->once()) - ->method('withTokenLock') - ->with('testuser', $this->isInstanceOf(\Closure::class)) - ->willReturnCallback(function ($userId, $callback) { - return $callback(); - }); - - $this->tokenRefresher->expects($this->once()) - ->method('refreshAccessToken') - ->with('refresh-token') - ->willReturn([ - 'access_token' => 'new-token', - 'refresh_token' => 'new-refresh-token', - 'expires_in' => 3600, - ]); - - $this->tokenStorage->expects($this->once()) - ->method('storeUserToken'); - - $result = $this->invokeRefreshUserTokenIfNeeded('testuser'); - - $this->assertEquals('refreshed', $result); - } - - public function testRefreshSkippedWhenTokenAlreadyRefreshedWhileWaitingForLock(): void { - $now = time(); - - // First call (before lock): token is expiring - // Calls inside lock callback: token is now fresh - $callCount = 0; - $this->tokenStorage->method('getUserToken') - ->with('testuser') - ->willReturnCallback(function () use (&$callCount, $now) { - $callCount++; - if ($callCount === 1) { - // First check: token is expiring - return [ - 'access_token' => 'expiring-token', - 'refresh_token' => 'refresh-token', - 'expires_at' => $now + 100, - 'issued_at' => $now - 3500, - ]; - } - // Inside lock: token was already refreshed - return [ - 'access_token' => 'already-refreshed-token', - 'refresh_token' => 'new-refresh-token', - 'expires_at' => $now + 3600, // Fresh token - 'issued_at' => $now, - ]; - }); - - // withTokenLock is called and executes the callback - $this->tokenStorage->expects($this->once()) - ->method('withTokenLock') - ->willReturnCallback(function ($userId, $callback) { - return $callback(); - }); - - // Token refresher should NOT be called since token is already fresh - $this->tokenRefresher->expects($this->never()) - ->method('refreshAccessToken'); - - $this->logger->expects($this->once()) - ->method('debug') - ->with($this->stringContains('already refreshed')); - - $result = $this->invokeRefreshUserTokenIfNeeded('testuser'); - - $this->assertEquals('skipped', $result); - } - - // ========================================================================= - // Helper Methods - // ========================================================================= - - /** - * Invoke the protected run() method. - */ - private function invokeRun(): void { - $reflection = new \ReflectionClass($this->job); - $method = $reflection->getMethod('run'); - $method->setAccessible(true); - $method->invoke($this->job, null); - } - - /** - * Invoke the private refreshUserTokenIfNeeded() method. - */ - private function invokeRefreshUserTokenIfNeeded(string $userId): string { - $reflection = new \ReflectionClass($this->job); - $method = $reflection->getMethod('refreshUserTokenIfNeeded'); - $method->setAccessible(true); - return $method->invoke($this->job, $userId); - } -} diff --git a/third_party/astrolabe/tests/unit/Service/IdpTokenRefresherTest.php b/third_party/astrolabe/tests/unit/Service/IdpTokenRefresherTest.php deleted file mode 100644 index 37c7096..0000000 --- a/third_party/astrolabe/tests/unit/Service/IdpTokenRefresherTest.php +++ /dev/null @@ -1,429 +0,0 @@ -config = $this->createMock(IConfig::class); - $this->clientService = $this->createMock(IClientService::class); - $this->httpClient = $this->createMock(IClient::class); - $this->logger = $this->createMock(LoggerInterface::class); - $this->mcpServerClient = $this->createMock(McpServerClient::class); - - $this->clientService->method('newClient')->willReturn($this->httpClient); - - $this->refresher = new IdpTokenRefresher( - $this->config, - $this->clientService, - $this->logger, - $this->mcpServerClient - ); - } - - // ========================================================================= - // getNextcloudBaseUrl() tests - // ========================================================================= - - /** - * @dataProvider provideBaseUrlTestCases - */ - public function testGetNextcloudBaseUrl(string $configValue, string $expected): void { - $this->config->method('getSystemValue') - ->with('astrolabe_internal_url', '') - ->willReturn($configValue); - - // Use reflection to test private method - $reflection = new \ReflectionClass($this->refresher); - $method = $reflection->getMethod('getNextcloudBaseUrl'); - $method->setAccessible(true); - - $result = $method->invoke($this->refresher); - - $this->assertEquals($expected, $result); - } - - /** - * Provides test cases for getNextcloudBaseUrl(). - * - * @return array - */ - public static function provideBaseUrlTestCases(): array { - return [ - 'default - no config' => ['', 'http://localhost'], - 'custom internal url' => ['http://web:8080', 'http://web:8080'], - 'custom url with trailing slash' => ['http://web:8080/', 'http://web:8080'], - 'kubernetes service' => ['http://nextcloud.default.svc:80', 'http://nextcloud.default.svc:80'], - 'https internal url' => ['https://internal.example.com', 'https://internal.example.com'], - ]; - } - - // ========================================================================= - // refreshAccessToken() tests - // ========================================================================= - - public function testRefreshAccessTokenFailsWithoutClientSecret(): void { - $this->config->method('getSystemValue') - ->willReturnMap([ - ['astrolabe_client_secret', '', ''], - ]); - - $this->logger->expects($this->once()) - ->method('warning') - ->with($this->stringContains('no client secret configured')); - - $result = $this->refresher->refreshAccessToken('test-refresh-token'); - - $this->assertNull($result); - } - - public function testRefreshAccessTokenFailsWithoutMcpServerUrl(): void { - $this->config->method('getSystemValue') - ->willReturnMap([ - ['astrolabe_client_secret', '', 'test-secret'], - ['mcp_server_url', '', ''], - ]); - - $this->logger->expects($this->once()) - ->method('error') - ->with( - $this->stringContains('Token refresh failed'), - $this->callback(fn ($ctx) => str_contains($ctx['error'], 'MCP server URL not configured')) - ); - - $result = $this->refresher->refreshAccessToken('test-refresh-token'); - - $this->assertNull($result); - } - - public function testRefreshAccessTokenWithInternalNextcloudOidc(): void { - // Setup config - $this->config->method('getSystemValue') - ->willReturnMap([ - ['astrolabe_client_secret', '', 'test-secret'], - ['mcp_server_url', '', 'http://mcp-server:8000'], - ['astrolabe_internal_url', '', ''], - ]); - - $this->mcpServerClient->method('getClientId') - ->willReturn('test-client-id'); - - // Mock MCP server status response (no external IdP configured) - $statusResponse = $this->createMock(IResponse::class); - $statusResponse->method('getBody') - ->willReturn(json_encode([ - 'version' => '1.0.0', - 'auth_mode' => 'multi_user_oauth', - // No 'oidc.discovery_url' = use internal Nextcloud OIDC - ])); - - // Mock token endpoint response - $tokenResponse = $this->createMock(IResponse::class); - $tokenResponse->method('getBody') - ->willReturn(json_encode([ - 'access_token' => 'new-access-token', - 'refresh_token' => 'new-refresh-token', - 'expires_in' => 3600, - 'token_type' => 'Bearer', - ])); - - // Setup HTTP client to return appropriate responses - $this->httpClient->method('get') - ->with('http://mcp-server:8000/api/v1/status') - ->willReturn($statusResponse); - - $this->httpClient->method('post') - ->with( - 'http://localhost/apps/oidc/token', - $this->callback(function ($options) { - // Verify the POST body contains expected parameters - $body = $options['body'] ?? ''; - return str_contains($body, 'grant_type=refresh_token') - && str_contains($body, 'client_id=test-client-id') - && str_contains($body, 'client_secret=test-secret') - && str_contains($body, 'refresh_token=test-refresh-token'); - }) - ) - ->willReturn($tokenResponse); - - $result = $this->refresher->refreshAccessToken('test-refresh-token'); - - $this->assertNotNull($result); - $this->assertEquals('new-access-token', $result['access_token']); - $this->assertEquals('new-refresh-token', $result['refresh_token']); - $this->assertEquals(3600, $result['expires_in']); - } - - public function testRefreshAccessTokenWithExternalIdp(): void { - // Setup config - $this->config->method('getSystemValue') - ->willReturnMap([ - ['astrolabe_client_secret', '', 'test-secret'], - ['mcp_server_url', '', 'http://mcp-server:8000'], - ]); - - $this->mcpServerClient->method('getClientId') - ->willReturn('test-client-id'); - - // Mock MCP server status response (external IdP configured) - $statusResponse = $this->createMock(IResponse::class); - $statusResponse->method('getBody') - ->willReturn(json_encode([ - 'version' => '1.0.0', - 'auth_mode' => 'multi_user_oauth', - 'oidc' => [ - 'discovery_url' => 'https://keycloak.example.com/realms/test/.well-known/openid-configuration', - ], - ])); - - // Mock OIDC discovery response - $discoveryResponse = $this->createMock(IResponse::class); - $discoveryResponse->method('getBody') - ->willReturn(json_encode([ - 'issuer' => 'https://keycloak.example.com/realms/test', - 'token_endpoint' => 'https://keycloak.example.com/realms/test/protocol/openid-connect/token', - 'authorization_endpoint' => 'https://keycloak.example.com/realms/test/protocol/openid-connect/auth', - ])); - - // Mock token endpoint response - $tokenResponse = $this->createMock(IResponse::class); - $tokenResponse->method('getBody') - ->willReturn(json_encode([ - 'access_token' => 'keycloak-access-token', - 'refresh_token' => 'keycloak-refresh-token', - 'expires_in' => 300, - 'token_type' => 'Bearer', - ])); - - // Setup HTTP client calls in order - $this->httpClient->method('get') - ->willReturnCallback(function ($url) use ($statusResponse, $discoveryResponse) { - if (str_contains($url, 'status')) { - return $statusResponse; - } - if (str_contains($url, '.well-known/openid-configuration')) { - return $discoveryResponse; - } - throw new \Exception("Unexpected URL: $url"); - }); - - $this->httpClient->method('post') - ->with( - 'https://keycloak.example.com/realms/test/protocol/openid-connect/token', - $this->anything() - ) - ->willReturn($tokenResponse); - - $result = $this->refresher->refreshAccessToken('test-refresh-token'); - - $this->assertNotNull($result); - $this->assertEquals('keycloak-access-token', $result['access_token']); - $this->assertEquals('keycloak-refresh-token', $result['refresh_token']); - $this->assertEquals(300, $result['expires_in']); - } - - public function testRefreshAccessTokenFailsOnMissingRefreshTokenInResponse(): void { - // Setup config - $this->config->method('getSystemValue') - ->willReturnMap([ - ['astrolabe_client_secret', '', 'test-secret'], - ['mcp_server_url', '', 'http://mcp-server:8000'], - ['astrolabe_internal_url', '', ''], - ]); - - $this->mcpServerClient->method('getClientId') - ->willReturn('test-client-id'); - - // Mock MCP server status response - $statusResponse = $this->createMock(IResponse::class); - $statusResponse->method('getBody') - ->willReturn(json_encode(['version' => '1.0.0'])); - - // Mock token response WITHOUT refresh_token (token rotation failure) - $tokenResponse = $this->createMock(IResponse::class); - $tokenResponse->method('getBody') - ->willReturn(json_encode([ - 'access_token' => 'new-access-token', - // Missing refresh_token! - 'expires_in' => 3600, - ])); - - $this->httpClient->method('get')->willReturn($statusResponse); - $this->httpClient->method('post')->willReturn($tokenResponse); - - $this->logger->expects($this->once()) - ->method('error') - ->with( - $this->stringContains('No refresh token in response'), - $this->anything() - ); - - $result = $this->refresher->refreshAccessToken('test-refresh-token'); - - $this->assertNull($result); - } - - public function testRefreshAccessTokenHandlesHttpException(): void { - // Setup config - $this->config->method('getSystemValue') - ->willReturnMap([ - ['astrolabe_client_secret', '', 'test-secret'], - ['mcp_server_url', '', 'http://mcp-server:8000'], - ]); - - // HTTP client throws exception - $this->httpClient->method('get') - ->willThrowException(new \Exception('Connection refused')); - - $this->logger->expects($this->once()) - ->method('error') - ->with( - $this->stringContains('Token refresh failed'), - $this->callback(fn ($ctx) => str_contains($ctx['error'], 'Connection refused')) - ); - - $result = $this->refresher->refreshAccessToken('test-refresh-token'); - - $this->assertNull($result); - } - - public function testRefreshAccessTokenHandlesInvalidStatusResponse(): void { - // Setup config - $this->config->method('getSystemValue') - ->willReturnMap([ - ['astrolabe_client_secret', '', 'test-secret'], - ['mcp_server_url', '', 'http://mcp-server:8000'], - ]); - - // Mock invalid JSON response - $statusResponse = $this->createMock(IResponse::class); - $statusResponse->method('getBody') - ->willReturn('not valid json'); - - $this->httpClient->method('get')->willReturn($statusResponse); - - $this->logger->expects($this->once()) - ->method('error') - ->with( - $this->stringContains('Token refresh failed'), - $this->callback(fn ($ctx) => str_contains($ctx['error'], 'Invalid status response')) - ); - - $result = $this->refresher->refreshAccessToken('test-refresh-token'); - - $this->assertNull($result); - } - - public function testRefreshAccessTokenHandlesInvalidDiscoveryResponse(): void { - // Setup config - $this->config->method('getSystemValue') - ->willReturnMap([ - ['astrolabe_client_secret', '', 'test-secret'], - ['mcp_server_url', '', 'http://mcp-server:8000'], - ]); - - $this->mcpServerClient->method('getClientId') - ->willReturn('test-client-id'); - - // Mock MCP server status response with external IdP - $statusResponse = $this->createMock(IResponse::class); - $statusResponse->method('getBody') - ->willReturn(json_encode([ - 'oidc' => [ - 'discovery_url' => 'https://keycloak.example.com/.well-known/openid-configuration', - ], - ])); - - // Mock invalid discovery response (missing token_endpoint) - $discoveryResponse = $this->createMock(IResponse::class); - $discoveryResponse->method('getBody') - ->willReturn(json_encode([ - 'issuer' => 'https://keycloak.example.com', - // Missing token_endpoint! - ])); - - $this->httpClient->method('get') - ->willReturnCallback(function ($url) use ($statusResponse, $discoveryResponse) { - if (str_contains($url, 'status')) { - return $statusResponse; - } - return $discoveryResponse; - }); - - $this->logger->expects($this->once()) - ->method('error') - ->with( - $this->stringContains('Token refresh failed'), - $this->callback(fn ($ctx) => str_contains($ctx['error'], 'Invalid OIDC discovery response')) - ); - - $result = $this->refresher->refreshAccessToken('test-refresh-token'); - - $this->assertNull($result); - } - - public function testRefreshAccessTokenHandlesInvalidTokenResponse(): void { - // Setup config - $this->config->method('getSystemValue') - ->willReturnMap([ - ['astrolabe_client_secret', '', 'test-secret'], - ['mcp_server_url', '', 'http://mcp-server:8000'], - ['astrolabe_internal_url', '', ''], - ]); - - $this->mcpServerClient->method('getClientId') - ->willReturn('test-client-id'); - - // Mock MCP server status response - $statusResponse = $this->createMock(IResponse::class); - $statusResponse->method('getBody') - ->willReturn(json_encode(['version' => '1.0.0'])); - - // Mock token response without access_token - $tokenResponse = $this->createMock(IResponse::class); - $tokenResponse->method('getBody') - ->willReturn(json_encode([ - 'error' => 'invalid_grant', - 'error_description' => 'Refresh token expired', - ])); - - $this->httpClient->method('get')->willReturn($statusResponse); - $this->httpClient->method('post')->willReturn($tokenResponse); - - $this->logger->expects($this->once()) - ->method('error') - ->with( - $this->stringContains('Token refresh failed'), - $this->callback(fn ($ctx) => str_contains($ctx['error'], 'Invalid token response')) - ); - - $result = $this->refresher->refreshAccessToken('test-refresh-token'); - - $this->assertNull($result); - } -} diff --git a/third_party/astrolabe/tests/unit/Service/McpTokenStorageTest.php b/third_party/astrolabe/tests/unit/Service/McpTokenStorageTest.php deleted file mode 100644 index d2bc761..0000000 --- a/third_party/astrolabe/tests/unit/Service/McpTokenStorageTest.php +++ /dev/null @@ -1,829 +0,0 @@ -config = $this->createMock(IConfig::class); - $this->crypto = $this->createMock(ICrypto::class); - $this->db = $this->createMock(IDBConnection::class); - $this->logger = $this->createMock(LoggerInterface::class); - $this->lockingProvider = $this->createMock(ILockingProvider::class); - - $this->storage = new McpTokenStorage( - $this->config, - $this->crypto, - $this->db, - $this->logger, - $this->lockingProvider - ); - } - - // ========================================================================= - // OAuth Token Storage Tests - // ========================================================================= - - public function testStoreUserToken(): void { - $userId = 'testuser'; - $accessToken = 'access-token-123'; - $refreshToken = 'refresh-token-456'; - $expiresAt = time() + 3600; - - $this->crypto->expects($this->once()) - ->method('encrypt') - ->with($this->callback(function (string $json) use ($accessToken, $refreshToken, $expiresAt) { - $data = json_decode($json, true); - return $data['access_token'] === $accessToken - && $data['refresh_token'] === $refreshToken - && $data['expires_at'] === $expiresAt - && isset($data['issued_at']); // issued_at should be set (defaults to time()) - })) - ->willReturn('encrypted-data'); - - $this->config->expects($this->once()) - ->method('setUserValue') - ->with($userId, 'astrolabe', 'oauth_tokens', 'encrypted-data'); - - $this->storage->storeUserToken($userId, $accessToken, $refreshToken, $expiresAt); - } - - public function testGetUserTokenReturnsTokenData(): void { - $userId = 'testuser'; - $tokenData = [ - 'access_token' => 'access-token-123', - 'refresh_token' => 'refresh-token-456', - 'expires_at' => time() + 3600, - ]; - - $this->config->method('getUserValue') - ->with($userId, 'astrolabe', 'oauth_tokens', '') - ->willReturn('encrypted-data'); - - $this->crypto->method('decrypt') - ->with('encrypted-data') - ->willReturn(json_encode($tokenData)); - - $result = $this->storage->getUserToken($userId); - - $this->assertEquals($tokenData, $result); - } - - public function testGetUserTokenReturnsNullWhenNoTokenStored(): void { - $userId = 'testuser'; - - $this->config->method('getUserValue') - ->with($userId, 'astrolabe', 'oauth_tokens', '') - ->willReturn(''); - - $result = $this->storage->getUserToken($userId); - - $this->assertNull($result); - } - - public function testGetUserTokenReturnsNullOnDecryptionFailure(): void { - $userId = 'testuser'; - - $this->config->method('getUserValue') - ->willReturn('encrypted-data'); - - $this->crypto->method('decrypt') - ->willThrowException(new \Exception('Decryption failed')); - - $result = $this->storage->getUserToken($userId); - - $this->assertNull($result); - } - - public function testDeleteUserToken(): void { - $userId = 'testuser'; - - $this->config->expects($this->once()) - ->method('deleteUserValue') - ->with($userId, 'astrolabe', 'oauth_tokens'); - - $this->storage->deleteUserToken($userId); - } - - // ========================================================================= - // Token Expiration Tests - // ========================================================================= - - public function testIsExpiredReturnsTrueWhenNoExpiresAt(): void { - $token = ['access_token' => 'test']; - - $this->assertTrue($this->storage->isExpired($token)); - } - - public function testIsExpiredReturnsTrueWhenExpired(): void { - $token = [ - 'access_token' => 'test', - 'expires_at' => time() - 100, // Expired 100 seconds ago - ]; - - $this->assertTrue($this->storage->isExpired($token)); - } - - public function testIsExpiredReturnsTrueWhenAboutToExpire(): void { - $token = [ - 'access_token' => 'test', - 'expires_at' => time() + 30, // Expires in 30 seconds (within 60s buffer) - ]; - - $this->assertTrue($this->storage->isExpired($token)); - } - - public function testIsExpiredReturnsFalseWhenValid(): void { - $token = [ - 'access_token' => 'test', - 'expires_at' => time() + 3600, // Expires in 1 hour - ]; - - $this->assertFalse($this->storage->isExpired($token)); - } - - // ========================================================================= - // getAccessToken with Refresh Callback Tests - // ========================================================================= - - public function testGetAccessTokenReturnsNullWhenNoToken(): void { - $userId = 'testuser'; - - $this->config->method('getUserValue') - ->willReturn(''); - - $result = $this->storage->getAccessToken($userId); - - $this->assertNull($result); - } - - public function testGetAccessTokenReturnsTokenWhenValid(): void { - $userId = 'testuser'; - $tokenData = [ - 'access_token' => 'valid-access-token', - 'refresh_token' => 'refresh-token', - 'expires_at' => time() + 3600, // Valid for 1 hour - ]; - - $this->config->method('getUserValue') - ->willReturn('encrypted-data'); - - $this->crypto->method('decrypt') - ->willReturn(json_encode($tokenData)); - - $result = $this->storage->getAccessToken($userId); - - $this->assertEquals('valid-access-token', $result); - } - - public function testGetAccessTokenRefreshesExpiredToken(): void { - $userId = 'testuser'; - $expiredTokenData = [ - 'access_token' => 'expired-access-token', - 'refresh_token' => 'old-refresh-token', - 'expires_at' => time() - 100, // Expired - ]; - - $newTokenData = [ - 'access_token' => 'new-access-token', - 'refresh_token' => 'new-refresh-token', - 'expires_in' => 3600, - ]; - - // First call returns expired token, subsequent calls for storing new token - $this->config->method('getUserValue') - ->willReturn('encrypted-data'); - - $this->crypto->method('decrypt') - ->willReturn(json_encode($expiredTokenData)); - - // Encrypt is called when storing the new token - $this->crypto->method('encrypt') - ->willReturn('new-encrypted-data'); - - $this->config->expects($this->once()) - ->method('setUserValue') - ->with($userId, 'astrolabe', 'oauth_tokens', 'new-encrypted-data'); - - // Refresh callback - $refreshCallback = function (string $refreshToken) use ($newTokenData) { - $this->assertEquals('old-refresh-token', $refreshToken); - return $newTokenData; - }; - - $result = $this->storage->getAccessToken($userId, $refreshCallback); - - $this->assertEquals('new-access-token', $result); - } - - public function testGetAccessTokenReturnsNullWhenRefreshFailsAndDeletesToken(): void { - $userId = 'testuser'; - $expiredTokenData = [ - 'access_token' => 'expired-access-token', - 'refresh_token' => 'old-refresh-token', - 'expires_at' => time() - 100, // Expired - ]; - - $this->config->method('getUserValue') - ->willReturn('encrypted-data'); - - $this->crypto->method('decrypt') - ->willReturn(json_encode($expiredTokenData)); - - // Expect stale token to be deleted when refresh fails - $this->config->expects($this->once()) - ->method('deleteUserValue') - ->with($userId, 'astrolabe', 'oauth_tokens'); - - // Refresh callback returns null (failure) - $refreshCallback = fn (string $refreshToken) => null; - - $result = $this->storage->getAccessToken($userId, $refreshCallback); - - $this->assertNull($result); - } - - public function testGetAccessTokenReturnsNullWhenExpiredAndNoCallbackAndDeletesToken(): void { - $userId = 'testuser'; - $expiredTokenData = [ - 'access_token' => 'expired-access-token', - 'refresh_token' => 'old-refresh-token', - 'expires_at' => time() - 100, // Expired - ]; - - $this->config->method('getUserValue') - ->willReturn('encrypted-data'); - - $this->crypto->method('decrypt') - ->willReturn(json_encode($expiredTokenData)); - - // Expect stale token to be deleted when expired with no callback - $this->config->expects($this->once()) - ->method('deleteUserValue') - ->with($userId, 'astrolabe', 'oauth_tokens'); - - // No refresh callback provided - $result = $this->storage->getAccessToken($userId, null); - - $this->assertNull($result); - } - - // ========================================================================= - // Token Refresh Locking Tests - // ========================================================================= - - public function testGetAccessTokenAcquiresLockWhenRefreshing(): void { - $userId = 'testuser'; - $expiredTokenData = [ - 'access_token' => 'expired-access-token', - 'refresh_token' => 'old-refresh-token', - 'expires_at' => time() - 100, // Expired - ]; - - $newTokenData = [ - 'access_token' => 'new-access-token', - 'refresh_token' => 'new-refresh-token', - 'expires_in' => 3600, - ]; - - $this->config->method('getUserValue') - ->willReturn('encrypted-data'); - - $this->crypto->method('decrypt') - ->willReturn(json_encode($expiredTokenData)); - - $this->crypto->method('encrypt') - ->willReturn('new-encrypted-data'); - - // Verify lock is acquired and released - $this->lockingProvider->expects($this->once()) - ->method('acquireLock') - ->with('astrolabe/oauth/tokens/testuser', ILockingProvider::LOCK_EXCLUSIVE); - - $this->lockingProvider->expects($this->once()) - ->method('releaseLock') - ->with('astrolabe/oauth/tokens/testuser', ILockingProvider::LOCK_EXCLUSIVE); - - $refreshCallback = fn (string $refreshToken) => $newTokenData; - - $result = $this->storage->getAccessToken($userId, $refreshCallback); - - $this->assertEquals('new-access-token', $result); - } - - public function testGetAccessTokenReturnsStaleTokenOnLockedException(): void { - $userId = 'testuser'; - $expiredTokenData = [ - 'access_token' => 'expired-access-token', - 'refresh_token' => 'old-refresh-token', - 'expires_at' => time() - 100, // Expired - ]; - - $this->config->method('getUserValue') - ->willReturn('encrypted-data'); - - $this->crypto->method('decrypt') - ->willReturn(json_encode($expiredTokenData)); - - // Lock acquisition fails - $this->lockingProvider->expects($this->once()) - ->method('acquireLock') - ->willThrowException(new LockedException('astrolabe/oauth/tokens/testuser')); - - // Refresh callback should NOT be called when lock fails - $refreshCallbackCalled = false; - $refreshCallback = function (string $refreshToken) use (&$refreshCallbackCalled) { - $refreshCallbackCalled = true; - return ['access_token' => 'new-token', 'expires_in' => 3600]; - }; - - $result = $this->storage->getAccessToken($userId, $refreshCallback); - - // Should return stale token instead of failing - $this->assertEquals('expired-access-token', $result); - $this->assertFalse($refreshCallbackCalled); - } - - public function testGetAccessTokenSkipsRefreshWhenTokenAlreadyRefreshedWhileWaitingForLock(): void { - $userId = 'testuser'; - $expiredTokenData = [ - 'access_token' => 'expired-access-token', - 'refresh_token' => 'old-refresh-token', - 'expires_at' => time() - 100, // Expired - ]; - - // After lock is acquired, token appears fresh (another process refreshed it) - $freshTokenData = [ - 'access_token' => 'fresh-access-token', - 'refresh_token' => 'fresh-refresh-token', - 'expires_at' => time() + 3600, // Valid for 1 hour - ]; - - $callCount = 0; - $this->config->method('getUserValue') - ->willReturn('encrypted-data'); - - // First call returns expired, subsequent calls return fresh - $this->crypto->method('decrypt') - ->willReturnCallback(function () use (&$callCount, $expiredTokenData, $freshTokenData) { - $callCount++; - return $callCount === 1 - ? json_encode($expiredTokenData) - : json_encode($freshTokenData); - }); - - $this->lockingProvider->expects($this->once()) - ->method('acquireLock'); - - $this->lockingProvider->expects($this->once()) - ->method('releaseLock'); - - // Refresh callback should NOT be called since token is already fresh - $refreshCallbackCalled = false; - $refreshCallback = function (string $refreshToken) use (&$refreshCallbackCalled) { - $refreshCallbackCalled = true; - return ['access_token' => 'new-token', 'expires_in' => 3600]; - }; - - $result = $this->storage->getAccessToken($userId, $refreshCallback); - - $this->assertEquals('fresh-access-token', $result); - $this->assertFalse($refreshCallbackCalled); - } - - public function testGetAccessTokenNoLockRequiredWhenNotExpired(): void { - $userId = 'testuser'; - $validTokenData = [ - 'access_token' => 'valid-access-token', - 'refresh_token' => 'refresh-token', - 'expires_at' => time() + 3600, // Valid for 1 hour - ]; - - $this->config->method('getUserValue') - ->willReturn('encrypted-data'); - - $this->crypto->method('decrypt') - ->willReturn(json_encode($validTokenData)); - - // Lock should NOT be acquired for valid tokens - $this->lockingProvider->expects($this->never()) - ->method('acquireLock'); - - $this->lockingProvider->expects($this->never()) - ->method('releaseLock'); - - $result = $this->storage->getAccessToken($userId); - - $this->assertEquals('valid-access-token', $result); - } - - // ========================================================================= - // App Password Storage Tests (Multi-User Basic Auth) - // ========================================================================= - - public function testStoreBackgroundSyncPassword(): void { - $userId = 'testuser'; - $appPassword = 'app-password-secret'; - - $this->crypto->expects($this->once()) - ->method('encrypt') - ->with($appPassword) - ->willReturn('encrypted-password'); - - // Expect three setUserValue calls: password, type, timestamp - $this->config->expects($this->exactly(3)) - ->method('setUserValue') - ->willReturnCallback(function ($uid, $app, $key, $value) use ($userId) { - $this->assertEquals($userId, $uid); - $this->assertEquals('astrolabe', $app); - $this->assertContains($key, [ - 'background_sync_password', - 'background_sync_type', - 'background_sync_provisioned_at' - ]); - return null; - }); - - $this->storage->storeBackgroundSyncPassword($userId, $appPassword); - } - - public function testGetBackgroundSyncPasswordReturnsPassword(): void { - $userId = 'testuser'; - $appPassword = 'app-password-secret'; - - $this->config->method('getUserValue') - ->with($userId, 'astrolabe', 'background_sync_password', '') - ->willReturn('encrypted-password'); - - $this->crypto->method('decrypt') - ->with('encrypted-password') - ->willReturn($appPassword); - - $result = $this->storage->getBackgroundSyncPassword($userId); - - $this->assertEquals($appPassword, $result); - } - - public function testGetBackgroundSyncPasswordReturnsNullWhenNotSet(): void { - $userId = 'testuser'; - - $this->config->method('getUserValue') - ->with($userId, 'astrolabe', 'background_sync_password', '') - ->willReturn(''); - - $result = $this->storage->getBackgroundSyncPassword($userId); - - $this->assertNull($result); - } - - public function testGetBackgroundSyncPasswordReturnsNullOnDecryptionFailure(): void { - $userId = 'testuser'; - - $this->config->method('getUserValue') - ->willReturn('encrypted-password'); - - $this->crypto->method('decrypt') - ->willThrowException(new \Exception('Decryption failed')); - - $result = $this->storage->getBackgroundSyncPassword($userId); - - $this->assertNull($result); - } - - public function testDeleteBackgroundSyncPassword(): void { - $userId = 'testuser'; - - // Expect three deleteUserValue calls - $this->config->expects($this->exactly(3)) - ->method('deleteUserValue') - ->willReturnCallback(function ($uid, $app, $key) use ($userId) { - $this->assertEquals($userId, $uid); - $this->assertEquals('astrolabe', $app); - $this->assertContains($key, [ - 'background_sync_password', - 'background_sync_type', - 'background_sync_provisioned_at' - ]); - return null; - }); - - $this->storage->deleteBackgroundSyncPassword($userId); - } - - // ========================================================================= - // Background Sync Access Check Tests - // ========================================================================= - - public function testHasBackgroundSyncAccessReturnsTrueWithOAuthToken(): void { - $userId = 'testuser'; - $tokenData = [ - 'access_token' => 'access-token', - 'refresh_token' => 'refresh-token', - 'expires_at' => time() + 3600, - ]; - - $this->config->method('getUserValue') - ->willReturnCallback(function ($uid, $app, $key, $default) use ($tokenData) { - if ($key === 'oauth_tokens') { - return 'encrypted-oauth-data'; - } - return $default; - }); - - $this->crypto->method('decrypt') - ->willReturn(json_encode($tokenData)); - - $result = $this->storage->hasBackgroundSyncAccess($userId); - - $this->assertTrue($result); - } - - public function testHasBackgroundSyncAccessReturnsTrueWithAppPassword(): void { - $userId = 'testuser'; - - $this->config->method('getUserValue') - ->willReturnCallback(function ($uid, $app, $key, $default) { - if ($key === 'oauth_tokens') { - return ''; // No OAuth tokens - } - if ($key === 'background_sync_password') { - return 'encrypted-password'; - } - return $default; - }); - - $this->crypto->method('decrypt') - ->willReturn('decrypted-app-password'); - - $result = $this->storage->hasBackgroundSyncAccess($userId); - - $this->assertTrue($result); - } - - public function testHasBackgroundSyncAccessReturnsFalseWithNeither(): void { - $userId = 'testuser'; - - $this->config->method('getUserValue') - ->willReturn(''); // No tokens or passwords - - $result = $this->storage->hasBackgroundSyncAccess($userId); - - $this->assertFalse($result); - } - - // ========================================================================= - // Background Sync Type Tests - // ========================================================================= - - public function testGetBackgroundSyncTypeReturnsAppPassword(): void { - $userId = 'testuser'; - - $this->config->method('getUserValue') - ->willReturnCallback(function ($uid, $app, $key, $default) { - if ($key === 'background_sync_type') { - return 'app_password'; - } - return $default; - }); - - $result = $this->storage->getBackgroundSyncType($userId); - - $this->assertEquals('app_password', $result); - } - - public function testGetBackgroundSyncTypeFallsBackToOAuth(): void { - $userId = 'testuser'; - $tokenData = [ - 'access_token' => 'access-token', - 'refresh_token' => 'refresh-token', - 'expires_at' => time() + 3600, - ]; - - $this->config->method('getUserValue') - ->willReturnCallback(function ($uid, $app, $key, $default) { - if ($key === 'background_sync_type') { - return ''; // Type not explicitly set - } - if ($key === 'oauth_tokens') { - return 'encrypted-oauth-data'; - } - return $default; - }); - - $this->crypto->method('decrypt') - ->willReturn(json_encode($tokenData)); - - $result = $this->storage->getBackgroundSyncType($userId); - - $this->assertEquals('oauth', $result); - } - - public function testGetBackgroundSyncTypeReturnsNullWhenNotProvisioned(): void { - $userId = 'testuser'; - - $this->config->method('getUserValue') - ->willReturn(''); - - $result = $this->storage->getBackgroundSyncType($userId); - - $this->assertNull($result); - } - - // ========================================================================= - // Background Sync Provisioned Timestamp Tests - // ========================================================================= - - public function testGetBackgroundSyncProvisionedAtReturnsTimestamp(): void { - $userId = 'testuser'; - $timestamp = time(); - - $this->config->method('getUserValue') - ->with($userId, 'astrolabe', 'background_sync_provisioned_at', '') - ->willReturn((string)$timestamp); - - $result = $this->storage->getBackgroundSyncProvisionedAt($userId); - - $this->assertEquals($timestamp, $result); - } - - public function testGetBackgroundSyncProvisionedAtReturnsNullWhenNotSet(): void { - $userId = 'testuser'; - - $this->config->method('getUserValue') - ->with($userId, 'astrolabe', 'background_sync_provisioned_at', '') - ->willReturn(''); - - $result = $this->storage->getBackgroundSyncProvisionedAt($userId); - - $this->assertNull($result); - } - - // ========================================================================= - // getAllUsersWithTokens Tests - // ========================================================================= - - public function testGetAllUsersWithTokensReturnsUserIds(): void { - $qb = $this->createMock(IQueryBuilder::class); - $expr = $this->createMock(IExpressionBuilder::class); - $result = $this->createMock(IResult::class); - - // Chain builder methods - $qb->method('select')->willReturnSelf(); - $qb->method('from')->willReturnSelf(); - $qb->method('where')->willReturnSelf(); - $qb->method('andWhere')->willReturnSelf(); - $qb->method('expr')->willReturn($expr); - $qb->method('createNamedParameter')->willReturnArgument(0); - $qb->method('executeQuery')->willReturn($result); - - // Mock expression builder - $expr->method('eq')->willReturn('mocked_condition'); - - // Mock result set with multiple users - $result->method('fetch')->willReturnOnConsecutiveCalls( - ['userid' => 'admin'], - ['userid' => 'alice'], - ['userid' => 'bob'], - false // End of results - ); - $result->expects($this->once())->method('closeCursor'); - - $this->db->method('getQueryBuilder')->willReturn($qb); - - $userIds = $this->storage->getAllUsersWithTokens(); - - $this->assertEquals(['admin', 'alice', 'bob'], $userIds); - } - - public function testGetAllUsersWithTokensReturnsEmptyArrayWhenNoTokens(): void { - $qb = $this->createMock(IQueryBuilder::class); - $expr = $this->createMock(IExpressionBuilder::class); - $result = $this->createMock(IResult::class); - - // Chain builder methods - $qb->method('select')->willReturnSelf(); - $qb->method('from')->willReturnSelf(); - $qb->method('where')->willReturnSelf(); - $qb->method('andWhere')->willReturnSelf(); - $qb->method('expr')->willReturn($expr); - $qb->method('createNamedParameter')->willReturnArgument(0); - $qb->method('executeQuery')->willReturn($result); - - // Mock expression builder - $expr->method('eq')->willReturn('mocked_condition'); - - // Mock empty result set - $result->method('fetch')->willReturn(false); - $result->expects($this->once())->method('closeCursor'); - - $this->db->method('getQueryBuilder')->willReturn($qb); - - $userIds = $this->storage->getAllUsersWithTokens(); - - $this->assertEquals([], $userIds); - } - - public function testGetAllUsersWithTokensWithLimitAndOffset(): void { - $qb = $this->createMock(IQueryBuilder::class); - $expr = $this->createMock(IExpressionBuilder::class); - $result = $this->createMock(IResult::class); - - // Chain builder methods - $qb->method('select')->willReturnSelf(); - $qb->method('from')->willReturnSelf(); - $qb->method('where')->willReturnSelf(); - $qb->method('andWhere')->willReturnSelf(); - $qb->method('expr')->willReturn($expr); - $qb->method('createNamedParameter')->willReturnArgument(0); - $qb->method('executeQuery')->willReturn($result); - - // Verify setMaxResults and setFirstResult are called with correct values - $qb->expects($this->once()) - ->method('setMaxResults') - ->with(50) - ->willReturnSelf(); - $qb->expects($this->once()) - ->method('setFirstResult') - ->with(100) - ->willReturnSelf(); - - // Mock expression builder - $expr->method('eq')->willReturn('mocked_condition'); - - // Mock result set - $result->method('fetch')->willReturnOnConsecutiveCalls( - ['userid' => 'user1'], - ['userid' => 'user2'], - false - ); - $result->expects($this->once())->method('closeCursor'); - - $this->db->method('getQueryBuilder')->willReturn($qb); - - $userIds = $this->storage->getAllUsersWithTokens(50, 100); - - $this->assertEquals(['user1', 'user2'], $userIds); - } - - public function testGetAllUsersWithTokensWithZeroLimitDoesNotSetMaxResults(): void { - $qb = $this->createMock(IQueryBuilder::class); - $expr = $this->createMock(IExpressionBuilder::class); - $result = $this->createMock(IResult::class); - - // Chain builder methods - $qb->method('select')->willReturnSelf(); - $qb->method('from')->willReturnSelf(); - $qb->method('where')->willReturnSelf(); - $qb->method('andWhere')->willReturnSelf(); - $qb->method('expr')->willReturn($expr); - $qb->method('createNamedParameter')->willReturnArgument(0); - $qb->method('executeQuery')->willReturn($result); - - // setMaxResults should NOT be called when limit is 0 - $qb->expects($this->never()) - ->method('setMaxResults'); - - // setFirstResult should NOT be called when offset is 0 - $qb->expects($this->never()) - ->method('setFirstResult'); - - // Mock expression builder - $expr->method('eq')->willReturn('mocked_condition'); - - // Mock result set - $result->method('fetch')->willReturn(false); - $result->expects($this->once())->method('closeCursor'); - - $this->db->method('getQueryBuilder')->willReturn($qb); - - $this->storage->getAllUsersWithTokens(0, 0); - } -} diff --git a/third_party/astrolabe/tests/unit/bootstrap.php b/third_party/astrolabe/tests/unit/bootstrap.php deleted file mode 100644 index a0d0e46..0000000 --- a/third_party/astrolabe/tests/unit/bootstrap.php +++ /dev/null @@ -1,13 +0,0 @@ - - - - . - - - - ../../lib - - - diff --git a/third_party/astrolabe/vendor-bin/cs-fixer/composer.json b/third_party/astrolabe/vendor-bin/cs-fixer/composer.json deleted file mode 100644 index dc131e7..0000000 --- a/third_party/astrolabe/vendor-bin/cs-fixer/composer.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "require-dev": { - "nextcloud/coding-standard": "^1.2" - }, - "config": { - "platform": { - "php": "8.1" - } - } -} diff --git a/third_party/astrolabe/vendor-bin/cs-fixer/composer.lock b/third_party/astrolabe/vendor-bin/cs-fixer/composer.lock deleted file mode 100644 index 62f4f6e..0000000 --- a/third_party/astrolabe/vendor-bin/cs-fixer/composer.lock +++ /dev/null @@ -1,171 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "59bdbac023efd7059e30cfd98dc00b94", - "packages": [], - "packages-dev": [ - { - "name": "kubawerlos/php-cs-fixer-custom-fixers", - "version": "v3.35.1", - "source": { - "type": "git", - "url": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers.git", - "reference": "2a35f80ae24ca77443a7af1599c3a3db1b6bd395" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/kubawerlos/php-cs-fixer-custom-fixers/zipball/2a35f80ae24ca77443a7af1599c3a3db1b6bd395", - "reference": "2a35f80ae24ca77443a7af1599c3a3db1b6bd395", - "shasum": "" - }, - "require": { - "ext-filter": "*", - "ext-tokenizer": "*", - "friendsofphp/php-cs-fixer": "^3.87", - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.6.24 || ^10.5.51 || ^11.5.32" - }, - "type": "library", - "autoload": { - "psr-4": { - "PhpCsFixerCustomFixers\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Kuba Werłos", - "email": "werlos@gmail.com" - } - ], - "description": "A set of custom fixers for PHP CS Fixer", - "support": { - "issues": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers/issues", - "source": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers/tree/v3.35.1" - }, - "funding": [ - { - "url": "https://github.com/kubawerlos", - "type": "github" - } - ], - "time": "2025-09-28T18:43:35+00:00" - }, - { - "name": "nextcloud/coding-standard", - "version": "v1.4.0", - "source": { - "type": "git", - "url": "https://github.com/nextcloud/coding-standard.git", - "reference": "8e06808c1423e9208d63d1bd205b9a38bd400011" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nextcloud/coding-standard/zipball/8e06808c1423e9208d63d1bd205b9a38bd400011", - "reference": "8e06808c1423e9208d63d1bd205b9a38bd400011", - "shasum": "" - }, - "require": { - "kubawerlos/php-cs-fixer-custom-fixers": "^3.22", - "php": "^8.0", - "php-cs-fixer/shim": "^3.17" - }, - "type": "library", - "autoload": { - "psr-4": { - "Nextcloud\\CodingStandard\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christoph Wurst", - "email": "christoph@winzerhof-wurst.at" - } - ], - "description": "Nextcloud coding standards for the php cs fixer", - "keywords": [ - "dev" - ], - "support": { - "issues": "https://github.com/nextcloud/coding-standard/issues", - "source": "https://github.com/nextcloud/coding-standard/tree/v1.4.0" - }, - "time": "2025-06-19T12:27:27+00:00" - }, - { - "name": "php-cs-fixer/shim", - "version": "v3.92.0", - "source": { - "type": "git", - "url": "https://github.com/PHP-CS-Fixer/shim.git", - "reference": "79e39b0d57adfd84c402d7b171b925d1e638597f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/shim/zipball/79e39b0d57adfd84c402d7b171b925d1e638597f", - "reference": "79e39b0d57adfd84c402d7b171b925d1e638597f", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-tokenizer": "*", - "php": "^7.4 || ^8.0" - }, - "replace": { - "friendsofphp/php-cs-fixer": "self.version" - }, - "suggest": { - "ext-dom": "For handling output formats in XML", - "ext-mbstring": "For handling non-UTF8 characters." - }, - "bin": [ - "php-cs-fixer", - "php-cs-fixer.phar" - ], - "type": "application", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Dariusz Rumiński", - "email": "dariusz.ruminski@gmail.com" - } - ], - "description": "A tool to automatically fix PHP code style", - "support": { - "issues": "https://github.com/PHP-CS-Fixer/shim/issues", - "source": "https://github.com/PHP-CS-Fixer/shim/tree/v3.92.0" - }, - "time": "2025-12-12T10:29:50+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": {}, - "prefer-stable": false, - "prefer-lowest": false, - "platform": {}, - "platform-dev": {}, - "platform-overrides": { - "php": "8.1" - }, - "plugin-api-version": "2.6.0" -} diff --git a/third_party/astrolabe/vendor-bin/openapi-extractor/composer.json b/third_party/astrolabe/vendor-bin/openapi-extractor/composer.json deleted file mode 100644 index 8ddb85d..0000000 --- a/third_party/astrolabe/vendor-bin/openapi-extractor/composer.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "require-dev": { - "nextcloud/openapi-extractor": "v1.8.7" - }, - "config": { - "platform": { - "php": "8.1" - } - } -} diff --git a/third_party/astrolabe/vendor-bin/openapi-extractor/composer.lock b/third_party/astrolabe/vendor-bin/openapi-extractor/composer.lock deleted file mode 100644 index d82d0ba..0000000 --- a/third_party/astrolabe/vendor-bin/openapi-extractor/composer.lock +++ /dev/null @@ -1,247 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "384d95db63f1a0aae08a0ae123ecf4bb", - "packages": [], - "packages-dev": [ - { - "name": "adhocore/cli", - "version": "v1.9.4", - "source": { - "type": "git", - "url": "https://github.com/adhocore/php-cli.git", - "reference": "474dc3d7ab139796be98b104d891476e3916b6f4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/adhocore/php-cli/zipball/474dc3d7ab139796be98b104d891476e3916b6f4", - "reference": "474dc3d7ab139796be98b104d891476e3916b6f4", - "shasum": "" - }, - "require": { - "php": ">=8.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Ahc\\Cli\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jitendra Adhikari", - "email": "jiten.adhikary@gmail.com" - } - ], - "description": "Command line interface library for PHP", - "keywords": [ - "argument-parser", - "argv-parser", - "cli", - "cli-action", - "cli-app", - "cli-color", - "cli-option", - "cli-writer", - "command", - "console", - "console-app", - "php-cli", - "php8", - "stream-input", - "stream-output" - ], - "support": { - "issues": "https://github.com/adhocore/php-cli/issues", - "source": "https://github.com/adhocore/php-cli/tree/v1.9.4" - }, - "funding": [ - { - "url": "https://paypal.me/ji10", - "type": "custom" - }, - { - "url": "https://github.com/adhocore", - "type": "github" - } - ], - "time": "2025-05-11T13:23:54+00:00" - }, - { - "name": "nextcloud/openapi-extractor", - "version": "v1.8.7", - "source": { - "type": "git", - "url": "https://github.com/nextcloud-releases/openapi-extractor.git", - "reference": "230f61925c362779652b0038a1314ce5f931e853" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nextcloud-releases/openapi-extractor/zipball/230f61925c362779652b0038a1314ce5f931e853", - "reference": "230f61925c362779652b0038a1314ce5f931e853", - "shasum": "" - }, - "require": { - "adhocore/cli": "^1.7", - "ext-simplexml": "*", - "nikic/php-parser": "^5.0", - "php": "^8.1", - "phpstan/phpdoc-parser": "^2.1" - }, - "require-dev": { - "nextcloud/coding-standard": "^1.4.0", - "nextcloud/ocp": "dev-master", - "rector/rector": "^2.2.8" - }, - "bin": [ - "bin/generate-spec", - "bin/merge-specs" - ], - "type": "library", - "autoload": { - "psr-4": { - "OpenAPIExtractor\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "AGPL-3.0-or-later" - ], - "description": "A tool for extracting OpenAPI specifications from Nextcloud source code", - "support": { - "issues": "https://github.com/nextcloud-releases/openapi-extractor/issues", - "source": "https://github.com/nextcloud-releases/openapi-extractor/tree/v1.8.7" - }, - "time": "2025-12-02T09:52:06+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v5.7.0", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "ext-json": "*", - "ext-tokenizer": "*", - "php": ">=7.4" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" - }, - "time": "2025-12-06T11:56:16+00:00" - }, - { - "name": "phpstan/phpdoc-parser", - "version": "2.3.0", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/1e0cd5370df5dd2e556a36b9c62f62e555870495", - "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "doctrine/annotations": "^2.0", - "nikic/php-parser": "^5.3.0", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^2.0", - "phpstan/phpstan-phpunit": "^2.0", - "phpstan/phpstan-strict-rules": "^2.0", - "phpunit/phpunit": "^9.6", - "symfony/process": "^5.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "PHPStan\\PhpDocParser\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPDoc parser with support for nullable, intersection and generic types", - "support": { - "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.0" - }, - "time": "2025-08-30T15:50:23+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": {}, - "prefer-stable": false, - "prefer-lowest": false, - "platform": {}, - "platform-dev": {}, - "platform-overrides": { - "php": "8.1" - }, - "plugin-api-version": "2.9.0" -} diff --git a/third_party/astrolabe/vendor-bin/phpunit/composer.json b/third_party/astrolabe/vendor-bin/phpunit/composer.json deleted file mode 100644 index fe8b171..0000000 --- a/third_party/astrolabe/vendor-bin/phpunit/composer.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "require-dev": { - "phpunit/phpunit": "^10.5" - }, - "config": { - "platform": { - "php": "8.1" - } - } -} diff --git a/third_party/astrolabe/vendor-bin/phpunit/composer.lock b/third_party/astrolabe/vendor-bin/phpunit/composer.lock deleted file mode 100644 index 66efdef..0000000 --- a/third_party/astrolabe/vendor-bin/phpunit/composer.lock +++ /dev/null @@ -1,1691 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "fb78960ff7e774a72d424270c4bd3d90", - "packages": [], - "packages-dev": [ - { - "name": "myclabs/deep-copy", - "version": "1.13.4", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", - "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3 <3.2.2" - }, - "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpspec/prophecy": "^1.10", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" - }, - "type": "library", - "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2025-08-01T08:46:24+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v5.7.0", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "ext-json": "*", - "ext-tokenizer": "*", - "php": ">=7.4" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" - }, - "time": "2025-12-06T11:56:16+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "54750ef60c58e43759730615a392c31c80e23176" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", - "reference": "54750ef60c58e43759730615a392c31c80e23176", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2024-03-03T12:33:53+00:00" - }, - { - "name": "phar-io/version", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" - }, - "time": "2022-02-21T01:04:05+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "10.1.16", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "7e308268858ed6baedc8704a304727d20bc07c77" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", - "reference": "7e308268858ed6baedc8704a304727d20bc07c77", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^4.19.1 || ^5.1.0", - "php": ">=8.1", - "phpunit/php-file-iterator": "^4.1.0", - "phpunit/php-text-template": "^3.0.1", - "sebastian/code-unit-reverse-lookup": "^3.0.0", - "sebastian/complexity": "^3.2.0", - "sebastian/environment": "^6.1.0", - "sebastian/lines-of-code": "^2.0.2", - "sebastian/version": "^4.0.1", - "theseer/tokenizer": "^1.2.3" - }, - "require-dev": { - "phpunit/phpunit": "^10.1" - }, - "suggest": { - "ext-pcov": "PHP extension that provides line coverage", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "10.1.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-08-22T04:31:57+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "4.1.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-08-31T06:24:48+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "4.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^10.0" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:56:09+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "3.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-08-31T14:07:24+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "6.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:57:52+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "10.5.63", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "33198268dad71e926626b618f3ec3966661e4d90" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/33198268dad71e926626b618f3ec3966661e4d90", - "reference": "33198268dad71e926626b618f3ec3966661e4d90", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.13.4", - "phar-io/manifest": "^2.0.4", - "phar-io/version": "^3.2.1", - "php": ">=8.1", - "phpunit/php-code-coverage": "^10.1.16", - "phpunit/php-file-iterator": "^4.1.0", - "phpunit/php-invoker": "^4.0.0", - "phpunit/php-text-template": "^3.0.1", - "phpunit/php-timer": "^6.0.0", - "sebastian/cli-parser": "^2.0.1", - "sebastian/code-unit": "^2.0.0", - "sebastian/comparator": "^5.0.5", - "sebastian/diff": "^5.1.1", - "sebastian/environment": "^6.1.0", - "sebastian/exporter": "^5.1.4", - "sebastian/global-state": "^6.0.2", - "sebastian/object-enumerator": "^5.0.0", - "sebastian/recursion-context": "^5.0.1", - "sebastian/type": "^4.0.0", - "sebastian/version": "^4.0.1" - }, - "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "10.5-dev" - } - }, - "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.63" - }, - "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", - "type": "tidelift" - } - ], - "time": "2026-01-27T05:48:37+00:00" - }, - { - "name": "sebastian/cli-parser", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", - "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", - "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-02T07:12:49+00:00" - }, - { - "name": "sebastian/code-unit", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:58:43+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:59:15+00:00" - }, - { - "name": "sebastian/comparator", - "version": "5.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "55dfef806eb7dfeb6e7a6935601fef866f8ca48d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55dfef806eb7dfeb6e7a6935601fef866f8ca48d", - "reference": "55dfef806eb7dfeb6e7a6935601fef866f8ca48d", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/diff": "^5.0", - "sebastian/exporter": "^5.0" - }, - "require-dev": { - "phpunit/phpunit": "^10.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", - "type": "tidelift" - } - ], - "time": "2026-01-24T09:25:16+00:00" - }, - { - "name": "sebastian/complexity", - "version": "3.2.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "68ff824baeae169ec9f2137158ee529584553799" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", - "reference": "68ff824baeae169ec9f2137158ee529584553799", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "security": "https://github.com/sebastianbergmann/complexity/security/policy", - "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-12-21T08:37:17+00:00" - }, - { - "name": "sebastian/diff", - "version": "5.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0", - "symfony/process": "^6.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-02T07:15:17+00:00" - }, - { - "name": "sebastian/environment", - "version": "6.1.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", - "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "https://github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-23T08:47:14+00:00" - }, - { - "name": "sebastian/exporter", - "version": "5.1.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "0735b90f4da94969541dac1da743446e276defa6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/0735b90f4da94969541dac1da743446e276defa6", - "reference": "0735b90f4da94969541dac1da743446e276defa6", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/recursion-context": "^5.0" - }, - "require-dev": { - "phpunit/phpunit": "^10.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", - "type": "tidelift" - } - ], - "time": "2025-09-24T06:09:11+00:00" - }, - { - "name": "sebastian/global-state", - "version": "6.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", - "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" - }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "https://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-02T07:19:19+00:00" - }, - { - "name": "sebastian/lines-of-code", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-12-21T08:38:20+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "5.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T07:08:32+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T07:06:18+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "5.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "47e34210757a2f37a97dcd207d032e1b01e64c7a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/47e34210757a2f37a97dcd207d032e1b01e64c7a", - "reference": "47e34210757a2f37a97dcd207d032e1b01e64c7a", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "https://github.com/sebastianbergmann/recursion-context", - "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", - "type": "tidelift" - } - ], - "time": "2025-08-10T07:50:56+00:00" - }, - { - "name": "sebastian/type", - "version": "4.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", - "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T07:10:45+00:00" - }, - { - "name": "sebastian/version", - "version": "4.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-07T11:34:05+00:00" - }, - { - "name": "theseer/tokenizer", - "version": "1.3.1", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", - "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.3.1" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2025-11-17T20:03:58+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": {}, - "prefer-stable": false, - "prefer-lowest": false, - "platform": {}, - "platform-dev": {}, - "platform-overrides": { - "php": "8.1" - }, - "plugin-api-version": "2.9.0" -} diff --git a/third_party/astrolabe/vendor-bin/psalm/composer.json b/third_party/astrolabe/vendor-bin/psalm/composer.json deleted file mode 100644 index 553d5af..0000000 --- a/third_party/astrolabe/vendor-bin/psalm/composer.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "require-dev": { - "vimeo/psalm": "^5.23" - }, - "config": { - "platform": { - "php": "8.1" - } - } -} diff --git a/third_party/astrolabe/vendor-bin/psalm/composer.lock b/third_party/astrolabe/vendor-bin/psalm/composer.lock deleted file mode 100644 index c1b8b07..0000000 --- a/third_party/astrolabe/vendor-bin/psalm/composer.lock +++ /dev/null @@ -1,2122 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "32bf499f5e7a4c18979304cf254c2878", - "packages": [], - "packages-dev": [ - { - "name": "amphp/amp", - "version": "v2.6.5", - "source": { - "type": "git", - "url": "https://github.com/amphp/amp.git", - "reference": "d7dda98dae26e56f3f6fcfbf1c1f819c9a993207" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/amp/zipball/d7dda98dae26e56f3f6fcfbf1c1f819c9a993207", - "reference": "d7dda98dae26e56f3f6fcfbf1c1f819c9a993207", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1", - "ext-json": "*", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^7 | ^8 | ^9", - "react/promise": "^2", - "vimeo/psalm": "^3.12" - }, - "type": "library", - "autoload": { - "files": [ - "lib/functions.php", - "lib/Internal/functions.php" - ], - "psr-4": { - "Amp\\": "lib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Bob Weinand", - "email": "bobwei9@hotmail.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A non-blocking concurrency framework for PHP applications.", - "homepage": "https://amphp.org/amp", - "keywords": [ - "async", - "asynchronous", - "awaitable", - "concurrency", - "event", - "event-loop", - "future", - "non-blocking", - "promise" - ], - "support": { - "irc": "irc://irc.freenode.org/amphp", - "issues": "https://github.com/amphp/amp/issues", - "source": "https://github.com/amphp/amp/tree/v2.6.5" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2025-09-03T19:41:28+00:00" - }, - { - "name": "amphp/byte-stream", - "version": "v1.8.2", - "source": { - "type": "git", - "url": "https://github.com/amphp/byte-stream.git", - "reference": "4f0e968ba3798a423730f567b1b50d3441c16ddc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/byte-stream/zipball/4f0e968ba3798a423730f567b1b50d3441c16ddc", - "reference": "4f0e968ba3798a423730f567b1b50d3441c16ddc", - "shasum": "" - }, - "require": { - "amphp/amp": "^2", - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1.4", - "friendsofphp/php-cs-fixer": "^2.3", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^6 || ^7 || ^8", - "psalm/phar": "^3.11.4" - }, - "type": "library", - "autoload": { - "files": [ - "lib/functions.php" - ], - "psr-4": { - "Amp\\ByteStream\\": "lib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A stream abstraction to make working with non-blocking I/O simple.", - "homepage": "https://amphp.org/byte-stream", - "keywords": [ - "amp", - "amphp", - "async", - "io", - "non-blocking", - "stream" - ], - "support": { - "issues": "https://github.com/amphp/byte-stream/issues", - "source": "https://github.com/amphp/byte-stream/tree/v1.8.2" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2024-04-13T18:00:56+00:00" - }, - { - "name": "composer/pcre", - "version": "3.3.2", - "source": { - "type": "git", - "url": "https://github.com/composer/pcre.git", - "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", - "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0" - }, - "conflict": { - "phpstan/phpstan": "<1.11.10" - }, - "require-dev": { - "phpstan/phpstan": "^1.12 || ^2", - "phpstan/phpstan-strict-rules": "^1 || ^2", - "phpunit/phpunit": "^8 || ^9" - }, - "type": "library", - "extra": { - "phpstan": { - "includes": [ - "extension.neon" - ] - }, - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Pcre\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "PCRE wrapping library that offers type-safe preg_* replacements.", - "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" - ], - "support": { - "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.3.2" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2024-11-12T16:29:46+00:00" - }, - { - "name": "composer/semver", - "version": "3.4.4", - "source": { - "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95", - "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.11", - "symfony/phpunit-bridge": "^3 || ^7" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Semver\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - }, - { - "name": "Rob Bast", - "email": "rob.bast@gmail.com", - "homepage": "http://robbast.nl" - } - ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", - "keywords": [ - "semantic", - "semver", - "validation", - "versioning" - ], - "support": { - "irc": "ircs://irc.libera.chat:6697/composer", - "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.4.4" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - } - ], - "time": "2025-08-20T19:15:30+00:00" - }, - { - "name": "composer/xdebug-handler", - "version": "3.0.5", - "source": { - "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", - "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", - "shasum": "" - }, - "require": { - "composer/pcre": "^1 || ^2 || ^3", - "php": "^7.2.5 || ^8.0", - "psr/log": "^1 || ^2 || ^3" - }, - "require-dev": { - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without Xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], - "support": { - "irc": "ircs://irc.libera.chat:6697/composer", - "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2024-05-06T16:37:16+00:00" - }, - { - "name": "dnoegel/php-xdg-base-dir", - "version": "v0.1.1", - "source": { - "type": "git", - "url": "https://github.com/dnoegel/php-xdg-base-dir.git", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "require-dev": { - "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" - }, - "type": "library", - "autoload": { - "psr-4": { - "XdgBaseDir\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "implementation of xdg base directory specification for php", - "support": { - "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", - "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" - }, - "time": "2019-12-04T15:06:13+00:00" - }, - { - "name": "doctrine/deprecations", - "version": "1.1.5", - "source": { - "type": "git", - "url": "https://github.com/doctrine/deprecations.git", - "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", - "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "phpunit/phpunit": "<=7.5 || >=13" - }, - "require-dev": { - "doctrine/coding-standard": "^9 || ^12 || ^13", - "phpstan/phpstan": "1.4.10 || 2.1.11", - "phpstan/phpstan-phpunit": "^1.0 || ^2", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12", - "psr/log": "^1 || ^2 || ^3" - }, - "suggest": { - "psr/log": "Allows logging deprecations via PSR-3 logger implementation" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Deprecations\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", - "homepage": "https://www.doctrine-project.org/", - "support": { - "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.5" - }, - "time": "2025-04-07T20:06:18+00:00" - }, - { - "name": "felixfbecker/advanced-json-rpc", - "version": "v3.2.1", - "source": { - "type": "git", - "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447", - "shasum": "" - }, - "require": { - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "php": "^7.1 || ^8.0", - "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0" - }, - "require-dev": { - "phpunit/phpunit": "^7.0 || ^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "AdvancedJsonRpc\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" - ], - "authors": [ - { - "name": "Felix Becker", - "email": "felix.b@outlook.com" - } - ], - "description": "A more advanced JSONRPC implementation", - "support": { - "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", - "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1" - }, - "time": "2021-06-11T22:34:44+00:00" - }, - { - "name": "felixfbecker/language-server-protocol", - "version": "v1.5.3", - "source": { - "type": "git", - "url": "https://github.com/felixfbecker/php-language-server-protocol.git", - "reference": "a9e113dbc7d849e35b8776da39edaf4313b7b6c9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/a9e113dbc7d849e35b8776da39edaf4313b7b6c9", - "reference": "a9e113dbc7d849e35b8776da39edaf4313b7b6c9", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "phpstan/phpstan": "*", - "squizlabs/php_codesniffer": "^3.1", - "vimeo/psalm": "^4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "LanguageServerProtocol\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" - ], - "authors": [ - { - "name": "Felix Becker", - "email": "felix.b@outlook.com" - } - ], - "description": "PHP classes for the Language Server Protocol", - "keywords": [ - "language", - "microsoft", - "php", - "server" - ], - "support": { - "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", - "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.3" - }, - "time": "2024-04-30T00:40:11+00:00" - }, - { - "name": "fidry/cpu-core-counter", - "version": "1.3.0", - "source": { - "type": "git", - "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "db9508f7b1474469d9d3c53b86f817e344732678" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/db9508f7b1474469d9d3c53b86f817e344732678", - "reference": "db9508f7b1474469d9d3c53b86f817e344732678", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "fidry/makefile": "^0.2.0", - "fidry/php-cs-fixer-config": "^1.1.2", - "phpstan/extension-installer": "^1.2.0", - "phpstan/phpstan": "^2.0", - "phpstan/phpstan-deprecation-rules": "^2.0.0", - "phpstan/phpstan-phpunit": "^2.0", - "phpstan/phpstan-strict-rules": "^2.0", - "phpunit/phpunit": "^8.5.31 || ^9.5.26", - "webmozarts/strict-phpunit": "^7.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Fidry\\CpuCoreCounter\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Théo FIDRY", - "email": "theo.fidry@gmail.com" - } - ], - "description": "Tiny utility to get the number of CPU cores.", - "keywords": [ - "CPU", - "core" - ], - "support": { - "issues": "https://github.com/theofidry/cpu-core-counter/issues", - "source": "https://github.com/theofidry/cpu-core-counter/tree/1.3.0" - }, - "funding": [ - { - "url": "https://github.com/theofidry", - "type": "github" - } - ], - "time": "2025-08-14T07:29:31+00:00" - }, - { - "name": "netresearch/jsonmapper", - "version": "v4.5.0", - "source": { - "type": "git", - "url": "https://github.com/cweiske/jsonmapper.git", - "reference": "8e76efb98ee8b6afc54687045e1b8dba55ac76e5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8e76efb98ee8b6afc54687045e1b8dba55ac76e5", - "reference": "8e76efb98ee8b6afc54687045e1b8dba55ac76e5", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=7.1" - }, - "require-dev": { - "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0 || ~10.0", - "squizlabs/php_codesniffer": "~3.5" - }, - "type": "library", - "autoload": { - "psr-0": { - "JsonMapper": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "OSL-3.0" - ], - "authors": [ - { - "name": "Christian Weiske", - "email": "cweiske@cweiske.de", - "homepage": "http://github.com/cweiske/jsonmapper/", - "role": "Developer" - } - ], - "description": "Map nested JSON structures onto PHP classes", - "support": { - "email": "cweiske@cweiske.de", - "issues": "https://github.com/cweiske/jsonmapper/issues", - "source": "https://github.com/cweiske/jsonmapper/tree/v4.5.0" - }, - "time": "2024-09-08T10:13:13+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v4.19.5", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "51bd93cc741b7fc3d63d20b6bdcd99fdaa359837" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/51bd93cc741b7fc3d63d20b6bdcd99fdaa359837", - "reference": "51bd93cc741b7fc3d63d20b6bdcd99fdaa359837", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.1" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.19.5" - }, - "time": "2025-12-06T11:45:25+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" - }, - "time": "2020-06-27T09:03:43+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "5.6.5", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "90614c73d3800e187615e2dd236ad0e2a01bf761" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/90614c73d3800e187615e2dd236ad0e2a01bf761", - "reference": "90614c73d3800e187615e2dd236ad0e2a01bf761", - "shasum": "" - }, - "require": { - "doctrine/deprecations": "^1.1", - "ext-filter": "*", - "php": "^7.4 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.7", - "phpstan/phpdoc-parser": "^1.7|^2.0", - "webmozart/assert": "^1.9.1" - }, - "require-dev": { - "mockery/mockery": "~1.3.5 || ~1.6.0", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-mockery": "^1.1", - "phpstan/phpstan-webmozart-assert": "^1.2", - "phpunit/phpunit": "^9.5", - "psalm/phar": "^5.26" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.5" - }, - "time": "2025-11-27T19:50:05+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.12.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "92a98ada2b93d9b201a613cb5a33584dde25f195" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/92a98ada2b93d9b201a613cb5a33584dde25f195", - "reference": "92a98ada2b93d9b201a613cb5a33584dde25f195", - "shasum": "" - }, - "require": { - "doctrine/deprecations": "^1.0", - "php": "^7.3 || ^8.0", - "phpdocumentor/reflection-common": "^2.0", - "phpstan/phpdoc-parser": "^1.18|^2.0" - }, - "require-dev": { - "ext-tokenizer": "*", - "phpbench/phpbench": "^1.2", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", - "phpunit/phpunit": "^9.5", - "rector/rector": "^0.13.9", - "vimeo/psalm": "^4.25" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.12.0" - }, - "time": "2025-11-21T15:09:14+00:00" - }, - { - "name": "phpstan/phpdoc-parser", - "version": "2.3.0", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/1e0cd5370df5dd2e556a36b9c62f62e555870495", - "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "doctrine/annotations": "^2.0", - "nikic/php-parser": "^5.3.0", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^2.0", - "phpstan/phpstan-phpunit": "^2.0", - "phpstan/phpstan-strict-rules": "^2.0", - "phpunit/phpunit": "^9.6", - "symfony/process": "^5.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "PHPStan\\PhpDocParser\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPDoc parser with support for nullable, intersection and generic types", - "support": { - "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.0" - }, - "time": "2025-08-30T15:50:23+00:00" - }, - { - "name": "psr/container", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" - }, - "time": "2021-11-05T16:47:00+00:00" - }, - { - "name": "psr/log", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/3.0.2" - }, - "time": "2024-09-11T13:17:53+00:00" - }, - { - "name": "sebastian/diff", - "version": "5.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0", - "symfony/process": "^6.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-02T07:15:17+00:00" - }, - { - "name": "spatie/array-to-xml", - "version": "3.4.3", - "source": { - "type": "git", - "url": "https://github.com/spatie/array-to-xml.git", - "reference": "7b9202dccfe18d4e3a13303156d6bbcc1c61dabf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/7b9202dccfe18d4e3a13303156d6bbcc1c61dabf", - "reference": "7b9202dccfe18d4e3a13303156d6bbcc1c61dabf", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "php": "^8.0" - }, - "require-dev": { - "mockery/mockery": "^1.2", - "pestphp/pest": "^1.21", - "spatie/pest-plugin-snapshots": "^1.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Spatie\\ArrayToXml\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Freek Van der Herten", - "email": "freek@spatie.be", - "homepage": "https://freek.dev", - "role": "Developer" - } - ], - "description": "Convert an array to xml", - "homepage": "https://github.com/spatie/array-to-xml", - "keywords": [ - "array", - "convert", - "xml" - ], - "support": { - "source": "https://github.com/spatie/array-to-xml/tree/3.4.3" - }, - "funding": [ - { - "url": "https://spatie.be/open-source/support-us", - "type": "custom" - }, - { - "url": "https://github.com/spatie", - "type": "github" - } - ], - "time": "2025-11-27T09:08:26+00:00" - }, - { - "name": "symfony/console", - "version": "v6.4.30", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "1b2813049506b39eb3d7e64aff033fd5ca26c97e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/1b2813049506b39eb3d7e64aff033fd5ca26c97e", - "reference": "1b2813049506b39eb3d7e64aff033fd5ca26c97e", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^5.4|^6.0|^7.0" - }, - "conflict": { - "symfony/dependency-injection": "<5.4", - "symfony/dotenv": "<5.4", - "symfony/event-dispatcher": "<5.4", - "symfony/lock": "<5.4", - "symfony/process": "<5.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0|3.0" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/event-dispatcher": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^5.4|^6.0|^7.0", - "symfony/messenger": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/stopwatch": "^5.4|^6.0|^7.0", - "symfony/var-dumper": "^5.4|^6.0|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command-line", - "console", - "terminal" - ], - "support": { - "source": "https://github.com/symfony/console/tree/v6.4.30" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-12-05T13:47:41+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v3.6.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, - "branch-alias": { - "dev-main": "3.6-dev" - } - }, - "autoload": { - "files": [ - "function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-25T14:21:43+00:00" - }, - { - "name": "symfony/filesystem", - "version": "v6.4.30", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "441c6b69f7222aadae7cbf5df588496d5ee37789" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/441c6b69f7222aadae7cbf5df588496d5ee37789", - "reference": "441c6b69f7222aadae7cbf5df588496d5ee37789", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8" - }, - "require-dev": { - "symfony/process": "^5.4|^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.4.30" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-11-26T14:43:45+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "provide": { - "ext-ctype": "*" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-09T11:45:10+00:00" - }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's grapheme_* functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-06-27T09:58:17+00:00" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "3833d7255cc303546435cb650316bff708a1c75c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", - "reference": "3833d7255cc303546435cb650316bff708a1c75c", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "intl", - "normalizer", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-09T11:45:10+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", - "shasum": "" - }, - "require": { - "ext-iconv": "*", - "php": ">=7.2" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-12-23T08:48:59+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v3.6.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", - "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, - "branch-alias": { - "dev-main": "3.6-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-15T11:30:57+00:00" - }, - { - "name": "symfony/string", - "version": "v6.4.30", - "source": { - "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "50590a057841fa6bf69d12eceffce3465b9e32cb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/50590a057841fa6bf69d12eceffce3465b9e32cb", - "reference": "50590a057841fa6bf69d12eceffce3465b9e32cb", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/translation-contracts": "<2.5" - }, - "require-dev": { - "symfony/http-client": "^5.4|^6.0|^7.0", - "symfony/intl": "^6.2|^7.0", - "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^5.4|^6.0|^7.0" - }, - "type": "library", - "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", - "homepage": "https://symfony.com", - "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], - "support": { - "source": "https://github.com/symfony/string/tree/v6.4.30" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-11-21T18:03:05+00:00" - }, - { - "name": "vimeo/psalm", - "version": "5.26.1", - "source": { - "type": "git", - "url": "https://github.com/vimeo/psalm.git", - "reference": "d747f6500b38ac4f7dfc5edbcae6e4b637d7add0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/d747f6500b38ac4f7dfc5edbcae6e4b637d7add0", - "reference": "d747f6500b38ac4f7dfc5edbcae6e4b637d7add0", - "shasum": "" - }, - "require": { - "amphp/amp": "^2.4.2", - "amphp/byte-stream": "^1.5", - "composer-runtime-api": "^2", - "composer/semver": "^1.4 || ^2.0 || ^3.0", - "composer/xdebug-handler": "^2.0 || ^3.0", - "dnoegel/php-xdg-base-dir": "^0.1.1", - "ext-ctype": "*", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-simplexml": "*", - "ext-tokenizer": "*", - "felixfbecker/advanced-json-rpc": "^3.1", - "felixfbecker/language-server-protocol": "^1.5.2", - "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1 || ^1.0.0", - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "nikic/php-parser": "^4.17", - "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", - "sebastian/diff": "^4.0 || ^5.0 || ^6.0", - "spatie/array-to-xml": "^2.17.0 || ^3.0", - "symfony/console": "^4.1.6 || ^5.0 || ^6.0 || ^7.0", - "symfony/filesystem": "^5.4 || ^6.0 || ^7.0" - }, - "conflict": { - "nikic/php-parser": "4.17.0" - }, - "provide": { - "psalm/psalm": "self.version" - }, - "require-dev": { - "amphp/phpunit-util": "^2.0", - "bamarni/composer-bin-plugin": "^1.4", - "brianium/paratest": "^6.9", - "ext-curl": "*", - "mockery/mockery": "^1.5", - "nunomaduro/mock-final-classes": "^1.1", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpdoc-parser": "^1.6", - "phpunit/phpunit": "^9.6", - "psalm/plugin-mockery": "^1.1", - "psalm/plugin-phpunit": "^0.18", - "slevomat/coding-standard": "^8.4", - "squizlabs/php_codesniffer": "^3.6", - "symfony/process": "^4.4 || ^5.0 || ^6.0 || ^7.0" - }, - "suggest": { - "ext-curl": "In order to send data to shepherd", - "ext-igbinary": "^2.0.5 is required, used to serialize caching data" - }, - "bin": [ - "psalm", - "psalm-language-server", - "psalm-plugin", - "psalm-refactor", - "psalter" - ], - "type": "project", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev", - "dev-2.x": "2.x-dev", - "dev-3.x": "3.x-dev", - "dev-4.x": "4.x-dev", - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psalm\\": "src/Psalm/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matthew Brown" - } - ], - "description": "A static analysis tool for finding errors in PHP applications", - "keywords": [ - "code", - "inspection", - "php", - "static analysis" - ], - "support": { - "docs": "https://psalm.dev/docs", - "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm" - }, - "time": "2024-09-08T18:53:08+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.12.1", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "9be6926d8b485f55b9229203f962b51ed377ba68" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/9be6926d8b485f55b9229203f962b51ed377ba68", - "reference": "9be6926d8b485f55b9229203f962b51ed377ba68", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "ext-date": "*", - "ext-filter": "*", - "php": "^7.2 || ^8.0" - }, - "suggest": { - "ext-intl": "", - "ext-simplexml": "", - "ext-spl": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.12.1" - }, - "time": "2025-10-29T15:56:20+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": {}, - "prefer-stable": false, - "prefer-lowest": false, - "platform": {}, - "platform-dev": {}, - "platform-overrides": { - "php": "8.1" - }, - "plugin-api-version": "2.6.0" -} diff --git a/third_party/astrolabe/vendor-bin/rector/composer.json b/third_party/astrolabe/vendor-bin/rector/composer.json deleted file mode 100644 index a266a58..0000000 --- a/third_party/astrolabe/vendor-bin/rector/composer.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "require-dev": { - "rector/rector": "^1.2" - } -} diff --git a/third_party/astrolabe/vendor-bin/rector/composer.lock b/third_party/astrolabe/vendor-bin/rector/composer.lock deleted file mode 100644 index eda7387..0000000 --- a/third_party/astrolabe/vendor-bin/rector/composer.lock +++ /dev/null @@ -1,131 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "eb58f3061bde78d58fa424c73947025f", - "packages": [], - "packages-dev": [ - { - "name": "phpstan/phpstan", - "version": "1.12.32", - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/2770dcdf5078d0b0d53f94317e06affe88419aa8", - "reference": "2770dcdf5078d0b0d53f94317e06affe88419aa8", - "shasum": "" - }, - "require": { - "php": "^7.2|^8.0" - }, - "conflict": { - "phpstan/phpstan-shim": "*" - }, - "bin": [ - "phpstan", - "phpstan.phar" - ], - "type": "library", - "autoload": { - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPStan - PHP Static Analysis Tool", - "keywords": [ - "dev", - "static analysis" - ], - "support": { - "docs": "https://phpstan.org/user-guide/getting-started", - "forum": "https://github.com/phpstan/phpstan/discussions", - "issues": "https://github.com/phpstan/phpstan/issues", - "security": "https://github.com/phpstan/phpstan/security/policy", - "source": "https://github.com/phpstan/phpstan-src" - }, - "funding": [ - { - "url": "https://github.com/ondrejmirtes", - "type": "github" - }, - { - "url": "https://github.com/phpstan", - "type": "github" - } - ], - "time": "2025-09-30T10:16:31+00:00" - }, - { - "name": "rector/rector", - "version": "1.2.10", - "source": { - "type": "git", - "url": "https://github.com/rectorphp/rector.git", - "reference": "40f9cf38c05296bd32f444121336a521a293fa61" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/40f9cf38c05296bd32f444121336a521a293fa61", - "reference": "40f9cf38c05296bd32f444121336a521a293fa61", - "shasum": "" - }, - "require": { - "php": "^7.2|^8.0", - "phpstan/phpstan": "^1.12.5" - }, - "conflict": { - "rector/rector-doctrine": "*", - "rector/rector-downgrade-php": "*", - "rector/rector-phpunit": "*", - "rector/rector-symfony": "*" - }, - "suggest": { - "ext-dom": "To manipulate phpunit.xml via the custom-rule command" - }, - "bin": [ - "bin/rector" - ], - "type": "library", - "autoload": { - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Instant Upgrade and Automated Refactoring of any PHP code", - "keywords": [ - "automation", - "dev", - "migration", - "refactoring" - ], - "support": { - "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/1.2.10" - }, - "funding": [ - { - "url": "https://github.com/tomasvotruba", - "type": "github" - } - ], - "time": "2024-11-08T13:59:10+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": {}, - "prefer-stable": false, - "prefer-lowest": false, - "platform": {}, - "platform-dev": {}, - "plugin-api-version": "2.6.0" -} diff --git a/third_party/astrolabe/vite.config.js b/third_party/astrolabe/vite.config.js deleted file mode 100644 index e8f1239..0000000 --- a/third_party/astrolabe/vite.config.js +++ /dev/null @@ -1,43 +0,0 @@ -import { defineConfig } from 'vite' -import vue from '@vitejs/plugin-vue' -import { resolve } from 'path' -import { readFileSync } from 'fs' - -// Read app info from info.xml for @nextcloud/vue -const infoXml = readFileSync(resolve(__dirname, 'appinfo/info.xml'), 'utf-8') -const appName = infoXml.match(/([^<]+)<\/id>/)?.[1] || 'astrolabe' -const appVersion = infoXml.match(/([^<]+)<\/version>/)?.[1] || '' - -export default defineConfig({ - plugins: [vue()], - define: { - appName: JSON.stringify(appName), - appVersion: JSON.stringify(appVersion), - }, - build: { - outDir: '.', - emptyOutDir: false, - cssCodeSplit: false, // Bundle all CSS into entry points (Nextcloud doesn't load CSS chunks) - rollupOptions: { - input: { - 'astrolabe-main': resolve(__dirname, 'src/main.js'), - 'astrolabe-adminSettings': resolve(__dirname, 'src/adminSettings.js'), - 'astrolabe-personalSettings': resolve(__dirname, 'src/personalSettings.js'), - }, - output: { - entryFileNames: 'js/[name].mjs', - chunkFileNames: 'js/[name]-[hash].chunk.mjs', - assetFileNames: (assetInfo) => { - // With cssCodeSplit:false, all CSS goes to a single file - // Name it astrolabe-main.css to match Nextcloud's Util::addStyle expectation - if (assetInfo.name && assetInfo.name.endsWith('.css')) { - return 'css/astrolabe-main.css'; - } - return 'js/[name][extname]'; - }, - }, - }, - sourcemap: true, - minify: 'terser', - }, -}) diff --git a/third_party/astrolabe/webpack.js b/third_party/astrolabe/webpack.js deleted file mode 100644 index 49ae69e..0000000 --- a/third_party/astrolabe/webpack.js +++ /dev/null @@ -1,27 +0,0 @@ -const webpackConfig = require('@nextcloud/webpack-vue-config') -const ESLintPlugin = require('eslint-webpack-plugin') -const StyleLintPlugin = require('stylelint-webpack-plugin') -const path = require('path') - -webpackConfig.entry = { - main: { import: path.join(__dirname, 'src', 'main.js'), filename: 'main.js' }, -} - -webpackConfig.plugins.push( - new ESLintPlugin({ - extensions: ['js', 'vue'], - files: 'src', - }), -) -webpackConfig.plugins.push( - new StyleLintPlugin({ - files: 'src/**/*.{css,scss,vue}', - }), -) - -webpackConfig.module.rules.push({ - test: /\.svg$/i, - type: 'asset/source', -}) - -module.exports = webpackConfig