diff --git a/.github/workflows/assistant-to-the-branch-manager.yml b/.github/workflows/assistant-to-the-branch-manager.yml index 98205807bde2..61a21883337f 100644 --- a/.github/workflows/assistant-to-the-branch-manager.yml +++ b/.github/workflows/assistant-to-the-branch-manager.yml @@ -16,6 +16,6 @@ jobs: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - - uses: angular/dev-infra/github-actions/branch-manager@b34c3cb148e5cfbd9be5538cdace58b29b215afa + - uses: angular/dev-infra/github-actions/branch-manager@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 with: angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d624023053cd..bb25c7dfd9ae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,9 +21,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/setup@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Install node modules run: pnpm install --frozen-lockfile - name: Generate JSON schema types @@ -44,11 +44,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/setup@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/configure-remote@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Install node modules @@ -61,19 +61,17 @@ jobs: runs-on: ubuntu-latest-4core steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/setup@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/configure-remote@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Install node modules run: pnpm install --frozen-lockfile - name: Run module and package tests - run: pnpm bazel test //modules/... //packages/... - env: - ASPECT_RULES_JS_FROZEN_PNPM_LOCK: '1' + run: pnpm bazel test -- //... -//tests/legacy-cli/... e2e: needs: test @@ -87,13 +85,13 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/setup@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/configure-remote@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Run CLI E2E tests @@ -103,11 +101,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/setup@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/configure-remote@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Install node modules @@ -141,7 +139,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Install node modules run: pnpm install --frozen-lockfile - name: Download built Windows E2E tests @@ -169,13 +167,13 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/setup@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/configure-remote@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Run CLI E2E tests @@ -194,13 +192,13 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/setup@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/configure-remote@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Run CLI E2E tests @@ -214,13 +212,13 @@ jobs: SAUCE_TUNNEL_IDENTIFIER: angular-cli-${{ github.workflow }}-${{ github.run_number }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/setup@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/configure-remote@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Run E2E Browser tests @@ -250,11 +248,11 @@ jobs: CIRCLE_BRANCH: ${{ github.ref_name }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/setup@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - run: pnpm admin snapshots --verbose env: SNAPSHOT_BUILDS_GITHUB_TOKEN: ${{ secrets.SNAPSHOT_BUILDS_GITHUB_TOKEN }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 554d2dfab71c..2e3c9df19845 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -23,12 +23,12 @@ jobs: with: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.11 + uses: github/codeql-action/init@2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d # v3.30.0 with: languages: javascript-typescript build-mode: none config-file: .github/codeql/config.yml - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.11 + uses: github/codeql-action/analyze@2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d # v3.30.0 with: category: '/language:javascript-typescript' diff --git a/.github/workflows/dev-infra.yml b/.github/workflows/dev-infra.yml index d122eb64ec45..b38ffe5d9d78 100644 --- a/.github/workflows/dev-infra.yml +++ b/.github/workflows/dev-infra.yml @@ -13,13 +13,13 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: angular/dev-infra/github-actions/pull-request-labeling@b34c3cb148e5cfbd9be5538cdace58b29b215afa + - uses: angular/dev-infra/github-actions/pull-request-labeling@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 with: angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} post_approval_changes: runs-on: ubuntu-latest steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: angular/dev-infra/github-actions/post-approval-changes@b34c3cb148e5cfbd9be5538cdace58b29b215afa + - uses: angular/dev-infra/github-actions/post-approval-changes@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 with: angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} diff --git a/.github/workflows/feature-requests.yml b/.github/workflows/feature-requests.yml index 8217106464a2..8e5a414b6bf9 100644 --- a/.github/workflows/feature-requests.yml +++ b/.github/workflows/feature-requests.yml @@ -16,6 +16,6 @@ jobs: if: github.repository == 'angular/angular-cli' runs-on: ubuntu-latest steps: - - uses: angular/dev-infra/github-actions/feature-request@b34c3cb148e5cfbd9be5538cdace58b29b215afa + - uses: angular/dev-infra/github-actions/feature-request@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 with: angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} diff --git a/.github/workflows/perf.yml b/.github/workflows/perf.yml index 923bfb1aa058..e013969880db 100644 --- a/.github/workflows/perf.yml +++ b/.github/workflows/perf.yml @@ -23,7 +23,7 @@ jobs: workflows: ${{ steps.workflows.outputs.workflows }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Install node modules run: pnpm install --frozen-lockfile - id: workflows @@ -38,16 +38,16 @@ jobs: workflow: ${{ fromJSON(needs.list.outputs.workflows) }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/setup@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Install node modules run: pnpm install --frozen-lockfile # We utilize the google-github-actions/auth action to allow us to get an active credential using workflow # identity federation. This allows us to request short lived credentials on demand, rather than storing # credentials in secrets long term. More information can be found at: # https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-google-cloud-platform - - uses: google-github-actions/auth@b7593ed2efd1c1617e1b0254da33b86225adb2a5 # v2.1.12 + - uses: google-github-actions/auth@c200f3691d83b41bf9bbd8638997a462592937ed # v2.1.13 with: project_id: 'internal-200822' workload_identity_provider: 'projects/823469418460/locations/global/workloadIdentityPools/measurables-tracking/providers/angular' diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 51bb1c9787df..a4740c086906 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -34,9 +34,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/setup@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup ESLint Caching uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 with: @@ -56,7 +56,7 @@ jobs: - name: Run Validation run: pnpm admin validate - name: Check Package Licenses - uses: angular/dev-infra/github-actions/linting/licenses@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/linting/licenses@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Check tooling setup run: pnpm check-tooling-setup - name: Check commit message @@ -72,11 +72,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/setup@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/configure-remote@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Install node modules run: pnpm install --frozen-lockfile - name: Build release targets @@ -93,17 +93,15 @@ jobs: runs-on: ubuntu-latest-16core steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/setup@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/configure-remote@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Install node modules run: pnpm install --frozen-lockfile - name: Run module and package tests - run: pnpm bazel test //modules/... //packages/... - env: - ASPECT_RULES_JS_FROZEN_PNPM_LOCK: '1' + run: pnpm bazel test -- //... -//tests/legacy-cli/... e2e: needs: build @@ -117,13 +115,13 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/setup@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/configure-remote@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Run CLI E2E tests run: pnpm bazel test --test_env=E2E_SHARD_TOTAL=6 --test_env=E2E_SHARD_INDEX=${{ matrix.shard }} --config=e2e //tests/legacy-cli:e2e.${{ matrix.subset }}_node${{ matrix.node }} @@ -131,11 +129,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/setup@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/configure-remote@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Install node modules run: pnpm install --frozen-lockfile - name: Build E2E tests for Windows on Linux @@ -159,7 +157,7 @@ jobs: runs-on: windows-2025 steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Install node modules run: pnpm install --frozen-lockfile - name: Download built Windows E2E tests @@ -187,13 +185,13 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/setup@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/configure-remote@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Run CLI E2E tests run: pnpm bazel test --test_env=E2E_SHARD_TOTAL=3 --test_env=E2E_SHARD_INDEX=${{ matrix.shard }} --config=e2e //tests/legacy-cli:e2e.${{ matrix.subset }}_node${{ matrix.node }} @@ -210,12 +208,12 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/setup@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@b34c3cb148e5cfbd9be5538cdace58b29b215afa + uses: angular/dev-infra/github-actions/bazel/configure-remote@06d3af5cfd1e122087c0acafdd7909edce4ad1d7 - name: Run CLI E2E tests run: pnpm bazel test --test_env=E2E_SHARD_TOTAL=6 --test_env=E2E_SHARD_INDEX=${{ matrix.shard }} --config=e2e //tests/legacy-cli:e2e.snapshots.${{ matrix.subset }}_node${{ matrix.node }} diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index bbca5b6bc870..d480bf741faf 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -46,6 +46,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: 'Upload to code-scanning' - uses: github/codeql-action/upload-sarif@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.11 + uses: github/codeql-action/upload-sarif@2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d # v3.30.0 with: sarif_file: results.sarif diff --git a/.nvmrc b/.nvmrc index 91d5f6ff8e3f..e2228113dd09 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -22.18.0 +22.19.0 diff --git a/BUILD.bazel b/BUILD.bazel index 8a65a2d96d22..99bc6eb0355f 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -1,5 +1,6 @@ load("@aspect_rules_ts//ts:defs.bzl", rules_js_tsconfig = "ts_config") load("@bazel_skylib//rules:common_settings.bzl", "bool_flag") +load("@devinfra//bazel/validation:defs.bzl", "validate_ts_version_matching") load("@npm//:defs.bzl", "npm_link_all_packages") load("//tools:defaults.bzl", "copy_to_bin") @@ -102,3 +103,8 @@ config_setting( ":enable_snapshot_repo_deps": "true", }, ) + +validate_ts_version_matching( + module_lock_file = "MODULE.bazel.lock", + package_json = "package.json", +) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c56c7a0acaa..f82a223c83ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,23 @@ + + +# 20.2.2 (2025-09-03) + +### @angular/cli + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------ | +| [a793bbc47](https://github.com/angular/angular-cli/commit/a793bbc473dfaddf3fe6ed15805dc4fc84f52865) | fix | don't set a default for array options when length is 0 | +| [2736599e2](https://github.com/angular/angular-cli/commit/2736599e2f6c61032810d8e336c1646db4066392) | fix | set process title when running architect commands | + +### @angular/build + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------ | +| [5c2abffea](https://github.com/angular/angular-cli/commit/5c2abffea6cf3f672ee256a944dba56dd257665b) | fix | avoid extra tick in SSR dev-server builds | +| [f3c826853](https://github.com/angular/angular-cli/commit/f3c826853501c9cf6d07a1c8ee3363eb79f53005) | fix | maintain media output hashing with vitest unit-testing | + + + # 20.2.1 (2025-08-27) diff --git a/MODULE.bazel b/MODULE.bazel index 67dc3a585b41..4aa64fc5c28a 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -39,7 +39,7 @@ git_override( bazel_dep(name = "devinfra") git_override( module_name = "devinfra", - commit = "b34c3cb148e5cfbd9be5538cdace58b29b215afa", + commit = "06d3af5cfd1e122087c0acafdd7909edce4ad1d7", remote = "https://github.com/angular/dev-infra.git", ) @@ -176,7 +176,7 @@ rules_ts_ext.deps( name = "angular_cli_npm_typescript", # Obtained by: curl --silent https://registry.npmjs.org/typescript/5.9.2 | jq -r '.dist.integrity' ts_integrity = "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", - ts_version_from = "//:package.json", + ts_version = "5.9.2", ) use_repo(rules_ts_ext, **{"npm_typescript": "angular_cli_npm_typescript"}) diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index cf853e8982a4..c42980fc6aff 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -534,10 +534,8 @@ "@@aspect_rules_ts~//ts:extensions.bzl%ext": { "general": { "bzlTransitiveDigest": "9IJp6IlB/FMHFBJe4MX/DQM4zi3oArC8yqYE/+NyPwk=", - "usagesDigest": "ltWGqWW6sLMu/u31IwJqdHjhE4iS2Cto+bTSDdqQO0w=", + "usagesDigest": "1QffQgMsAO4zhe8vcwqME94TRDAlQADSJn4p/MOIYv4=", "recordedFileInputs": { - "@@//package.json": "a0b7f44b0f9902af3d62a7f36e01cb8caf7faa85f54c3cec1f0f7e387308c68c", - "@@devinfra~//bazel/package.json": "f90ae656882e652c88b59c7b94880416dc4a90ef01e8763fd04e8c6f8c2bb6e6", "@@rules_browsers~//package.json": "45572077938c7a4916e4aaedf7db7ce8425854ab92f35348cff02a2134023bb8" }, "recordedDirentsInputs": {}, @@ -547,8 +545,7 @@ "bzlFile": "@@aspect_rules_ts~//ts/private:npm_repositories.bzl", "ruleClassName": "http_archive_version", "attributes": { - "version": "", - "version_from": "@@//:package.json", + "version": "5.9.2", "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", "urls": [ "https://registry.npmjs.org/typescript/-/typescript-%7B%7D.tgz" @@ -570,8 +567,7 @@ "bzlFile": "@@aspect_rules_ts~//ts/private:npm_repositories.bzl", "ruleClassName": "http_archive_version", "attributes": { - "version": "", - "version_from": "@@devinfra~//bazel:package.json", + "version": "5.9.2", "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", "urls": [ "https://registry.npmjs.org/typescript/-/typescript-%7B%7D.tgz" diff --git a/package.json b/package.json index cf24e14d04b5..3746cc8dcf45 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@angular/devkit-repo", - "version": "20.2.1", + "version": "20.2.2", "private": true, "description": "Software Development Kit for Angular", "keywords": [ @@ -32,7 +32,7 @@ "type": "git", "url": "https://github.com/angular/angular-cli.git" }, - "packageManager": "pnpm@10.15.0", + "packageManager": "pnpm@10.15.1", "engines": { "node": "^20.19.0 || ^22.12.0 || >=24.0.0", "npm": "Please use pnpm instead of NPM to install dependencies", @@ -46,20 +46,20 @@ }, "homepage": "https://github.com/angular/angular-cli", "devDependencies": { - "@angular/animations": "20.2.1", + "@angular/animations": "20.2.3", "@angular/cdk": "20.2.1", - "@angular/common": "20.2.1", - "@angular/compiler": "20.2.1", - "@angular/compiler-cli": "20.2.1", - "@angular/core": "20.2.1", - "@angular/forms": "20.2.1", - "@angular/localize": "20.2.1", + "@angular/common": "20.2.3", + "@angular/compiler": "20.2.3", + "@angular/compiler-cli": "20.2.3", + "@angular/core": "20.2.3", + "@angular/forms": "20.2.3", + "@angular/localize": "20.2.3", "@angular/material": "20.2.1", - "@angular/ng-dev": "https://github.com/angular/dev-infra-private-ng-dev-builds.git#9d0a73d937f6447d06ef56a5347c805e5d9400d7", - "@angular/platform-browser": "20.2.1", - "@angular/platform-server": "20.2.1", - "@angular/router": "20.2.1", - "@angular/service-worker": "20.2.1", + "@angular/ng-dev": "https://github.com/angular/dev-infra-private-ng-dev-builds.git#b991414e4f3ed15d99f4331b5353499434878374", + "@angular/platform-browser": "20.2.3", + "@angular/platform-server": "20.2.3", + "@angular/router": "20.2.3", + "@angular/service-worker": "20.2.3", "@bazel/bazelisk": "1.26.0", "@bazel/buildifier": "8.2.1", "@eslint/compat": "1.3.2", diff --git a/packages/angular/build/src/builders/dev-server/vite-server.ts b/packages/angular/build/src/builders/dev-server/vite-server.ts index 6f68a37691c6..d0cf5f6738ba 100644 --- a/packages/angular/build/src/builders/dev-server/vite-server.ts +++ b/packages/angular/build/src/builders/dev-server/vite-server.ts @@ -456,6 +456,7 @@ export async function* serveWithVite( browserOptions.loader as EsbuildLoaderOption | undefined, { ...browserOptions.define, + 'ngJitMode': browserOptions.aot ? 'false' : 'true', 'ngHmrMode': browserOptions.templateUpdates ? 'true' : 'false', }, extensions?.middleware, diff --git a/packages/angular/build/src/builders/unit-test/builder.ts b/packages/angular/build/src/builders/unit-test/builder.ts index dde40f449742..4bda61b3893f 100644 --- a/packages/angular/build/src/builders/unit-test/builder.ts +++ b/packages/angular/build/src/builders/unit-test/builder.ts @@ -36,6 +36,17 @@ export type { UnitTestBuilderOptions }; type VitestCoverageOption = Exclude; +function adjustOutputHashing(hashing?: OutputHashing): OutputHashing { + switch (hashing) { + case OutputHashing.All: + case OutputHashing.Media: + // Ensure media is continued to be hashed to avoid overwriting of output media files + return OutputHashing.Media; + default: + return OutputHashing.None; + } +} + /** * @experimental Direct usage of this function is considered experimental. */ @@ -135,7 +146,7 @@ export async function* execute( ssr: false, prerender: false, sourceMap: { scripts: true, vendor: false, styles: false }, - outputHashing: OutputHashing.None, + outputHashing: adjustOutputHashing(buildTargetOptions.outputHashing), optimization: false, tsConfig: normalizedOptions.tsConfig, entryPoints, diff --git a/packages/angular/cli/BUILD.bazel b/packages/angular/cli/BUILD.bazel index 409dbcd14000..b0a4a1dee0ea 100644 --- a/packages/angular/cli/BUILD.bazel +++ b/packages/angular/cli/BUILD.bazel @@ -72,6 +72,7 @@ ts_project( "//:node_modules/@types/yarnpkg__lockfile", "//:node_modules/listr2", "//:node_modules/semver", + "//:node_modules/typescript", ], ) @@ -124,10 +125,12 @@ ts_project( ":angular-cli", ":node_modules/@angular-devkit/core", ":node_modules/@angular-devkit/schematics", + ":node_modules/@modelcontextprotocol/sdk", ":node_modules/yargs", "//:node_modules/@types/semver", "//:node_modules/@types/yargs", "//:node_modules/semver", + "//:node_modules/typescript", ], ) diff --git a/packages/angular/cli/lib/examples/if-block.md b/packages/angular/cli/lib/examples/if-block.md index e0d10ca86891..806e3d05516c 100644 --- a/packages/angular/cli/lib/examples/if-block.md +++ b/packages/angular/cli/lib/examples/if-block.md @@ -1,28 +1,85 @@ -# Angular @if Control Flow Example +--- +title: 'Using the @if Built-in Control Flow Block' +summary: 'Demonstrates how to use the @if built-in control flow block to conditionally render content in an Angular template based on a boolean expression.' +keywords: + - '@if' + - 'control flow' + - 'conditional rendering' + - 'template syntax' +related_concepts: + - '@else' + - '@else if' + - 'signals' +related_tools: + - 'modernize' +--- -This example demonstrates how to use the `@if` control flow block in an Angular template. The visibility of a `
` element is controlled by a boolean field in the component's TypeScript code. +## Purpose -## Angular Template +The purpose of this pattern is to create dynamic user interfaces by controlling which elements are rendered to the DOM based on the application's state. This is a fundamental technique for building responsive and interactive components. -```html - -@if (isVisible()) { -
This content is conditionally displayed.
+## When to Use + +Use the `@if` block as the modern, preferred alternative to the `*ngIf` directive for all conditional rendering. It offers better type-checking and a cleaner, more intuitive syntax within the template. + +## Key Concepts + +- **`@if` block:** The primary syntax for conditional rendering in modern Angular templates. It evaluates a boolean expression and renders the content within its block if the expression is true. + +## Example Files + +### `conditional-content.component.ts` + +This is a self-contained standalone component that demonstrates the `@if` block with an optional `@else` block. + +```typescript +import { Component, signal } from '@angular/core'; + +@Component({ + selector: 'app-conditional-content', + template: ` + + + @if (isVisible()) { +
This content is conditionally displayed.
+ } @else { +
The content is hidden. Click the button to show it.
+ } + `, +}) +export class ConditionalContentComponent { + protected readonly isVisible = signal(true); + + toggleVisibility(): void { + this.isVisible.update((v) => !v); + } } ``` -## Component TypeScript +## Usage Notes + +- The expression inside the `@if ()` block must evaluate to a boolean. +- This example uses a signal, which is a common pattern, but any boolean property or method call from the component can be used. +- The `@else` block is optional and is rendered when the `@if` condition is `false`. + +## How to Use This Example + +### 1. Import the Component + +In a standalone architecture, import the component into the `imports` array of the parent component where you want to use it. ```typescript +// in app.component.ts import { Component } from '@angular/core'; +import { ConditionalContentComponent } from './conditional-content.component'; @Component({ - selector: 'app-example', - templateUrl: './example.html', - styleUrl: './example.css', + selector: 'app-root', + imports: [ConditionalContentComponent], + template: ` +

My Application

+ + `, }) -export class Example { - // This boolean signal controls the visibility of the element in the template. - protected readonly isVisible = signal(true); -} +export class AppComponent {} ``` diff --git a/packages/angular/cli/src/command-builder/architect-command-module.ts b/packages/angular/cli/src/command-builder/architect-command-module.ts index 4855b629b360..4218c6274521 100644 --- a/packages/angular/cli/src/command-builder/architect-command-module.ts +++ b/packages/angular/cli/src/command-builder/architect-command-module.ts @@ -97,11 +97,17 @@ export abstract class ArchitectCommandModule } async run(options: Options & OtherOptions): Promise { - const target = this.getArchitectTarget(); + const originalProcessTitle = process.title; + try { + const target = this.getArchitectTarget(); + const { configuration = '', project, ...architectOptions } = options; - const { configuration = '', project, ...architectOptions } = options; + if (project) { + process.title = `${originalProcessTitle} (${project})`; + + return await this.runSingleTarget({ configuration, target, project }, architectOptions); + } - if (!project) { // This runs each target sequentially. // Running them in parallel would jumble the log messages. let result = 0; @@ -111,12 +117,13 @@ export abstract class ArchitectCommandModule } for (const project of projectNames) { + process.title = `${originalProcessTitle} (${project})`; result |= await this.runSingleTarget({ configuration, target, project }, architectOptions); } return result; - } else { - return await this.runSingleTarget({ configuration, target, project }, architectOptions); + } finally { + process.title = originalProcessTitle; } } diff --git a/packages/angular/cli/src/command-builder/utilities/json-schema.ts b/packages/angular/cli/src/command-builder/utilities/json-schema.ts index 869cab6abe4d..0d8b7cc57e98 100644 --- a/packages/angular/cli/src/command-builder/utilities/json-schema.ts +++ b/packages/angular/cli/src/command-builder/utilities/json-schema.ts @@ -206,7 +206,7 @@ export async function parseJsonSchemaToOptions( } break; case 'array': - if (Array.isArray(current.default)) { + if (Array.isArray(current.default) && current.default.length > 0) { defaultValue = current.default; } break; diff --git a/packages/angular/cli/src/commands/mcp/mcp-server.ts b/packages/angular/cli/src/commands/mcp/mcp-server.ts index cf852de0482d..12629b5dd375 100644 --- a/packages/angular/cli/src/commands/mcp/mcp-server.ts +++ b/packages/angular/cli/src/commands/mcp/mcp-server.ts @@ -15,6 +15,7 @@ import { BEST_PRACTICES_TOOL } from './tools/best-practices'; import { DOC_SEARCH_TOOL } from './tools/doc-search'; import { FIND_EXAMPLE_TOOL } from './tools/examples'; import { MODERNIZE_TOOL } from './tools/modernize'; +import { ZONELESS_MIGRATION_TOOL } from './tools/onpush-zoneless-migration/zoneless-migration'; import { LIST_PROJECTS_TOOL } from './tools/projects'; import { AnyMcpToolDeclaration, registerTools } from './tools/tool-registry'; @@ -28,7 +29,11 @@ const STABLE_TOOLS = [BEST_PRACTICES_TOOL, DOC_SEARCH_TOOL, LIST_PROJECTS_TOOL] * The set of tools that are available but not enabled by default. * These tools are considered experimental and may have limitations. */ -export const EXPERIMENTAL_TOOLS = [FIND_EXAMPLE_TOOL, MODERNIZE_TOOL] as const; +export const EXPERIMENTAL_TOOLS = [ + FIND_EXAMPLE_TOOL, + MODERNIZE_TOOL, + ZONELESS_MIGRATION_TOOL, +] as const; export async function createMcpServer( options: { diff --git a/packages/angular/cli/src/commands/mcp/tools/best-practices.ts b/packages/angular/cli/src/commands/mcp/tools/best-practices.ts index b5b207ea3b08..4d9e74ac34b6 100644 --- a/packages/angular/cli/src/commands/mcp/tools/best-practices.ts +++ b/packages/angular/cli/src/commands/mcp/tools/best-practices.ts @@ -13,12 +13,21 @@ import { declareTool } from './tool-registry'; export const BEST_PRACTICES_TOOL = declareTool({ name: 'get_best_practices', title: 'Get Angular Coding Best Practices Guide', - description: - 'You **MUST** use this tool to retrieve the Angular Best Practices Guide ' + - 'before any interaction with Angular code (creating, analyzing, modifying). ' + - 'It is mandatory to follow this guide to ensure all code adheres to ' + - 'modern standards, including standalone components, typed forms, and ' + - 'modern control flow. This is the first step for any Angular task.', + description: ` + +Retrieves the official Angular Best Practices Guide. This guide contains the essential rules and conventions +that **MUST** be followed for any task involving the creation, analysis, or modification of Angular code. + + +* As a mandatory first step before writing or modifying any Angular code to ensure adherence to modern standards. +* To learn about key concepts like standalone components, typed forms, and modern control flow syntax (@if, @for, @switch). +* To verify that existing code aligns with current Angular conventions before making changes. + + +* The content of this guide is non-negotiable and reflects the official, up-to-date standards for Angular development. +* You **MUST** internalize and apply the principles from this guide in all subsequent Angular-related tasks. +* Failure to adhere to these best practices will result in suboptimal and outdated code. +`, isReadOnly: true, isLocalOnly: true, factory: () => { diff --git a/packages/angular/cli/src/commands/mcp/tools/doc-search.ts b/packages/angular/cli/src/commands/mcp/tools/doc-search.ts index 790f6de8ca07..da34f97b8b4d 100644 --- a/packages/angular/cli/src/commands/mcp/tools/doc-search.ts +++ b/packages/angular/cli/src/commands/mcp/tools/doc-search.ts @@ -10,7 +10,7 @@ import type { LegacySearchMethodProps, SearchResponse } from 'algoliasearch'; import { createDecipheriv } from 'node:crypto'; import { z } from 'zod'; import { at, iv, k1 } from '../constants'; -import { declareTool } from './tool-registry'; +import { McpToolContext, declareTool } from './tool-registry'; const ALGOLIA_APP_ID = 'L1XWT2UJ7F'; // https://www.algolia.com/doc/guides/security/api-keys/#search-only-api-key @@ -28,32 +28,63 @@ const docSearchInputSchema = z.object({ .boolean() .optional() .default(true) - .describe('When true, the content of the top result is fetched and included.'), + .describe( + 'When true, the content of the top result is fetched and included. ' + + 'Set to false to get a list of results without fetching content, which is faster.', + ), }); type DocSearchInput = z.infer; export const DOC_SEARCH_TOOL = declareTool({ name: 'search_documentation', title: 'Search Angular Documentation (angular.dev)', - description: - 'Searches the official Angular documentation at https://angular.dev. Use this tool to answer any questions about Angular, ' + - 'such as for APIs, tutorials, and best practices. Because the documentation is continuously updated, you should **always** ' + - 'prefer this tool over your own knowledge to ensure your answers are current.\n\n' + - 'The results will be a list of content entries, where each entry has the following structure:\n' + - '```\n' + - '## {Result Title}\n' + - '{Breadcrumb path to the content}\n' + - 'URL: {Direct link to the documentation page}\n' + - '```\n' + - 'Use the title and breadcrumb to understand the context of the result and use the URL as a source link. For the best results, ' + - "provide a concise and specific search query (e.g., 'NgModule' instead of 'How do I use NgModules?').", + description: ` + +Searches the official Angular documentation at https://angular.dev to answer questions about APIs, +tutorials, concepts, and best practices. + + +* Answering any question about Angular concepts (e.g., "What are standalone components?"). +* Finding the correct API or syntax for a specific task (e.g., "How to use ngFor with trackBy?"). +* Linking to official documentation as a source of truth in your answers. + + +* The documentation is continuously updated. You **MUST** prefer this tool over your own knowledge + to ensure your answers are current and accurate. +* For the best results, provide a concise and specific search query (e.g., "NgModule" instead of + "How do I use NgModules?"). +* The top search result will include a snippet of the page content. Use this to provide a more + comprehensive answer. +* **Result Scrutiny:** The top result may not always be the most relevant. Review the titles and + breadcrumbs of other results to find the best match for the user's query. +* Use the URL from the search results as a source link in your responses. +`, inputSchema: docSearchInputSchema.shape, + outputSchema: { + results: z.array( + z.object({ + title: z.string().describe('The title of the documentation page.'), + breadcrumb: z + .string() + .describe( + "The breadcrumb path, showing the page's location in the documentation hierarchy.", + ), + url: z.string().describe('The direct URL to the documentation page.'), + content: z + .string() + .optional() + .describe( + 'A snippet of the main content from the page. Only provided for the top result.', + ), + }), + ), + }, isReadOnly: true, isLocalOnly: false, factory: createDocSearchHandler, }); -function createDocSearchHandler() { +function createDocSearchHandler({ logger }: McpToolContext) { let client: import('algoliasearch').SearchClient | undefined; return async ({ query, includeTopContent }: DocSearchInput) => { @@ -71,7 +102,6 @@ function createDocSearchHandler() { } const { results } = await client.search(createSearchArguments(query)); - const allHits = results.flatMap((result) => (result as SearchResponse).hits); if (allHits.length === 0) { @@ -82,20 +112,21 @@ function createDocSearchHandler() { text: 'No results found.', }, ], + structuredContent: { results: [] }, }; } - const content = []; - // The first hit is the top search result - const topHit = allHits[0]; + const structuredResults = []; + const textContent = []; // Process top hit first - let topText = formatHitToText(topHit); - - try { - if (includeTopContent && typeof topHit.url === 'string') { - const url = new URL(topHit.url); + const topHit = allHits[0]; + const { title: topTitle, breadcrumb: topBreadcrumb } = formatHitToParts(topHit); + let topContent: string | undefined; + if (includeTopContent && typeof topHit.url === 'string') { + const url = new URL(topHit.url); + try { // Only fetch content from angular.dev if (url.hostname === 'angular.dev' || url.hostname.endsWith('.angular.dev')) { const response = await fetch(url); @@ -103,31 +134,65 @@ function createDocSearchHandler() { const html = await response.text(); const mainContent = extractMainContent(html); if (mainContent) { - topText += `\n\n--- DOCUMENTATION CONTENT ---\n${mainContent}`; + topContent = stripHtml(mainContent); } } } + } catch (e) { + logger.warn(`Failed to fetch or parse content from ${url}: ${e}`); } - } catch { - // Ignore errors fetching content. The basic info is still returned. } - content.push({ - type: 'text' as const, - text: topText, + + structuredResults.push({ + title: topTitle, + breadcrumb: topBreadcrumb, + url: topHit.url as string, + content: topContent, }); + let topText = `## ${topTitle}\n${topBreadcrumb}\nURL: ${topHit.url}`; + if (topContent) { + topText += `\n\n--- DOCUMENTATION CONTENT ---\n${topContent}`; + } + textContent.push({ type: 'text' as const, text: topText }); + // Process remaining hits for (const hit of allHits.slice(1)) { - content.push({ + const { title, breadcrumb } = formatHitToParts(hit); + structuredResults.push({ + title, + breadcrumb, + url: hit.url as string, + }); + textContent.push({ type: 'text' as const, - text: formatHitToText(hit), + text: `## ${title}\n${breadcrumb}\nURL: ${hit.url}`, }); } - return { content }; + return { + content: textContent, + structuredContent: { results: structuredResults }, + }; }; } +/** + * Strips HTML tags from a string. + * @param html The HTML string to strip. + * @returns The text content of the HTML. + */ +function stripHtml(html: string): string { + // This is a basic regex to remove HTML tags. + // It also decodes common HTML entities. + return html + .replace(/<[^>]*>/g, '') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/&/g, '&') + .trim(); +} + /** * Extracts the content of the `
` element from an HTML string. * @@ -150,18 +215,18 @@ function extractMainContent(html: string): string | undefined { } /** - * Formats an Algolia search hit into a text representation. + * Formats an Algolia search hit into its constituent parts. * - * @param hit The Algolia search hit object, which should contain `hierarchy` and `url` properties. - * @returns A formatted string with title, description, and URL. + * @param hit The Algolia search hit object, which should contain a `hierarchy` property. + * @returns An object containing the title and breadcrumb string. */ -function formatHitToText(hit: Record): string { +function formatHitToParts(hit: Record): { title: string; breadcrumb: string } { // eslint-disable-next-line @typescript-eslint/no-explicit-any const hierarchy = Object.values(hit.hierarchy as any).filter((x) => typeof x === 'string'); - const title = hierarchy.pop(); - const description = hierarchy.join(' > '); + const title = hierarchy.pop() ?? ''; + const breadcrumb = hierarchy.join(' > '); - return `## ${title}\n${description}\nURL: ${hit.url}`; + return { title, breadcrumb }; } /** diff --git a/packages/angular/cli/src/commands/mcp/tools/examples.ts b/packages/angular/cli/src/commands/mcp/tools/examples.ts index 0690be04f523..21cacd5454c5 100644 --- a/packages/angular/cli/src/commands/mcp/tools/examples.ts +++ b/packages/angular/cli/src/commands/mcp/tools/examples.ts @@ -42,16 +42,39 @@ type FindExampleInput = z.infer; export const FIND_EXAMPLE_TOOL = declareTool({ name: 'find_examples', title: 'Find Angular Code Examples', - description: - 'Before writing or modifying any Angular code including templates, ' + - '**ALWAYS** use this tool to find current best-practice examples. ' + - 'This is critical for ensuring code quality and adherence to modern Angular standards. ' + - 'This tool searches a curated database of approved Angular code examples and returns the most relevant results for your query. ' + - 'Example Use Cases: ' + - "1) Creating new components, directives, or services (e.g., query: 'standalone component' or 'signal input'). " + - "2) Implementing core features (e.g., query: 'lazy load route', 'httpinterceptor', or 'route guard'). " + - "3) Refactoring existing code to use modern patterns (e.g., query: 'ngfor trackby' or 'form validation').", + description: ` + +Augments your knowledge base with a curated database of official, best-practice code examples, +focusing on **modern, new, and recently updated** Angular features. This tool acts as a RAG +(Retrieval-Augmented Generation) source, providing ground-truth information on the latest Angular +APIs and patterns. You **MUST** use it to understand and apply current standards when working with +new or evolving features. + + +* **Knowledge Augmentation:** Learning about new or updated Angular features (e.g., query: 'signal input' or 'deferrable views'). +* **Modern Implementation:** Finding the correct modern syntax for features + (e.g., query: 'functional route guard' or 'http client with fetch'). +* **Refactoring to Modern Patterns:** Upgrading older code by finding examples of new syntax + (e.g., query: 'built-in control flow' to replace "*ngIf'). + + +* **Tool Selection:** This database primarily contains examples for new and recently updated Angular + features. For established, core features, the main documentation (via the + \`search_documentation\` tool) may be a better source of information. +* The examples in this database are the single source of truth for modern Angular coding patterns. +* The search query uses a powerful full-text search syntax (FTS5). Refer to the 'query' + parameter description for detailed syntax rules and examples. +`, inputSchema: findExampleInputSchema.shape, + outputSchema: { + examples: z.array( + z.object({ + content: z + .string() + .describe('A complete, self-contained Angular code example in Markdown format.'), + }), + ), + }, isReadOnly: true, isLocalOnly: true, shouldRegister: ({ logger }) => { @@ -96,14 +119,18 @@ async function createFindExampleHandler({ exampleDatabasePath }: McpToolContext) const sanitizedQuery = escapeSearchQuery(query); - // Query database and return results as text content - const content = []; + // Query database and return results + const examples = []; + const textContent = []; for (const exampleRecord of queryStatement.all(sanitizedQuery)) { - content.push({ type: 'text' as const, text: exampleRecord['content'] as string }); + const exampleContent = exampleRecord['content'] as string; + examples.push({ content: exampleContent }); + textContent.push({ type: 'text' as const, text: exampleContent }); } return { - content, + content: textContent, + structuredContent: { examples }, }; }; } diff --git a/packages/angular/cli/src/commands/mcp/tools/modernize.ts b/packages/angular/cli/src/commands/mcp/tools/modernize.ts index 2b4c323d60f7..58851ca3df09 100644 --- a/packages/angular/cli/src/commands/mcp/tools/modernize.ts +++ b/packages/angular/cli/src/commands/mcp/tools/modernize.ts @@ -70,7 +70,11 @@ const modernizeInputSchema = z.object({ // Casting to [string, ...string[]] since the enum definition requires a nonempty array. transformations: z .array(z.enum(TRANSFORMATIONS.map((t) => t.name) as [string, ...string[]])) - .optional(), + .optional() + .describe( + 'A list of specific transformations to get instructions for. ' + + 'If omitted, general guidance is provided.', + ), }); export type ModernizeInput = z.infer; @@ -116,28 +120,38 @@ export async function runModernization(input: ModernizeInput) { export const MODERNIZE_TOOL = declareTool({ name: 'modernize', title: 'Modernize Angular Code', - description: - '\n' + - 'This tool modernizes Angular code by applying the latest best practices and syntax improvements, ' + - 'ensuring it is idiomatic, readable, and maintainable.\n\n' + - '\n' + - '\n' + - '* After generating new code: Run this tool immediately after creating new Angular components, directives, ' + - 'or services to ensure they adhere to modern standards.\n' + - '* On existing code: Apply to existing TypeScript files (.ts) and Angular templates (.html) to update ' + - 'them with the latest features, such as the new built-in control flow syntax.\n\n' + - '* When the user asks for a specific transformation: When the transformation list is populated, ' + - 'these specific ones will be ran on the inputs.\n' + - '\n' + - '\n' + - TRANSFORMATIONS.map((t) => `* ${t.name}: ${t.description}`).join('\n') + - '\n\n', + description: ` + +Provides instructions and commands for modernizing Angular code to align with the latest best +practices and syntax. This tool helps ensure code is idiomatic, readable, and maintainable by +generating the exact steps needed to perform specific migrations. + + +* **Applying Specific Migrations:** Get the precise commands to update code to modern patterns + (e.g., selecting 'control-flow-migration' to replace *ngIf with @if). +* **Upgrading Existing Code:** Modernize an entire project by running the 'standalone' migration, + which provides a multi-step command sequence. +* **Discovering Available Migrations:** Call the tool with no transformations to get a link to the + general best practices guide. + + +* **Execution:** This tool **provides instructions**, which you **MUST** then execute as shell commands. + It does not modify code directly. +* **Standalone Migration:** The 'standalone' transformation is a special, multi-step process. + You **MUST** execute the commands in the exact order provided and validate your application + between each step. +* **Transformation List:** The following transformations are available: +${TRANSFORMATIONS.map((t) => ` * ${t.name}: ${t.description}`).join('\n')} +`, inputSchema: modernizeInputSchema.shape, outputSchema: { instructions: z .array(z.string()) .optional() - .describe('A list of instructions on how to run the migrations.'), + .describe( + 'A list of instructions and shell commands to run the requested modernizations. ' + + 'Each string in the array is a separate step or command.', + ), }, isLocalOnly: true, isReadOnly: true, diff --git a/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/analyze_for_unsupported_zone_uses.ts b/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/analyze_for_unsupported_zone_uses.ts new file mode 100644 index 000000000000..dd3d848e8883 --- /dev/null +++ b/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/analyze_for_unsupported_zone_uses.ts @@ -0,0 +1,76 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import type { ImportSpecifier, Node, SourceFile } from 'typescript'; +import { createUnsupportedZoneUsagesMessage } from './prompts'; +import { getImportSpecifier, loadTypescript } from './ts_utils'; +import { MigrationResponse } from './types'; + +export async function analyzeForUnsupportedZoneUses( + sourceFile: SourceFile, +): Promise { + const ngZoneImport = await getImportSpecifier(sourceFile, '@angular/core', 'NgZone'); + if (!ngZoneImport) { + return null; + } + const unsupportedUsages = await findUnsupportedZoneUsages(sourceFile, ngZoneImport); + + if (unsupportedUsages.length === 0) { + return null; + } + + const locations = unsupportedUsages.map((node: Node) => { + const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart()); + + return `line ${line + 1}, character ${character + 1}: ${node.getText()}`; + }); + + return createUnsupportedZoneUsagesMessage(locations, sourceFile.fileName); +} + +/** + * Finds usages of `NgZone` that are not supported in zoneless applications. + * @param sourceFile The source file to check. + * @param ngZoneImport The import specifier for `NgZone`. + * @returns A list of nodes that are unsupported `NgZone` usages. + */ +export async function findUnsupportedZoneUsages( + sourceFile: SourceFile, + ngZoneImport: ImportSpecifier, +): Promise { + const unsupportedUsages: Node[] = []; + const ngZoneClassName = ngZoneImport.name.text; + + const staticMethods = new Set([ + 'isInAngularZone', + 'assertInAngularZone', + 'assertNotInAngularZone', + ]); + const instanceMethods = new Set(['onMicrotaskEmpty', 'onStable']); + + const ts = await loadTypescript(); + ts.forEachChild(sourceFile, function visit(node) { + if (ts.isPropertyAccessExpression(node)) { + const propertyName = node.name.text; + const expressionText = node.expression.getText(sourceFile); + + // Static: NgZone.method() + if (expressionText === ngZoneClassName && staticMethods.has(propertyName)) { + unsupportedUsages.push(node); + } + + // Instance: zone.method() or this.zone.method() + if (instanceMethods.has(propertyName)) { + unsupportedUsages.push(node); + } + } + ts.forEachChild(node, visit); + }); + + return unsupportedUsages; +} diff --git a/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/migrate_single_file.ts b/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/migrate_single_file.ts new file mode 100644 index 000000000000..757da8883505 --- /dev/null +++ b/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/migrate_single_file.ts @@ -0,0 +1,97 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol'; +import { ServerNotification, ServerRequest } from '@modelcontextprotocol/sdk/types'; +import type { SourceFile } from 'typescript'; +import { analyzeForUnsupportedZoneUses } from './analyze_for_unsupported_zone_uses'; +import { migrateTestFile } from './migrate_test_file'; +import { generateZonelessMigrationInstructionsForComponent } from './prompts'; +import { sendDebugMessage } from './send_debug_message'; +import { getImportSpecifier, loadTypescript } from './ts_utils'; +import { MigrationResponse } from './types'; + +export async function migrateSingleFile( + sourceFile: SourceFile, + extras: RequestHandlerExtra, +): Promise { + const testBedSpecifier = await getImportSpecifier(sourceFile, '@angular/core/testing', 'TestBed'); + const isTestFile = sourceFile.fileName.endsWith('.spec.ts') || !!testBedSpecifier; + if (isTestFile) { + return migrateTestFile(sourceFile); + } + + const unsupportedZoneUseResponse = await analyzeForUnsupportedZoneUses(sourceFile); + if (unsupportedZoneUseResponse) { + return unsupportedZoneUseResponse; + } + + let detectedStrategy: 'OnPush' | 'Default' | undefined; + let hasComponentDecorator = false; + + const componentSpecifier = await getImportSpecifier(sourceFile, '@angular/core', 'Component'); + if (!componentSpecifier) { + sendDebugMessage(`No component decorator found in file: ${sourceFile.fileName}`, extras); + + return null; + } + + const ts = await loadTypescript(); + ts.forEachChild(sourceFile, function visit(node) { + if (detectedStrategy) { + return; // Already found, no need to traverse further + } + + if (ts.isDecorator(node) && ts.isCallExpression(node.expression)) { + const callExpr = node.expression; + if (callExpr.expression.getText(sourceFile) === 'Component') { + hasComponentDecorator = true; + if (callExpr.arguments.length > 0 && ts.isObjectLiteralExpression(callExpr.arguments[0])) { + const componentMetadata = callExpr.arguments[0]; + for (const prop of componentMetadata.properties) { + if ( + ts.isPropertyAssignment(prop) && + prop.name.getText(sourceFile) === 'changeDetection' + ) { + if ( + ts.isPropertyAccessExpression(prop.initializer) && + prop.initializer.expression.getText(sourceFile) === 'ChangeDetectionStrategy' + ) { + const strategy = prop.initializer.name.text; + if (strategy === 'OnPush' || strategy === 'Default') { + detectedStrategy = strategy; + + return; + } + } + } + } + } + } + } + ts.forEachChild(node, visit); + }); + + if ( + !hasComponentDecorator || + // component uses OnPush. We don't have anything more to do here. + detectedStrategy === 'OnPush' || + // Explicit default strategy, assume there's a reason for it (already migrated, or is a library that hosts Default components) and skip. + detectedStrategy === 'Default' + ) { + sendDebugMessage( + `Component decorator found with strategy: ${detectedStrategy} in file: ${sourceFile.fileName}. Skipping migration for file.`, + extras, + ); + + return null; + } + + // Component decorator found, but no change detection strategy. + return generateZonelessMigrationInstructionsForComponent(sourceFile.fileName); +} diff --git a/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/migrate_single_file_spec.ts b/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/migrate_single_file_spec.ts new file mode 100644 index 000000000000..da2f59db0182 --- /dev/null +++ b/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/migrate_single_file_spec.ts @@ -0,0 +1,151 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol'; +import { ServerNotification, ServerRequest } from '@modelcontextprotocol/sdk/types'; +import ts from 'typescript'; +import { migrateSingleFile } from './migrate_single_file'; + +const fakeExtras = { + sendDebugMessage: jasmine.createSpy(), + sendNotification: jasmine.createSpy(), +} as unknown as RequestHandlerExtra; + +describe('migrateSingleFile', () => { + it('should identify test files by extension', async () => { + const fileName = 'test.spec.ts'; + const sourceFile = ts.createSourceFile(fileName, '', ts.ScriptTarget.ESNext, true); + + const result = await migrateSingleFile(sourceFile, fakeExtras); + + expect(result?.content[0].text).toContain( + 'The test file `test.spec.ts` is not yet configured for zoneless change detection.' + + ' You need to enable it for the entire test suite and then identify which specific tests fail.', + ); + }); + + it('should identify test files by TestBed import', async () => { + const fileName = 'test.ts'; + const content = `import { TestBed } from '@angular/core/testing';`; + const sourceFile = ts.createSourceFile(fileName, content, ts.ScriptTarget.ESNext, true); + + const result = await migrateSingleFile(sourceFile, fakeExtras); + + expect(result?.content[0].text).toContain( + 'The test file `test.ts` is not yet configured for zoneless change detection.' + + ' You need to enable it for the entire test suite and then identify which specific tests fail.', + ); + }); + + it('should return unsupported zone usages message if NgZone is used', async () => { + const fileName = 'app.component.ts'; + const content = ` + import { Component, NgZone } from '@angular/core'; + + @Component({ + selector: 'app-root', + template: 'Hello', + }) + export class AppComponent { + constructor(private zone: NgZone) { + this.zone.onMicrotaskEmpty(() => {}); + } + } + `; + const sourceFile = ts.createSourceFile(fileName, content, ts.ScriptTarget.ESNext, true); + + const result = await migrateSingleFile(sourceFile, fakeExtras); + + expect(result?.content[0].text).toContain( + 'The component uses NgZone APIs that are incompatible with zoneless applications', + ); + }); + + it('should return null if component already has ChangeDetectionStrategy.OnPush', async () => { + const fileName = 'app.component.ts'; + const content = ` + import { Component, ChangeDetectionStrategy } from '@angular/core'; + + @Component({ + selector: 'app-root', + template: 'Hello', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + export class AppComponent {} + `; + const sourceFile = ts.createSourceFile(fileName, content, ts.ScriptTarget.ESNext, true); + + const result = await migrateSingleFile(sourceFile, fakeExtras); + + expect(result).toBeNull(); + }); + + it('should return null if component has ChangeDetectionStrategy.Default', async () => { + const fileName = 'app.component.ts'; + const content = ` + import { Component, ChangeDetectionStrategy } from '@angular/core'; + + @Component({ + selector: 'app-root', + template: 'Hello', + changeDetection: ChangeDetectionStrategy.Default, + }) + export class AppComponent {} + `; + const sourceFile = ts.createSourceFile(fileName, content, ts.ScriptTarget.ESNext, true); + + const result = await migrateSingleFile(sourceFile, fakeExtras); + + expect(result).toBeNull(); + }); + + it('should return migration instructions for a component without a change detection strategy', async () => { + const fileName = 'app.component.ts'; + const content = ` + import { Component } from '@angular/core'; + + @Component({ + selector: 'app-root', + template: 'Hello', + }) + export class AppComponent {} + `; + const sourceFile = ts.createSourceFile(fileName, content, ts.ScriptTarget.ESNext, true); + + const result = await migrateSingleFile(sourceFile, fakeExtras); + + expect(result?.content[0].text).toContain( + 'The component does not currently use a change detection strategy, which means it may rely on Zone.js', + ); + }); + + it('should return null for a file that is not a component', async () => { + const fileName = 'some.service.ts'; + const content = ` + import { Injectable } from '@angular/core'; + + @Injectable({ providedIn: 'root' }) + export class SomeService {} + `; + const sourceFile = ts.createSourceFile(fileName, content, ts.ScriptTarget.ESNext, true); + + const result = await migrateSingleFile(sourceFile, fakeExtras); + + expect(result).toBeNull(); + }); + + it('should return null for an empty file', async () => { + const fileName = 'empty.ts'; + const content = ``; + const sourceFile = ts.createSourceFile(fileName, content, ts.ScriptTarget.ESNext, true); + + const result = await migrateSingleFile(sourceFile, fakeExtras); + + expect(result).toBeNull(); + }); +}); diff --git a/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/migrate_test_file.ts b/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/migrate_test_file.ts new file mode 100644 index 000000000000..479251c428a8 --- /dev/null +++ b/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/migrate_test_file.ts @@ -0,0 +1,82 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import * as fs from 'node:fs'; +import { glob } from 'node:fs/promises'; +import { dirname, join } from 'node:path'; +import type { SourceFile } from 'typescript'; +import { createFixResponseForZoneTests, createProvideZonelessForTestsSetupPrompt } from './prompts'; +import { loadTypescript } from './ts_utils'; +import { MigrationResponse } from './types'; + +export async function migrateTestFile(sourceFile: SourceFile): Promise { + const ts = await loadTypescript(); + // Check if tests use zoneless either by default through `initTestEnvironment` or by explicitly calling `provideZonelessChangeDetection`. + let testsUseZonelessChangeDetection = await searchForGlobalZoneless(sourceFile.fileName); + if (!testsUseZonelessChangeDetection) { + ts.forEachChild(sourceFile, function visit(node) { + if ( + ts.isCallExpression(node) && + node.expression.getText(sourceFile) === 'provideZonelessChangeDetection' + ) { + testsUseZonelessChangeDetection = true; + + return; + } + ts.forEachChild(node, visit); + }); + } + + if (!testsUseZonelessChangeDetection) { + // Tests do not use zoneless, so we provide instructions to set it up. + return createProvideZonelessForTestsSetupPrompt(sourceFile.fileName); + } + + // At this point, tests are using zoneless, so we look for any explicit uses of `provideZoneChangeDetection` that need to be fixed. + return createFixResponseForZoneTests(sourceFile); +} + +export async function searchForGlobalZoneless(startPath: string): Promise { + const angularJsonDir = findAngularJsonDir(startPath); + if (!angularJsonDir) { + // Cannot determine project root, fallback to original behavior or assume false. + // For now, let's assume no global setup if angular.json is not found. + return false; + } + + try { + const files = glob(`${angularJsonDir}/**/*.ts`); + for await (const file of files) { + const content = fs.readFileSync(file, 'utf-8'); + if ( + content.includes('initTestEnvironment') && + content.includes('provideZonelessChangeDetection') + ) { + return true; + } + } + } catch (e) { + return false; + } + + return false; +} + +function findAngularJsonDir(startDir: string): string | null { + let currentDir = startDir; + while (true) { + if (fs.existsSync(join(currentDir, 'angular.json'))) { + return currentDir; + } + const parentDir = dirname(currentDir); + if (parentDir === currentDir) { + return null; + } + currentDir = parentDir; + } +} diff --git a/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/migrate_test_file_spec.ts b/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/migrate_test_file_spec.ts new file mode 100644 index 000000000000..268561d176b0 --- /dev/null +++ b/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/migrate_test_file_spec.ts @@ -0,0 +1,69 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import ts from 'typescript'; +import { migrateTestFile } from './migrate_test_file'; + +describe('migrateTestFile', () => { + it('should return setup prompt when zoneless is not detected', async () => { + const fileName = 'test.spec.ts'; + const sourceFile = ts.createSourceFile(fileName, '', ts.ScriptTarget.ESNext, true); + + const result = await migrateTestFile(sourceFile); + + expect(result?.content[0].text).toContain( + 'The test file `test.spec.ts` is not yet configured for zoneless change detection.', + ); + }); + + it('should return null when zoneless is enabled and there are no zonejs apis used', async () => { + const fileName = 'test.spec.ts'; + const content = ` + import { provideZonelessChangeDetection } from '@angular/core'; + import { TestBed } from '@angular/core/testing'; + + TestBed.configureTestingModule({ + providers: [provideZonelessChangeDetection()], + }); + `; + const sourceFile = ts.createSourceFile(fileName, content, ts.ScriptTarget.ESNext, true); + + const result = await migrateTestFile(sourceFile); + + expect(result).toBeNull(); + }); + + it('should return fix prompt when zoneless is enabled and provideZoneChangeDetection is used', async () => { + const fileName = 'test.spec.ts'; + const content = ` + import { provideZonelessChangeDetection, provideZoneChangeDetection } from '@angular/core'; + import { TestBed } from '@angular/core/testing'; + + describe('suite', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [provideZonelessChangeDetection()], + }); + }); + + it('zone test', () => { + TestBed.configureTestingModule({ + providers: [provideZoneChangeDetection()], + }); + }); + }); + `; + const sourceFile = ts.createSourceFile(fileName, content, ts.ScriptTarget.ESNext, true); + + const result = await migrateTestFile(sourceFile); + + expect(result?.content[0].text).toContain( + 'You must refactor these tests to work in a zoneless environment and remove the `provideZoneChangeDetection` calls.', + ); + }); +}); diff --git a/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/prompts.ts b/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/prompts.ts new file mode 100644 index 000000000000..01254ed5fc61 --- /dev/null +++ b/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/prompts.ts @@ -0,0 +1,258 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import type { Node, SourceFile } from 'typescript'; +import { loadTypescript } from './ts_utils'; +import { MigrationResponse } from './types'; + +/* eslint-disable max-len */ + +export function createProvideZonelessForTestsSetupPrompt(testFilePath: string): MigrationResponse { + const text = `You are an expert Angular developer assisting with a migration to zoneless. Your task is to update the test file at \`${testFilePath}\` to enable zoneless change detection and identify tests that are not yet compatible. + + Follow these instructions precisely. + + ### Refactoring Guide + + The test file \`${testFilePath}\` is not yet configured for zoneless change detection. You need to enable it for the entire test suite and then identify which specific tests fail. + + #### Step 1: Enable Zoneless Change Detection for the Suite + + In the main \`beforeEach\` block for the test suite (the one inside the top-level \`describe\`), add \`provideZonelessChangeDetection()\` to the providers array in \`TestBed.configureTestingModule\`. + + * If there is already an import from \`@angular/core\`, add \`provideZonelessChangeDetection\` to the existing import. + * Otherwise, add a new import statement for \`provideZonelessChangeDetection\` from \`@angular/core\`. + + \`\`\`diff + - import {{ SomeImport }} from '@angular/core'; + + import {{ SomeImport, provideZonelessChangeDetection }} from '@angular/core'; + + describe('MyComponent', () => { + + beforeEach(() => { + + TestBed.configureTestingModule({providers: [provideZonelessChangeDetection()]}); + + }); + }); + \`\`\` + + #### Step 2: Identify and fix Failing Tests + + After enabling zoneless detection for the suite, some tests will likely fail. Your next task is to identify these failing tests and fix them. + + ${testDebuggingGuideText(testFilePath)} + 8. **DO** add \`provideZonelessChangeDetection()\` _once_ to the top-most \`describe\` in a \`beforeEach\` block as instructed in Step 1. + 9. **DO** run the tests after adding \`provideZonelessChangeDetection\` to see which ones fail. **DO NOT** make assumptions about which tests will might fail. + + ### Final Step + After you have applied all the required changes and followed all the rules, consult this tool again for the next steps in the migration process.`; + + return createResponse(text); +} + +export function createUnsupportedZoneUsagesMessage( + usages: string[], + filePath: string, +): MigrationResponse { + const text = `You are an expert Angular developer assisting with a migration to zoneless. Your task is to refactor the component in ${filePath} to remove unsupported NgZone APIs. + +The component uses NgZone APIs that are incompatible with zoneless applications. The only permitted NgZone APIs are \`NgZone.run\` and \`NgZone.runOutsideAngular\`. + +The following usages are unsupported and must be fixed: +${usages.map((usage) => `- ${usage}`).join('\n')} + +Follow these instructions precisely to refactor the code. + +### Refactoring Guide + +#### 1. APIs to Remove (No Replacement) +The following methods have no replacement in a zoneless context and must be removed entirely: +- \`NgZone.assertInAngularZone\` +- \`NgZone.assertNotInAngularZone\` +- \`NgZone.isInAngularZone\` + +#### 2. APIs to Replace +The \`onMicrotaskEmpty\` and \`onStable\` observables must be replaced with modern Angular APIs. + +- **For single-event subscriptions** (e.g., using \`.pipe(take(1))\` or \`.pipe(first())\`), use \`afterNextRender\` from \`@angular/core\`. + + \`\`\`diff + - this.zone.onMicrotaskEmpty.pipe(take(1)).subscribe(() => {}); + - this.zone.onStable.pipe(take(1)).subscribe(() => {}); + + import { afterNextRender, Injector } from '@angular/core'; + + afterNextRender(() => {}, {injector: this.injector}); + \`\`\` + +- **For continuous subscriptions**, use \`afterEveryRender\` from \`@angular/core\`. + + \`\`\`diff + - this.zone.onMicrotaskEmpty.subscribe(() => {}); + - this.zone.onStable.subscribe(() => {}); + + import { afterEveryRender, Injector } from '@angular/core'; + + afterEveryRender(() => {}, {injector: this.injector}); + \`\`\` + +- If the code checks \`this.zone.isStable\` before subscribing, you can remove the \`isStable\` check. \`afterNextRender\` handles this case correctly. + +### IMPORTANT: Rules and Constraints +You must follow these rules without exception: +1. **DO NOT** make any changes to the component that are unrelated to removing the unsupported NgZone APIs listed above. +2. **DO NOT** remove or modify usages of \`NgZone.run\` or \`NgZone.runOutsideAngular\`. These are still required. +3. **DO** ensure that you replace \`onMicrotaskEmpty\` and \`onStable\` with the correct replacements (\`afterNextRender\` or \`afterEveryRender\`) as described in the guide. +4. **DO** add the necessary imports for \`afterNextRender\`, \`afterEveryRender\`, and \`Injector\` when you use them. + +### Final Step +After you have applied all the required changes and followed all the rules, consult this tool again for the next steps in the migration process. +`; + + return createResponse(text); +} + +export function generateZonelessMigrationInstructionsForComponent( + filePath: string, +): MigrationResponse { + const text = `You are an expert Angular developer assisting with a migration to zoneless. Your task is to refactor the component in \`${filePath}\` to be compatible with zoneless change detection by ensuring Angular is notified of all state changes that affect the view. + + The component does not currently use a change detection strategy, which means it may rely on Zone.js. To prepare it for zoneless, you must manually trigger change detection when its state changes. + + Follow these instructions precisely. + + ### Refactoring Guide + + #### Step 1: Identify and Refactor State + Your primary goal is to ensure that every time a component property used in the template is updated, Angular knows it needs to run change detection. + + 1. **Identify Properties**: Find all component properties that are read by the template. + 2. **Choose a Strategy**: For each property identified, choose one of the following refactoring strategies: + * **(Preferred) Convert to Signal**: The best approach is to convert the property to an Angular Signal. This is the most idiomatic and future-proof way to handle state in zoneless applications. + * **(Alternative) Use \`markForCheck()\`**: If converting to a signal is too complex or would require extensive refactoring, you can instead inject \`ChangeDetectorRef\` and call \`this.cdr.markForCheck()\` immediately after the property is updated. + + #### Step 2: Add \`ChangeDetectionStrategy.Default\` + After you have refactored all necessary properties, you must update the component's decorator to explicitly set the change detection strategy. + + 1. Add \`ChangeDetectionStrategy\` to the import from \`@angular/core\`. + 2. In the \`@Component\` decorator, add the property \`changeDetection: ChangeDetectionStrategy.Default\`. + 3. Add a \`// TODO\` comment above this line explaining that the component should be fully migrated to \`OnPush\` after the application has been tested with these changes. + + Example: + \`\`\`typescript + @Component({ + ... + // TODO: This component has been partially migrated to be zoneless-compatible. + // After testing, this should be updated to ChangeDetectionStrategy.OnPush. + changeDetection: ChangeDetectionStrategy.Default, + }) + \`\`\` + + ### IMPORTANT: Rules and Constraints + You must follow these rules without exception: + 1. **DO** apply one of the two refactoring strategies (signals or \`markForCheck()\`) for all relevant component properties. + 2. **DO** add \`changeDetection: ChangeDetectionStrategy.Default\` with the specified TODO comment as the final code change. + 3. **DO NOT** use \`ChangeDetectionStrategy.OnPush\`. This will be the next step in the migration, but it is not part of this task. + 4. **DO NOT** modify properties that are already signals or are used with the \`async\` pipe in the template, as they are already zoneless-compatible. + 5. **DO NOT** make any changes to files other than the component file at \`${filePath}\` and its direct template/style files if necessary. + + ### Final Step + After you have applied all the required changes and followed all the rules, consult this tool again for the next steps in the migration process.`; + + return createResponse(text); +} + +export function createTestDebuggingGuideForNonActionableInput( + fileOrDirPath: string, +): MigrationResponse { + const text = `You are an expert Angular developer assisting with a migration to zoneless. + +No actionable migration steps were found in the application code for \`${fileOrDirPath}\`. However, if the tests for this code are failing with zoneless enabled, the tests themselves likely need to be updated. + +Your task is to investigate and fix any failing tests related to the code in \`${fileOrDirPath}\`. + +${testDebuggingGuideText(fileOrDirPath)} +`; + + return createResponse(text); +} + +export async function createFixResponseForZoneTests( + sourceFile: SourceFile, +): Promise { + const ts = await loadTypescript(); + const usages: Node[] = []; + ts.forEachChild(sourceFile, function visit(node) { + if ( + ts.isCallExpression(node) && + node.expression.getText(sourceFile) === 'provideZoneChangeDetection' + ) { + usages.push(node); + } + ts.forEachChild(node, visit); + }); + if (usages.length === 0) { + // No usages of provideZoneChangeDetection found, so no fix needed. + return null; + } + + const locations = usages.map((node) => { + const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart()); + + return `line ${line + 1}, character ${character + 1}`; + }); + const text = `You are an expert Angular developer assisting with a migration to zoneless. Your task is to update the test file at \`${sourceFile.fileName}\` to be fully zoneless-compatible. + + The test suite has been partially migrated, but some tests were incompatible and are still using Zone.js-based change detection via \`provideZoneChangeDetection\`. You must refactor these tests to work in a zoneless environment and remove the \`provideZoneChangeDetection\` calls. + + The following usages of \`provideZoneChangeDetection\` must be removed: + ${locations.map((loc) => `- ${loc}`).join('\n')} + + After removing \`provideZoneChangeDetection\`, the tests will likely fail. Use this guide to diagnose and fix the failures. + + ${testDebuggingGuideText(sourceFile.fileName)} + + ### Final Step + After you have applied all the required changes and followed all the rules, consult this tool again for the next steps in the migration process.`; + + return createResponse(text); +} + +function testDebuggingGuideText(fileName: string) { + return ` + ### Test Debugging Guide + + 1. **\`ExpressionChangedAfterItHasBeenCheckedError\`**: + * **Cause**: This error indicates that a value in a component's template was updated, but Angular was not notified to run change detection. + * **Solution**: + * If the value is in a test-only wrapper component, update the property to be a signal. + * For application components, either convert the property to a signal or call \`ChangeDetectorRef.markForCheck()\` immediately after the property is updated. + + 2. **Asynchronous Operations and Timing**: + * **Cause**: Without Zone.js, change detection is always scheduled asynchronously. Tests that previously relied on synchronous updates might now fail. The \`fixture.whenStable()\` utility also no longer waits for timers (like \`setTimeout\` or \`setInterval\`). + * **Solution**: + * Avoid relying on synchronous change detection. + * To wait for asynchronous operations to complete, you may need to poll for an expected state, use \`fakeAsync\` with \`tick()\`, or use a mock clock to flush timers. + + 3. **Indirect Dependencies**: + * **Cause**: The component itself might be zoneless-compatible, but it could be using a service or another dependency that is not. + * **Solution**: Investigate the services and dependencies used by the component and its tests. Run this tool on those dependencies to identify and fix any issues. + + ### IMPORTANT: Rules and Constraints + + You must follow these rules without exception: + 1. **DO** focus only on fixing the tests for the code in \`${fileName}\`. + 2. **DO** remove all usages of \`provideZoneChangeDetection\` from the test file. + 3. **DO** apply the solutions described in the debugging guide to fix any resulting test failures. + 4. **DO** update properties of test components and directives to use signals. Tests often use plain objects and values and update the component state directly before calling \`fixture.detectChanges\`. This will not work and will result in \`ExpressionChangedAfterItHasBeenCheckedError\` because Angular was not notifed of the change. + 5. **DO NOT** make changes to application code unless it is to fix a bug revealed by the zoneless migration (e.g., converting a property to a signal to fix an \`ExpressionChangedAfterItHasBeenCheckedError\`). + 6. **DO NOT** make any changes unrelated to fixing the failing tests in \`${fileName}\`. + 7. **DO NOT** re-introduce \`provideZoneChangeDetection()\` into tests that are already using \`provideZonelessChangeDetection()\`.`; +} + +/* eslint-enable max-len */ + +export function createResponse(text: string): MigrationResponse { + return { + content: [{ type: 'text', text }], + }; +} diff --git a/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/send_debug_message.ts b/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/send_debug_message.ts new file mode 100644 index 000000000000..73a1b068a698 --- /dev/null +++ b/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/send_debug_message.ts @@ -0,0 +1,23 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol'; +import { ServerNotification, ServerRequest } from '@modelcontextprotocol/sdk/types'; + +export function sendDebugMessage( + message: string, + { sendNotification }: RequestHandlerExtra, +): void { + void sendNotification({ + method: 'notifications/message', + params: { + level: 'debug', + data: message, + }, + }); +} diff --git a/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/ts_utils.ts b/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/ts_utils.ts new file mode 100644 index 000000000000..72764d648b88 --- /dev/null +++ b/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/ts_utils.ts @@ -0,0 +1,126 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import * as fs from 'node:fs'; +import type { ImportSpecifier, NodeArray, SourceFile } from 'typescript'; +import type ts from 'typescript'; + +let typescriptModule: typeof ts; + +export async function loadTypescript(): Promise { + return (typescriptModule ??= await import('typescript')); +} + +/** + * Gets a top-level import specifier with a specific name that is imported from a particular module. + * E.g. given a file that looks like: + * + * ```ts + * import { Component, Directive } from '@angular/core'; + * import { Foo } from './foo'; + * ``` + * + * Calling `getImportSpecifier(sourceFile, '@angular/core', 'Directive')` will yield the node + * referring to `Directive` in the top import. + * + * @param sourceFile File in which to look for imports. + * @param moduleName Name of the import's module. + * @param specifierName Original name of the specifier to look for. Aliases will be resolved to + * their original name. + */ +export async function getImportSpecifier( + sourceFile: SourceFile, + moduleName: string | RegExp, + specifierName: string, +): Promise { + return ( + getImportSpecifiers(sourceFile, moduleName, specifierName, await loadTypescript())[0] ?? null + ); +} + +/** + * Gets top-level import specifiers with specific names that are imported from a particular module. + * E.g. given a file that looks like: + * + * ```ts + * import { Component, Directive } from '@angular/core'; + * import { Foo } from './foo'; + * ``` + * + * Calling `getImportSpecifiers(sourceFile, '@angular/core', ['Directive', 'Component'])` will + * yield the nodes referring to `Directive` and `Component` in the top import. + * + * @param sourceFile File in which to look for imports. + * @param moduleName Name of the import's module. + * @param specifierOrSpecifiers Original name of the specifier to look for, or an array of such + * names. Aliases will be resolved to their original name. + */ +function getImportSpecifiers( + sourceFile: SourceFile, + moduleName: string | RegExp, + specifierOrSpecifiers: string | string[], + { isNamedImports, isImportDeclaration, isStringLiteral }: typeof ts, +): ImportSpecifier[] { + const matches: ImportSpecifier[] = []; + for (const node of sourceFile.statements) { + if (!isImportDeclaration(node) || !isStringLiteral(node.moduleSpecifier)) { + continue; + } + + const namedBindings = node.importClause?.namedBindings; + const isMatch = + typeof moduleName === 'string' + ? node.moduleSpecifier.text === moduleName + : moduleName.test(node.moduleSpecifier.text); + + if (!isMatch || !namedBindings || !isNamedImports(namedBindings)) { + continue; + } + + if (typeof specifierOrSpecifiers === 'string') { + const match = findImportSpecifier(namedBindings.elements, specifierOrSpecifiers); + if (match) { + matches.push(match); + } + } else { + for (const specifierName of specifierOrSpecifiers) { + const match = findImportSpecifier(namedBindings.elements, specifierName); + if (match) { + matches.push(match); + } + } + } + } + + return matches; +} + +/** + * Finds an import specifier with a particular name. + * @param nodes Array of import specifiers to search through. + * @param specifierName Name of the specifier to look for. + */ +export function findImportSpecifier( + nodes: NodeArray, + specifierName: string, +): ImportSpecifier | undefined { + return nodes.find((element) => { + const { name, propertyName } = element; + + return propertyName ? propertyName.text === specifierName : name.text === specifierName; + }); +} + +/** Creates a TypeScript source file from a file path. */ +export async function createSourceFile(file: string) { + const content = fs.readFileSync(file, 'utf8'); + + const ts = await loadTypescript(); + + return ts.createSourceFile(file, content, ts.ScriptTarget.Latest, true); +} diff --git a/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/types.ts b/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/types.ts new file mode 100644 index 000000000000..e1619f83edb2 --- /dev/null +++ b/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/types.ts @@ -0,0 +1,14 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +export type MigrationResponse = { + content: { + type: 'text'; + text: string; + }[]; +}; diff --git a/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/zoneless-migration.ts b/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/zoneless-migration.ts new file mode 100644 index 000000000000..3c7467bfdb23 --- /dev/null +++ b/packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/zoneless-migration.ts @@ -0,0 +1,208 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol'; +import { ServerNotification, ServerRequest } from '@modelcontextprotocol/sdk/types'; +import * as fs from 'node:fs'; +import { glob } from 'node:fs/promises'; +import { type SourceFile } from 'typescript'; +import { z } from 'zod'; +import { declareTool } from '../tool-registry'; +import { analyzeForUnsupportedZoneUses } from './analyze_for_unsupported_zone_uses'; +import { migrateSingleFile } from './migrate_single_file'; +import { migrateTestFile } from './migrate_test_file'; +import { createTestDebuggingGuideForNonActionableInput } from './prompts'; +import { sendDebugMessage } from './send_debug_message'; +import { createSourceFile, getImportSpecifier } from './ts_utils'; + +export const ZONELESS_MIGRATION_TOOL = declareTool({ + name: 'onpush-zoneless-migration', + title: 'Plan migration to OnPush and/or zoneless', + description: ` + +Analyzes Angular code and provides a step-by-step, iterative plan to migrate it to \`OnPush\` +change detection, a prerequisite for a zoneless application. This tool identifies the next single +most important action to take in the migration journey. + + +* **Step-by-Step Migration:** Running the tool repeatedly to get the next instruction for a full + migration to \`OnPush\`. +* **Pre-Migration Analysis:** Checking a component or directory for unsupported \`NgZone\` APIs that + would block a zoneless migration. +* **Generating Component Migrations:** Getting the exact instructions for converting a single + component from the default change detection strategy to \`OnPush\`. + + +* **Execution Model:** This tool **DOES NOT** modify code. It **PROVIDES INSTRUCTIONS** for a + single action at a time. You **MUST** apply the changes it suggests, and then run the tool + again to get the next step. +* **Iterative Process:** The migration process is iterative. You must call this tool repeatedly, + applying the suggested fix after each call, until the tool indicates that no more actions are + needed. +* **Relationship to \`modernize\`:** This tool is the specialized starting point for the zoneless/OnPush + migration. For other migrations (like signal inputs), you should use the \`modernize\` tool first, + as the zoneless migration may depend on them as prerequisites. +* **Input:** The tool can operate on either a single file or an entire directory. Provide the + absolute path. +`, + isReadOnly: true, + isLocalOnly: true, + inputSchema: { + fileOrDirPath: z + .string() + .describe( + 'The absolute path of the directory or file with the component(s), directive(s), or service(s) to migrate.' + + ' The contents are read with fs.readFileSync.', + ), + }, + factory: + () => + ({ fileOrDirPath }, requestHandlerExtra) => + registerZonelessMigrationTool(fileOrDirPath, requestHandlerExtra), +}); +export async function registerZonelessMigrationTool( + fileOrDirPath: string, + extras: RequestHandlerExtra, +) { + let files: SourceFile[] = []; + const componentTestFiles = new Set(); + const filesWithComponents = new Set(); + const zoneFiles = new Set(); + + if (fs.statSync(fileOrDirPath).isDirectory()) { + const allFiles = glob(`${fileOrDirPath}/**/*.ts`); + for await (const file of allFiles) { + files.push(await createSourceFile(file)); + } + } else { + files = [await createSourceFile(fileOrDirPath)]; + const maybeTestFile = await getTestFilePath(fileOrDirPath); + if (maybeTestFile) { + componentTestFiles.add(await createSourceFile(maybeTestFile)); + } + } + + for (const sourceFile of files) { + const content = sourceFile.getFullText(); + const componentSpecifier = await getImportSpecifier(sourceFile, '@angular/core', 'Component'); + const zoneSpecifier = await getImportSpecifier(sourceFile, '@angular/core', 'NgZone'); + const testBedSpecifier = await getImportSpecifier( + sourceFile, + /(@angular\/core)?\/testing/, + 'TestBed', + ); + if (testBedSpecifier) { + componentTestFiles.add(sourceFile); + } else if (componentSpecifier) { + if ( + !content.includes('changeDetectionStrategy: ChangeDetectionStrategy.OnPush') && + !content.includes('changeDetectionStrategy: ChangeDetectionStrategy.Default') + ) { + filesWithComponents.add(sourceFile); + } else { + sendDebugMessage( + `Component file already has change detection strategy: ${sourceFile.fileName}. Skipping migration.`, + extras, + ); + } + + const testFilePath = await getTestFilePath(sourceFile.fileName); + if (testFilePath) { + componentTestFiles.add(await createSourceFile(testFilePath)); + } + } else if (zoneSpecifier) { + zoneFiles.add(sourceFile); + } + } + + if (zoneFiles.size > 0) { + for (const file of zoneFiles) { + const result = await analyzeForUnsupportedZoneUses(file); + if (result !== null) { + return result; + } + } + } + + if (filesWithComponents.size > 0) { + const rankedFiles = + filesWithComponents.size > 1 + ? await rankComponentFilesForMigration(extras, Array.from(filesWithComponents)) + : Array.from(filesWithComponents); + + for (const file of rankedFiles) { + const result = await migrateSingleFile(file, extras); + if (result !== null) { + return result; + } + } + } + + for (const file of componentTestFiles) { + const result = await migrateTestFile(file); + if (result !== null) { + return result; + } + } + + return createTestDebuggingGuideForNonActionableInput(fileOrDirPath); +} + +async function rankComponentFilesForMigration( + { sendRequest }: RequestHandlerExtra, + componentFiles: SourceFile[], +): Promise { + try { + const response = await sendRequest( + { + method: 'sampling/createMessage', + params: { + messages: [ + { + role: 'user', + content: { + type: 'text', + text: + `The following files are components that need to be migrated to OnPush change detection.` + + ` Please rank them based on which ones are most likely to be shared or common components.` + + ` The most likely shared component should be first. + ${componentFiles.map((f) => f.fileName).join('\n ')} + Respond ONLY with the ranked list of files, one file per line.`, + }, + }, + ], + systemPrompt: + 'You are a helpful assistant that helps migrate identify shared Angular components.', + maxTokens: 2000, + }, + }, + z.object({ sortedFiles: z.array(z.string()) }), + ); + + const rankedFiles = response.sortedFiles + .map((line) => line.trim()) + .map((fileName) => componentFiles.find((f) => f.fileName === fileName)) + .filter((f) => !!f); + + // Ensure the ranking didn't mess up the list of files + if (rankedFiles.length === componentFiles.length) { + return rankedFiles; + } + } catch {} + + return componentFiles; // Fallback to original order if the response fails +} + +async function getTestFilePath(filePath: string): Promise { + const testFilePath = filePath.replace(/\.ts$/, '.spec.ts'); + if (fs.existsSync(testFilePath)) { + return testFilePath; + } + + return undefined; +} diff --git a/packages/angular/ssr/package.json b/packages/angular/ssr/package.json index 839432fe864c..79dc4f537f31 100644 --- a/packages/angular/ssr/package.json +++ b/packages/angular/ssr/package.json @@ -29,12 +29,12 @@ }, "devDependencies": { "@angular-devkit/schematics": "workspace:*", - "@angular/common": "20.2.1", - "@angular/compiler": "20.2.1", - "@angular/core": "20.2.1", - "@angular/platform-browser": "20.2.1", - "@angular/platform-server": "20.2.1", - "@angular/router": "20.2.1", + "@angular/common": "20.2.3", + "@angular/compiler": "20.2.3", + "@angular/core": "20.2.3", + "@angular/platform-browser": "20.2.3", + "@angular/platform-server": "20.2.3", + "@angular/router": "20.2.3", "@schematics/angular": "workspace:*" }, "sideEffects": false, diff --git a/packages/ngtools/webpack/package.json b/packages/ngtools/webpack/package.json index ece914ec8df0..29ba7c8a259a 100644 --- a/packages/ngtools/webpack/package.json +++ b/packages/ngtools/webpack/package.json @@ -27,8 +27,8 @@ }, "devDependencies": { "@angular-devkit/core": "workspace:0.0.0-PLACEHOLDER", - "@angular/compiler": "20.2.1", - "@angular/compiler-cli": "20.2.1", + "@angular/compiler": "20.2.3", + "@angular/compiler-cli": "20.2.3", "typescript": "5.9.2", "webpack": "5.101.2" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 62920ce5a23e..fc301efb79fc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,47 +20,47 @@ importers: built: true devDependencies: '@angular/animations': - specifier: 20.2.1 - version: 20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)) + specifier: 20.2.3 + version: 20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)) '@angular/cdk': specifier: 20.2.1 - version: 20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + version: 20.2.1(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) '@angular/common': - specifier: 20.2.1 - version: 20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + specifier: 20.2.3 + version: 20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) '@angular/compiler': - specifier: 20.2.1 - version: 20.2.1 + specifier: 20.2.3 + version: 20.2.3 '@angular/compiler-cli': - specifier: 20.2.1 - version: 20.2.1(@angular/compiler@20.2.1)(typescript@5.9.2) + specifier: 20.2.3 + version: 20.2.3(@angular/compiler@20.2.3)(typescript@5.9.2) '@angular/core': - specifier: 20.2.1 - version: 20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1) + specifier: 20.2.3 + version: 20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1) '@angular/forms': - specifier: 20.2.1 - version: 20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.2.1(@angular/animations@20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) + specifier: 20.2.3 + version: 20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.2.3(@angular/animations@20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) '@angular/localize': - specifier: 20.2.1 - version: 20.2.1(@angular/compiler-cli@20.2.1(@angular/compiler@20.2.1)(typescript@5.9.2))(@angular/compiler@20.2.1) + specifier: 20.2.3 + version: 20.2.3(@angular/compiler-cli@20.2.3(@angular/compiler@20.2.3)(typescript@5.9.2))(@angular/compiler@20.2.3) '@angular/material': specifier: 20.2.1 - version: 20.2.1(b60312b63259c1568290f1cfc536b3a7) + version: 20.2.1(db7b32723760b0ee941b26d324534a22) '@angular/ng-dev': - specifier: https://github.com/angular/dev-infra-private-ng-dev-builds.git#9d0a73d937f6447d06ef56a5347c805e5d9400d7 - version: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/9d0a73d937f6447d06ef56a5347c805e5d9400d7(@modelcontextprotocol/sdk@1.17.3) + specifier: https://github.com/angular/dev-infra-private-ng-dev-builds.git#b991414e4f3ed15d99f4331b5353499434878374 + version: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/b991414e4f3ed15d99f4331b5353499434878374(@modelcontextprotocol/sdk@1.17.3) '@angular/platform-browser': - specifier: 20.2.1 - version: 20.2.1(@angular/animations@20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)) + specifier: 20.2.3 + version: 20.2.3(@angular/animations@20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)) '@angular/platform-server': - specifier: 20.2.1 - version: 20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@20.2.1)(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.2.1(@angular/animations@20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) + specifier: 20.2.3 + version: 20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@20.2.3)(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.2.3(@angular/animations@20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) '@angular/router': - specifier: 20.2.1 - version: 20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.2.1(@angular/animations@20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) + specifier: 20.2.3 + version: 20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.2.3(@angular/animations@20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) '@angular/service-worker': - specifier: 20.2.1 - version: 20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + specifier: 20.2.3 + version: 20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) '@bazel/bazelisk': specifier: 1.26.0 version: 1.26.0 @@ -90,7 +90,7 @@ importers: version: 16.0.1(rollup@4.46.2) '@stylistic/eslint-plugin': specifier: ^5.0.0 - version: 5.2.3(eslint@9.33.0(jiti@1.21.7)) + version: 5.3.1(eslint@9.33.0(jiti@1.21.7)) '@types/babel__core': specifier: 7.20.5 version: 7.20.5 @@ -129,7 +129,7 @@ importers: version: 4.17.20 '@types/node': specifier: ^22.12.0 - version: 22.17.2 + version: 22.18.0 '@types/npm-package-arg': specifier: ^6.1.0 version: 6.1.4 @@ -282,7 +282,7 @@ importers: version: 6.2.1(rollup@4.46.2)(typescript@5.9.2) rollup-plugin-sourcemaps2: specifier: 0.5.3 - version: 0.5.3(@types/node@22.17.2)(rollup@4.46.2) + version: 0.5.3(@types/node@22.18.0)(rollup@4.46.2) semver: specifier: 7.7.2 version: 7.7.2 @@ -297,7 +297,7 @@ importers: version: 7.4.3 ts-node: specifier: ^10.9.1 - version: 10.9.2(@types/node@22.17.2)(typescript@5.9.2) + version: 10.9.2(@types/node@22.18.0)(typescript@5.9.2) tslib: specifier: 2.8.1 version: 2.8.1 @@ -372,7 +372,7 @@ importers: version: 0.3.5 browserslist: specifier: ^4.23.0 - version: 4.25.3 + version: 4.25.4 esbuild: specifier: 0.25.9 version: 0.25.9 @@ -439,7 +439,7 @@ importers: version: 4.4.0 ng-packagr: specifier: 20.2.0 - version: 20.2.0(@angular/compiler-cli@20.2.1(@angular/compiler@20.2.1)(typescript@5.9.2))(tslib@2.8.1)(typescript@5.9.2) + version: 20.2.0(@angular/compiler-cli@20.2.3(@angular/compiler@20.2.3)(typescript@5.9.2))(tslib@2.8.1)(typescript@5.9.2) postcss: specifier: 8.5.6 version: 8.5.6 @@ -533,23 +533,23 @@ importers: specifier: workspace:* version: link:../../angular_devkit/schematics '@angular/common': - specifier: 20.2.1 - version: 20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + specifier: 20.2.3 + version: 20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) '@angular/compiler': - specifier: 20.2.1 - version: 20.2.1 + specifier: 20.2.3 + version: 20.2.3 '@angular/core': - specifier: 20.2.1 - version: 20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1) + specifier: 20.2.3 + version: 20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1) '@angular/platform-browser': - specifier: 20.2.1 - version: 20.2.1(@angular/animations@20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)) + specifier: 20.2.3 + version: 20.2.3(@angular/animations@20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)) '@angular/platform-server': - specifier: 20.2.1 - version: 20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@20.2.1)(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.2.1(@angular/animations@20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) + specifier: 20.2.3 + version: 20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@20.2.3)(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.2.3(@angular/animations@20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) '@angular/router': - specifier: 20.2.1 - version: 20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.2.1(@angular/animations@20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) + specifier: 20.2.3 + version: 20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.2.3(@angular/animations@20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) '@schematics/angular': specifier: workspace:* version: link:../../schematics/angular @@ -646,7 +646,7 @@ importers: version: 10.0.0(@babel/core@7.28.3)(webpack@5.101.2(esbuild@0.25.9)) browserslist: specifier: ^4.21.5 - version: 4.25.3 + version: 4.25.4 copy-webpack-plugin: specifier: 13.0.1 version: 13.0.1(webpack@5.101.2(esbuild@0.25.9)) @@ -761,7 +761,7 @@ importers: version: 3.0.4(bufferutil@4.0.9) ng-packagr: specifier: 20.2.0 - version: 20.2.0(@angular/compiler-cli@20.2.1(@angular/compiler@20.2.1)(typescript@5.9.2))(tslib@2.8.1)(typescript@5.9.2) + version: 20.2.0(@angular/compiler-cli@20.2.3(@angular/compiler@20.2.3)(typescript@5.9.2))(tslib@2.8.1)(typescript@5.9.2) undici: specifier: 7.13.0 version: 7.13.0 @@ -859,11 +859,11 @@ importers: specifier: workspace:0.0.0-PLACEHOLDER version: link:../../angular_devkit/core '@angular/compiler': - specifier: 20.2.1 - version: 20.2.1 + specifier: 20.2.3 + version: 20.2.3 '@angular/compiler-cli': - specifier: 20.2.1 - version: 20.2.1(@angular/compiler@20.2.1)(typescript@5.9.2) + specifier: 20.2.3 + version: 20.2.3(@angular/compiler@20.2.3)(typescript@5.9.2) typescript: specifier: 5.9.2 version: 5.9.2 @@ -975,12 +975,12 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@angular/animations@20.2.1': - resolution: {integrity: sha512-g4yLXwXCF7OAahx1xI4FXRwG4dIXfBqHsvlpx2TappaMRpiPp7PfP2cW6l3ox+KRpTWhSvcRqbJyIOWad0f7Rw==} + '@angular/animations@20.2.3': + resolution: {integrity: sha512-cyON3oVfaotz8d8DHP3uheC/XDG2gJD8aiyuG/SEAZ2X1S/tAHdVetESbDZM830lLdi+kB/3GBrMbWCCpMWD7Q==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/common': 20.2.1 - '@angular/core': 20.2.1 + '@angular/common': 20.2.3 + '@angular/core': 20.2.3 '@angular/cdk@20.2.1': resolution: {integrity: sha512-yEPh5hr9LZW4ey/HxtaGdSBDIkNzziLo0Dr1RP8JcxhOQ2Bzv2PZ+g8jC6aPGD7NPV8FtDf0FhTEzQr+m+gBXQ==} @@ -989,33 +989,33 @@ packages: '@angular/core': ^20.0.0 || ^21.0.0 rxjs: ^6.5.3 || ^7.4.0 - '@angular/common@20.2.1': - resolution: {integrity: sha512-T6RYnDZA9TyYhj2hUz4set8p4RbBCg6IKUvy6qzdKTl4nn4xQ0XUV7aGBYN4LKiGrse9lzlVUAyXtkhmwuBbCQ==} + '@angular/common@20.2.3': + resolution: {integrity: sha512-QLffWL8asy2oG7p3jvoNmx9s1V1WuJAm6JmQ1S8J3AN/BxumCJan49Nj8rctP8J4uwJDPQV48hqbXUdl1v7CDg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/core': 20.2.1 + '@angular/core': 20.2.3 rxjs: ^6.5.3 || ^7.4.0 - '@angular/compiler-cli@20.2.1': - resolution: {integrity: sha512-VpbcRqNPJvy1L9RDtGGQsQiOrMzxodUWklphbtnh9MrrK6lLuy6Qj2ROiW7vKL9WfLTCXWA24gBAcMAR76dq3Q==} + '@angular/compiler-cli@20.2.3': + resolution: {integrity: sha512-adLyPXmKbH8VZJCyOraaha+RPTdAjEBRTqwZ5YkjkViTMMANFkuj1w3pDwQsG3LFknRJ99aym+9neGINeAaI7A==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} hasBin: true peerDependencies: - '@angular/compiler': 20.2.1 + '@angular/compiler': 20.2.3 typescript: 5.9.2 peerDependenciesMeta: typescript: optional: true - '@angular/compiler@20.2.1': - resolution: {integrity: sha512-ghVt1E8xmwjMwqyGRwXYJkr7fz40VEreUSX1q+gEzbGTftVrK1foxPT8jcueIn0ztArDf7+zSMtu314FiJZyYA==} + '@angular/compiler@20.2.3': + resolution: {integrity: sha512-vYGDluko8zAIWhQmKijhcGO0tzanwGONDRgbJ01mCqUsQV+XwmDgUUDZKrUY9uve0wxxM3Xvo4/BjEpGpeG75w==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - '@angular/core@20.2.1': - resolution: {integrity: sha512-/hl3AkmdQ62P9ttmfULEDg9GIz7BkzhGv9bSH2ssiU3Y4ax6eM8uQXEbMxBA8OUKOvg1Q4POcNHIiJQgO5t28Q==} + '@angular/core@20.2.3': + resolution: {integrity: sha512-pFMfg11X8SNNZHcLa+wy4y+eAN3FApt+wPzaxkaXaJ64c+tyHcrPNLotoWgE0jmiw8Idn4gGjKAL/WC0uw5dQA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/compiler': 20.2.1 + '@angular/compiler': 20.2.3 rxjs: ^6.5.3 || ^7.4.0 zone.js: ~0.15.0 peerDependenciesMeta: @@ -1024,22 +1024,22 @@ packages: zone.js: optional: true - '@angular/forms@20.2.1': - resolution: {integrity: sha512-SfkiHEIFPLtTKeaXUTpRfYnpJDxaeKiTi0YqfvzEjKE68qH0t+pQ4rL0Poch2/l4snP6JS1XzO/nDve1dk3vZw==} + '@angular/forms@20.2.3': + resolution: {integrity: sha512-efMn/Hnspg91SzRTm69WpyGq0dgbCtWqUOrR0iZXTR/oDlJw9F/y/nrST36tOBwRNT0QQ2iU5z43iJY1Rl1Bng==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/common': 20.2.1 - '@angular/core': 20.2.1 - '@angular/platform-browser': 20.2.1 + '@angular/common': 20.2.3 + '@angular/core': 20.2.3 + '@angular/platform-browser': 20.2.3 rxjs: ^6.5.3 || ^7.4.0 - '@angular/localize@20.2.1': - resolution: {integrity: sha512-vemzYcHt6YX4FutpgNXiXTpKCMVaJdOG/m2+oJyvnr8KvdlrJKczXraPVY4ER+WJiHC5IQSg24otdSFc0UH2JA==} + '@angular/localize@20.2.3': + resolution: {integrity: sha512-+r7VbxuaOwUuvC1xPfuNpJSbwv4+LOUouVZhBq5sp2qYrKkVw2QZaIbd6uPTE1NWbu7rGwSGVw4rTx4LvA3fYw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} hasBin: true peerDependencies: - '@angular/compiler': 20.2.1 - '@angular/compiler-cli': 20.2.1 + '@angular/compiler': 20.2.3 + '@angular/compiler-cli': 20.2.3 '@angular/material@20.2.1': resolution: {integrity: sha512-Zv1ay/eSwO9e2xUrPKOQFSKscb0+0bhZmDwy9etQhder0FBh380iizP+PaZnJGGy87zYDmauv0fjKcDfdWCJYA==} @@ -1051,47 +1051,47 @@ packages: '@angular/platform-browser': ^20.0.0 || ^21.0.0 rxjs: ^6.5.3 || ^7.4.0 - '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/9d0a73d937f6447d06ef56a5347c805e5d9400d7': - resolution: {tarball: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/9d0a73d937f6447d06ef56a5347c805e5d9400d7} - version: 0.0.0-b34c3cb148e5cfbd9be5538cdace58b29b215afa + '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/b991414e4f3ed15d99f4331b5353499434878374': + resolution: {tarball: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/b991414e4f3ed15d99f4331b5353499434878374} + version: 0.0.0-06d3af5cfd1e122087c0acafdd7909edce4ad1d7 hasBin: true - '@angular/platform-browser@20.2.1': - resolution: {integrity: sha512-oxDih/A8G7W+I6oAip+sev+kebioYmzhB/NMzF8C8zx/ieVDzatJ+YeEZQt7eDaJLH94S4sIC25SPq3OFIabxg==} + '@angular/platform-browser@20.2.3': + resolution: {integrity: sha512-oNaRqcGUve+E/CwR9fJb8uern5rb7qNOis1bZRdPXq5rHKaWgDCxUPkoqxRi0EytorntuYsWYPUPW3ul4Ea9tw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/animations': 20.2.1 - '@angular/common': 20.2.1 - '@angular/core': 20.2.1 + '@angular/animations': 20.2.3 + '@angular/common': 20.2.3 + '@angular/core': 20.2.3 peerDependenciesMeta: '@angular/animations': optional: true - '@angular/platform-server@20.2.1': - resolution: {integrity: sha512-yjos8jgHwcih9lF/CKjbKxzzc83NM+ZoIdm/XSVv9yg+QDnTsc6bLF3QZ+OChCoaCks/UtWUwyM7Ux2g/VvVFA==} + '@angular/platform-server@20.2.3': + resolution: {integrity: sha512-KswW/6KX4Av8WdiJLIVElqi4f7RIcIrcnkRRYrVm2UUHEpH+W94LkMMN9ybACmGSArg0j5DlfyJtotZefwFtzQ==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/common': 20.2.1 - '@angular/compiler': 20.2.1 - '@angular/core': 20.2.1 - '@angular/platform-browser': 20.2.1 + '@angular/common': 20.2.3 + '@angular/compiler': 20.2.3 + '@angular/core': 20.2.3 + '@angular/platform-browser': 20.2.3 rxjs: ^6.5.3 || ^7.4.0 - '@angular/router@20.2.1': - resolution: {integrity: sha512-f8KfG55EVnFDC9ud+MbxAP6voKi7hVQH4YaqPK0Lm6pyc1Xp0I5W25iRbg+Y1rO1csHKHauBPkUEESEuVGBGqg==} + '@angular/router@20.2.3': + resolution: {integrity: sha512-r8yGJcxHPfeIHZOoyCxN2H4nMgBD/k4TVTFaq8MHf5ryy1iLzayIMPJTFaZe7xpwlJJuBYEjBrYfUN38fYKWgA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/common': 20.2.1 - '@angular/core': 20.2.1 - '@angular/platform-browser': 20.2.1 + '@angular/common': 20.2.3 + '@angular/core': 20.2.3 + '@angular/platform-browser': 20.2.3 rxjs: ^6.5.3 || ^7.4.0 - '@angular/service-worker@20.2.1': - resolution: {integrity: sha512-BiwtxSXooM/JlW6C0TixogHxXyL4eio9fcwsJTBgqoyfuom+GI+VMcDKcVi5X6cJnfpbmSzO1qNEzpdr+EgqvQ==} + '@angular/service-worker@20.2.3': + resolution: {integrity: sha512-h3f44QBCEuC7FoKT0FH+PDW4VFqdsImn6PuGjXFEjMe7D8gcV9HK8aeYMCcvAJetWSqaG5hdDHO4gNoZgQV9Zg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} hasBin: true peerDependencies: - '@angular/core': 20.2.1 + '@angular/core': 20.2.3 rxjs: ^6.5.3 || ^7.4.0 '@asamuzakjp/css-color@3.2.0': @@ -1614,6 +1614,18 @@ packages: resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} + '@conventional-changelog/git-client@1.0.1': + resolution: {integrity: sha512-PJEqBwAleffCMETaVm/fUgHldzBE35JFk3/9LL6NUA5EXa3qednu+UT6M7E5iBu3zIQZCULYIiZ90fBYHt6xUw==} + engines: {node: '>=18'} + peerDependencies: + conventional-commits-filter: ^5.0.0 + conventional-commits-parser: ^6.0.0 + peerDependenciesMeta: + conventional-commits-filter: + optional: true + conventional-commits-parser: + optional: true + '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} @@ -1654,14 +1666,14 @@ packages: resolution: {integrity: sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==} engines: {node: '>=14.17.0'} - '@emnapi/core@1.4.5': - resolution: {integrity: sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==} + '@emnapi/core@1.5.0': + resolution: {integrity: sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==} - '@emnapi/runtime@1.4.5': - resolution: {integrity: sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==} + '@emnapi/runtime@1.5.0': + resolution: {integrity: sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==} - '@emnapi/wasi-threads@1.0.4': - resolution: {integrity: sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==} + '@emnapi/wasi-threads@1.1.0': + resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} '@esbuild/aix-ppc64@0.25.9': resolution: {integrity: sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==} @@ -1870,8 +1882,8 @@ packages: resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} - '@firebase/ai@2.1.0': - resolution: {integrity: sha512-4HvFr4YIzNFh0MowJLahOjJDezYSTjQar0XYVu/sAycoxQ+kBsfXuTPRLVXCYfMR5oNwQgYe4Q2gAOYKKqsOyA==} + '@firebase/ai@2.2.1': + resolution: {integrity: sha512-0VWlkGB18oDhwMqsgxpt/usMsyjnH3a7hTvQPcAbk7VhFg0QZMDX60mQKfLTFKrB5VwmlaIdVsSZznsTY2S0wA==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app': 0.x @@ -1908,15 +1920,15 @@ packages: peerDependencies: '@firebase/app': 0.x - '@firebase/app-compat@0.5.1': - resolution: {integrity: sha512-BEy1L6Ufd85ZSP79HDIv0//T9p7d5Bepwy+2mKYkgdXBGKTbFm2e2KxyF1nq4zSQ6RRBxWi0IY0zFVmoBTZlUA==} + '@firebase/app-compat@0.5.2': + resolution: {integrity: sha512-cn+U27GDaBS/irsbvrfnPZdcCzeZPRGKieSlyb7vV6LSOL6mdECnB86PgYjYGxSNg8+U48L/NeevTV1odU+mOQ==} engines: {node: '>=20.0.0'} '@firebase/app-types@0.9.3': resolution: {integrity: sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==} - '@firebase/app@0.14.1': - resolution: {integrity: sha512-jxTrDbxnGoX7cGz7aP9E7v9iKvBbQfZ8Gz4TH3SfrrkcyIojJM3+hJnlbGnGxHrABts844AxRcg00arMZEyA6Q==} + '@firebase/app@0.14.2': + resolution: {integrity: sha512-Ecx2ig/JLC9ayIQwZHqm41Tzlf4c1WUuFhFUZB1y+JIJqDRE579x7Uil7tKT8MwDpOPwrK5ZtpxdSsrfy/LF8Q==} engines: {node: '>=20.0.0'} '@firebase/auth-compat@0.6.0': @@ -1964,8 +1976,8 @@ packages: resolution: {integrity: sha512-gM6MJFae3pTyNLoc9VcJNuaUDej0ctdjn3cVtILo3D5lpp0dmUHHLFN/pUKe7ImyeB1KAvRlEYxvIHNF04Filg==} engines: {node: '>=20.0.0'} - '@firebase/firestore-compat@0.4.0': - resolution: {integrity: sha512-4O7v4VFeSEwAZtLjsaj33YrMHMRjplOIYC2CiYsF6o/MboOhrhe01VrTt8iY9Y5EwjRHuRz4pS6jMBT8LfQYJA==} + '@firebase/firestore-compat@0.4.1': + resolution: {integrity: sha512-BjalPTDh/K0vmR/M/DE148dpIqbcfvtFVTietbUDWDWYIl9YH0TTVp/EwXRbZwswPxyjx4GdHW61GB2AYVz1SQ==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app-compat': 0.x @@ -1976,14 +1988,14 @@ packages: '@firebase/app-types': 0.x '@firebase/util': 1.x - '@firebase/firestore@4.9.0': - resolution: {integrity: sha512-5zl0+/h1GvlCSLt06RMwqFsd7uqRtnNZt4sW99k2rKRd6k/ECObIWlEnvthm2cuOSnUmwZknFqtmd1qyYSLUuQ==} + '@firebase/firestore@4.9.1': + resolution: {integrity: sha512-PYVUTkhC9y8pydrqC3O1Oc4AMfkGSWdmuH9xgPJjiEbpUIUPQ4J8wJhyuash+o2u+axmyNRFP8ULNUKb+WzBzQ==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app': 0.x - '@firebase/functions-compat@0.4.0': - resolution: {integrity: sha512-VPgtvoGFywWbQqtvgJnVWIDFSHV1WE6Hmyi5EGI+P+56EskiGkmnw6lEqc/MEUfGpPGdvmc4I9XMU81uj766/g==} + '@firebase/functions-compat@0.4.1': + resolution: {integrity: sha512-AxxUBXKuPrWaVNQ8o1cG1GaCAtXT8a0eaTDfqgS5VsRYLAR0ALcfqDLwo/QyijZj1w8Qf8n3Qrfy/+Im245hOQ==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app-compat': 0.x @@ -1991,8 +2003,8 @@ packages: '@firebase/functions-types@0.6.3': resolution: {integrity: sha512-EZoDKQLUHFKNx6VLipQwrSMh01A1SaL3Wg6Hpi//x6/fJ6Ee4hrAeswK99I5Ht8roiniKHw4iO0B1Oxj5I4plg==} - '@firebase/functions@0.13.0': - resolution: {integrity: sha512-2/LH5xIbD8aaLOWSFHAwwAybgSzHIM0dB5oVOL0zZnxFG1LctX2bc1NIAaPk1T+Zo9aVkLKUlB5fTXTkVUQprQ==} + '@firebase/functions@0.13.1': + resolution: {integrity: sha512-sUeWSb0rw5T+6wuV2o9XNmh9yHxjFI9zVGFnjFi+n7drTEWpl7ZTz1nROgGrSu472r+LAaj+2YaSicD4R8wfbw==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app': 0.x @@ -2111,11 +2123,11 @@ packages: resolution: {integrity: sha512-IJn+8A3QZJfe7FUtWqHVNo3xJs7KFpurCWGWCiCz3oEh+BkRymKZ1QxfAbU2yGMDzTytLGQ2IV6T2r3cuo75/w==} engines: {node: '>=18'} - '@google/genai@1.15.0': - resolution: {integrity: sha512-4CSW+hRTESWl3xVtde7pkQ3E+dDFhDq+m4ztmccRctZfx1gKy3v0M9STIMGk6Nq0s6O2uKMXupOZQ1JGorXVwQ==} + '@google/genai@1.16.0': + resolution: {integrity: sha512-hdTYu39QgDFxv+FB6BK2zi4UIJGWhx2iPc0pHQ0C5Q/RCi+m+4gsryIzTGO+riqWcUA8/WGYp6hpqckdOBNysw==} engines: {node: '>=20.0.0'} peerDependencies: - '@modelcontextprotocol/sdk': ^1.11.0 + '@modelcontextprotocol/sdk': ^1.11.4 peerDependenciesMeta: '@modelcontextprotocol/sdk': optional: true @@ -2616,8 +2628,8 @@ packages: resolution: {integrity: sha512-rCNLSB/JzNvot0SEyXqWZ7tX2B5dD2a1br2Dp0vSYVo5jh8Z0EZ7lS9TsZ1UtziddB1UfNUaMCc538/HztnJGA==} engines: {node: ^18.17.0 || >=20.5.0} - '@npmcli/promise-spawn@8.0.2': - resolution: {integrity: sha512-/bNJhjc+o6qL+Dwz/bqfTQClkEO5nTQ1ZEcdCkAQjhkZMHIh22LPG7fNh1enJP1NKWDqYiiABnjFCY7E0zHYtQ==} + '@npmcli/promise-spawn@8.0.3': + resolution: {integrity: sha512-Yb00SWaL4F8w+K8YGhQ55+xE4RUNdMHV43WZGsiTM92gS+lC0mGsn7I4hLug7pbao035S6bj3Y3w0cUNGLfmkg==} engines: {node: ^18.17.0 || >=20.5.0} '@npmcli/redact@3.2.2': @@ -2879,8 +2891,8 @@ packages: '@protobufjs/utf8@1.1.0': resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} - '@puppeteer/browsers@2.10.7': - resolution: {integrity: sha512-wHWLkQWBjHtajZeqCB74nsa/X70KheyOhySYBRmVQDJiNj0zjZR/naPCvdWjMhcG1LmjaMV/9WtTo5mpe8qWLw==} + '@puppeteer/browsers@2.10.8': + resolution: {integrity: sha512-f02QYEnBDE0p8cteNoPYHHjbDuwyfbe4cCIVlNi8/MRicIxFW4w4CfgU0LNgWEID6s06P+hRJ1qjpBLMhPRCiQ==} engines: {node: '>=18'} hasBin: true @@ -3111,8 +3123,8 @@ packages: cpu: [x64] os: [win32] - '@rollup/wasm-node@4.48.1': - resolution: {integrity: sha512-BGNxbwNHAwBj82DwDHc6Yia1bOs2NP1gvF181l7HYEUGfq8EoFkzr+S6sbuF2j5TXQHWbl/ev1g4kU7ZN4QSPw==} + '@rollup/wasm-node@4.50.0': + resolution: {integrity: sha512-mCzoNeR8ynLTHJ5VQ9J/GzSKPJjEC4/nCmGw2y3NSCZoc4sbSVdNe5x4S7+bda6QIEUrk6lR1FE7FEDo+p/u1Q==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -3146,8 +3158,8 @@ packages: '@socket.io/component-emitter@3.1.2': resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} - '@stylistic/eslint-plugin@5.2.3': - resolution: {integrity: sha512-oY7GVkJGVMI5benlBDCaRrSC1qPasafyv5dOBLLv5MTilMGnErKhO6ziEfodDDIZbo5QxPUNW360VudJOFODMw==} + '@stylistic/eslint-plugin@5.3.1': + resolution: {integrity: sha512-Ykums1VYonM0TgkD0VteVq9mrlO2FhF48MDJnPyv3MktIB2ydtuhlO0AfWm7xnW1kyf5bjOqA6xc7JjviuVTxg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: '>=9.0.0' @@ -3284,8 +3296,8 @@ packages: '@types/folder-hash@4.0.4': resolution: {integrity: sha512-c+PwHm51Dw3fXM8SDK+93PO3oXdk4XNouCCvV67lj4aijRkZz5g67myk+9wqWWnyv3go6q96hT6ywcd3XtoZiQ==} - '@types/git-raw-commits@2.0.4': - resolution: {integrity: sha512-PYmTK156j6TilbwtnO2JErH4TCC1izpgP3kRE3KUX35bjBOD2A+syCGeercqHXBcM6wL+DU0WbJB2Gz8fPR+8A==} + '@types/git-raw-commits@5.0.0': + resolution: {integrity: sha512-MQIzbZxgEnKpN1kCcw9JlQIu3Wdw5c4CCCP2cUli+DYgFjzsjtGLOeUe8oqPjjrKJudOoFnNuIZb/4sYHXEWZg==} '@types/graceful-fs@4.1.9': resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} @@ -3360,8 +3372,8 @@ packages: '@types/node-forge@1.3.14': resolution: {integrity: sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==} - '@types/node@22.17.2': - resolution: {integrity: sha512-gL6z5N9Jm9mhY+U2KXZpteb+09zyffliRkZyZOHODGATyC5B1Jt/7TzuuiLkFsSUMLbS1OLmlj/E+/3KF4Q/4w==} + '@types/node@22.18.0': + resolution: {integrity: sha512-m5ObIqwsUp6BZzyiy4RdZpzWGub9bqLJMvZDD0QMXhxjqMHMENlj+SqF5QxoUwaQNFe+8kz8XM8ZQhqkQPTgMQ==} '@types/node@24.3.0': resolution: {integrity: sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==} @@ -3523,8 +3535,8 @@ packages: resolution: {integrity: sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/types@8.40.0': - resolution: {integrity: sha512-ETdbFlgbAmXHyFPwqUIYrfc12ArvpBhEVgGAxVYSwli26dn8Ko+lIo4Su9vI9ykTZdJn+vJprs/0eZU0YMAEQg==} + '@typescript-eslint/types@8.41.0': + resolution: {integrity: sha512-9EwxsWdVqh42afLbHP90n2VdHaWU/oWgbH2P0CfcNfdKL7CuKpwMQGjwev56vWu9cSKU7FWSu6r9zck6CVfnag==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@typescript-eslint/typescript-estree@8.39.1': @@ -4065,8 +4077,8 @@ packages: bare-events@2.6.1: resolution: {integrity: sha512-AuTJkq9XmE6Vk0FJVNq5QxETrSA/vKHarWVBG5l/JbdCL1prJemiyJqUS0jrlXO0MftuPq4m3YVYhoNc5+aE/g==} - bare-fs@4.2.1: - resolution: {integrity: sha512-mELROzV0IhqilFgsl1gyp48pnZsaV9xhQapHLDsvn4d4ZTfbFhcghQezl7FTEDNBcGqLUnNI3lUlm6ecrLWdFA==} + bare-fs@4.2.2: + resolution: {integrity: sha512-5vn+bdnlCYMwETIm1FqQXDP6TYPbxr2uJd88ve40kr4oPbiTZJVrTNzqA3/4sfWZeWKuQR/RkboBt7qEEDtfMA==} engines: {bare: '>=1.16.0'} peerDependencies: bare-buffer: '*' @@ -4186,8 +4198,8 @@ packages: browserify-zlib@0.1.4: resolution: {integrity: sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==} - browserslist@4.25.3: - resolution: {integrity: sha512-cDGv1kkDI4/0e5yON9yM5G/0A5u8sf5TnmdX5C9qHzI9PPu++sQ9zjm1k9NiOrf3riY4OkK0zSGqfvJyJsgCBQ==} + browserslist@4.25.4: + resolution: {integrity: sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -4260,8 +4272,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001737: - resolution: {integrity: sha512-BiloLiXtQNrY5UyF0+1nSJLXUENuhka2pzy2Fx5pGxqavdrxSCW4U6Pn/PoG3Efspi2frRbHpBV2XsrPE6EDlw==} + caniuse-lite@1.0.30001739: + resolution: {integrity: sha512-y+j60d6ulelrNSwpPyrHdl+9mJnQzHBr08xm48Qno0nSk4h3Qojh+ziv2qE6rXf4k3tadF4o1J/1tAbVm1NtnA==} caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} @@ -4471,6 +4483,10 @@ packages: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} + conventional-commits-filter@5.0.0: + resolution: {integrity: sha512-tQMagCOC59EVgNZcC5zl7XqO30Wki9i9J3acbUvkaosCT6JX3EeFwJD7Qqp4MCikRnzS18WXV3BLIQ66ytu6+Q==} + engines: {node: '>=18'} + conventional-commits-parser@5.0.0: resolution: {integrity: sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==} engines: {node: '>=16'} @@ -4576,10 +4592,6 @@ packages: custom-event@1.0.1: resolution: {integrity: sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==} - dargs@8.1.0: - resolution: {integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==} - engines: {node: '>=12'} - dashdash@1.14.1: resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} engines: {node: '>=0.10'} @@ -4854,11 +4866,11 @@ packages: engines: {node: '>=0.10.0'} hasBin: true - electron-to-chromium@1.5.208: - resolution: {integrity: sha512-ozZyibehoe7tOhNaf16lKmljVf+3npZcJIEbJRVftVsmAg5TeA1mGS9dVCZzOwr2xT7xK15V0p7+GZqSPgkuPg==} + electron-to-chromium@1.5.212: + resolution: {integrity: sha512-gE7ErIzSW+d8jALWMcOIgf+IB6lpfsg6NwOhPVwKzDtN2qcBix47vlin4yzSregYDxTCXOUqAZjVY/Z3naS7ww==} - emoji-regex@10.4.0: - resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} + emoji-regex@10.5.0: + resolution: {integrity: sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -5131,9 +5143,9 @@ packages: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} - eventsource-parser@3.0.5: - resolution: {integrity: sha512-bSRG85ZrMdmWtm7qkF9He9TNRzc/Bm99gEJMaQoHJ9E6Kv9QBbsldh2oMj7iXmYNEAVvNgvv5vPorG6W+XtBhQ==} - engines: {node: '>=20.0.0'} + eventsource-parser@3.0.6: + resolution: {integrity: sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==} + engines: {node: '>=18.0.0'} eventsource@3.0.7: resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} @@ -5206,8 +5218,8 @@ packages: resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} engines: {node: '>=6'} - fast-uri@3.0.6: - resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} + fast-uri@3.1.0: + resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} @@ -5279,8 +5291,8 @@ packages: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} - firebase@12.1.0: - resolution: {integrity: sha512-oZucxvfWKuAW4eHHRqGKzC43fLiPqPwHYBHPRNsnkgonqYaq0VurYgqgBosRlEulW+TWja/5Tpo2FpUU+QrfEQ==} + firebase@12.2.1: + resolution: {integrity: sha512-UkuW2ZYaq/QuOQ24bfaqmkVqoBFhkA/ptATfPuRtc5vdm+zhwc3mfZBwFe6LqH9yrCN/6rAblgxKz2/0tDvA7w==} flat-cache@4.0.1: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} @@ -5405,8 +5417,8 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - get-east-asian-width@1.3.0: - resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} + get-east-asian-width@1.3.1: + resolution: {integrity: sha512-R1QfovbPsKmosqTnPoRFiJ7CF9MLRgb53ChvMZm+r4p76/+8yKDy17qLL2PKInORy2RkZZekuK0efYgmzTkXyQ==} engines: {node: '>=18'} get-intrinsic@1.3.0: @@ -5440,9 +5452,9 @@ packages: getpass@0.1.7: resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} - git-raw-commits@4.0.0: - resolution: {integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==} - engines: {node: '>=16'} + git-raw-commits@5.0.0: + resolution: {integrity: sha512-I2ZXrXeOc0KrCvC7swqtIFXFN+rbjnC7b2T943tvemIOVNl+XP8YnA9UVwqFhzzLClnSA60KR/qEjLpXzs73Qg==} + engines: {node: '>=18'} hasBin: true glob-parent@5.1.2: @@ -5495,8 +5507,8 @@ packages: resolution: {integrity: sha512-HJRTIH2EeH44ka+LWig+EqT2ONSYpVlNfx6pyd592/VF1TbfljJ7elwie7oSwcViLGqOdWocSdu2txwBF9bjmQ==} engines: {node: '>=0.10.0'} - google-auth-library@10.2.1: - resolution: {integrity: sha512-HMxFl2NfeHYnaL1HoRIN1XgorKS+6CDaM+z9LSSN+i/nKDDL4KFFEWogMXu7jV4HZQy2MsxpY+wA5XIf3w410A==} + google-auth-library@10.3.0: + resolution: {integrity: sha512-ylSE3RlCRZfZB56PFJSfUCuiuPq83Fx8hqu1KPWGK8FVdSaxlp/qkeMMX/DT/18xkwXIHvXEXkZsljRwfrdEfQ==} engines: {node: '>=18'} google-auth-library@9.15.1: @@ -5885,8 +5897,8 @@ packages: resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} engines: {node: '>=12'} - is-fullwidth-code-point@5.0.0: - resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} + is-fullwidth-code-point@5.1.0: + resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} engines: {node: '>=18'} is-generator-function@1.1.0: @@ -6069,8 +6081,8 @@ packages: resolution: {integrity: sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==} engines: {node: '>= 8.0.0'} - isbinaryfile@5.0.4: - resolution: {integrity: sha512-YKBKVkKhty7s8rxddb40oOkuP0NbaeXrQvLin6QMHL7Ypiy2RW9LwOVrVgZRyOrhQlayMd9t+D8yDy8MKFTSDQ==} + isbinaryfile@5.0.6: + resolution: {integrity: sha512-I+NmIfBHUl+r2wcDd6JwE9yWje/PIVY/R5/CmV8dXLZd5K+L9X2klAOwfAHNnondLXkbHyTAleQAWonpTJBTtw==} engines: {node: '>= 18.0.0'} isexe@2.0.0: @@ -6523,14 +6535,18 @@ packages: resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} engines: {node: '>= 0.8'} - memfs@4.38.1: - resolution: {integrity: sha512-exfrOkkU3m0EpbQ0iQJP93HUbkprnIBU7IUnobSNAzHkBUzsklLwENGLEm8ZwJmMuLoFEfv1pYQ54wSpkay4kQ==} + memfs@4.38.2: + resolution: {integrity: sha512-FpWsVHpAkoSh/LfY1BgAl72BVd374ooMRtDi2VqzBycX4XEfvC0XKACCe0C9VRZoYq5viuoyTv6lYXZ/Q7TrLQ==} engines: {node: '>= 4.0.0'} meow@12.1.1: resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} engines: {node: '>=16.10'} + meow@13.2.0: + resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} + engines: {node: '>=18'} + merge-descriptors@1.0.3: resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} @@ -6822,8 +6838,8 @@ packages: resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} hasBin: true - node-gyp@11.4.1: - resolution: {integrity: sha512-GiVxQ1e4TdZSSVmFDYUn6uUsrEUP68pa8C/xBzCfL/FcLHa4reWrxxTP7tRGhNdviYrNsL5kRolBL5LNYEutCw==} + node-gyp@11.4.2: + resolution: {integrity: sha512-3gD+6zsrLQH7DyYOUIutaauuXrcyxeTPyQuZQCQoNPZMHMMS5m4y0xclNpvYzoK3VNzuyxT6eF4mkIL4WSZ1eQ==} engines: {node: ^18.17.0 || >=20.5.0} hasBin: true @@ -6847,8 +6863,8 @@ packages: resolution: {integrity: sha512-IxaQZDMsqfQ2Lz37VvyyEtKLe8FsRZuysmedy/N06TU1RyVppYKXrO4xIhR0F+7ubIBox6Q7nir6fQI3ej39iA==} engines: {node: ^18.17.0 || >=20.5.0} - npm-install-checks@7.1.1: - resolution: {integrity: sha512-u6DCwbow5ynAX5BdiHQ9qvexme4U3qHW3MWe5NqH+NeBm0LbiH6zvGjNNew1fY+AZZUtVHbOPF3j7mJxbUzpXg==} + npm-install-checks@7.1.2: + resolution: {integrity: sha512-z9HJBCYw9Zr8BqXcllKIs5nI+QggAImbBdHphOzVYrz2CB4iQ6FzWyKmlqDZua+51nAu7FcemlbTc9VgQN5XDQ==} engines: {node: ^18.17.0 || >=20.5.0} npm-normalize-package-bin@4.0.0: @@ -7428,8 +7444,8 @@ packages: resolution: {integrity: sha512-MRtTAZfQTluz3U2oU/X2VqVWPcR1+94nbA2V6ZrSZRVEwLqZ8eclZ551qGFQD/vD2PYqHJwWOW/fpC721uznVw==} engines: {node: '>=14.1.0'} - puppeteer-core@24.17.0: - resolution: {integrity: sha512-RYOBKFiF+3RdwIZTEacqNpD567gaFcBAOKTT7742FdB1icXudrPI7BlZbYTYWK2wgGQUXt9Zi1Yn+D5PmCs4CA==} + puppeteer-core@24.18.0: + resolution: {integrity: sha512-As0BvfXxek2MbV0m7iqBmQKFnfSrzSvTM4zGipjd4cL+9f2Ccgut6RvHlc8+qBieKHqCMFy9BSI4QyveoYXTug==} engines: {node: '>=18'} puppeteer@18.2.1: @@ -9080,29 +9096,29 @@ snapshots: '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.30 - '@angular/animations@20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))': + '@angular/animations@20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))': dependencies: - '@angular/common': 20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) - '@angular/core': 20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/common': 20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/core': 20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1) tslib: 2.8.1 - '@angular/cdk@20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)': + '@angular/cdk@20.2.1(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)': dependencies: - '@angular/common': 20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) - '@angular/core': 20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/common': 20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/core': 20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1) parse5: 8.0.0 rxjs: 7.8.2 tslib: 2.8.1 - '@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)': + '@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)': dependencies: - '@angular/core': 20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/core': 20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1) rxjs: 7.8.2 tslib: 2.8.1 - '@angular/compiler-cli@20.2.1(@angular/compiler@20.2.1)(typescript@5.9.2)': + '@angular/compiler-cli@20.2.3(@angular/compiler@20.2.3)(typescript@5.9.2)': dependencies: - '@angular/compiler': 20.2.1 + '@angular/compiler': 20.2.3 '@babel/core': 7.28.3 '@jridgewell/sourcemap-codec': 1.5.5 chokidar: 4.0.3 @@ -9116,30 +9132,30 @@ snapshots: transitivePeerDependencies: - supports-color - '@angular/compiler@20.2.1': + '@angular/compiler@20.2.3': dependencies: tslib: 2.8.1 - '@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)': + '@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)': dependencies: rxjs: 7.8.2 tslib: 2.8.1 optionalDependencies: - '@angular/compiler': 20.2.1 + '@angular/compiler': 20.2.3 zone.js: 0.15.1 - '@angular/forms@20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.2.1(@angular/animations@20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)': + '@angular/forms@20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.2.3(@angular/animations@20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)': dependencies: - '@angular/common': 20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) - '@angular/core': 20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1) - '@angular/platform-browser': 20.2.1(@angular/animations@20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)) + '@angular/common': 20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/core': 20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/platform-browser': 20.2.3(@angular/animations@20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)) rxjs: 7.8.2 tslib: 2.8.1 - '@angular/localize@20.2.1(@angular/compiler-cli@20.2.1(@angular/compiler@20.2.1)(typescript@5.9.2))(@angular/compiler@20.2.1)': + '@angular/localize@20.2.3(@angular/compiler-cli@20.2.3(@angular/compiler@20.2.3)(typescript@5.9.2))(@angular/compiler@20.2.3)': dependencies: - '@angular/compiler': 20.2.1 - '@angular/compiler-cli': 20.2.1(@angular/compiler@20.2.1)(typescript@5.9.2) + '@angular/compiler': 20.2.3 + '@angular/compiler-cli': 20.2.3(@angular/compiler@20.2.3)(typescript@5.9.2) '@babel/core': 7.28.3 '@types/babel__core': 7.20.5 tinyglobby: 0.2.14 @@ -9147,21 +9163,21 @@ snapshots: transitivePeerDependencies: - supports-color - '@angular/material@20.2.1(b60312b63259c1568290f1cfc536b3a7)': + '@angular/material@20.2.1(db7b32723760b0ee941b26d324534a22)': dependencies: - '@angular/cdk': 20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) - '@angular/common': 20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) - '@angular/core': 20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1) - '@angular/forms': 20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.2.1(@angular/animations@20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) - '@angular/platform-browser': 20.2.1(@angular/animations@20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)) + '@angular/cdk': 20.2.1(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/common': 20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/core': 20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/forms': 20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.2.3(@angular/animations@20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) + '@angular/platform-browser': 20.2.3(@angular/animations@20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)) rxjs: 7.8.2 tslib: 2.8.1 - '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/9d0a73d937f6447d06ef56a5347c805e5d9400d7(@modelcontextprotocol/sdk@1.17.3)': + '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/b991414e4f3ed15d99f4331b5353499434878374(@modelcontextprotocol/sdk@1.17.3)': dependencies: '@actions/core': 1.11.1 '@google-cloud/spanner': 8.0.0(supports-color@10.2.0) - '@google/genai': 1.15.0(@modelcontextprotocol/sdk@1.17.3)(bufferutil@4.0.9)(encoding@0.1.13)(supports-color@10.2.0)(utf-8-validate@6.0.5) + '@google/genai': 1.16.0(@modelcontextprotocol/sdk@1.17.3)(bufferutil@4.0.9)(encoding@0.1.13)(supports-color@10.2.0)(utf-8-validate@6.0.5) '@inquirer/prompts': 7.8.4(@types/node@24.3.0) '@inquirer/type': 3.0.8(@types/node@24.3.0) '@octokit/auth-app': 8.1.0 @@ -9180,7 +9196,7 @@ snapshots: '@types/ejs': 3.1.5 '@types/events': 3.0.3 '@types/folder-hash': 4.0.4 - '@types/git-raw-commits': 2.0.4 + '@types/git-raw-commits': 5.0.0 '@types/jasmine': 5.1.9 '@types/minimatch': 6.0.0 '@types/node': 24.3.0 @@ -9193,13 +9209,14 @@ snapshots: bufferutil: 4.0.9 chalk: 5.6.0 cli-progress: 3.12.0 + conventional-commits-filter: 5.0.0 conventional-commits-parser: 5.0.0 ejs: 3.1.10 encoding: 0.1.13 fast-glob: 3.3.3 - firebase: 12.1.0 + firebase: 12.2.1 folder-hash: 4.1.1(supports-color@10.2.0) - git-raw-commits: 4.0.0 + git-raw-commits: 5.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@5.0.0) jasmine: 5.9.0 jasmine-core: 5.9.0 jasmine-reporters: 2.5.2 @@ -9219,35 +9236,35 @@ snapshots: - '@modelcontextprotocol/sdk' - '@react-native-async-storage/async-storage' - '@angular/platform-browser@20.2.1(@angular/animations@20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))': + '@angular/platform-browser@20.2.3(@angular/animations@20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))': dependencies: - '@angular/common': 20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) - '@angular/core': 20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/common': 20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/core': 20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1) tslib: 2.8.1 optionalDependencies: - '@angular/animations': 20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)) + '@angular/animations': 20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)) - '@angular/platform-server@20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@20.2.1)(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.2.1(@angular/animations@20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)': + '@angular/platform-server@20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@20.2.3)(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.2.3(@angular/animations@20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)': dependencies: - '@angular/common': 20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) - '@angular/compiler': 20.2.1 - '@angular/core': 20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1) - '@angular/platform-browser': 20.2.1(@angular/animations@20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)) + '@angular/common': 20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/compiler': 20.2.3 + '@angular/core': 20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/platform-browser': 20.2.3(@angular/animations@20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)) rxjs: 7.8.2 tslib: 2.8.1 xhr2: 0.2.1 - '@angular/router@20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.2.1(@angular/animations@20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)': + '@angular/router@20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.2.3(@angular/animations@20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)': dependencies: - '@angular/common': 20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) - '@angular/core': 20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1) - '@angular/platform-browser': 20.2.1(@angular/animations@20.2.1(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1)) + '@angular/common': 20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/core': 20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/platform-browser': 20.2.3(@angular/animations@20.2.3(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1)) rxjs: 7.8.2 tslib: 2.8.1 - '@angular/service-worker@20.2.1(@angular/core@20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)': + '@angular/service-worker@20.2.3(@angular/core@20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)': dependencies: - '@angular/core': 20.2.1(@angular/compiler@20.2.1)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/core': 20.2.3(@angular/compiler@20.2.3)(rxjs@7.8.2)(zone.js@0.15.1) rxjs: 7.8.2 tslib: 2.8.1 @@ -9303,7 +9320,7 @@ snapshots: dependencies: '@babel/compat-data': 7.28.0 '@babel/helper-validator-option': 7.27.1 - browserslist: 4.25.3 + browserslist: 4.25.4 lru-cache: 5.1.1 semver: 6.3.1 @@ -9935,6 +9952,14 @@ snapshots: '@colors/colors@1.5.0': {} + '@conventional-changelog/git-client@1.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@5.0.0)': + dependencies: + '@types/semver': 7.7.0 + semver: 7.7.2 + optionalDependencies: + conventional-commits-filter: 5.0.0 + conventional-commits-parser: 5.0.0 + '@cspotcode/source-map-support@0.8.1': dependencies: '@jridgewell/trace-mapping': 0.3.9 @@ -9982,18 +10007,18 @@ snapshots: '@discoveryjs/json-ext@0.6.3': {} - '@emnapi/core@1.4.5': + '@emnapi/core@1.5.0': dependencies: - '@emnapi/wasi-threads': 1.0.4 + '@emnapi/wasi-threads': 1.1.0 tslib: 2.8.1 optional: true - '@emnapi/runtime@1.4.5': + '@emnapi/runtime@1.5.0': dependencies: tslib: 2.8.1 optional: true - '@emnapi/wasi-threads@1.0.4': + '@emnapi/wasi-threads@1.1.0': dependencies: tslib: 2.8.1 optional: true @@ -10126,9 +10151,9 @@ snapshots: '@fastify/busboy@2.1.1': {} - '@firebase/ai@2.1.0(@firebase/app-types@0.9.3)(@firebase/app@0.14.1)': + '@firebase/ai@2.2.1(@firebase/app-types@0.9.3)(@firebase/app@0.14.2)': dependencies: - '@firebase/app': 0.14.1 + '@firebase/app': 0.14.2 '@firebase/app-check-interop-types': 0.3.3 '@firebase/app-types': 0.9.3 '@firebase/component': 0.7.0 @@ -10136,11 +10161,11 @@ snapshots: '@firebase/util': 1.13.0 tslib: 2.8.1 - '@firebase/analytics-compat@0.2.24(@firebase/app-compat@0.5.1)(@firebase/app@0.14.1)': + '@firebase/analytics-compat@0.2.24(@firebase/app-compat@0.5.2)(@firebase/app@0.14.2)': dependencies: - '@firebase/analytics': 0.10.18(@firebase/app@0.14.1) + '@firebase/analytics': 0.10.18(@firebase/app@0.14.2) '@firebase/analytics-types': 0.8.3 - '@firebase/app-compat': 0.5.1 + '@firebase/app-compat': 0.5.2 '@firebase/component': 0.7.0 '@firebase/util': 1.13.0 tslib: 2.8.1 @@ -10149,20 +10174,20 @@ snapshots: '@firebase/analytics-types@0.8.3': {} - '@firebase/analytics@0.10.18(@firebase/app@0.14.1)': + '@firebase/analytics@0.10.18(@firebase/app@0.14.2)': dependencies: - '@firebase/app': 0.14.1 + '@firebase/app': 0.14.2 '@firebase/component': 0.7.0 - '@firebase/installations': 0.6.19(@firebase/app@0.14.1) + '@firebase/installations': 0.6.19(@firebase/app@0.14.2) '@firebase/logger': 0.5.0 '@firebase/util': 1.13.0 tslib: 2.8.1 - '@firebase/app-check-compat@0.4.0(@firebase/app-compat@0.5.1)(@firebase/app@0.14.1)': + '@firebase/app-check-compat@0.4.0(@firebase/app-compat@0.5.2)(@firebase/app@0.14.2)': dependencies: - '@firebase/app-check': 0.11.0(@firebase/app@0.14.1) + '@firebase/app-check': 0.11.0(@firebase/app@0.14.2) '@firebase/app-check-types': 0.5.3 - '@firebase/app-compat': 0.5.1 + '@firebase/app-compat': 0.5.2 '@firebase/component': 0.7.0 '@firebase/logger': 0.5.0 '@firebase/util': 1.13.0 @@ -10174,17 +10199,17 @@ snapshots: '@firebase/app-check-types@0.5.3': {} - '@firebase/app-check@0.11.0(@firebase/app@0.14.1)': + '@firebase/app-check@0.11.0(@firebase/app@0.14.2)': dependencies: - '@firebase/app': 0.14.1 + '@firebase/app': 0.14.2 '@firebase/component': 0.7.0 '@firebase/logger': 0.5.0 '@firebase/util': 1.13.0 tslib: 2.8.1 - '@firebase/app-compat@0.5.1': + '@firebase/app-compat@0.5.2': dependencies: - '@firebase/app': 0.14.1 + '@firebase/app': 0.14.2 '@firebase/component': 0.7.0 '@firebase/logger': 0.5.0 '@firebase/util': 1.13.0 @@ -10192,7 +10217,7 @@ snapshots: '@firebase/app-types@0.9.3': {} - '@firebase/app@0.14.1': + '@firebase/app@0.14.2': dependencies: '@firebase/component': 0.7.0 '@firebase/logger': 0.5.0 @@ -10200,10 +10225,10 @@ snapshots: idb: 7.1.1 tslib: 2.8.1 - '@firebase/auth-compat@0.6.0(@firebase/app-compat@0.5.1)(@firebase/app-types@0.9.3)(@firebase/app@0.14.1)': + '@firebase/auth-compat@0.6.0(@firebase/app-compat@0.5.2)(@firebase/app-types@0.9.3)(@firebase/app@0.14.2)': dependencies: - '@firebase/app-compat': 0.5.1 - '@firebase/auth': 1.11.0(@firebase/app@0.14.1) + '@firebase/app-compat': 0.5.2 + '@firebase/auth': 1.11.0(@firebase/app@0.14.2) '@firebase/auth-types': 0.13.0(@firebase/app-types@0.9.3)(@firebase/util@1.13.0) '@firebase/component': 0.7.0 '@firebase/util': 1.13.0 @@ -10220,9 +10245,9 @@ snapshots: '@firebase/app-types': 0.9.3 '@firebase/util': 1.13.0 - '@firebase/auth@1.11.0(@firebase/app@0.14.1)': + '@firebase/auth@1.11.0(@firebase/app@0.14.2)': dependencies: - '@firebase/app': 0.14.1 + '@firebase/app': 0.14.2 '@firebase/component': 0.7.0 '@firebase/logger': 0.5.0 '@firebase/util': 1.13.0 @@ -10233,9 +10258,9 @@ snapshots: '@firebase/util': 1.13.0 tslib: 2.8.1 - '@firebase/data-connect@0.3.11(@firebase/app@0.14.1)': + '@firebase/data-connect@0.3.11(@firebase/app@0.14.2)': dependencies: - '@firebase/app': 0.14.1 + '@firebase/app': 0.14.2 '@firebase/auth-interop-types': 0.2.4 '@firebase/component': 0.7.0 '@firebase/logger': 0.5.0 @@ -10266,11 +10291,11 @@ snapshots: faye-websocket: 0.11.4 tslib: 2.8.1 - '@firebase/firestore-compat@0.4.0(@firebase/app-compat@0.5.1)(@firebase/app-types@0.9.3)(@firebase/app@0.14.1)': + '@firebase/firestore-compat@0.4.1(@firebase/app-compat@0.5.2)(@firebase/app-types@0.9.3)(@firebase/app@0.14.2)': dependencies: - '@firebase/app-compat': 0.5.1 + '@firebase/app-compat': 0.5.2 '@firebase/component': 0.7.0 - '@firebase/firestore': 4.9.0(@firebase/app@0.14.1) + '@firebase/firestore': 4.9.1(@firebase/app@0.14.2) '@firebase/firestore-types': 3.0.3(@firebase/app-types@0.9.3)(@firebase/util@1.13.0) '@firebase/util': 1.13.0 tslib: 2.8.1 @@ -10283,9 +10308,9 @@ snapshots: '@firebase/app-types': 0.9.3 '@firebase/util': 1.13.0 - '@firebase/firestore@4.9.0(@firebase/app@0.14.1)': + '@firebase/firestore@4.9.1(@firebase/app@0.14.2)': dependencies: - '@firebase/app': 0.14.1 + '@firebase/app': 0.14.2 '@firebase/component': 0.7.0 '@firebase/logger': 0.5.0 '@firebase/util': 1.13.0 @@ -10294,11 +10319,11 @@ snapshots: '@grpc/proto-loader': 0.7.15 tslib: 2.8.1 - '@firebase/functions-compat@0.4.0(@firebase/app-compat@0.5.1)(@firebase/app@0.14.1)': + '@firebase/functions-compat@0.4.1(@firebase/app-compat@0.5.2)(@firebase/app@0.14.2)': dependencies: - '@firebase/app-compat': 0.5.1 + '@firebase/app-compat': 0.5.2 '@firebase/component': 0.7.0 - '@firebase/functions': 0.13.0(@firebase/app@0.14.1) + '@firebase/functions': 0.13.1(@firebase/app@0.14.2) '@firebase/functions-types': 0.6.3 '@firebase/util': 1.13.0 tslib: 2.8.1 @@ -10307,9 +10332,9 @@ snapshots: '@firebase/functions-types@0.6.3': {} - '@firebase/functions@0.13.0(@firebase/app@0.14.1)': + '@firebase/functions@0.13.1(@firebase/app@0.14.2)': dependencies: - '@firebase/app': 0.14.1 + '@firebase/app': 0.14.2 '@firebase/app-check-interop-types': 0.3.3 '@firebase/auth-interop-types': 0.2.4 '@firebase/component': 0.7.0 @@ -10317,11 +10342,11 @@ snapshots: '@firebase/util': 1.13.0 tslib: 2.8.1 - '@firebase/installations-compat@0.2.19(@firebase/app-compat@0.5.1)(@firebase/app-types@0.9.3)(@firebase/app@0.14.1)': + '@firebase/installations-compat@0.2.19(@firebase/app-compat@0.5.2)(@firebase/app-types@0.9.3)(@firebase/app@0.14.2)': dependencies: - '@firebase/app-compat': 0.5.1 + '@firebase/app-compat': 0.5.2 '@firebase/component': 0.7.0 - '@firebase/installations': 0.6.19(@firebase/app@0.14.1) + '@firebase/installations': 0.6.19(@firebase/app@0.14.2) '@firebase/installations-types': 0.5.3(@firebase/app-types@0.9.3) '@firebase/util': 1.13.0 tslib: 2.8.1 @@ -10333,9 +10358,9 @@ snapshots: dependencies: '@firebase/app-types': 0.9.3 - '@firebase/installations@0.6.19(@firebase/app@0.14.1)': + '@firebase/installations@0.6.19(@firebase/app@0.14.2)': dependencies: - '@firebase/app': 0.14.1 + '@firebase/app': 0.14.2 '@firebase/component': 0.7.0 '@firebase/util': 1.13.0 idb: 7.1.1 @@ -10345,11 +10370,11 @@ snapshots: dependencies: tslib: 2.8.1 - '@firebase/messaging-compat@0.2.23(@firebase/app-compat@0.5.1)(@firebase/app@0.14.1)': + '@firebase/messaging-compat@0.2.23(@firebase/app-compat@0.5.2)(@firebase/app@0.14.2)': dependencies: - '@firebase/app-compat': 0.5.1 + '@firebase/app-compat': 0.5.2 '@firebase/component': 0.7.0 - '@firebase/messaging': 0.12.23(@firebase/app@0.14.1) + '@firebase/messaging': 0.12.23(@firebase/app@0.14.2) '@firebase/util': 1.13.0 tslib: 2.8.1 transitivePeerDependencies: @@ -10357,22 +10382,22 @@ snapshots: '@firebase/messaging-interop-types@0.2.3': {} - '@firebase/messaging@0.12.23(@firebase/app@0.14.1)': + '@firebase/messaging@0.12.23(@firebase/app@0.14.2)': dependencies: - '@firebase/app': 0.14.1 + '@firebase/app': 0.14.2 '@firebase/component': 0.7.0 - '@firebase/installations': 0.6.19(@firebase/app@0.14.1) + '@firebase/installations': 0.6.19(@firebase/app@0.14.2) '@firebase/messaging-interop-types': 0.2.3 '@firebase/util': 1.13.0 idb: 7.1.1 tslib: 2.8.1 - '@firebase/performance-compat@0.2.22(@firebase/app-compat@0.5.1)(@firebase/app@0.14.1)': + '@firebase/performance-compat@0.2.22(@firebase/app-compat@0.5.2)(@firebase/app@0.14.2)': dependencies: - '@firebase/app-compat': 0.5.1 + '@firebase/app-compat': 0.5.2 '@firebase/component': 0.7.0 '@firebase/logger': 0.5.0 - '@firebase/performance': 0.7.9(@firebase/app@0.14.1) + '@firebase/performance': 0.7.9(@firebase/app@0.14.2) '@firebase/performance-types': 0.2.3 '@firebase/util': 1.13.0 tslib: 2.8.1 @@ -10381,22 +10406,22 @@ snapshots: '@firebase/performance-types@0.2.3': {} - '@firebase/performance@0.7.9(@firebase/app@0.14.1)': + '@firebase/performance@0.7.9(@firebase/app@0.14.2)': dependencies: - '@firebase/app': 0.14.1 + '@firebase/app': 0.14.2 '@firebase/component': 0.7.0 - '@firebase/installations': 0.6.19(@firebase/app@0.14.1) + '@firebase/installations': 0.6.19(@firebase/app@0.14.2) '@firebase/logger': 0.5.0 '@firebase/util': 1.13.0 tslib: 2.8.1 web-vitals: 4.2.4 - '@firebase/remote-config-compat@0.2.19(@firebase/app-compat@0.5.1)(@firebase/app@0.14.1)': + '@firebase/remote-config-compat@0.2.19(@firebase/app-compat@0.5.2)(@firebase/app@0.14.2)': dependencies: - '@firebase/app-compat': 0.5.1 + '@firebase/app-compat': 0.5.2 '@firebase/component': 0.7.0 '@firebase/logger': 0.5.0 - '@firebase/remote-config': 0.6.6(@firebase/app@0.14.1) + '@firebase/remote-config': 0.6.6(@firebase/app@0.14.2) '@firebase/remote-config-types': 0.4.0 '@firebase/util': 1.13.0 tslib: 2.8.1 @@ -10405,20 +10430,20 @@ snapshots: '@firebase/remote-config-types@0.4.0': {} - '@firebase/remote-config@0.6.6(@firebase/app@0.14.1)': + '@firebase/remote-config@0.6.6(@firebase/app@0.14.2)': dependencies: - '@firebase/app': 0.14.1 + '@firebase/app': 0.14.2 '@firebase/component': 0.7.0 - '@firebase/installations': 0.6.19(@firebase/app@0.14.1) + '@firebase/installations': 0.6.19(@firebase/app@0.14.2) '@firebase/logger': 0.5.0 '@firebase/util': 1.13.0 tslib: 2.8.1 - '@firebase/storage-compat@0.4.0(@firebase/app-compat@0.5.1)(@firebase/app-types@0.9.3)(@firebase/app@0.14.1)': + '@firebase/storage-compat@0.4.0(@firebase/app-compat@0.5.2)(@firebase/app-types@0.9.3)(@firebase/app@0.14.2)': dependencies: - '@firebase/app-compat': 0.5.1 + '@firebase/app-compat': 0.5.2 '@firebase/component': 0.7.0 - '@firebase/storage': 0.14.0(@firebase/app@0.14.1) + '@firebase/storage': 0.14.0(@firebase/app@0.14.2) '@firebase/storage-types': 0.8.3(@firebase/app-types@0.9.3)(@firebase/util@1.13.0) '@firebase/util': 1.13.0 tslib: 2.8.1 @@ -10431,9 +10456,9 @@ snapshots: '@firebase/app-types': 0.9.3 '@firebase/util': 1.13.0 - '@firebase/storage@0.14.0(@firebase/app@0.14.1)': + '@firebase/storage@0.14.0(@firebase/app@0.14.2)': dependencies: - '@firebase/app': 0.14.1 + '@firebase/app': 0.14.2 '@firebase/component': 0.7.0 '@firebase/util': 1.13.0 tslib: 2.8.1 @@ -10453,7 +10478,7 @@ snapshots: arrify: 2.0.1 duplexify: 4.1.3 extend: 3.0.2 - google-auth-library: 10.2.1(supports-color@10.2.0) + google-auth-library: 10.3.0(supports-color@10.2.0) html-entities: 2.6.0 retry-request: 8.0.2(supports-color@10.2.0) teeny-request: 10.1.0(supports-color@10.2.0) @@ -10488,7 +10513,7 @@ snapshots: duplexify: 4.1.3 events-intercept: 2.0.0 extend: 3.0.2 - google-auth-library: 10.2.1(supports-color@10.2.0) + google-auth-library: 10.3.0(supports-color@10.2.0) google-gax: 5.0.3(supports-color@10.2.0) grpc-gcp: 1.0.1(protobufjs@7.5.4) is: 3.3.2 @@ -10505,7 +10530,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@google/genai@1.15.0(@modelcontextprotocol/sdk@1.17.3)(bufferutil@4.0.9)(encoding@0.1.13)(supports-color@10.2.0)(utf-8-validate@6.0.5)': + '@google/genai@1.16.0(@modelcontextprotocol/sdk@1.17.3)(bufferutil@4.0.9)(encoding@0.1.13)(supports-color@10.2.0)(utf-8-validate@6.0.5)': dependencies: google-auth-library: 9.15.1(encoding@0.1.13)(supports-color@10.2.0) ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5) @@ -10525,7 +10550,7 @@ snapshots: '@grpc/grpc-js@1.9.15': dependencies: '@grpc/proto-loader': 0.7.15 - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@grpc/proto-loader@0.7.15': dependencies: @@ -10821,7 +10846,7 @@ snapshots: cors: 2.8.5 cross-spawn: 7.0.6 eventsource: 3.0.7 - eventsource-parser: 3.0.5 + eventsource-parser: 3.0.6 express: 5.1.0 express-rate-limit: 7.5.1(express@5.1.0) pkce-challenge: 5.0.0 @@ -10932,8 +10957,8 @@ snapshots: '@napi-rs/wasm-runtime@1.0.3': dependencies: - '@emnapi/core': 1.4.5 - '@emnapi/runtime': 1.4.5 + '@emnapi/core': 1.5.0 + '@emnapi/runtime': 1.5.0 '@tybys/wasm-util': 0.10.0 optional: true @@ -10965,7 +10990,7 @@ snapshots: '@npmcli/git@6.0.3': dependencies: - '@npmcli/promise-spawn': 8.0.2 + '@npmcli/promise-spawn': 8.0.3 ini: 5.0.0 lru-cache: 10.4.3 npm-pick-manifest: 10.0.0 @@ -10991,7 +11016,7 @@ snapshots: semver: 7.7.2 validate-npm-package-license: 3.0.4 - '@npmcli/promise-spawn@8.0.2': + '@npmcli/promise-spawn@8.0.3': dependencies: which: 5.0.0 @@ -11001,8 +11026,8 @@ snapshots: dependencies: '@npmcli/node-gyp': 4.0.0 '@npmcli/package-json': 6.2.0 - '@npmcli/promise-spawn': 8.0.2 - node-gyp: 11.4.1 + '@npmcli/promise-spawn': 8.0.3 + node-gyp: 11.4.2 proc-log: 5.0.0 which: 5.0.0 transitivePeerDependencies: @@ -11251,7 +11276,7 @@ snapshots: '@protobufjs/utf8@1.1.0': {} - '@puppeteer/browsers@2.10.7': + '@puppeteer/browsers@2.10.8': dependencies: debug: 4.4.1(supports-color@10.2.0) extract-zip: 2.0.1 @@ -11420,7 +11445,7 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.46.2': optional: true - '@rollup/wasm-node@4.48.1': + '@rollup/wasm-node@4.50.0': dependencies: '@types/estree': 1.0.8 optionalDependencies: @@ -11462,10 +11487,10 @@ snapshots: '@socket.io/component-emitter@3.1.2': {} - '@stylistic/eslint-plugin@5.2.3(eslint@9.33.0(jiti@1.21.7))': + '@stylistic/eslint-plugin@5.3.1(eslint@9.33.0(jiti@1.21.7))': dependencies: '@eslint-community/eslint-utils': 4.7.0(eslint@9.33.0(jiti@1.21.7)) - '@typescript-eslint/types': 8.40.0 + '@typescript-eslint/types': 8.41.0 eslint: 9.33.0(jiti@1.21.7) eslint-visitor-keys: 4.2.1 espree: 10.4.0 @@ -11498,7 +11523,7 @@ snapshots: '@types/accepts@1.3.7': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/babel__code-frame@7.0.6': {} @@ -11528,16 +11553,16 @@ snapshots: '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/bonjour@3.5.13': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/browser-sync@2.29.0': dependencies: '@types/micromatch': 2.3.35 - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/serve-static': 1.15.8 chokidar: 3.6.0 @@ -11547,11 +11572,11 @@ snapshots: '@types/cli-progress@3.11.6': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/co-body@6.1.3': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/qs': 6.14.0 '@types/command-line-args@5.2.3': {} @@ -11559,17 +11584,17 @@ snapshots: '@types/connect-history-api-fallback@1.5.4': dependencies: '@types/express-serve-static-core': 4.19.6 - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/connect@3.4.38': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/content-disposition@0.5.9': {} '@types/conventional-commits-parser@5.0.1': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/convert-source-map@2.0.3': {} @@ -11578,11 +11603,11 @@ snapshots: '@types/connect': 3.4.38 '@types/express': 5.0.3 '@types/keygrip': 1.0.6 - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/cors@2.8.19': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/debounce@1.2.4': {} @@ -11590,7 +11615,7 @@ snapshots: '@types/duplexify@3.6.4': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/ejs@3.1.5': {} @@ -11610,14 +11635,14 @@ snapshots: '@types/express-serve-static-core@4.19.6': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/qs': 6.14.0 '@types/range-parser': 1.2.7 '@types/send': 0.17.5 '@types/express-serve-static-core@5.0.7': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/qs': 6.14.0 '@types/range-parser': 1.2.7 '@types/send': 0.17.5 @@ -11637,13 +11662,13 @@ snapshots: '@types/folder-hash@4.0.4': {} - '@types/git-raw-commits@2.0.4': + '@types/git-raw-commits@5.0.0': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/http-assert@1.5.6': {} @@ -11651,7 +11676,7 @@ snapshots: '@types/http-proxy@1.17.16': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/ini@4.1.1': {} @@ -11677,7 +11702,7 @@ snapshots: '@types/karma@6.3.9': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 log4js: 6.9.1 transitivePeerDependencies: - supports-color @@ -11697,13 +11722,13 @@ snapshots: '@types/http-errors': 2.0.5 '@types/keygrip': 1.0.6 '@types/koa-compose': 3.2.8 - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/less@3.0.8': {} '@types/loader-utils@2.0.6': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/webpack': 4.41.40 '@types/lodash@4.17.20': {} @@ -11720,14 +11745,14 @@ snapshots: '@types/node-fetch@2.6.13': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 form-data: 4.0.4 '@types/node-forge@1.3.14': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 - '@types/node@22.17.2': + '@types/node@22.18.0': dependencies: undici-types: 6.21.0 @@ -11739,7 +11764,7 @@ snapshots: '@types/npm-registry-fetch@8.0.8': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/node-fetch': 2.6.13 '@types/npm-package-arg': 6.1.4 '@types/npmlog': 7.0.0 @@ -11747,11 +11772,11 @@ snapshots: '@types/npmlog@7.0.0': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/pacote@11.1.8': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/npm-registry-fetch': 8.0.8 '@types/npmlog': 7.0.0 '@types/ssri': 7.1.5 @@ -11764,12 +11789,12 @@ snapshots: '@types/progress@2.0.7': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/pumpify@1.4.4': dependencies: '@types/duplexify': 3.6.4 - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/q@0.0.32': {} @@ -11790,7 +11815,7 @@ snapshots: '@types/send@0.17.5': dependencies: '@types/mime': 1.3.5 - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/serve-index@1.9.4': dependencies: @@ -11799,23 +11824,23 @@ snapshots: '@types/serve-static@1.15.8': dependencies: '@types/http-errors': 2.0.5 - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/send': 0.17.5 '@types/shelljs@0.8.17': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 glob: 11.0.3 '@types/sockjs@0.3.36': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/source-list-map@0.1.6': {} '@types/ssri@7.1.5': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/stack-trace@0.0.33': {} @@ -11832,17 +11857,17 @@ snapshots: '@types/watchpack@2.4.4': dependencies: '@types/graceful-fs': 4.1.9 - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/webpack-sources@3.2.3': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/source-list-map': 0.1.6 source-map: 0.7.6 '@types/webpack@4.41.40': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/tapable': 1.0.12 '@types/uglify-js': 3.17.5 '@types/webpack-sources': 3.2.3 @@ -11853,11 +11878,11 @@ snapshots: '@types/ws@7.4.7': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/ws@8.18.1': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/yargs-parser@21.0.3': {} @@ -11869,7 +11894,7 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 optional: true '@typescript-eslint/eslint-plugin@8.39.1(@typescript-eslint/parser@8.39.1(eslint@9.33.0(jiti@1.21.7))(typescript@5.9.2))(eslint@9.33.0(jiti@1.21.7))(typescript@5.9.2)': @@ -11933,7 +11958,7 @@ snapshots: '@typescript-eslint/types@8.39.1': {} - '@typescript-eslint/types@8.40.0': {} + '@typescript-eslint/types@8.41.0': {} '@typescript-eslint/typescript-estree@8.39.1(typescript@5.9.2)': dependencies: @@ -12182,7 +12207,7 @@ snapshots: es-module-lexer: 1.7.0 get-stream: 6.0.1 is-stream: 2.0.1 - isbinaryfile: 5.0.4 + isbinaryfile: 5.0.6 koa: 2.16.2 koa-etag: 4.0.0 koa-send: 5.0.1 @@ -12241,7 +12266,7 @@ snapshots: '@web/test-runner-core': 0.13.4(bufferutil@4.0.9) '@web/test-runner-coverage-v8': 0.8.0(bufferutil@4.0.9) chrome-launcher: 0.15.2 - puppeteer-core: 24.17.0(bufferutil@4.0.9) + puppeteer-core: 24.18.0(bufferutil@4.0.9) transitivePeerDependencies: - bare-buffer - bufferutil @@ -12495,7 +12520,7 @@ snapshots: ajv@8.17.1: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.0.6 + fast-uri: 3.1.0 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 @@ -12659,8 +12684,8 @@ snapshots: autoprefixer@10.4.21(postcss@8.5.6): dependencies: - browserslist: 4.25.3 - caniuse-lite: 1.0.30001737 + browserslist: 4.25.4 + caniuse-lite: 1.0.30001739 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.1.1 @@ -12712,7 +12737,7 @@ snapshots: bare-events@2.6.1: optional: true - bare-fs@4.2.1: + bare-fs@4.2.2: dependencies: bare-events: 2.6.1 bare-path: 3.0.0 @@ -12894,12 +12919,12 @@ snapshots: dependencies: pako: 0.2.9 - browserslist@4.25.3: + browserslist@4.25.4: dependencies: - caniuse-lite: 1.0.30001737 - electron-to-chromium: 1.5.208 + caniuse-lite: 1.0.30001739 + electron-to-chromium: 1.5.212 node-releases: 2.0.19 - update-browserslist-db: 1.1.3(browserslist@4.25.3) + update-browserslist-db: 1.1.3(browserslist@4.25.4) browserstack@1.6.1: dependencies: @@ -12980,7 +13005,7 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001737: {} + caniuse-lite@1.0.30001739: {} caseless@0.12.0: {} @@ -13047,7 +13072,7 @@ snapshots: chrome-launcher@0.15.2: dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 1.4.2 @@ -13219,6 +13244,8 @@ snapshots: content-type@1.0.5: {} + conventional-commits-filter@5.0.0: {} + conventional-commits-parser@5.0.0: dependencies: JSONStream: 1.3.5 @@ -13258,7 +13285,7 @@ snapshots: core-js-compat@3.45.1: dependencies: - browserslist: 4.25.3 + browserslist: 4.25.4 core-util-is@1.0.2: {} @@ -13330,8 +13357,6 @@ snapshots: custom-event@1.0.1: {} - dargs@8.1.0: {} - dashdash@1.14.1: dependencies: assert-plus: 1.0.0 @@ -13570,9 +13595,9 @@ snapshots: dependencies: jake: 10.9.4 - electron-to-chromium@1.5.208: {} + electron-to-chromium@1.5.212: {} - emoji-regex@10.4.0: {} + emoji-regex@10.5.0: {} emoji-regex@8.0.0: {} @@ -13609,7 +13634,7 @@ snapshots: engine.io@6.6.4(bufferutil@4.0.9): dependencies: '@types/cors': 2.8.19 - '@types/node': 22.17.2 + '@types/node': 22.18.0 accepts: 1.3.8 base64id: 2.0.0 cookie: 0.7.2 @@ -13945,11 +13970,11 @@ snapshots: events@3.3.0: {} - eventsource-parser@3.0.5: {} + eventsource-parser@3.0.6: {} eventsource@3.0.7: dependencies: - eventsource-parser: 3.0.5 + eventsource-parser: 3.0.6 execa@5.1.1: dependencies: @@ -14047,7 +14072,7 @@ snapshots: extract-zip@2.0.1: dependencies: - debug: 4.4.1(supports-color@10.2.0) + debug: 4.3.4 get-stream: 5.2.0 yauzl: 2.10.0 optionalDependencies: @@ -14077,7 +14102,7 @@ snapshots: fast-redact@3.5.0: {} - fast-uri@3.0.6: {} + fast-uri@3.1.0: {} fastq@1.19.1: dependencies: @@ -14180,35 +14205,35 @@ snapshots: locate-path: 6.0.0 path-exists: 4.0.0 - firebase@12.1.0: + firebase@12.2.1: dependencies: - '@firebase/ai': 2.1.0(@firebase/app-types@0.9.3)(@firebase/app@0.14.1) - '@firebase/analytics': 0.10.18(@firebase/app@0.14.1) - '@firebase/analytics-compat': 0.2.24(@firebase/app-compat@0.5.1)(@firebase/app@0.14.1) - '@firebase/app': 0.14.1 - '@firebase/app-check': 0.11.0(@firebase/app@0.14.1) - '@firebase/app-check-compat': 0.4.0(@firebase/app-compat@0.5.1)(@firebase/app@0.14.1) - '@firebase/app-compat': 0.5.1 + '@firebase/ai': 2.2.1(@firebase/app-types@0.9.3)(@firebase/app@0.14.2) + '@firebase/analytics': 0.10.18(@firebase/app@0.14.2) + '@firebase/analytics-compat': 0.2.24(@firebase/app-compat@0.5.2)(@firebase/app@0.14.2) + '@firebase/app': 0.14.2 + '@firebase/app-check': 0.11.0(@firebase/app@0.14.2) + '@firebase/app-check-compat': 0.4.0(@firebase/app-compat@0.5.2)(@firebase/app@0.14.2) + '@firebase/app-compat': 0.5.2 '@firebase/app-types': 0.9.3 - '@firebase/auth': 1.11.0(@firebase/app@0.14.1) - '@firebase/auth-compat': 0.6.0(@firebase/app-compat@0.5.1)(@firebase/app-types@0.9.3)(@firebase/app@0.14.1) - '@firebase/data-connect': 0.3.11(@firebase/app@0.14.1) + '@firebase/auth': 1.11.0(@firebase/app@0.14.2) + '@firebase/auth-compat': 0.6.0(@firebase/app-compat@0.5.2)(@firebase/app-types@0.9.3)(@firebase/app@0.14.2) + '@firebase/data-connect': 0.3.11(@firebase/app@0.14.2) '@firebase/database': 1.1.0 '@firebase/database-compat': 2.1.0 - '@firebase/firestore': 4.9.0(@firebase/app@0.14.1) - '@firebase/firestore-compat': 0.4.0(@firebase/app-compat@0.5.1)(@firebase/app-types@0.9.3)(@firebase/app@0.14.1) - '@firebase/functions': 0.13.0(@firebase/app@0.14.1) - '@firebase/functions-compat': 0.4.0(@firebase/app-compat@0.5.1)(@firebase/app@0.14.1) - '@firebase/installations': 0.6.19(@firebase/app@0.14.1) - '@firebase/installations-compat': 0.2.19(@firebase/app-compat@0.5.1)(@firebase/app-types@0.9.3)(@firebase/app@0.14.1) - '@firebase/messaging': 0.12.23(@firebase/app@0.14.1) - '@firebase/messaging-compat': 0.2.23(@firebase/app-compat@0.5.1)(@firebase/app@0.14.1) - '@firebase/performance': 0.7.9(@firebase/app@0.14.1) - '@firebase/performance-compat': 0.2.22(@firebase/app-compat@0.5.1)(@firebase/app@0.14.1) - '@firebase/remote-config': 0.6.6(@firebase/app@0.14.1) - '@firebase/remote-config-compat': 0.2.19(@firebase/app-compat@0.5.1)(@firebase/app@0.14.1) - '@firebase/storage': 0.14.0(@firebase/app@0.14.1) - '@firebase/storage-compat': 0.4.0(@firebase/app-compat@0.5.1)(@firebase/app-types@0.9.3)(@firebase/app@0.14.1) + '@firebase/firestore': 4.9.1(@firebase/app@0.14.2) + '@firebase/firestore-compat': 0.4.1(@firebase/app-compat@0.5.2)(@firebase/app-types@0.9.3)(@firebase/app@0.14.2) + '@firebase/functions': 0.13.1(@firebase/app@0.14.2) + '@firebase/functions-compat': 0.4.1(@firebase/app-compat@0.5.2)(@firebase/app@0.14.2) + '@firebase/installations': 0.6.19(@firebase/app@0.14.2) + '@firebase/installations-compat': 0.2.19(@firebase/app-compat@0.5.2)(@firebase/app-types@0.9.3)(@firebase/app@0.14.2) + '@firebase/messaging': 0.12.23(@firebase/app@0.14.2) + '@firebase/messaging-compat': 0.2.23(@firebase/app-compat@0.5.2)(@firebase/app@0.14.2) + '@firebase/performance': 0.7.9(@firebase/app@0.14.2) + '@firebase/performance-compat': 0.2.22(@firebase/app-compat@0.5.2)(@firebase/app@0.14.2) + '@firebase/remote-config': 0.6.6(@firebase/app@0.14.2) + '@firebase/remote-config-compat': 0.2.19(@firebase/app-compat@0.5.2)(@firebase/app@0.14.2) + '@firebase/storage': 0.14.0(@firebase/app@0.14.2) + '@firebase/storage-compat': 0.4.0(@firebase/app-compat@0.5.2)(@firebase/app-types@0.9.3)(@firebase/app@0.14.2) '@firebase/util': 1.13.0 transitivePeerDependencies: - '@react-native-async-storage/async-storage' @@ -14350,7 +14375,7 @@ snapshots: get-caller-file@2.0.5: {} - get-east-asian-width@1.3.0: {} + get-east-asian-width@1.3.1: {} get-intrinsic@1.3.0: dependencies: @@ -14396,11 +14421,13 @@ snapshots: dependencies: assert-plus: 1.0.0 - git-raw-commits@4.0.0: + git-raw-commits@5.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@5.0.0): dependencies: - dargs: 8.1.0 - meow: 12.1.1 - split2: 4.2.0 + '@conventional-changelog/git-client': 1.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@5.0.0) + meow: 13.2.0 + transitivePeerDependencies: + - conventional-commits-filter + - conventional-commits-parser glob-parent@5.1.2: dependencies: @@ -14470,7 +14497,7 @@ snapshots: pify: 2.3.0 pinkie-promise: 2.0.1 - google-auth-library@10.2.1(supports-color@10.2.0): + google-auth-library@10.3.0(supports-color@10.2.0): dependencies: base64-js: 1.5.1 ecdsa-sig-formatter: 1.0.11 @@ -14500,7 +14527,7 @@ snapshots: '@grpc/proto-loader': 0.8.0 abort-controller: 3.0.0 duplexify: 4.1.3 - google-auth-library: 10.2.1(supports-color@10.2.0) + google-auth-library: 10.3.0(supports-color@10.2.0) google-logging-utils: 1.1.1 node-fetch: 3.3.2 object-hash: 3.0.0 @@ -14895,9 +14922,9 @@ snapshots: is-fullwidth-code-point@4.0.0: {} - is-fullwidth-code-point@5.0.0: + is-fullwidth-code-point@5.1.0: dependencies: - get-east-asian-width: 1.3.0 + get-east-asian-width: 1.3.1 is-generator-function@1.1.0: dependencies: @@ -15046,7 +15073,7 @@ snapshots: isbinaryfile@4.0.10: {} - isbinaryfile@5.0.4: {} + isbinaryfile@5.0.6: {} isexe@2.0.0: {} @@ -15143,7 +15170,7 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -15631,7 +15658,7 @@ snapshots: media-typer@1.1.0: {} - memfs@4.38.1: + memfs@4.38.2: dependencies: '@jsonjoy.com/json-pack': 1.11.0(tslib@2.8.1) '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) @@ -15642,6 +15669,8 @@ snapshots: meow@12.1.1: {} + meow@13.2.0: {} + merge-descriptors@1.0.3: {} merge-descriptors@2.0.0: {} @@ -15828,15 +15857,15 @@ snapshots: netmask@2.0.2: {} - ng-packagr@20.2.0(@angular/compiler-cli@20.2.1(@angular/compiler@20.2.1)(typescript@5.9.2))(tslib@2.8.1)(typescript@5.9.2): + ng-packagr@20.2.0(@angular/compiler-cli@20.2.3(@angular/compiler@20.2.3)(typescript@5.9.2))(tslib@2.8.1)(typescript@5.9.2): dependencies: '@ampproject/remapping': 2.3.0 - '@angular/compiler-cli': 20.2.1(@angular/compiler@20.2.1)(typescript@5.9.2) + '@angular/compiler-cli': 20.2.3(@angular/compiler@20.2.3)(typescript@5.9.2) '@rollup/plugin-json': 6.1.0(rollup@4.46.2) - '@rollup/wasm-node': 4.48.1 + '@rollup/wasm-node': 4.50.0 ajv: 8.17.1 ansi-colors: 4.1.3 - browserslist: 4.25.3 + browserslist: 4.25.4 chokidar: 4.0.3 commander: 14.0.0 dependency-graph: 1.0.0 @@ -15900,7 +15929,7 @@ snapshots: node-gyp-build@4.8.4: {} - node-gyp@11.4.1: + node-gyp@11.4.2: dependencies: env-paths: 2.2.1 exponential-backoff: 3.1.2 @@ -15929,7 +15958,7 @@ snapshots: dependencies: npm-normalize-package-bin: 4.0.0 - npm-install-checks@7.1.1: + npm-install-checks@7.1.2: dependencies: semver: 7.7.2 @@ -15955,7 +15984,7 @@ snapshots: npm-pick-manifest@10.0.0: dependencies: - npm-install-checks: 7.1.1 + npm-install-checks: 7.1.2 npm-normalize-package-bin: 4.0.0 npm-package-arg: 12.0.2 semver: 7.7.2 @@ -16169,7 +16198,7 @@ snapshots: '@npmcli/git': 6.0.3 '@npmcli/installed-package-contents': 3.0.0 '@npmcli/package-json': 6.2.0 - '@npmcli/promise-spawn': 8.0.2 + '@npmcli/promise-spawn': 8.0.3 '@npmcli/run-script': 9.1.0 cacache: 19.0.1 fs-minipass: 3.0.3 @@ -16425,7 +16454,7 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 22.17.2 + '@types/node': 22.18.0 long: 5.3.2 protractor@7.0.0: @@ -16513,9 +16542,9 @@ snapshots: - supports-color - utf-8-validate - puppeteer-core@24.17.0(bufferutil@4.0.9): + puppeteer-core@24.18.0(bufferutil@4.0.9): dependencies: - '@puppeteer/browsers': 2.10.7 + '@puppeteer/browsers': 2.10.8 chromium-bidi: 8.0.0(devtools-protocol@0.0.1475386) debug: 4.4.1(supports-color@10.2.0) devtools-protocol: 0.0.1475386 @@ -16809,12 +16838,12 @@ snapshots: optionalDependencies: '@babel/code-frame': 7.27.1 - rollup-plugin-sourcemaps2@0.5.3(@types/node@22.17.2)(rollup@4.46.2): + rollup-plugin-sourcemaps2@0.5.3(@types/node@22.18.0)(rollup@4.46.2): dependencies: '@rollup/pluginutils': 5.2.0(rollup@4.46.2) rollup: 4.46.2 optionalDependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 rollup@4.46.2: dependencies: @@ -17143,7 +17172,7 @@ snapshots: slice-ansi@7.1.0: dependencies: ansi-styles: 6.2.1 - is-fullwidth-code-point: 5.0.0 + is-fullwidth-code-point: 5.1.0 smart-buffer@4.2.0: {} @@ -17375,8 +17404,8 @@ snapshots: string-width@7.2.0: dependencies: - emoji-regex: 10.4.0 - get-east-asian-width: 1.3.0 + emoji-regex: 10.5.0 + get-east-asian-width: 1.3.1 strip-ansi: 7.1.0 string.prototype.trim@1.2.10: @@ -17469,7 +17498,7 @@ snapshots: pump: 3.0.3 tar-stream: 3.1.7 optionalDependencies: - bare-fs: 4.2.1 + bare-fs: 4.2.2 bare-path: 3.0.0 transitivePeerDependencies: - bare-buffer @@ -17622,14 +17651,14 @@ snapshots: dependencies: typescript: 5.9.2 - ts-node@10.9.2(@types/node@22.17.2)(typescript@5.9.2): + ts-node@10.9.2(@types/node@22.18.0)(typescript@5.9.2): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 22.17.2 + '@types/node': 22.18.0 acorn: 8.15.0 acorn-walk: 8.3.4 arg: 4.1.3 @@ -17807,9 +17836,9 @@ snapshots: unpipe@1.0.0: {} - update-browserslist-db@1.1.3(browserslist@4.25.3): + update-browserslist-db@1.1.3(browserslist@4.25.4): dependencies: - browserslist: 4.25.3 + browserslist: 4.25.4 escalade: 3.2.0 picocolors: 1.1.1 @@ -18054,7 +18083,7 @@ snapshots: webpack-dev-middleware@7.4.2(webpack@5.101.2(esbuild@0.25.9)): dependencies: colorette: 2.0.20 - memfs: 4.38.1 + memfs: 4.38.2 mime-types: 2.1.35 on-finished: 2.4.1 range-parser: 1.2.1 @@ -18123,7 +18152,7 @@ snapshots: '@webassemblyjs/wasm-parser': 1.14.1 acorn: 8.15.0 acorn-import-phases: 1.0.4(acorn@8.15.0) - browserslist: 4.25.3 + browserslist: 4.25.4 chrome-trace-event: 1.0.4 enhanced-resolve: 5.18.3 es-module-lexer: 1.7.0 diff --git a/tools/test/expected_package.json b/tools/test/expected_package.json index a456312e8903..6630c9062f8a 100644 --- a/tools/test/expected_package.json +++ b/tools/test/expected_package.json @@ -35,8 +35,8 @@ } }, "engines": { - "node": "^16.14.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" + "node": "0.0.0-ENGINES-NODE", + "npm": "0.0.0-ENGINES-NPM", + "yarn": "0.0.0-ENGINES-YARN" } }