diff --git a/.github/codeql/config.yml b/.github/codeql/config.yml deleted file mode 100644 index ad81a268eda4..000000000000 --- a/.github/codeql/config.yml +++ /dev/null @@ -1,8 +0,0 @@ -name: 'Angular CLI CodeQL config' - -query-filters: - # TODO(josephperrott): reevaluate if these can be reenabled. - - exclude: - id: js/bad-code-sanitization - - exclude: - id: js/regex-injection diff --git a/.github/workflows/assistant-to-the-branch-manager.yml b/.github/workflows/assistant-to-the-branch-manager.yml index 94fdfb8df840..adb1937840ae 100644 --- a/.github/workflows/assistant-to-the-branch-manager.yml +++ b/.github/workflows/assistant-to-the-branch-manager.yml @@ -2,6 +2,7 @@ name: DevInfra on: push: + # zizmor: ignore[dangerous-triggers] - {Trigger is safe as workflow does not checkout untrusted code} pull_request_target: types: [opened, synchronize, reopened, ready_for_review, labeled] @@ -17,6 +18,6 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - - uses: angular/dev-infra/github-actions/branch-manager@ba726e7bca0b08b125ccc6f93c233749e1213c17 + - uses: angular/dev-infra/github-actions/branch-manager@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main with: angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 57b31cb9c2f1..9ca3788bd8d5 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@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/setup@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - 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@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/setup@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/configure-remote@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Install node modules @@ -61,11 +61,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/setup@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/configure-remote@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Install node modules @@ -84,13 +84,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/setup@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/configure-remote@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Run CLI E2E tests @@ -100,11 +100,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/setup@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/configure-remote@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Install node modules @@ -137,7 +137,7 @@ jobs: runs-on: windows-2025 steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Install node modules run: pnpm install --frozen-lockfile - name: Download built Windows E2E tests @@ -164,13 +164,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/setup@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/configure-remote@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Run CLI E2E tests @@ -188,13 +188,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/setup@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/configure-remote@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Run CLI E2E tests @@ -208,34 +208,35 @@ 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@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/setup@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/configure-remote@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} + - name: Start Sauce Connect + uses: saucelabs/sauce-connect-action@cb88b508c6f9ff4d84490093733315dbd55de022 # v3 + timeout-minutes: 10 + with: + username: ${{ vars.SAUCE_USERNAME }} + accessKey: ${{ secrets.SAUCE_ACCESS_KEY }} + region: us-west-1 + tunnelName: ${{ env.SAUCE_TUNNEL_IDENTIFIER }} + proxyLocalhost: allow + # By default we disable SSL bumping for all requests. This is because SSL bumping is not needed + # for our test setup and in order to perform the SSL bumping, Saucelabs intercepts all HTTP + # requests in the tunnel VM and modifies them. This can cause flakiness as it makes all requests + # dependent on the SSL bumping middleware. + # See: https://wiki.saucelabs.com/display/DOCS/Troubleshooting+Sauce+Connect#TroubleshootingSauceConnect-DisablingSSLBumping + tlsPassthroughDomains: all - name: Run E2E Browser tests env: SAUCE_USERNAME: ${{ vars.SAUCE_USERNAME }} SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }} - SAUCE_LOG_FILE: /tmp/angular/sauce-connect.log - SAUCE_READY_FILE: /tmp/angular/sauce-connect-ready-file.lock - SAUCE_PID_FILE: /tmp/angular/sauce-connect-pid-file.lock - SAUCE_TUNNEL_IDENTIFIER: 'angular-${{ github.run_number }}' - SAUCE_READY_FILE_TIMEOUT: 120 - run: | - ./scripts/saucelabs/start-tunnel.sh & - ./scripts/saucelabs/wait-for-tunnel.sh - pnpm bazel test --config=saucelabs //tests:e2e.saucelabs - ./scripts/saucelabs/stop-tunnel.sh - - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - if: ${{ failure() }} - with: - name: sauce-connect-log - path: ${{ env.SAUCE_CONNECT_DIR_IN_HOST }}/sauce-connect.log + run: pnpm bazel test --config=saucelabs //tests:e2e.saucelabs publish-snapshots: needs: build @@ -244,11 +245,11 @@ jobs: CIRCLE_BRANCH: ${{ github.ref_name }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/setup@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - 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 deleted file mode 100644 index f95ab2f4ac05..000000000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: 'CodeQL' - -on: - push: - branches: ['main', '*.*.x'] - schedule: - - cron: '39 9 * * 1' - -permissions: {} - -jobs: - analyze: - name: Analyze - runs-on: 'ubuntu-latest' - permissions: - security-events: write - packages: read - strategy: - fail-fast: false - steps: - - name: Checkout repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - name: Initialize CodeQL - uses: github/codeql-action/init@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 - with: - languages: javascript-typescript - build-mode: none - config-file: .github/codeql/config.yml - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 - with: - category: '/language:javascript-typescript' diff --git a/.github/workflows/dev-infra.yml b/.github/workflows/dev-infra.yml index e0efdf2b94e4..3de13736b60d 100644 --- a/.github/workflows/dev-infra.yml +++ b/.github/workflows/dev-infra.yml @@ -1,6 +1,7 @@ name: DevInfra on: + # zizmor: ignore[dangerous-triggers] - {Trigger is safe as workflow does not checkout untrusted code} pull_request_target: types: [opened, synchronize, reopened] issues: @@ -15,21 +16,21 @@ jobs: if: github.event_name == 'pull_request_target' runs-on: ubuntu-latest steps: - - uses: angular/dev-infra/github-actions/labeling/pull-request@649c3afeaa46674507b9625537e49de54a695e2b + - uses: angular/dev-infra/github-actions/labeling/pull-request@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main with: angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} post_approval_changes: if: github.event_name == 'pull_request_target' runs-on: ubuntu-latest steps: - - uses: angular/dev-infra/github-actions/post-approval-changes@649c3afeaa46674507b9625537e49de54a695e2b + - uses: angular/dev-infra/github-actions/post-approval-changes@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main with: angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} issue_labels: if: github.event_name == 'issues' runs-on: ubuntu-latest steps: - - uses: angular/dev-infra/github-actions/labeling/issue@649c3afeaa46674507b9625537e49de54a695e2b + - uses: angular/dev-infra/github-actions/labeling/issue@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main with: angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} google-generative-ai-key: ${{ secrets.GOOGLE_GENERATIVE_AI_KEY }} diff --git a/.github/workflows/perf.yml b/.github/workflows/perf.yml index dac67ebcbe7f..83dfe2812a83 100644 --- a/.github/workflows/perf.yml +++ b/.github/workflows/perf.yml @@ -9,7 +9,6 @@ on: permissions: contents: 'read' - id-token: 'write' defaults: run: @@ -23,7 +22,7 @@ jobs: workflows: ${{ steps.workflows.outputs.workflows }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Install node modules run: pnpm install --frozen-lockfile - id: workflows @@ -33,14 +32,17 @@ jobs: timeout-minutes: 30 runs-on: ubuntu-latest needs: list + permissions: + contents: 'read' + id-token: 'write' strategy: matrix: workflow: ${{ fromJSON(needs.list.outputs.workflows) }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/setup@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - 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 @@ -52,4 +54,7 @@ jobs: project_id: 'internal-200822' workload_identity_provider: 'projects/823469418460/locations/global/workloadIdentityPools/measurables-tracking/providers/angular' service_account: 'measures-uploader@internal-200822.iam.gserviceaccount.com' - - run: pnpm ng-dev perf workflows --name ${{ matrix.workflow }} --commit-sha ${{github.sha}} + - run: pnpm ng-dev perf workflows --name "$WORKFLOW" --commit-sha "$COMMIT_SHA" + env: + WORKFLOW: ${{ matrix.workflow }} + COMMIT_SHA: ${{ github.sha }} diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 0f5a37f5751a..453a75f453ae 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -23,7 +23,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - - uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2 + - uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3 id: filter with: filters: | @@ -34,9 +34,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/setup@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup ESLint Caching uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: @@ -66,17 +66,17 @@ jobs: # it has been merged. run: pnpm ng-dev format changed --check ${{ github.event.pull_request.base.sha }} - name: Check Package Licenses - uses: angular/dev-infra/github-actions/linting/licenses@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/linting/licenses@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main build: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/setup@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/configure-remote@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Install node modules run: pnpm install --frozen-lockfile - name: Build release targets @@ -93,11 +93,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/setup@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/configure-remote@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Install node modules run: pnpm install --frozen-lockfile - name: Run module and package tests @@ -114,13 +114,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/setup@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/configure-remote@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - 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:e2e.${{ matrix.subset }}_node${{ matrix.node }} @@ -128,11 +128,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/setup@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/configure-remote@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Install node modules run: pnpm install --frozen-lockfile - name: Build E2E tests for Windows on Linux @@ -156,7 +156,7 @@ jobs: runs-on: windows-2025 steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Install node modules run: pnpm install --frozen-lockfile - name: Download built Windows E2E tests @@ -183,13 +183,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/setup@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/configure-remote@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - 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:e2e.${{ matrix.subset }}_node${{ matrix.node }} @@ -205,12 +205,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/setup@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@ba726e7bca0b08b125ccc6f93c233749e1213c17 + uses: angular/dev-infra/github-actions/bazel/configure-remote@fa43fd2864c3bec677cd47f4e095370850cdf8bc # main - 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:e2e.snapshots.${{ matrix.subset }}_node${{ matrix.node }} diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml deleted file mode 100644 index 2e9f8b03919a..000000000000 --- a/.github/workflows/scorecard.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: OpenSSF Scorecard -on: - branch_protection_rule: - schedule: - - cron: '0 2 * * 0' - push: - branches: [main] - workflow_dispatch: - -# Declare default permissions as read only. -permissions: - contents: read - -jobs: - analysis: - name: Scorecards analysis - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - # Needed to upload the results to code-scanning dashboard. - security-events: write - # Needed to publish results - id-token: write - - steps: - - name: 'Checkout code' - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - name: 'Run analysis' - uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 - with: - results_file: results.sarif - results_format: sarif - publish_results: true - - # Upload the results as artifacts. - - name: 'Upload artifact' - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: SARIF file - path: results.sarif - retention-days: 5 - - # Upload the results to GitHub's code scanning dashboard. - - name: 'Upload to code-scanning' - uses: github/codeql-action/upload-sarif@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 - with: - sarif_file: results.sarif diff --git a/.nvmrc b/.nvmrc index f9e7451e7715..c94711948a66 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -22.23.1 +22.23.2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 8867117ff498..0338eb32b41e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,50 +1,247 @@ - + -# 22.0.8 (2026-07-23) +# 22.1.6 (2026-08-26) + +### @angular/build + +| Commit | Type | Description | +| ---------------------------------------------------------------------------------------------------- | ---- | --------------------------------------------------------- | +| [3f132eaa97](https://github.com/angular/angular-cli/commit/3f132eaa97b95e16c58b8095c2566e3c78190446) | fix | ignore side-effect annotations in unit test builds | +| [5b1028936f](https://github.com/angular/angular-cli/commit/5b1028936f6e9582917f95ac37942dca0ee2c659) | perf | batch prerender routes and share in-memory server bundles | + +### @angular/ssr + +| Commit | Type | Description | +| ---------------------------------------------------------------------------------------------------- | ---- | ----------------------------------------------------- | +| [76818cb811](https://github.com/angular/angular-cli/commit/76818cb811a8fe669575f988fec2e4528dca8c73) | fix | abort web request signal when node request is aborted | + + + + + +# 22.1.5 (2026-08-19) ### @angular/cli -| Commit | Type | Description | -| --------------------------------------------------------------------------------------------------- | ---- | -------------------------------------------------------- | -| [41c356256](https://github.com/angular/angular-cli/commit/41c356256525469a41ea72896b1ddff91a4e6e55) | fix | batch Prettier invocations during migration formatting | -| [bc87c85c3](https://github.com/angular/angular-cli/commit/bc87c85c3c660e969cf77a493dc4ee58fd831214) | fix | update MCP devserver tool names to conform to spec regex | +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ---------------------------------------------------------------- | +| [e672271f8](https://github.com/angular/angular-cli/commit/e672271f81e7b8b422b98c17fca5b67896d40844) | fix | enforce MCP roots in get_best_practices tool | +| [a14916cc4](https://github.com/angular/angular-cli/commit/a14916cc4b13412205d3e4a1c32d7e40be52f0e1) | fix | handle errors from isAllowedWorkspacePath in best-practices tool | +| [d6e1cddff](https://github.com/angular/angular-cli/commit/d6e1cddff92842f6889585ae7899efc028decc78) | fix | throw on out-of-roots workspace in best-practices tool | + +### @schematics/angular + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------ | +| [ba2b0e4c2](https://github.com/angular/angular-cli/commit/ba2b0e4c291842c699fdbeaaddec1531dbdd7952) | fix | transform fail() to expect.fail() in refactor-jasmine-vitest | + +### @angular/build + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------- | +| [cba72902d](https://github.com/angular/angular-cli/commit/cba72902d42022bd5a1bd17b23d65cacc0013e35) | fix | correct misleading error message for top-level await | +| [b4679998c](https://github.com/angular/angular-cli/commit/b4679998c205b6cce01d40fad24c4ee7954aa48d) | fix | disable code splitting for unit test builds | +| [ff1d3565e](https://github.com/angular/angular-cli/commit/ff1d3565e87749a8347c3be98cd4a7ebccb69fc0) | fix | preserve integrity and crossorigin in autoCsp loader | +| [1fc1fb05c](https://github.com/angular/angular-cli/commit/1fc1fb05cfe2c69ee7b9345b582d3c2177b923fd) | perf | traverse AST with iterative post-order walker in i18n inliner | + + + + + +# 22.1.4 (2026-08-13) + +### @angular/cli + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------- | +| [67a29899b](https://github.com/angular/angular-cli/commit/67a29899b07f760bac9582cbc6175966cce1c5d2) | fix | disable searching current directory for bare executable names on Windows | +| [1b0ba5c17](https://github.com/angular/angular-cli/commit/1b0ba5c17f0be2679b31bad1bee8b435315dac1a) | fix | serialize configuration as a single argv token in run_target strategies ([#33657](https://github.com/angular/angular-cli/pull/33657)) | +| [9440432d2](https://github.com/angular/angular-cli/commit/9440432d273c044965508d80e808c2fe123af0aa) | perf | avoid eager module loading during global bootstrap | + +### @schematics/angular + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------- | +| [d4a48e3ab](https://github.com/angular/angular-cli/commit/d4a48e3abe320e090eefe17cb70abdf8e7eafaed) | fix | generate CLAUDE.md for Claude Code instead of AGENTS.md | +| [d451f15b2](https://github.com/angular/angular-cli/commit/d451f15b2838a8282363dcb30161dd5dc858750f) | fix | import UrlSegment instead of subPath in guard generator | ### @angular/build | Commit | Type | Description | | --------------------------------------------------------------------------------------------------- | ---- | ----------------------------------------------------------------- | -| [5724bf632](https://github.com/angular/angular-cli/commit/5724bf632eba59eccdd941beae8aafad35ce003e) | fix | canonicalize drive letter casing for workspace root on Windows | -| [b8bdbaa1e](https://github.com/angular/angular-cli/commit/b8bdbaa1ea1c58f061580bd58c015078f57c1530) | fix | ensure import map integrity keys are valid URL-like specifiers | -| [212a7bb21](https://github.com/angular/angular-cli/commit/212a7bb21eca131f32fd7b4e7b5a9ab87f2bfded) | fix | favor istanbul coverage provider when browser testing is enabled | -| [bc760b005](https://github.com/angular/angular-cli/commit/bc760b005e0dae10a2dfd31a7f0f772482305398) | fix | preserve custom config options in runnerConfig for vitest | -| [19cda7415](https://github.com/angular/angular-cli/commit/19cda7415693f36e911a736a32576110905b6600) | fix | remap metafile paths when workspace root is a symlink or junction | -| [fdcc98c79](https://github.com/angular/angular-cli/commit/fdcc98c7912f45431268fdf66c8b132bd119bc27) | perf | skip semantic affected-file walk when type checking is disabled | +| [46fcb29d6](https://github.com/angular/angular-cli/commit/46fcb29d6c1ded962de95449d63716c13950f59a) | fix | count statically imported chunks in the initial total | +| [796b57684](https://github.com/angular/angular-cli/commit/796b576843191a4d5c74e4f9363ec0e46ae3a881) | fix | normalize setupFiles paths to POSIX for vitest runner | +| [c805e5cfb](https://github.com/angular/angular-cli/commit/c805e5cfb308d02a1944ef446d0a01af8a7ec6d2) | fix | prevent syntax corruption for Crockford-style enum IIFE | +| [cc6c17716](https://github.com/angular/angular-cli/commit/cc6c17716df5c411efca5e6f4c960f0565f45d90) | fix | prevent syntax corruption in oxc transform | +| [a142f6f83](https://github.com/angular/angular-cli/commit/a142f6f83d2f501b64f2404909ef9325bbfa70fb) | fix | return direct file contents for non-Angular TypeScript files | +| [956c6578d](https://github.com/angular/angular-cli/commit/956c6578d31d8482c04dc45723d7ab3b4fe355a5) | fix | return only lowest version per target engine | +| [689b5b116](https://github.com/angular/angular-cli/commit/689b5b116717140da98494e61ac5ea5ad7b68d73) | fix | set target for Rolldown dependency prebundling in Vite dev server | +| [70461f6ed](https://github.com/angular/angular-cli/commit/70461f6ed2e30aeaad2b93400ad00d9274665967) | perf | avoid encoding the inline source map before remapping | +| [22cce7563](https://github.com/angular/angular-cli/commit/22cce7563e82f17373b69e590d3e445767bd9264) | perf | batch last_accessed updates in sqlite cache store | +| [ab2ed18d5](https://github.com/angular/angular-cli/commit/ab2ed18d5739e8565403062ca74aa2d5cb3b95ec) | perf | hash the i18n inline cache key options once per locale | +| [34516ff73](https://github.com/angular/angular-cli/commit/34516ff736185e20ef8239b1fed8eda1f0193f62) | perf | optimize template string size calculation in server manifest | +| [712971c37](https://github.com/angular/angular-cli/commit/712971c370738beaebff18f6995859b1713ed8ae) | perf | share i18n translations with the inliner workers by reference | +| [78f8c5fef](https://github.com/angular/angular-cli/commit/78f8c5fef44dc6ff466b17c98fa1d01222cb1781) | perf | use Map for chunk asset size lookups in budget calculator | + +### @angular/ssr + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | -------------------------------------------------- | +| [2331c1047](https://github.com/angular/angular-cli/commit/2331c10476830e7a53e0f2fa4a2f37dad58e2d5d) | fix | destroy platform when response stream is cancelled | - + -# 22.1.0-next.4 (2026-07-15) +# 22.1.3 (2026-08-05) ### @angular/cli -| Commit | Type | Description | -| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------ | -| [3789ceee1](https://github.com/angular/angular-cli/commit/3789ceee18b4528c2acb7989b5d41c32d386a8a8) | fix | copy packageManager field and yarn config for temp installs | -| [b0b3a47ae](https://github.com/angular/angular-cli/commit/b0b3a47ae95f4e98e1280ff5c9e3751ccecee5a8) | fix | support resolving subproject dependencies in pnpm workspaces | +| Commit | Type | Description | +| ---------------------------------------------------------------------------------------------------- | ---- | --------------------------------------------------------------------------------------------------------------------------------------------- | +| [f837b788c6](https://github.com/angular/angular-cli/commit/f837b788c6a23e7661db5455192f5a84d20e9b37) | fix | always install package during ng add to inspect manifest on disk for schematics ([#33718](https://github.com/angular/angular-cli/pull/33718)) | +| [72ae93638d](https://github.com/angular/angular-cli/commit/72ae93638dd83b3877773ac0d9f7e4c4e9056a33) | fix | correctly report available package updates during bare ng update | +| [a949e06568](https://github.com/angular/angular-cli/commit/a949e0656855786e4274159be09242ff9c4eb012) | fix | discover migrations from installed packages when omitted by registry metadata ([#33718](https://github.com/angular/angular-cli/pull/33718)) | +| [1d9122fd50](https://github.com/angular/angular-cli/commit/1d9122fd50f8a9b82199d44f9b0e075726279538) | fix | normalize Windows drive-letter casing for process.cwd | + +### @angular/build + +| Commit | Type | Description | +| ---------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------------------------------------------------------- | +| [a4860d505a](https://github.com/angular/angular-cli/commit/a4860d505aff0b43fc608cd0745ed187b1d407b5) | fix | prevent build process hang on unhandled error ([#33715](https://github.com/angular/angular-cli/pull/33715)) | +| [7686d66cab](https://github.com/angular/angular-cli/commit/7686d66cabcdfe90748ac405686d42674a19576f) | fix | retain watch files on error in load result cache | +| [25b7cf7504](https://github.com/angular/angular-cli/commit/25b7cf7504838d541abfba043d9ea3d616a23c04) | fix | support case-insensitive and alternative license file names | +| [4fd81402ce](https://github.com/angular/angular-cli/commit/4fd81402ce5f2f3db45a17ee0d116f12edf8d254) | perf | release build resources early in non-watch mode ([#33715](https://github.com/angular/angular-cli/pull/33715)) | + +### @angular/ssr + +| Commit | Type | Description | +| ---------------------------------------------------------------------------------------------------- | ---- | ---------------------------------------------------------- | +| [6af906cb94](https://github.com/angular/angular-cli/commit/6af906cb94bd0686b4c0431989e054711c74892a) | fix | settle writeResponseToNodeResponse when client disconnects | +| [917d3b2254](https://github.com/angular/angular-cli/commit/917d3b22549c19b91e03ceb0775a3a758142b9de) | perf | avoid buffering request body when sanitizing headers | + + + + + +# 22.1.2 (2026-07-30) + +### @angular/cli + +| Commit | Type | Description | +| ---------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------- | +| [57db27ea91](https://github.com/angular/angular-cli/commit/57db27ea910b102854267dfcd77e8fe60f23993c) | fix | add packages with built-in schematics to devDependencies only | + +### @angular/build + +| Commit | Type | Description | +| ---------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------------------ | +| [baed978885](https://github.com/angular/angular-cli/commit/baed978885585fceadc64f0151d7474054d57d6a) | fix | prevent IIFE wrapper interleaving for adjacent classes in minified files | + + + + + +# 22.1.1 (2026-07-30) + +### @angular/cli + +| Commit | Type | Description | +| ---------------------------------------------------------------------------------------------------- | ---- | ----------------------------------------------- | +| [ab971a8543](https://github.com/angular/angular-cli/commit/ab971a8543d80dfc93fdddf49598564f25196160) | fix | support npm 12 metadata array and error formats | + +### @angular/build + +| Commit | Type | Description | +| ---------------------------------------------------------------------------------------------------- | ---- | --------------------------------------------------------------- | +| [db24220fb8](https://github.com/angular/angular-cli/commit/db24220fb8efb5c9416e375a468672ff69d0659d) | fix | rewrite paths from sandboxed execroots when running under Bazel | + + + + + +# 22.1.0 (2026-07-29) + +## Deprecations + +### @angular-devkit/core + +- `stringToFileBuffer` and `fileBufferToString` are deprecated. Use standard Web APIs (`TextEncoder` and `TextDecoder`) instead. + + Internal usages within the repository have been removed and replaced with standard Web APIs. The public API golden file for `@angular-devkit/core` has been updated to reflect the deprecations. ### @schematics/angular -| Commit | Type | Description | -| --------------------------------------------------------------------------------------------------- | ---- | ---------------------------------- | -| [b345bb54d](https://github.com/angular/angular-cli/commit/b345bb54d3ec7c73f9db70400f823d90aeab8fa8) | fix | remove unused spec tsconfig outDir | +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ----------------------------------------------------- | +| [89d7f59cd](https://github.com/angular/angular-cli/commit/89d7f59cd7cc5d821ac0e81b1fee50e27877c976) | feat | update ai-config to include Angular MCP server config | +| [b345bb54d](https://github.com/angular/angular-cli/commit/b345bb54d3ec7c73f9db70400f823d90aeab8fa8) | fix | remove unused spec tsconfig outDir | + +### @angular/cli + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ----------------------------------------------------------------------- | +| [f59bcf529](https://github.com/angular/angular-cli/commit/f59bcf52917bc5e25b97c863f96127ec8d0f12f5) | fix | abort and guide manual mitigation when updating catalog packages | +| [48f90f5d5](https://github.com/angular/angular-cli/commit/48f90f5d5e5dd6369b2ccf044a722271c82dffd6) | fix | prevent Yarn registry environment variable override | +| [c963ecbec](https://github.com/angular/angular-cli/commit/c963ecbec241d42dfb419ae081ba22429e37f09e) | fix | remove algoliasearch dependency and support latest docs versions | +| [6859d25c3](https://github.com/angular/angular-cli/commit/6859d25c32b6c93cbbf2d4ad4143aa10b52b7588) | fix | resolve correct registry name when using npm alias syntax during update | +| [3a2589dac](https://github.com/angular/angular-cli/commit/3a2589dac684dfe26b2151b940bd40280d7c5d8e) | fix | respect client-side release age settings during update resolution | +| [5c3101bff](https://github.com/angular/angular-cli/commit/5c3101bff2e1b9d0b0e4668a183e8bcab8a1540e) | fix | revert package.json changes if installation tasks fail during update | +| [7932caaf9](https://github.com/angular/angular-cli/commit/7932caaf987c5692d6624f6af23e65ce3f6d27fd) | fix | robustly parse npm manifest from array | + +### @angular-devkit/core + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | -------- | --------------------------------------------------- | +| [fd336d365](https://github.com/angular/angular-cli/commit/fd336d365dbfe8f558db177a8da24790914a541b) | refactor | deprecate stringToFileBuffer and fileBufferToString | ### @angular/build -| Commit | Type | Description | -| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------ | -| [0c18dc0f6](https://github.com/angular/angular-cli/commit/0c18dc0f6d4f36d7bbb6f35b37bfa688e8fcf7d2) | feat | emit debug ids for stable subresource integrity hashes | -| [291caab61](https://github.com/angular/angular-cli/commit/291caab6158fa804f6221dd024a5b96e6181eaad) | fix | prevent stripping nested sourceMappingURL comments | +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ---------------------------------------------------------------------------- | +| [34d558c3c](https://github.com/angular/angular-cli/commit/34d558c3c98e1b59a2c2808fc04bfbb63dfe8acf) | feat | add built-in SQLite cache store fallback | +| [0c18dc0f6](https://github.com/angular/angular-cli/commit/0c18dc0f6d4f36d7bbb6f35b37bfa688e8fcf7d2) | feat | emit debug ids for stable subresource integrity hashes | +| [51f69276f](https://github.com/angular/angular-cli/commit/51f69276fd2b2aab0e94901e79a51f6860ef8690) | feat | enable chunk optimization for server builds | +| [10dc30f9c](https://github.com/angular/angular-cli/commit/10dc30f9c680f46f65b5beb030f2a75c422a3e71) | feat | migrate advanced optimization Babel plugins to oxc-parser + magic-string | +| [917393a4c](https://github.com/angular/angular-cli/commit/917393a4cd85172574b155f727da5c1eae196fb1) | feat | migrate i18n inliner to oxc-parser + magic-string | +| [52ae7f862](https://github.com/angular/angular-cli/commit/52ae7f862a581cac97d5a9b33c9b71b830d95b19) | feat | share persistent build cache across git worktrees | +| [95510511d](https://github.com/angular/angular-cli/commit/95510511d963384c5a03298300246aa34a62328a) | fix | add bounded timeout to vitest executor disposal | +| [62b11e316](https://github.com/angular/angular-cli/commit/62b11e316e8248161877592acee5954b2a8c9c66) | fix | anchor debug ID comment matching and make injection idempotent | +| [6d9b360e5](https://github.com/angular/angular-cli/commit/6d9b360e5f2b7ab3d4ace4db35f674166630f658) | fix | prevent esbuild service hang on internal component stylesheet builds | +| [291caab61](https://github.com/angular/angular-cli/commit/291caab6158fa804f6221dd024a5b96e6181eaad) | fix | prevent stripping nested sourceMappingURL comments | +| [0e3ca3dfb](https://github.com/angular/angular-cli/commit/0e3ca3dfba8ef60217089d93a321660ebb6fb838) | fix | support hyphens and underscores when stripping chunk hash in chunk optimizer | +| [585d08af8](https://github.com/angular/angular-cli/commit/585d08af881a35653dc5e7b1ee7a75b42e154517) | perf | default chunk optimization to use Rolldown | +| [09d0a11a8](https://github.com/angular/angular-cli/commit/09d0a11a8b832f156aea100ad3497c5221fc0f50) | perf | enable fast-path AST printing with sourcemaps in AotCompilation | + +### @angular/ssr + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------- | +| [7ef9ed24d](https://github.com/angular/angular-cli/commit/7ef9ed24d3c111474ae21c06cb2b05a21804f586) | feat | support the standard Forwarded header | + + + + + +# 22.0.8 (2026-07-23) + +### @angular/cli + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | -------------------------------------------------------- | +| [41c356256](https://github.com/angular/angular-cli/commit/41c356256525469a41ea72896b1ddff91a4e6e55) | fix | batch Prettier invocations during migration formatting | +| [bc87c85c3](https://github.com/angular/angular-cli/commit/bc87c85c3c660e969cf77a493dc4ee58fd831214) | fix | update MCP devserver tool names to conform to spec regex | + +### @angular/build + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ----------------------------------------------------------------- | +| [5724bf632](https://github.com/angular/angular-cli/commit/5724bf632eba59eccdd941beae8aafad35ce003e) | fix | canonicalize drive letter casing for workspace root on Windows | +| [b8bdbaa1e](https://github.com/angular/angular-cli/commit/b8bdbaa1ea1c58f061580bd58c015078f57c1530) | fix | ensure import map integrity keys are valid URL-like specifiers | +| [212a7bb21](https://github.com/angular/angular-cli/commit/212a7bb21eca131f32fd7b4e7b5a9ab87f2bfded) | fix | favor istanbul coverage provider when browser testing is enabled | +| [bc760b005](https://github.com/angular/angular-cli/commit/bc760b005e0dae10a2dfd31a7f0f772482305398) | fix | preserve custom config options in runnerConfig for vitest | +| [19cda7415](https://github.com/angular/angular-cli/commit/19cda7415693f36e911a736a32576110905b6600) | fix | remap metafile paths when workspace root is a symlink or junction | +| [fdcc98c79](https://github.com/angular/angular-cli/commit/fdcc98c7912f45431268fdf66c8b132bd119bc27) | perf | skip semantic affected-file walk when type checking is disabled | @@ -85,30 +282,6 @@ - - -# 22.1.0-next.3 (2026-07-09) - -### @angular/build - -| Commit | Type | Description | -| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------------------ | -| [34d558c3c](https://github.com/angular/angular-cli/commit/34d558c3c98e1b59a2c2808fc04bfbb63dfe8acf) | feat | add built-in SQLite cache store fallback | -| [52ae7f862](https://github.com/angular/angular-cli/commit/52ae7f862a581cac97d5a9b33c9b71b830d95b19) | feat | share persistent build cache across git worktrees | -| [41bd100dd](https://github.com/angular/angular-cli/commit/41bd100dd8edebdf6c7279e1c7d3847ee5f22702) | fix | fallback to build target preserveSymlinks option in karma runner | -| [6d9b360e5](https://github.com/angular/angular-cli/commit/6d9b360e5f2b7ab3d4ace4db35f674166630f658) | fix | prevent esbuild service hang on internal component stylesheet builds | -| [85c53d990](https://github.com/angular/angular-cli/commit/85c53d9909b8bcb35a360044a0afde5352d45d72) | fix | prevent externalizing builder-injected i18n locale data | -| [004cc4104](https://github.com/angular/angular-cli/commit/004cc410487b2dbb80001f045cd19f899c980ccc) | fix | strip all vite id prefixes from minified code with external dependencies | -| [09d0a11a8](https://github.com/angular/angular-cli/commit/09d0a11a8b832f156aea100ad3497c5221fc0f50) | perf | enable fast-path AST printing with sourcemaps in AotCompilation | - -### @angular/ssr - -| Commit | Type | Description | -| --------------------------------------------------------------------------------------------------- | ---- | -------------------------------------------------------------- | -| [0bd22dae0](https://github.com/angular/angular-cli/commit/0bd22dae09a83e36ed3863ca2b050666cc8d7aec) | fix | replace all route parameters when resolving relative redirects | - - - # 22.0.6 (2026-07-08) @@ -129,47 +302,6 @@ - - -# 22.1.0-next.2 (2026-07-01) - -### @angular/cli - -| Commit | Type | Description | -| --------------------------------------------------------------------------------------------------- | ---- | ----------------------------------------------------------------- | -| [010cef665](https://github.com/angular/angular-cli/commit/010cef6657365cad8529c164d7c594ca598180a0) | fix | gracefully handle package manager errors in command handler | -| [3a2589dac](https://github.com/angular/angular-cli/commit/3a2589dac684dfe26b2151b940bd40280d7c5d8e) | fix | respect client-side release age settings during update resolution | -| [edb4594de](https://github.com/angular/angular-cli/commit/edb4594deb5ff96967c1ce13b4494e3fd675ebec) | fix | respect release age policy in update bootstrapping logic | - -### @schematics/angular - -| Commit | Type | Description | -| --------------------------------------------------------------------------------------------------- | ---- | --------------------------------- | -| [0b3172e07](https://github.com/angular/angular-cli/commit/0b3172e076b75df5b8c3066a115d1151f8b0bad9) | fix | remove unused app tsconfig outDir | - -### @angular-devkit/build-angular - -| Commit | Type | Description | -| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------ | -| [2d3eb7fb3](https://github.com/angular/angular-cli/commit/2d3eb7fb3b43b64c476296581481dbf67cb57b1d) | fix | prevent OS command injection in ssr-dev-server builder | - -### @angular/build - -| Commit | Type | Description | -| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------------------- | -| [75c1dce38](https://github.com/angular/angular-cli/commit/75c1dce387075d3ea9d6da572f7daa589856bc0e) | fix | auto-inject localize/init in library unit tests | -| [dc27e17fc](https://github.com/angular/angular-cli/commit/dc27e17fc2cbb91b10b508a7e46cd72734959ffa) | fix | inherit preserveSymlinks option from build target in unit-test builder | -| [61e25fb1d](https://github.com/angular/angular-cli/commit/61e25fb1db56694da800f330dd65cb7e50ea2d11) | fix | load zone.js dynamically for library unit tests | -| [0010b922f](https://github.com/angular/angular-cli/commit/0010b922f8fc5a9c57b9512594f9c3b4da3fa2ae) | fix | scope createRequire module resolution using paths to prevent parent paths | - -### @angular/ssr - -| Commit | Type | Description | -| --------------------------------------------------------------------------------------------------- | ---- | ----------------------------------------- | -| [d9fb854c9](https://github.com/angular/angular-cli/commit/d9fb854c9a48ba8852d57f3fa8f7a9640ee0aab2) | fix | preserve response headers during redirect | - - - # 22.0.5 (2026-07-01) @@ -247,43 +379,6 @@ - - -# 22.1.0-next.1 (2026-06-24) - -### @angular/cli - -| Commit | Type | Description | -| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------- | -| [48f90f5d5](https://github.com/angular/angular-cli/commit/48f90f5d5e5dd6369b2ccf044a722271c82dffd6) | fix | prevent Yarn registry environment variable override | -| [38e0fabc0](https://github.com/angular/angular-cli/commit/38e0fabc05eb5d622a25c68692d7d073485750e3) | fix | support registry metadata fetching under bun package manager | -| [3ce6e5fc3](https://github.com/angular/angular-cli/commit/3ce6e5fc3b4f4b5fb6ac99cc82023bf01894d14c) | perf | implement semaphore backpressure throttling in PackageManager | - -### @schematics/angular - -| Commit | Type | Description | -| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------ | -| [01008f1c6](https://github.com/angular/angular-cli/commit/01008f1c69321d0a8b5b8344672b594a68fe83b6) | fix | remove default workspace vscode mcp.json configuration | - -### @angular/build - -| Commit | Type | Description | -| --------------------------------------------------------------------------------------------------- | ---- | -------------------------------------------------------------------- | -| [851711b03](https://github.com/angular/angular-cli/commit/851711b031603293b58e33357c70eea7675452e3) | fix | aggregate parallel worker performance timings on the main thread | -| [585d08af8](https://github.com/angular/angular-cli/commit/585d08af881a35653dc5e7b1ee7a75b42e154517) | perf | default chunk optimization to use Rolldown | -| [3019c8032](https://github.com/angular/angular-cli/commit/3019c8032ba9462d0edc614940b26ade24e45ec8) | perf | dispose builder result context early in non-watch mode | -| [583736a4d](https://github.com/angular/angular-cli/commit/583736a4de8b3d0b4d79709a445809c264e38c17) | perf | implement semaphore backpressure throttling in JavaScriptTransformer | - -### @angular/ssr - -| Commit | Type | Description | -| --------------------------------------------------------------------------------------------------- | ---- | --------------------------------------------------------------------- | -| [7ef9ed24d](https://github.com/angular/angular-cli/commit/7ef9ed24d3c111474ae21c06cb2b05a21804f586) | feat | support the standard Forwarded header | -| [37f1a7491](https://github.com/angular/angular-cli/commit/37f1a749132d55a81cec231bd260ed280b10fc00) | fix | avoid caching non-SSG page lookups | -| [5875b6024](https://github.com/angular/angular-cli/commit/5875b6024ff9e59fddf7481b6b961d73ae809963) | fix | prioritize options over environment variables in AngularNodeAppEngine | - - - # 22.0.4 (2026-06-24) @@ -402,44 +497,6 @@ - - -# 22.1.0-next.0 (2026-06-11) - -## Deprecations - -### @angular-devkit/core - -- `stringToFileBuffer` and `fileBufferToString` are deprecated. Use standard Web APIs (`TextEncoder` and `TextDecoder`) instead. - - Internal usages within the repository have been removed and replaced with standard Web APIs. The public API golden file for `@angular-devkit/core` has been updated to reflect the deprecations. - -### @schematics/angular - -| Commit | Type | Description | -| --------------------------------------------------------------------------------------------------- | ---- | ----------------------------------------------------- | -| [89d7f59cd](https://github.com/angular/angular-cli/commit/89d7f59cd7cc5d821ac0e81b1fee50e27877c976) | feat | update ai-config to include Angular MCP server config | - -### @angular/cli - -| Commit | Type | Description | -| --------------------------------------------------------------------------------------------------- | ---- | -------------------------------------- | -| [7932caaf9](https://github.com/angular/angular-cli/commit/7932caaf987c5692d6624f6af23e65ce3f6d27fd) | fix | robustly parse npm manifest from array | - -### @angular-devkit/core - -| Commit | Type | Description | -| --------------------------------------------------------------------------------------------------- | -------- | --------------------------------------------------- | -| [fd336d365](https://github.com/angular/angular-cli/commit/fd336d365dbfe8f558db177a8da24790914a541b) | refactor | deprecate stringToFileBuffer and fileBufferToString | - -### @angular/ssr - -| Commit | Type | Description | -| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------------ | -| [ddcef9d48](https://github.com/angular/angular-cli/commit/ddcef9d484e205c5fcfd93d184425c1c1af19c34) | fix | correct grammar in console warning for redirected location headers | - - - # 20.3.28 (2026-06-11) diff --git a/MODULE.bazel b/MODULE.bazel index 4b82a12dc781..2dfa059ffe2d 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -7,48 +7,48 @@ module( bazel_dep(name = "platforms", version = "1.1.0") bazel_dep(name = "yq.bzl", version = "0.3.6") bazel_dep(name = "rules_nodejs", version = "6.7.5") -bazel_dep(name = "aspect_rules_js", version = "3.2.3") -bazel_dep(name = "aspect_rules_ts", version = "3.9.2") -bazel_dep(name = "rules_pkg", version = "1.2.0") +bazel_dep(name = "aspect_rules_js", version = "3.4.1") +bazel_dep(name = "aspect_rules_ts", version = "3.10.1") +bazel_dep(name = "rules_pkg", version = "1.3.0") bazel_dep(name = "rules_cc", version = "0.2.22") bazel_dep(name = "jq.bzl", version = "0.6.1") -bazel_dep(name = "bazel_lib", version = "3.5.0") -bazel_dep(name = "bazel_skylib", version = "1.9.0") -bazel_dep(name = "aspect_rules_esbuild", version = "0.26.0") +bazel_dep(name = "bazel_lib", version = "3.7.1") +bazel_dep(name = "bazel_skylib", version = "1.9.2") +bazel_dep(name = "aspect_rules_esbuild", version = "0.27.0") bazel_dep(name = "aspect_rules_jasmine", version = "2.0.4") bazel_dep(name = "rules_angular") git_override( module_name = "rules_angular", - commit = "db445dccfe48aad20be6ee3df456df91660ff217", + commit = "ed98d720477b10c13f3d0ccee72f929c777f6ccd", remote = "https://github.com/angular/rules_angular.git", ) bazel_dep(name = "devinfra") git_override( module_name = "devinfra", - commit = "daa0b5ecd15668d12163f70d4c9836ada70808c9", + commit = "fa43fd2864c3bec677cd47f4e095370850cdf8bc", remote = "https://github.com/angular/dev-infra.git", ) bazel_dep(name = "rules_browsers") git_override( module_name = "rules_browsers", - commit = "3a6bd40f9be945dc51c976a21424c656448f9b09", + commit = "c6cb5590120af8ae8125343f9fc522b7b66eb0e8", remote = "https://github.com/angular/rules_browsers.git", ) node = use_extension("@rules_nodejs//nodejs:extensions.bzl", "node") node.toolchain( node_repositories = { - "22.23.1-darwin_arm64": ("node-v22.23.1-darwin-arm64.tar.gz", "node-v22.23.1-darwin-arm64", "ef28d8fab2c0e4314522d4bb1b7173270aa3937e93b92cb7de79c112ac1fa953"), - "22.23.1-darwin_amd64": ("node-v22.23.1-darwin-x64.tar.gz", "node-v22.23.1-darwin-x64", "b8da981b8a0b1241b70249204916da76c63573ddf5814dbd2d1e41069105cb81"), - "22.23.1-linux_arm64": ("node-v22.23.1-linux-arm64.tar.xz", "node-v22.23.1-linux-arm64", "0294e8b915ab75f92c7513d2fcb830ae06e10684e6c603e99a87dbf8835389c1"), - "22.23.1-linux_ppc64le": ("node-v22.23.1-linux-ppc64le.tar.xz", "node-v22.23.1-linux-ppc64le", "a645bcb7bbc498d09ba9249b5c6414aa6d0a461d8854afc61e32096646ba5e66"), - "22.23.1-linux_s390x": ("node-v22.23.1-linux-s390x.tar.xz", "node-v22.23.1-linux-s390x", "f16b5636ba925b462e627c5e0ef47de3255bf4a7b38d56db58e2cf165df19c3c"), - "22.23.1-linux_amd64": ("node-v22.23.1-linux-x64.tar.xz", "node-v22.23.1-linux-x64", "9749e988f437343b7fa832c69ded82a312e41a03116d766797ac14f6f9eee578"), - "22.23.1-windows_amd64": ("node-v22.23.1-win-x64.zip", "node-v22.23.1-win-x64", "7df0bc9375723f4a86b3aa1b7cc73342423d9677a8df4538aca31a049e309c29"), + "22.23.2-darwin_arm64": ("node-v22.23.2-darwin-arm64.tar.gz", "node-v22.23.2-darwin-arm64", "61130f394c1630d211dd50aecc4353d379480f36d3ac913cd85dbba1aed585c6"), + "22.23.2-darwin_amd64": ("node-v22.23.2-darwin-x64.tar.gz", "node-v22.23.2-darwin-x64", "58e99022c2ff89395576cc7fd4d98cea24bb68081475d5f88b801ee8729fb026"), + "22.23.2-linux_arm64": ("node-v22.23.2-linux-arm64.tar.xz", "node-v22.23.2-linux-arm64", "fff4078c5def658577f92c88db7db3bc0072924bfb93fe52c1e744a54e94abb8"), + "22.23.2-linux_ppc64le": ("node-v22.23.2-linux-ppc64le.tar.xz", "node-v22.23.2-linux-ppc64le", "e2ba10110ad34096c051fe47134fcd12175ecc48e7e879d7d4c78b70cf66442c"), + "22.23.2-linux_s390x": ("node-v22.23.2-linux-s390x.tar.xz", "node-v22.23.2-linux-s390x", "50aa0935c7caee2f95434f84c2c19f16e4f223257eadb341a3a2d5aaa545bbe6"), + "22.23.2-linux_amd64": ("node-v22.23.2-linux-x64.tar.xz", "node-v22.23.2-linux-x64", "d60acfe00a2932254bb0ad20e01b0d74397a0875595de719654b214f4b03f307"), + "22.23.2-windows_amd64": ("node-v22.23.2-win-x64.zip", "node-v22.23.2-win-x64", "1177b4137ba5adaa56354ae40f1080c7450e8ae09cecb47da459d1c52ac99f97"), }, - node_version = "22.23.1", + node_version = "22.23.2", ) use_repo( node, @@ -131,8 +131,8 @@ use_repo( pnpm = use_extension("@aspect_rules_js//npm:extensions.bzl", "pnpm") pnpm.pnpm( name = "pnpm", - pnpm_version = "11.15.1", - pnpm_version_integrity = "sha512-gTULB+U8lTigLx8jA7QpD6LXvgTlbiqXDEzEtBfcdh3hlu2r1J1Vx9yVgNuBAHxEFD5OPX5GKzAA0jwlUSLQZQ==", + pnpm_version = "11.24.0", + pnpm_version_integrity = "sha512-vSfjRel23LC+C3oSKCF7BJqBfiGx81XJDb59xGZxiVqLwebQbCRVRQXqk+oLRfSJon7Bv7yN5qlln8oPFvoAAA==", ) use_repo(pnpm, "pnpm") diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index eb446604633b..780cef563755 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -18,20 +18,22 @@ "https://bcr.bazel.build/modules/aspect_bazel_lib/2.22.5/source.json": "ac2c3213df8f985785f1d0aeb7f0f73d5324e6e67d593d9b9470fb74a25d4a9b", "https://bcr.bazel.build/modules/aspect_bazel_lib/2.7.7/MODULE.bazel": "491f8681205e31bb57892d67442ce448cda4f472a8e6b3dc062865e29a64f89c", "https://bcr.bazel.build/modules/aspect_bazel_lib/2.8.1/MODULE.bazel": "812d2dd42f65dca362152101fbec418029cc8fd34cbad1a2fde905383d705838", - "https://bcr.bazel.build/modules/aspect_rules_esbuild/0.26.0/MODULE.bazel": "6c902d97038c3ab07b6c4e67c97abc61b20182fcfa84fa7dee82fc724f12e455", - "https://bcr.bazel.build/modules/aspect_rules_esbuild/0.26.0/source.json": "4cc3ece7ab661bb391a9e24fe55c4b567d60a9ea9d9e91d772dad373cbcb6217", + "https://bcr.bazel.build/modules/aspect_rules_esbuild/0.27.0/MODULE.bazel": "877dafc0b925f8af19e8bc2abed04a757bb565c57c1866e8851ac4d15ed5e6d2", + "https://bcr.bazel.build/modules/aspect_rules_esbuild/0.27.0/source.json": "21f8738b3e62310ef43b7cef4284e1bafd69bd8e4e50251b71b20bbfed4372d8", "https://bcr.bazel.build/modules/aspect_rules_jasmine/2.0.4/MODULE.bazel": "fbb819eb8b7e5d7f67fdd38f7cecb413e287594cd666ce192c72c8828527775a", "https://bcr.bazel.build/modules/aspect_rules_jasmine/2.0.4/source.json": "81ffb708333cd98ec3c0b4cc004f4d5cf92a16914b5196a2892c45141bba7cff", "https://bcr.bazel.build/modules/aspect_rules_js/2.0.0/MODULE.bazel": "b45b507574aa60a92796e3e13c195cd5744b3b8aff516a9c0cb5ae6a048161c5", - "https://bcr.bazel.build/modules/aspect_rules_js/3.0.3/MODULE.bazel": "28a30e8fc33bf64a67835d64d124f6e05a7d59648dcb27b110fb3502f761e503", - "https://bcr.bazel.build/modules/aspect_rules_js/3.2.3/MODULE.bazel": "3a0363a5b8ec4931488dc327c577a78c1f5a725293ebffaa5d2613283701aa8a", - "https://bcr.bazel.build/modules/aspect_rules_js/3.2.3/source.json": "fa3187962f5fdeee0c6226792904aaafb2cf585717a264fa4393a767bffb99fe", - "https://bcr.bazel.build/modules/aspect_rules_ts/3.9.2/MODULE.bazel": "feeb6c45b69c995eca3e5ca5872658c80df658022e01044eca00cf472bb89142", - "https://bcr.bazel.build/modules/aspect_rules_ts/3.9.2/source.json": "cf3075502f798f71a9c5707a7684eaf0b86da11ed440fd90ea34385dc297676a", + "https://bcr.bazel.build/modules/aspect_rules_js/3.4.0/MODULE.bazel": "88844ac411e1961f4574a92f3c5be5b20d1c6997778c6b88316c5c3b4b60e284", + "https://bcr.bazel.build/modules/aspect_rules_js/3.4.1/MODULE.bazel": "e46853c134b48bc84c9bb5c4a4c8ae792dcfd5277acac9d90c444d65fa43dd19", + "https://bcr.bazel.build/modules/aspect_rules_js/3.4.1/source.json": "b11f550b53d451800ebd0b4f38a048aea33fbfbd78fb5c77dca847f6b9b47a3b", + "https://bcr.bazel.build/modules/aspect_rules_ts/3.10.0/MODULE.bazel": "69d06f57f30f4a2b6e53471584a9559d3b7cd7f891e1699876991230c7cabb95", + "https://bcr.bazel.build/modules/aspect_rules_ts/3.10.1/MODULE.bazel": "035205a7834b0ed9724ed3c4790e12d1c779ef2520d72496ab234e6307715e6c", + "https://bcr.bazel.build/modules/aspect_rules_ts/3.10.1/source.json": "d42b6560206adb5524caad2abc40ae0b5b34478dd38184a9f6ea4a5fed848cd6", "https://bcr.bazel.build/modules/aspect_tools_telemetry/0.2.8/MODULE.bazel": "aa975a83e72bcaac62ee61ab12b788ea324a1d05c4aab28aadb202f647881679", "https://bcr.bazel.build/modules/aspect_tools_telemetry/0.3.3/MODULE.bazel": "37c764292861c2f70314efa9846bb6dbb44fc0308903b3285da6528305450183", "https://bcr.bazel.build/modules/aspect_tools_telemetry/0.4.2/MODULE.bazel": "f31aa84151d31e98cffd43eb7217ccff5ec52bdd5f2d10db8f053aeb23342eca", - "https://bcr.bazel.build/modules/aspect_tools_telemetry/0.4.2/source.json": "d027d264e6b6e7fc421e38189f4374fcd14a67e0bd6e0e705de8c2185c3787e1", + "https://bcr.bazel.build/modules/aspect_tools_telemetry/0.5.1/MODULE.bazel": "9d94e5c22c0019995c0a3216a6abb1717dc3f35acccf4e6267a55d6df38367aa", + "https://bcr.bazel.build/modules/aspect_tools_telemetry/0.5.1/source.json": "dbe0a75bf1f741b18c7b72dd4d205fa5a45c8c135fee15f7fdd1a2b50ba0fdde", "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8", "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d", @@ -51,9 +53,9 @@ "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", "https://bcr.bazel.build/modules/bazel_lib/3.0.0-rc.0/MODULE.bazel": "d6e00979a98ac14ada5e31c8794708b41434d461e7e7ca39b59b765e6d233b18", "https://bcr.bazel.build/modules/bazel_lib/3.0.0/MODULE.bazel": "22b70b80ac89ad3f3772526cd9feee2fa412c2b01933fea7ed13238a448d370d", - "https://bcr.bazel.build/modules/bazel_lib/3.2.2/MODULE.bazel": "e2c890c8a515d6bca9c66d47718aa9e44b458fde64ec7204b8030bf2d349058c", - "https://bcr.bazel.build/modules/bazel_lib/3.5.0/MODULE.bazel": "1eba0ba67d418d99fb682c36147a9e1725abbc8fc25544be64702e32eda2be29", - "https://bcr.bazel.build/modules/bazel_lib/3.5.0/source.json": "98d49ec7e2b15298c990f09ec8cdea8d4788c2885497aa9cbb0a74e36e994df8", + "https://bcr.bazel.build/modules/bazel_lib/3.7.0/MODULE.bazel": "d7c10ed67f0f7f1fda179db8f86c22642581bd614882e1a50545fbe069525173", + "https://bcr.bazel.build/modules/bazel_lib/3.7.1/MODULE.bazel": "b6fd9b2f8fab956420c11836f416efac4a70e20804ae384ebe62773a4ed70046", + "https://bcr.bazel.build/modules/bazel_lib/3.7.1/source.json": "635fdaa28b50c04febc5e60ef51bc913d3bc87bfbaac7045449273c2341648cb", "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e", "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686", @@ -69,7 +71,8 @@ "https://bcr.bazel.build/modules/bazel_skylib/1.8.1/MODULE.bazel": "88ade7293becda963e0e3ea33e7d54d3425127e0a326e0d17da085a5f1f03ff6", "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/MODULE.bazel": "69ad6927098316848b34a9142bcc975e018ba27f08c4ff403f50c1b6e646ca67", "https://bcr.bazel.build/modules/bazel_skylib/1.9.0/MODULE.bazel": "72997b29dfd95c3fa0d0c48322d05590418edef451f8db8db5509c57875fb4b7", - "https://bcr.bazel.build/modules/bazel_skylib/1.9.0/source.json": "7ad77c1e8c1b84222d9b3f3cae016a76639435744c19330b0b37c0a3c9da7dc0", + "https://bcr.bazel.build/modules/bazel_skylib/1.9.2/MODULE.bazel": "8c51259b0f4481475586dbfede7591e57b75702e637f840f6138eec80c34b270", + "https://bcr.bazel.build/modules/bazel_skylib/1.9.2/source.json": "41cbde7546542dee2f26e3f10bf1c4ac57909943194b7ac48cc5238a01893aa8", "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84", "https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8", "https://bcr.bazel.build/modules/gawk/5.3.2.bcr.1/MODULE.bazel": "cdf8cbe5ee750db04b78878c9633cc76e80dcf4416cbe982ac3a9222f80713c8", @@ -170,8 +173,8 @@ "https://bcr.bazel.build/modules/rules_nodejs/6.7.5/source.json": "d60ee5a76258b1c8f99545ed24172b44d43ba64ca1a2dfc04371ef203df19fdf", "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc", "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff", - "https://bcr.bazel.build/modules/rules_pkg/1.2.0/MODULE.bazel": "c7db3c2b407e673c7a39e3625dc05dc9f12d6682cbd82a3a5924a13b491eda7e", - "https://bcr.bazel.build/modules/rules_pkg/1.2.0/source.json": "9062e00845bf91a4247465d371baa837adf9b6ff44c542f73ba084f07667e1dc", + "https://bcr.bazel.build/modules/rules_pkg/1.3.0/MODULE.bazel": "ae0bdefbacc990c91f843206c90cf0f4be620639a5bf22119043599ba86d51a3", + "https://bcr.bazel.build/modules/rules_pkg/1.3.0/source.json": "58ae84c545141762f7c434c0ce78bfb55ef0be08d84863e7f0503fff135fe4e2", "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06", "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7", "https://bcr.bazel.build/modules/rules_proto/6.0.0/MODULE.bazel": "b531d7f09f58dce456cd61b4579ce8c86b38544da75184eadaf0a7cb7966453f", @@ -185,7 +188,6 @@ "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58", "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", "https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7", - "https://bcr.bazel.build/modules/rules_python/1.0.0/MODULE.bazel": "898a3d999c22caa585eb062b600f88654bf92efb204fa346fb55f6f8edffca43", "https://bcr.bazel.build/modules/rules_python/1.7.0/MODULE.bazel": "d01f995ecd137abf30238ad9ce97f8fc3ac57289c8b24bd0bf53324d937a14f8", "https://bcr.bazel.build/modules/rules_python/1.7.0/source.json": "028a084b65dcf8f4dc4f82f8778dbe65df133f234b316828a82e060d81bdce32", "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c", @@ -201,14 +203,12 @@ "https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5", "https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216", "https://bcr.bazel.build/modules/tar.bzl/0.10.4/MODULE.bazel": "e8f9ff79199e8d9eaad7f1b0a77ad74b30bb82d794b87d8ca942bead5de83ae9", - "https://bcr.bazel.build/modules/tar.bzl/0.10.7/MODULE.bazel": "e06d0072c8adef7b9efbeec951d7e6b4b7e6bfa5845c3d8f402289c7b5d6331c", - "https://bcr.bazel.build/modules/tar.bzl/0.10.7/source.json": "c660155f239fcfadfb85f0b9ff304b95390632c15e3f6cb718cd3e08f2bb5c86", + "https://bcr.bazel.build/modules/tar.bzl/0.10.8/MODULE.bazel": "443884cabe241f640cfef256b1de2ccb116752895532900a4be9500e1124323f", + "https://bcr.bazel.build/modules/tar.bzl/0.10.8/source.json": "4173be64b38e471d92d2eb139a6496311de6de75e710f04edce78c43122c5419", "https://bcr.bazel.build/modules/tar.bzl/0.2.1/MODULE.bazel": "52d1c00a80a8cc67acbd01649e83d8dd6a9dc426a6c0b754a04fe8c219c76468", "https://bcr.bazel.build/modules/tar.bzl/0.5.1/MODULE.bazel": "7c2eb3dcfc53b0f3d6f9acdfd911ca803eaf92aadf54f8ca6e4c1f3aee288351", - "https://bcr.bazel.build/modules/tar.bzl/0.6.0/MODULE.bazel": "a3584b4edcfafcabd9b0ef9819808f05b372957bbdff41601429d5fd0aac2e7c", "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", "https://bcr.bazel.build/modules/yq.bzl/0.1.1/MODULE.bazel": "9039681f9bcb8958ee2c87ffc74bdafba9f4369096a2b5634b88abc0eaefa072", - "https://bcr.bazel.build/modules/yq.bzl/0.3.2/MODULE.bazel": "0384efa70e8033d842ea73aa4b7199fa099709e236a7264345c03937166670b6", "https://bcr.bazel.build/modules/yq.bzl/0.3.4/MODULE.bazel": "d3a270662f5d766cd7229732d65a5a5bc485240c3007343dd279edfb60c9ae27", "https://bcr.bazel.build/modules/yq.bzl/0.3.6/MODULE.bazel": "985c2a0cb4ad9994bb0e33cc7fae931c91105eeefe3faa355b8f4c258d0607c0", "https://bcr.bazel.build/modules/yq.bzl/0.3.6/source.json": "678aaf6e291164f3cd761bb3e872e8a151248f413dbb63c5524a50b82a5bc890", @@ -222,8 +222,8 @@ "moduleExtensions": { "@@aspect_rules_esbuild+//esbuild:extensions.bzl%esbuild": { "general": { - "bzlTransitiveDigest": "DE8ssop85SA4kEHMbyc2ajgEW3TNsQFbT4L6IfuwTZo=", - "usagesDigest": "LSQ+zZp7JNgnBONTxxXnwGr4NTh2qtQYk7qwXXz5qWo=", + "bzlTransitiveDigest": "yziqvbws9noFTds23HE5koMAI5QqGgQ7qmxOQkVtiw4=", + "usagesDigest": "LZ71sshnfqI8R/HeWwBTwawxIa7KnitayBl2hYrqPo4=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, @@ -437,8 +437,8 @@ }, "@@aspect_tools_telemetry+//:extension.bzl%telemetry": { "general": { - "bzlTransitiveDigest": "4w9RM0xjdKo1crk5zL20a/TuhqO0P1z1LsuXDneBXD4=", - "usagesDigest": "hqK7Zzp+y5jlPhecF8Z77KSrR9zpTS+H88Epy3pRc/s=", + "bzlTransitiveDigest": "zFgbaCUuPzH6bIE7CBHBVCqjWSJ78/WNXisdzXaKSnU=", + "usagesDigest": "2cLMn8ZcqY/6j/zH70TrPob+ENshTw9h48kUHxn1cUM=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": { @@ -449,13 +449,13 @@ "repoRuleId": "@@aspect_tools_telemetry+//:extension.bzl%tel_repository", "attributes": { "deps": { - "aspect_rules_js": "3.2.3", - "aspect_rules_ts": "3.9.2", - "aspect_rules_esbuild": "0.26.0", + "aspect_rules_js": "3.4.1", + "aspect_rules_ts": "3.10.1", + "aspect_rules_esbuild": "0.27.0", "aspect_rules_jasmine": "2.0.4", - "aspect_tools_telemetry": "0.4.2" + "aspect_tools_telemetry": "0.5.1" }, - "last_notice": 0 + "last_notice": 1 } } }, @@ -539,7 +539,7 @@ }, "@@rules_browsers+//browsers:extensions.bzl%browsers": { "general": { - "bzlTransitiveDigest": "3W9m9j39szqkOoSVVqamCaSwCCw7x5Wq1kcYTwYBNOc=", + "bzlTransitiveDigest": "85AglD+Q1+ncEIApuW5Ng/2cY4OkSMPrOZ05Jp4CTmk=", "usagesDigest": "FmXYJVoVJlnfUU8x8gObSvu4qWcco/9Faw61aC/wBF0=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, @@ -548,9 +548,9 @@ "rules_browsers_chrome_linux": { "repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo", "attributes": { - "sha256": "13d6638183ccab406ee16e28730826bd3ea57fe564a741bc935401221dfec64f", + "sha256": "1a20882bf1a4f9d1167171b6905efe359bb229be1ce636ae9c931f3d285fbabe", "urls": [ - "https://storage.googleapis.com/chrome-for-testing-public/152.0.7960.0/linux64/chrome-headless-shell-linux64.zip" + "https://storage.googleapis.com/chrome-for-testing-public/154.0.8013.0/linux64/chrome-headless-shell-linux64.zip" ], "named_files": { "CHROME-HEADLESS-SHELL": "chrome-headless-shell-linux64/chrome-headless-shell" @@ -566,9 +566,9 @@ "rules_browsers_chrome_mac": { "repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo", "attributes": { - "sha256": "b50ee6ddb3bf30c91f3094fa41cc8e8de60e317c63ef058db2375346cde78d98", + "sha256": "1b0e0a078fc62c2b9f8cf837d41461084bd4064cf50cfc15ff84447a1f1b8dab", "urls": [ - "https://storage.googleapis.com/chrome-for-testing-public/152.0.7960.0/mac-x64/chrome-headless-shell-mac-x64.zip" + "https://storage.googleapis.com/chrome-for-testing-public/154.0.8013.0/mac-x64/chrome-headless-shell-mac-x64.zip" ], "named_files": { "CHROME-HEADLESS-SHELL": "chrome-headless-shell-mac-x64/chrome-headless-shell" @@ -584,9 +584,9 @@ "rules_browsers_chrome_mac_arm": { "repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo", "attributes": { - "sha256": "49859c1d3b0d29a82c58765e9e5fe21efa0bf7c03a86fc91eb5f3f94f34c45b6", + "sha256": "7438714da3696778b697b277a2df1d9701b99819ae58f5ab809b1009933677ec", "urls": [ - "https://storage.googleapis.com/chrome-for-testing-public/152.0.7960.0/mac-arm64/chrome-headless-shell-mac-arm64.zip" + "https://storage.googleapis.com/chrome-for-testing-public/154.0.8013.0/mac-arm64/chrome-headless-shell-mac-arm64.zip" ], "named_files": { "CHROME-HEADLESS-SHELL": "chrome-headless-shell-mac-arm64/chrome-headless-shell" @@ -602,9 +602,9 @@ "rules_browsers_chrome_win64": { "repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo", "attributes": { - "sha256": "d161d88a999effd212ce87df2ff710be1a25a495cc428d4c3029feccd02dafe9", + "sha256": "4349c800be1f063adc0f1a7e820d024b43ea73917a6893a3f6b3797a5200d49b", "urls": [ - "https://storage.googleapis.com/chrome-for-testing-public/152.0.7960.0/win64/chrome-headless-shell-win64.zip" + "https://storage.googleapis.com/chrome-for-testing-public/154.0.8013.0/win64/chrome-headless-shell-win64.zip" ], "named_files": { "CHROME-HEADLESS-SHELL": "chrome-headless-shell-win64/chrome-headless-shell.exe" @@ -620,9 +620,9 @@ "rules_browsers_chromedriver_linux": { "repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo", "attributes": { - "sha256": "7bb2eedf7030523ba617704bf6c3e472b5974d048d7fa6ac6a764904556c6f36", + "sha256": "d275f01236831bd44c6b6712ba5bec0a028b1ce9473a6182aceae6657740a3d3", "urls": [ - "https://storage.googleapis.com/chrome-for-testing-public/152.0.7960.0/linux64/chromedriver-linux64.zip" + "https://storage.googleapis.com/chrome-for-testing-public/154.0.8013.0/linux64/chromedriver-linux64.zip" ], "named_files": { "CHROMEDRIVER": "chromedriver-linux64/chromedriver" @@ -636,9 +636,9 @@ "rules_browsers_chromedriver_mac": { "repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo", "attributes": { - "sha256": "5c1fffef90ecea2bb0c12c5a9c0549116fc7acda13cce15881da4aa8b74e6794", + "sha256": "cb331889191aa8ab11be6d5a3cc4de760f8cf63dbea5d1f22c80cf16ae68e46f", "urls": [ - "https://storage.googleapis.com/chrome-for-testing-public/152.0.7960.0/mac-x64/chromedriver-mac-x64.zip" + "https://storage.googleapis.com/chrome-for-testing-public/154.0.8013.0/mac-x64/chromedriver-mac-x64.zip" ], "named_files": { "CHROMEDRIVER": "chromedriver-mac-x64/chromedriver" @@ -652,9 +652,9 @@ "rules_browsers_chromedriver_mac_arm": { "repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo", "attributes": { - "sha256": "a33d54c99a50fef25cbedb7c3d3cdd838dd784556138648bcc5da5814109a306", + "sha256": "1584dc9ae35f4a22c4ba4b142335d91d6d3096813395d3acaf135fb6e716ce8e", "urls": [ - "https://storage.googleapis.com/chrome-for-testing-public/152.0.7960.0/mac-arm64/chromedriver-mac-arm64.zip" + "https://storage.googleapis.com/chrome-for-testing-public/154.0.8013.0/mac-arm64/chromedriver-mac-arm64.zip" ], "named_files": { "CHROMEDRIVER": "chromedriver-mac-arm64/chromedriver" @@ -668,9 +668,9 @@ "rules_browsers_chromedriver_win64": { "repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo", "attributes": { - "sha256": "2673d6a87dabd50c516d4d69b4daf742ff6169877c04bb226971503012262d8c", + "sha256": "061b4d1be9eb2a11ed036b3e562b565ebfd257fcd7cda3681a58e63bff5dd6d0", "urls": [ - "https://storage.googleapis.com/chrome-for-testing-public/152.0.7960.0/win64/chromedriver-win64.zip" + "https://storage.googleapis.com/chrome-for-testing-public/154.0.8013.0/win64/chromedriver-win64.zip" ], "named_files": { "CHROMEDRIVER": "chromedriver-win64/chromedriver.exe" @@ -684,9 +684,9 @@ "rules_browsers_firefox_linux": { "repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo", "attributes": { - "sha256": "748704b06ffaabc8bd2b3351c93c244db4e29bfe21af6ecb4d6c124c7bd4a234", + "sha256": "7665cd49ab13417270748325838e565136adbc76d41bbd76fb24d15a0cc7792b", "urls": [ - "https://archive.mozilla.org/pub/firefox/releases/152.0/linux-x86_64/en-US/firefox-152.0.tar.xz" + "https://archive.mozilla.org/pub/firefox/releases/154.0/linux-x86_64/en-US/firefox-154.0.tar.xz" ], "named_files": { "FIREFOX": "firefox/firefox" @@ -700,9 +700,9 @@ "rules_browsers_firefox_mac": { "repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo", "attributes": { - "sha256": "b8a46188850d2fb32f16ad3c0829b08cd689bc714b8ee18fd9b09bb60629004d", + "sha256": "b0295d3b77ec632a60282cf2b9770e1dada085879d00e43d8d23fddf5015e06a", "urls": [ - "https://archive.mozilla.org/pub/firefox/releases/152.0/mac/en-US/Firefox%20152.0.dmg" + "https://archive.mozilla.org/pub/firefox/releases/154.0/mac/en-US/Firefox%20154.0.dmg" ], "named_files": { "FIREFOX": "Firefox.app/Contents/MacOS/firefox" @@ -716,9 +716,9 @@ "rules_browsers_firefox_mac_arm": { "repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo", "attributes": { - "sha256": "b8a46188850d2fb32f16ad3c0829b08cd689bc714b8ee18fd9b09bb60629004d", + "sha256": "b0295d3b77ec632a60282cf2b9770e1dada085879d00e43d8d23fddf5015e06a", "urls": [ - "https://archive.mozilla.org/pub/firefox/releases/152.0/mac/en-US/Firefox%20152.0.dmg" + "https://archive.mozilla.org/pub/firefox/releases/154.0/mac/en-US/Firefox%20154.0.dmg" ], "named_files": { "FIREFOX": "Firefox.app/Contents/MacOS/firefox" @@ -732,9 +732,9 @@ "rules_browsers_firefox_win64": { "repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo", "attributes": { - "sha256": "3c426623ff83cb014402607c7ec99fea5b39eec2e44a07f639680c393ff9784e", + "sha256": "6b3c996d27b50dca8e5b6dd2956233cc6bf4720cea3f0847a9423c2cd6759e73", "urls": [ - "https://archive.mozilla.org/pub/firefox/releases/152.0/win64/en-US/Firefox%20Setup%20152.0.exe" + "https://archive.mozilla.org/pub/firefox/releases/154.0/win64/en-US/Firefox%20Setup%20154.0.exe" ], "named_files": { "FIREFOX": "core/firefox.exe" @@ -1175,7 +1175,7 @@ "@@yq.bzl+//yq:extensions.bzl%yq": { "general": { "bzlTransitiveDigest": "UfFMy8CWK4/dVo/tfaSAIYUiDGNAPes5eRllx9O9Q9Q=", - "usagesDigest": "Sllnnruao+9gE+ivwtmfqL78yZPGXm4HVMOBoVEIW0U=", + "usagesDigest": "eEOK0cJsj9/GBF2ShPyWYqgDUBnB4T9UVZlCprAY7Iw=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, @@ -1256,7 +1256,7 @@ }, "facts": { "@@aspect_tools_telemetry+//:extension.bzl%telemetry": { - "notice_version": "1" + "notice_version": "2" } } } diff --git a/constants.bzl b/constants.bzl index 6987637a4442..88f85d3477b0 100644 --- a/constants.bzl +++ b/constants.bzl @@ -3,10 +3,10 @@ RELEASE_ENGINES_NODE = "^22.22.3 || ^24.15.0 || >=26.0.0" RELEASE_ENGINES_NPM = "^6.11.0 || ^7.5.6 || >=8.0.0" RELEASE_ENGINES_YARN = ">= 1.13.0" -NG_PACKAGR_VERSION = "^22.1.0-next.0" -ANGULAR_FW_VERSION = "^22.1.0-next.0" -ANGULAR_FW_PEER_DEP = "^22.0.0 || ^22.1.0-next.0" -NG_PACKAGR_PEER_DEP = "^22.0.0 || ^22.1.0-next.0" +NG_PACKAGR_VERSION = "^22.1.0" +ANGULAR_FW_VERSION = "^22.1.0" +ANGULAR_FW_PEER_DEP = "^22.0.0" +NG_PACKAGR_PEER_DEP = "^22.0.0" # Baseline widely-available date in `YYYY-MM-DD` format which defines Angular's # browser support. This date serves as the source of truth for the Angular CLI's diff --git a/goldens/public-api/angular/build/index.api.md b/goldens/public-api/angular/build/index.api.md index 3c0b9bd67c53..c9d83bc6fd9b 100644 --- a/goldens/public-api/angular/build/index.api.md +++ b/goldens/public-api/angular/build/index.api.md @@ -243,6 +243,7 @@ export type UnitTestBuilderOptions = { runner?: Runner; runnerConfig?: RunnerConfig; setupFiles?: string[]; + splitting?: boolean; tsConfig?: string; ui?: boolean; watch?: boolean; diff --git a/modules/testing/builder/package.json b/modules/testing/builder/package.json index 9aede9dc7d10..048981abdc06 100644 --- a/modules/testing/builder/package.json +++ b/modules/testing/builder/package.json @@ -8,7 +8,7 @@ "browser-sync": "3.0.4", "istanbul-lib-instrument": "6.0.3", "jsdom": "29.1.1", - "ng-packagr": "22.1.0-next.3", + "ng-packagr": "22.1.1", "rxjs": "7.8.2", "vitest": "4.1.10" } diff --git a/package.json b/package.json index f67f33227c76..ec833bf1c173 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@angular/devkit-repo", - "version": "22.1.0-next.4", + "version": "22.1.6", "private": true, "description": "Software Development Kit for Angular", "keywords": [ @@ -28,12 +28,12 @@ "type": "git", "url": "git+https://github.com/angular/angular-cli.git" }, - "packageManager": "pnpm@11.15.1", + "packageManager": "pnpm@11.24.0", "engines": { "node": "^22.22.3 || ^24.15.0 || >=26.0.0", "npm": "Please use pnpm instead of NPM to install dependencies", "yarn": "Please use pnpm instead of Yarn to install dependencies", - "pnpm": "11.15.1" + "pnpm": "11.24.0" }, "author": "Angular Authors", "license": "MIT", @@ -42,23 +42,23 @@ }, "homepage": "https://github.com/angular/angular-cli", "dependencies": { - "@angular/compiler-cli": "22.1.0-rc.0", + "@angular/compiler-cli": "22.1.4", "typescript": "6.0.3" }, "devDependencies": { - "@angular/animations": "22.1.0-rc.0", - "@angular/cdk": "22.1.0-next.4", - "@angular/common": "22.1.0-rc.0", - "@angular/compiler": "22.1.0-rc.0", - "@angular/core": "22.1.0-rc.0", - "@angular/forms": "22.1.0-rc.0", - "@angular/localize": "22.1.0-rc.0", - "@angular/material": "22.1.0-next.4", - "@angular/ng-dev": "https://github.com/angular/dev-infra-private-ng-dev-builds.git#7a67d5221a9efec2b69b102759d04223a3fc8552", - "@angular/platform-browser": "22.1.0-rc.0", - "@angular/platform-server": "22.1.0-rc.0", - "@angular/router": "22.1.0-rc.0", - "@angular/service-worker": "22.1.0-rc.0", + "@angular/animations": "22.1.4", + "@angular/cdk": "22.1.4", + "@angular/common": "22.1.4", + "@angular/compiler": "22.1.4", + "@angular/core": "22.1.4", + "@angular/forms": "22.1.4", + "@angular/localize": "22.1.4", + "@angular/material": "22.1.4", + "@angular/ng-dev": "https://github.com/angular/dev-infra-private-ng-dev-builds.git#beec8fe17573a33c9934487ce99ce9cce3e3f6bf", + "@angular/platform-browser": "22.1.4", + "@angular/platform-server": "22.1.4", + "@angular/router": "22.1.4", + "@angular/service-worker": "22.1.4", "@babel/core": "8.0.1", "@bazel/bazelisk": "1.28.1", "@bazel/buildifier": "8.2.1", @@ -96,8 +96,8 @@ "@typescript-eslint/parser": "8.64.0", "ajv": "8.20.0", "buffer": "6.0.3", - "esbuild": "0.28.1", - "esbuild-wasm": "0.28.1", + "esbuild": "0.28.2", + "esbuild-wasm": "0.28.2", "eslint": "10.7.0", "eslint-config-prettier": "10.1.8", "eslint-plugin-import": "2.32.0", diff --git a/packages/angular/build/BUILD.bazel b/packages/angular/build/BUILD.bazel index 7325ec88d35b..5a6f811e3ee5 100644 --- a/packages/angular/build/BUILD.bazel +++ b/packages/angular/build/BUILD.bazel @@ -338,7 +338,7 @@ npm_package( ], stamp_files = [ "src/utils/version.js", - "src/tools/esbuild/utils.js", + "src/tools/esbuild/target.js", "src/utils/normalize-cache.js", "src/utils/supported-browsers.js", ], diff --git a/packages/angular/build/package.json b/packages/angular/build/package.json index a049f92d4a73..b1cb07d7db7b 100644 --- a/packages/angular/build/package.json +++ b/packages/angular/build/package.json @@ -27,13 +27,13 @@ "@vitejs/plugin-basic-ssl": "2.3.0", "beasties": "0.4.3", "browserslist": "^4.26.0", - "esbuild": "0.28.1", + "esbuild": "0.28.2", "https-proxy-agent": "9.1.0", "jsonc-parser": "3.3.1", - "listr2": "10.2.2", + "listr2": "11.0.0", "magic-string": "1.0.0", "mrmime": "2.0.1", - "oxc-parser": "0.140.0", + "oxc-parser": "0.142.0", "parse5-html-rewriting-stream": "8.0.1", "picomatch": "4.0.5", "piscina": "5.2.0", @@ -54,9 +54,9 @@ "@oxc-project/types": "0.140.0", "istanbul-lib-instrument": "6.0.3", "jsdom": "29.1.1", - "less": "4.6.7", - "ng-packagr": "22.1.0-next.3", - "postcss": "8.5.19", + "less": "4.9.0", + "ng-packagr": "22.1.1", + "postcss": "8.5.25", "rollup": "4.62.2", "rxjs": "7.8.2", "vitest": "4.1.10" diff --git a/packages/angular/build/src/builders/application/build-action.ts b/packages/angular/build/src/builders/application/build-action.ts index d7dbdc8cfe21..dbec8d687b9f 100644 --- a/packages/angular/build/src/builders/application/build-action.ts +++ b/packages/angular/build/src/builders/application/build-action.ts @@ -81,7 +81,7 @@ export async function* runEsBuildBuildAction( const withProgress: typeof withSpinner = progress ? withSpinner : withNoProgress; // Initial build - let result: ExecutionResult; + let result: ExecutionResult | undefined; try { // Perform the build action result = await withProgress('Building...', () => action()); @@ -89,8 +89,8 @@ export async function* runEsBuildBuildAction( // Log all diagnostic (error/warning/logs) messages await logMessages(logger, result, colors, jsonLogs); } finally { - // Ensure Sass workers are shutdown if not watching - if (!watch) { + // Ensure Sass workers are shutdown if not watching or if the initial build failed + if (!watch || !result) { shutdownSassWorkerPool(); } } diff --git a/packages/angular/build/src/builders/application/chunk-optimizer.ts b/packages/angular/build/src/builders/application/chunk-optimizer.ts index 7d7a6e56b829..2241a4204999 100644 --- a/packages/angular/build/src/builders/application/chunk-optimizer.ts +++ b/packages/angular/build/src/builders/application/chunk-optimizer.ts @@ -418,6 +418,7 @@ export async function optimizeChunks( const record = createInitialFileRecord(entryRecord.depth + 1); + original.initialFiles.set(importPath, record); entriesToAnalyze.push([importPath, record]); } } diff --git a/packages/angular/build/src/builders/application/execute-build.ts b/packages/angular/build/src/builders/application/execute-build.ts index 21beb57bf478..d0213a9b8a79 100644 --- a/packages/angular/build/src/builders/application/execute-build.ts +++ b/packages/angular/build/src/builders/application/execute-build.ts @@ -18,10 +18,11 @@ import { checkCommonJSModules } from '../../tools/esbuild/commonjs-checker'; import { LOCALE_DATA_BASE_MODULE } from '../../tools/esbuild/i18n-locale-plugin'; import { extractLicenses } from '../../tools/esbuild/license-extractor'; import { profileAsync } from '../../tools/esbuild/profiling'; +import { transformSupportedBrowsersToTargets } from '../../tools/esbuild/target'; import { calculateEstimatedTransferSizes, + isZonelessApp, logBuildStats, - transformSupportedBrowsersToTargets, } from '../../tools/esbuild/utils'; import { BudgetCalculatorResult, checkBudgets } from '../../utils/bundle-calculator'; import { optimizeChunksThreshold } from '../../utils/environment-options'; @@ -36,6 +37,10 @@ import { inlineI18n, loadActiveTranslations } from './i18n'; import { NormalizedApplicationBuildOptions } from './options'; import { createComponentStyleBundler, setupBundlerContexts } from './setup-bundling'; +/** The esbuild error text prefix used to detect top-level await errors. */ +const TOP_LEVEL_AWAIT_ERROR_TEXT = + 'Top-level await is not available in the configured target environment'; + // eslint-disable-next-line max-lines-per-function export async function executeBuild( options: NormalizedApplicationBuildOptions, @@ -74,12 +79,19 @@ export async function executeBuild( let bundlingResult: BundleContextResult; let templateUpdates: Map | undefined; let angularCompilationContext: AngularCompilationContext | undefined; + let executionResult: ExecutionResult | undefined; try { if (rebuildState) { bundlerContexts = rebuildState.rebuildContexts; componentStyleBundler = rebuildState.componentStyleBundler; codeBundleCache = rebuildState.codeBundleCache; templateUpdates = rebuildState.templateUpdates; + executionResult = new ExecutionResult( + bundlerContexts, + componentStyleBundler, + codeBundleCache, + templateUpdates, + ); // Reset template updates for new rebuild templateUpdates?.clear(); @@ -122,6 +134,12 @@ export async function executeBuild( angularCompilationContext, templateUpdates, ); + executionResult = new ExecutionResult( + bundlerContexts, + componentStyleBundler, + codeBundleCache, + templateUpdates, + ); // Bundle everything on initial build bundlingResult = await BundlerContext.bundleAll([ @@ -138,234 +156,259 @@ export async function executeBuild( const componentResults = await componentStyleBundler.bundleAllFiles(true, true); bundlingResult = BundlerContext.mergeResults([bundlingResult, ...componentResults]); } - } catch (error) { - await angularCompilationContext?.dispose(); - throw error; - } - - const executionResult = new ExecutionResult( - bundlerContexts, - componentStyleBundler, - codeBundleCache, - templateUpdates, - ); - executionResult.addWarnings(bundlingResult.warnings); - - // Add used external component style referenced files to be watched - if (options.externalRuntimeStyles) { - executionResult.extraWatchFiles.push(...componentStyleBundler.collectReferencedFiles()); - } - // Return if the bundling has errors - if (bundlingResult.errors) { - executionResult.addErrors(bundlingResult.errors); - - return executionResult; - } + executionResult.addWarnings(bundlingResult.warnings); - // Optimize chunks if enabled and threshold is met. - // This pass uses Rollup/Rolldown to further optimize chunks generated by esbuild. - if (options.optimizationOptions.scripts) { - // Count lazy chunks (files not needed for initial load). - // Advanced chunk optimization is most beneficial when there are multiple lazy chunks. - const { metafile, initialFiles } = bundlingResult; - const lazyChunksCount = Object.keys(metafile.outputs).filter( - (path) => path.endsWith('.js') && !initialFiles.has(path), - ).length; - - // Only run if the number of lazy chunks meets the configured threshold. - // This avoids overhead for small projects with few chunks. - if (lazyChunksCount >= optimizeChunksThreshold) { - const { optimizeChunks } = await import('./chunk-optimizer'); - const optimizationResult = await profileAsync('OPTIMIZE_CHUNKS', () => - optimizeChunks( - bundlingResult, - options.sourcemapOptions.scripts ? !options.sourcemapOptions.hidden || 'hidden' : false, - ), - ); + // Add used external component style referenced files to be watched + if (options.externalRuntimeStyles) { + executionResult.extraWatchFiles.push(...componentStyleBundler.collectReferencedFiles()); + } - if (optimizationResult.errors) { - executionResult.addErrors(optimizationResult.errors); + // In non-watch mode, the bundler rebuild contexts and Angular compilation + // are no longer needed once bundling completes. Dispose them early to free + // worker processes, TypeScript ASTs, and caches before post-bundling steps + // execute or before returning bundling errors. + // This is fire-and-forget so worker teardown runs concurrently in the background + // without blocking the critical path of post-bundle optimization steps. + // Any in-flight disposal is awaited in the builder action's finally block. + if (!options.watch) { + void angularCompilationContext?.dispose(); + void executionResult.dispose(); + } - return executionResult; + // Return if the bundling has errors + if (bundlingResult.errors) { + // If Zone.js is used, augment top-level await errors with a more helpful message. + // esbuild's default error mentions "target environment" with browser versions, but + // the actual reason is that async/await is downleveled for Zone.js compatibility. + if (!isZonelessApp(options.polyfills)) { + for (const error of bundlingResult.errors) { + if (error.text?.startsWith(TOP_LEVEL_AWAIT_ERROR_TEXT)) { + error.notes ??= []; + error.notes.push({ + text: + 'Top-level await is not supported in applications that use Zone.js. ' + + 'Consider removing Zone.js or moving this code into an async function. \n' + + 'For more information about zoneless Angular applications, visit: https://angular.dev/guide/zoneless', + location: null, + }); + } + } } - bundlingResult = optimizationResult; + executionResult.addErrors(bundlingResult.errors); + + return executionResult; } - } - // Analyze external imports if external options are enabled - if (options.externalPackages || bundlingResult.externalConfiguration) { - const { - externalConfiguration = [], - externalImports: { browser = [], server = [] }, - } = bundlingResult; - // Similar to esbuild, --external:@foo/bar automatically implies --external:@foo/bar/*, - // which matches import paths like @foo/bar/baz. - // This means all paths within the @foo/bar package are also marked as external. - const exclusionsPrefixes = externalConfiguration.map((exclusion) => exclusion + '/'); - const exclusions = new Set(externalConfiguration); - const explicitExternal = new Set(); - - const isExplicitExternal = (dep: string): boolean => { - // Locale-data imports are injected by the builder itself (see i18n-locale-plugin) and must stay resolvable - // even when the containing package is externalized by the user. - if (dep.startsWith(`${LOCALE_DATA_BASE_MODULE}/`)) { - return false; - } + // Optimize chunks if enabled and threshold is met. + // This pass uses Rollup/Rolldown to further optimize chunks generated by esbuild. + if (options.optimizationOptions.scripts) { + // Count lazy chunks (files not needed for initial load). + // Advanced chunk optimization is most beneficial when there are multiple lazy chunks. + const { metafile, initialFiles } = bundlingResult; + const lazyChunksCount = Object.keys(metafile.outputs).filter( + (path) => path.endsWith('.js') && !initialFiles.has(path), + ).length; + + // Only run if the number of lazy chunks meets the configured threshold. + // This avoids overhead for small projects with few chunks. + if (lazyChunksCount >= optimizeChunksThreshold) { + const { optimizeChunks } = await import('./chunk-optimizer'); + const optimizationResult = await profileAsync('OPTIMIZE_CHUNKS', () => + optimizeChunks( + bundlingResult, + options.sourcemapOptions.scripts ? !options.sourcemapOptions.hidden || 'hidden' : false, + ), + ); + + if (optimizationResult.errors) { + executionResult.addErrors(optimizationResult.errors); + + return executionResult; + } - if (exclusions.has(dep)) { - return true; + bundlingResult = optimizationResult; } + } - for (const prefix of exclusionsPrefixes) { - if (dep.startsWith(prefix)) { + // Analyze external imports if external options are enabled + if (options.externalPackages || bundlingResult.externalConfiguration) { + const { + externalConfiguration = [], + externalImports: { browser = [], server = [] }, + } = bundlingResult; + // Similar to esbuild, --external:@foo/bar automatically implies --external:@foo/bar/*, + // which matches import paths like @foo/bar/baz. + // This means all paths within the @foo/bar package are also marked as external. + const exclusionsPrefixes = externalConfiguration.map((exclusion) => exclusion + '/'); + const exclusions = new Set(externalConfiguration); + const explicitExternal = new Set(); + + const isExplicitExternal = (dep: string): boolean => { + // Locale-data imports are injected by the builder itself (see i18n-locale-plugin) and must stay resolvable + // even when the containing package is externalized by the user. + if (dep.startsWith(`${LOCALE_DATA_BASE_MODULE}/`)) { + return false; + } + + if (exclusions.has(dep)) { return true; } - } - return false; - }; + for (const prefix of exclusionsPrefixes) { + if (dep.startsWith(prefix)) { + return true; + } + } - const implicitBrowser: string[] = []; - for (const dep of browser) { - if (isExplicitExternal(dep)) { - explicitExternal.add(dep); - } else { - implicitBrowser.push(dep); + return false; + }; + + const implicitBrowser: string[] = []; + for (const dep of browser) { + if (isExplicitExternal(dep)) { + explicitExternal.add(dep); + } else { + implicitBrowser.push(dep); + } } - } - const implicitServer: string[] = []; - for (const dep of server) { - if (isExplicitExternal(dep)) { - explicitExternal.add(dep); - } else { - implicitServer.push(dep); + const implicitServer: string[] = []; + for (const dep of server) { + if (isExplicitExternal(dep)) { + explicitExternal.add(dep); + } else { + implicitServer.push(dep); + } } - } - executionResult.setExternalMetadata(implicitBrowser, implicitServer, [...explicitExternal]); - } + executionResult.setExternalMetadata(implicitBrowser, implicitServer, [...explicitExternal]); + } - const { metafile, initialFiles, outputFiles } = bundlingResult; + const { metafile, initialFiles, outputFiles } = bundlingResult; - executionResult.outputFiles.push(...outputFiles); + executionResult.outputFiles.push(...outputFiles); - // Analyze files for bundle budget failures if present - let budgetFailures: BudgetCalculatorResult[] | undefined; - if (options.budgets) { - const compatStats = generateBudgetStats(metafile, outputFiles, initialFiles); - budgetFailures = [...checkBudgets(options.budgets, compatStats, true)]; - for (const { message, severity } of budgetFailures) { - if (severity === 'error') { - executionResult.addError(message); - } else { - executionResult.addWarning(message); + // Analyze files for bundle budget failures if present + let budgetFailures: BudgetCalculatorResult[] | undefined; + if (options.budgets) { + const compatStats = generateBudgetStats(metafile, outputFiles, initialFiles); + budgetFailures = [...checkBudgets(options.budgets, compatStats, true)]; + for (const { message, severity } of budgetFailures) { + if (severity === 'error') { + executionResult.addError(message); + } else { + executionResult.addWarning(message); + } } } - } - - // Calculate estimated transfer size if scripts are optimized - let estimatedTransferSizes; - if (optimizationOptions.scripts || optimizationOptions.styles.minify) { - estimatedTransferSizes = await calculateEstimatedTransferSizes(executionResult.outputFiles); - } - // Check metafile for CommonJS module usage if optimizing scripts - if (optimizationOptions.scripts) { - const messages = checkCommonJSModules(metafile, options.allowedCommonJsDependencies); - executionResult.addWarnings(messages); - } + // Calculate estimated transfer size if scripts are optimized + let estimatedTransferSizes; + if (optimizationOptions.scripts || optimizationOptions.styles.minify) { + estimatedTransferSizes = await calculateEstimatedTransferSizes(executionResult.outputFiles); + } - // Copy assets - if (assets) { - executionResult.addAssets(await resolveAssets(assets, workspaceRoot)); - } + // Check metafile for CommonJS module usage if optimizing scripts + if (optimizationOptions.scripts) { + const messages = checkCommonJSModules(metafile, options.allowedCommonJsDependencies); + executionResult.addWarnings(messages); + } - // Extract and write licenses for used packages - if (options.extractLicenses) { - executionResult.addOutputFile( - '3rdpartylicenses.txt', - await extractLicenses(metafile, workspaceRoot), - BuildOutputFileType.Root, - ); - } + // Copy assets + if (assets) { + executionResult.addAssets(await resolveAssets(assets, workspaceRoot)); + } - // Watch input index HTML file if configured - if (options.indexHtmlOptions) { - executionResult.extraWatchFiles.push(options.indexHtmlOptions.input); - executionResult.htmlIndexPath = options.indexHtmlOptions.output; - executionResult.htmlBaseHref = options.baseHref; - } + // Extract and write licenses for used packages + if (options.extractLicenses) { + executionResult.addOutputFile( + '3rdpartylicenses.txt', + await extractLicenses(metafile, workspaceRoot), + BuildOutputFileType.Root, + ); + } - // Create server app engine manifest - if (serverEntryPoint) { - executionResult.addOutputFile( - SERVER_APP_ENGINE_MANIFEST_FILENAME, - generateAngularServerAppEngineManifest(i18nOptions, security.allowedHosts, baseHref), - BuildOutputFileType.ServerRoot, - ); - } + // Watch input index HTML file if configured + if (options.indexHtmlOptions) { + executionResult.extraWatchFiles.push(options.indexHtmlOptions.input); + executionResult.htmlIndexPath = options.indexHtmlOptions.output; + executionResult.htmlBaseHref = options.baseHref; + } - // Perform i18n translation inlining if enabled - if (i18nOptions.shouldInline) { - const result = await inlineI18n(metafile, options, executionResult, initialFiles); - executionResult.addErrors(result.errors); - executionResult.addWarnings(result.warnings); - executionResult.addPrerenderedRoutes(result.prerenderedRoutes); - } else { - const result = await executePostBundleSteps( - metafile, - options, - executionResult.outputFiles, - executionResult.assetFiles, - initialFiles, - // Set lang attribute to the defined source locale if present - i18nOptions.hasDefinedSourceLocale ? i18nOptions.sourceLocale : undefined, - ); + // Create server app engine manifest + if (serverEntryPoint) { + executionResult.addOutputFile( + SERVER_APP_ENGINE_MANIFEST_FILENAME, + generateAngularServerAppEngineManifest(i18nOptions, security.allowedHosts, baseHref), + BuildOutputFileType.ServerRoot, + ); + } - // Deduplicate and add errors and warnings - executionResult.addErrors([...new Set(result.errors)]); - executionResult.addWarnings([...new Set(result.warnings)]); + // Perform i18n translation inlining if enabled + if (i18nOptions.shouldInline) { + const result = await inlineI18n(metafile, options, executionResult, initialFiles); + executionResult.addErrors(result.errors); + executionResult.addWarnings(result.warnings); + executionResult.addPrerenderedRoutes(result.prerenderedRoutes); + } else { + const result = await executePostBundleSteps( + metafile, + options, + executionResult.outputFiles, + executionResult.assetFiles, + initialFiles, + // Set lang attribute to the defined source locale if present + i18nOptions.hasDefinedSourceLocale ? i18nOptions.sourceLocale : undefined, + ); - executionResult.addPrerenderedRoutes(result.prerenderedRoutes); - executionResult.outputFiles.push(...result.additionalOutputFiles); - executionResult.assetFiles.push(...result.additionalAssets); - } + // Deduplicate and add errors and warnings + executionResult.addErrors([...new Set(result.errors)]); + executionResult.addWarnings([...new Set(result.warnings)]); - executionResult.addOutputFile( - 'prerendered-routes.json', - JSON.stringify({ routes: executionResult.prerenderedRoutes }, null, 2), - BuildOutputFileType.Root, - ); + executionResult.addPrerenderedRoutes(result.prerenderedRoutes); + executionResult.outputFiles.push(...result.additionalOutputFiles); + executionResult.assetFiles.push(...result.additionalAssets); + } - // Write metafile if stats option is enabled - if (options.stats) { executionResult.addOutputFile( - 'stats.json', - JSON.stringify(metafile, null, 2), + 'prerendered-routes.json', + JSON.stringify({ routes: executionResult.prerenderedRoutes }, null, 2), BuildOutputFileType.Root, ); - } - if (!jsonLogs && !options.quiet) { - const changedFiles = - rebuildState && executionResult.findChangedFiles(rebuildState.previousOutputInfo); - executionResult.addLog( - logBuildStats( - metafile, - outputFiles, - initialFiles, - budgetFailures, - colors, - changedFiles, - estimatedTransferSizes, - !!ssrOptions, - verbose, - ), - ); - } + // Write metafile if stats option is enabled + if (options.stats) { + executionResult.addOutputFile( + 'stats.json', + JSON.stringify(metafile, null, 2), + BuildOutputFileType.Root, + ); + } + + if (!jsonLogs && !options.quiet) { + const changedFiles = + rebuildState && executionResult.findChangedFiles(rebuildState.previousOutputInfo); + executionResult.addLog( + logBuildStats( + metafile, + outputFiles, + initialFiles, + budgetFailures, + colors, + changedFiles, + estimatedTransferSizes, + !!ssrOptions, + verbose, + ), + ); + } - return executionResult; + return executionResult; + } catch (error) { + await Promise.allSettled([angularCompilationContext?.dispose(), executionResult?.dispose()]); + + throw error; + } } diff --git a/packages/angular/build/src/builders/application/options.ts b/packages/angular/build/src/builders/application/options.ts index 4ec810ff3c07..abe3298aa093 100644 --- a/packages/angular/build/src/builders/application/options.ts +++ b/packages/angular/build/src/builders/application/options.ts @@ -126,6 +126,20 @@ interface InternalOptions { * Suppress build summary and stats table. */ quiet?: boolean; + + /** + * Disables esbuild code splitting for the browser code bundle. + * + * Splitting emits shared chunks whose exports are read across chunk boundaries as live ESM + * bindings. A module hoisted into a shared chunk is wrapped in a lazy initializer, so its exported + * value is only assigned once that initializer runs. Runners that load the generated output + * through a module runner rather than the browser's own ESM implementation do not reliably + * preserve those bindings, and an importing chunk can observe the export as `undefined`. + * + * Test bundles are never downloaded by a browser, so there is nothing for splitting to optimize + * there. Used exclusively for tests and shouldn't be used for other kinds of builds. + */ + disableCodeSplitting?: boolean; } /** Full set of options for `application` builder. */ @@ -160,7 +174,7 @@ export async function normalizeOptions( options.preserveSymlinks ?? process.execArgv.includes('--preserve-symlinks'); // Setup base paths based on workspace root and project information - const workspaceRoot = canonicalizePath(context.workspaceRoot, preserveSymlinks); + const workspaceRoot = canonicalizePath(context.workspaceRoot); const projectMetadata = await context.getProjectMetadata(projectName); const { projectRoot, projectSourceRoot } = getProjectRootPaths(workspaceRoot, projectMetadata); @@ -439,6 +453,7 @@ export async function normalizeOptions( partialSSRBuild = false, externalRuntimeStyles, instrumentForCoverage, + disableCodeSplitting, } = options; // Return all the normalized options @@ -475,6 +490,7 @@ export async function normalizeOptions( watch, workspaceRoot, entryPoints, + disableCodeSplitting, optimizationOptions, outputOptions, outExtension, diff --git a/packages/angular/build/src/builders/application/setup-bundling.ts b/packages/angular/build/src/builders/application/setup-bundling.ts index bb53c0bae902..79209ba0eaf9 100644 --- a/packages/angular/build/src/builders/application/setup-bundling.ts +++ b/packages/angular/build/src/builders/application/setup-bundling.ts @@ -19,7 +19,7 @@ import { import { BundlerContext } from '../../tools/esbuild/bundler-context'; import { createGlobalScriptsBundleOptions } from '../../tools/esbuild/global-scripts'; import { createGlobalStylesBundleOptions } from '../../tools/esbuild/global-styles'; -import { getSupportedNodeTargets } from '../../tools/esbuild/utils'; +import { getSupportedNodeTargets } from '../../tools/esbuild/target'; import type { NormalizedApplicationBuildOptions } from './options'; /** diff --git a/packages/angular/build/src/builders/application/tests/behavior/rebuild-global_styles_spec.ts b/packages/angular/build/src/builders/application/tests/behavior/rebuild-global_styles_spec.ts index 22c4c32202bd..2de5c5f229ca 100644 --- a/packages/angular/build/src/builders/application/tests/behavior/rebuild-global_styles_spec.ts +++ b/packages/angular/build/src/builders/application/tests/behavior/rebuild-global_styles_spec.ts @@ -132,5 +132,119 @@ describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => { { outputLogsOnFailure: false }, ); }); + + it('rebuilds PostCSS stylesheet after error on rebuild from plugin dependency', async () => { + harness.useTarget('build', { + ...BASE_OPTIONS, + watch: true, + styles: ['src/styles.css'], + }); + + await harness.writeFile( + 'test-plugin.js', + ` + const fs = require('fs'); + const path = require('path'); + module.exports = () => { + return { + postcssPlugin: 'test-plugin', + Once(root, { result }) { + const themePath = path.join(path.dirname(root.source.input.file), 'theme.json'); + result.messages.push({ + type: 'dependency', + file: themePath, + }); + const data = fs.readFileSync(themePath, 'utf-8'); + const json = JSON.parse(data); + root.append('body { color: ' + json.color + '; }'); + }, + }; + }; + module.exports.postcss = true; + `, + ); + await harness.writeFile( + '.postcssrc.json', + JSON.stringify({ + plugins: { + './test-plugin.js': {}, + }, + }), + ); + await harness.writeFile('src/styles.css', '/* base */'); + await harness.writeFile('src/theme.json', '{"color": "aqua"}'); + + await harness.executeWithCases( + [ + async ({ result }) => { + expect(result?.success).toBe(true); + harness.expectFile('dist/browser/styles.css').content.toContain('color: aqua'); + harness.expectFile('dist/browser/styles.css').content.not.toContain('color: blue'); + + await harness.writeFile('src/theme.json', 'invalid-json'); + }, + async ({ result }) => { + expect(result?.success).toBe(false); + + await harness.writeFile('src/theme.json', '{"color": "blue"}'); + }, + ({ result }) => { + expect(result?.success).toBe(true); + harness.expectFile('dist/browser/styles.css').content.not.toContain('color: aqua'); + harness.expectFile('dist/browser/styles.css').content.toContain('color: blue'); + }, + ], + { outputLogsOnFailure: false }, + ); + }); + + it('rebuilds PostCSS stylesheet after CSS syntax error on initial build from import', async () => { + harness.useTarget('build', { + ...BASE_OPTIONS, + watch: true, + styles: ['src/styles.css'], + }); + + await harness.writeFile( + 'noop-plugin.js', + ` + module.exports = () => ({ postcssPlugin: 'noop-plugin' }); + module.exports.postcss = true; + `, + ); + await harness.writeFile( + '.postcssrc.json', + JSON.stringify({ + plugins: { + './noop-plugin.js': {}, + }, + }), + ); + await harness.writeFile('src/styles.css', "@import './a.css';"); + await harness.writeFile('src/a.css', "a { ' }"); + + await harness.executeWithCases( + [ + async ({ result }) => { + expect(result?.success).toBe(false); + + await harness.writeFile('src/a.css', 'body { color: aqua; }'); + }, + async ({ result }) => { + expect(result?.success).toBe(true); + harness.expectFile('dist/browser/styles.css').content.toContain('color: aqua'); + harness.expectFile('dist/browser/styles.css').content.not.toContain('color: blue'); + + await harness.writeFile('src/a.css', 'body { color: blue; }'); + }, + ({ result }) => { + expect(result?.success).toBe(true); + harness.expectFile('dist/browser/styles.css').content.not.toContain('color: aqua'); + harness.expectFile('dist/browser/styles.css').content.toContain('color: blue'); + }, + ], + { outputLogsOnFailure: false }, + ); + }); }); }); diff --git a/packages/angular/build/src/builders/application/tests/behavior/top-level-await-error_spec.ts b/packages/angular/build/src/builders/application/tests/behavior/top-level-await-error_spec.ts new file mode 100644 index 000000000000..b0220529ee28 --- /dev/null +++ b/packages/angular/build/src/builders/application/tests/behavior/top-level-await-error_spec.ts @@ -0,0 +1,67 @@ +/** + * @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 { buildApplication } from '../../index'; +import { APPLICATION_BUILDER_INFO, BASE_OPTIONS, describeBuilder } from '../setup'; + +describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => { + describe('Behavior: "Top-level await error message"', () => { + it('should show a Zone.js-specific error when top-level await is used with Zone.js', async () => { + await harness.writeFile( + 'src/main.ts', + ` + // The export makes this file a module, which is required for top-level await. + export const value = await Promise.resolve('test'); + console.log(value); + `, + ); + + harness.useTarget('build', { + ...BASE_OPTIONS, + polyfills: ['zone.js'], + }); + + const { result, logs } = await harness.executeOnce({ outputLogsOnFailure: false }); + expect(result?.success).toBeFalse(); + expect(logs).toContain( + jasmine.objectContaining({ + message: jasmine.stringMatching( + 'Top-level await is not supported in applications that use Zone.js', + ), + }), + ); + }); + + it('should not show a Zone.js-specific error when top-level await is used without Zone.js', async () => { + await harness.writeFile( + 'src/main.ts', + ` + // The export makes this file a module, which is required for top-level await. + export const value = await Promise.resolve('test'); + console.log(value); + `, + ); + + harness.useTarget('build', { + ...BASE_OPTIONS, + polyfills: [], + }); + + const { result, logs } = await harness.executeOnce({ outputLogsOnFailure: false }); + expect(result?.success).toBeTrue(); + expect(logs).not.toContain( + jasmine.objectContaining({ + level: 'error', + message: jasmine.stringContaining( + 'Top-level await is not supported in applications that use Zone.js', + ), + }), + ); + }); + }); +}); diff --git a/packages/angular/build/src/builders/application/tests/options/extract-licenses_spec.ts b/packages/angular/build/src/builders/application/tests/options/extract-licenses_spec.ts index 402200a27f9d..2c495e703a7b 100644 --- a/packages/angular/build/src/builders/application/tests/options/extract-licenses_spec.ts +++ b/packages/angular/build/src/builders/application/tests/options/extract-licenses_spec.ts @@ -55,5 +55,96 @@ describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => { harness.expectFile('dist/3rdpartylicenses.txt').content.toContain('MIT'); harness.expectFile('dist/browser/en-US/main.js').toExist(); }); + + it(`should extract license from a package with a lowercase 'license' file`, async () => { + await harness.writeFile( + 'node_modules/test-package-a/package.json', + JSON.stringify({ + name: 'test-package-a', + version: '1.0.0', + main: 'index.js', + license: 'MIT', + }), + ); + await harness.writeFile( + 'node_modules/test-package-a/index.js', + 'console.log("test-package-a");', + ); + await harness.writeFile('node_modules/test-package-a/license', 'TEST_LOWERCASE_LICENSE_TEXT'); + await harness.appendToFile('src/main.ts', "\nimport 'test-package-a';\n"); + + harness.useTarget('build', { + ...BASE_OPTIONS, + extractLicenses: true, + }); + + const { result } = await harness.executeOnce(); + expect(result?.success).toBeTrue(); + harness + .expectFile('dist/3rdpartylicenses.txt') + .content.toContain('TEST_LOWERCASE_LICENSE_TEXT'); + }); + + it(`should extract license from a package with an alternative license file name (e.g., 'MIT-LICENCE.txt')`, async () => { + await harness.writeFile( + 'node_modules/test-package-b/package.json', + JSON.stringify({ + name: 'test-package-b', + version: '1.0.0', + main: 'index.js', + license: 'MIT', + }), + ); + await harness.writeFile( + 'node_modules/test-package-b/index.js', + 'console.log("test-package-b");', + ); + await harness.writeFile( + 'node_modules/test-package-b/MIT-LICENCE.txt', + 'TEST_ALTERNATIVE_LICENSE_TEXT', + ); + await harness.appendToFile('src/main.ts', "\nimport 'test-package-b';\n"); + + harness.useTarget('build', { + ...BASE_OPTIONS, + extractLicenses: true, + }); + + const { result } = await harness.executeOnce(); + expect(result?.success).toBeTrue(); + harness + .expectFile('dist/3rdpartylicenses.txt') + .content.toContain('TEST_ALTERNATIVE_LICENSE_TEXT'); + }); + + it(`should extract license from a package with a custom license file specified in package.json`, async () => { + await harness.writeFile( + 'node_modules/test-package-c/package.json', + JSON.stringify({ + name: 'test-package-c', + version: '1.0.0', + main: 'index.js', + license: 'SEE LICENSE IN custom-license.md', + }), + ); + await harness.writeFile( + 'node_modules/test-package-c/index.js', + 'console.log("test-package-c");', + ); + await harness.writeFile( + 'node_modules/test-package-c/custom-license.md', + 'TEST_CUSTOM_LICENSE_TEXT', + ); + await harness.appendToFile('src/main.ts', "\nimport 'test-package-c';\n"); + + harness.useTarget('build', { + ...BASE_OPTIONS, + extractLicenses: true, + }); + + const { result } = await harness.executeOnce(); + expect(result?.success).toBeTrue(); + harness.expectFile('dist/3rdpartylicenses.txt').content.toContain('TEST_CUSTOM_LICENSE_TEXT'); + }); }); }); diff --git a/packages/angular/build/src/builders/application/tests/options/index_spec.ts b/packages/angular/build/src/builders/application/tests/options/index_spec.ts index 11228658bbce..b53467caaec6 100644 --- a/packages/angular/build/src/builders/application/tests/options/index_spec.ts +++ b/packages/angular/build/src/builders/application/tests/options/index_spec.ts @@ -79,16 +79,17 @@ describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => { harness.expectFile('dist/browser/index.html').content.toContain('TEST_123'); }); - // TODO: Build needs to be fixed to not throw an unhandled exception for this case - xit('should fail build when a string path to non-existent file', async () => { + it('should fail build and terminate cleanly when a string path to non-existent file is provided', async () => { harness.useTarget('build', { ...BASE_OPTIONS, index: 'src/not-here.html', }); - const { result } = await harness.executeOnce({ outputLogsOnFailure: false }); + const { result, error } = await harness.executeOnce({ outputLogsOnException: false }); - expect(result?.success).toBe(false); + expect(result).toBeUndefined(); + expect(error).toEqual(jasmine.any(Error)); + expect(error?.message).toMatch(/Failed to read index HTML file/i); harness.expectFile('dist/browser/index.html').toNotExist(); }); diff --git a/packages/angular/build/src/builders/application/tests/options/subresource-integrity_spec.ts b/packages/angular/build/src/builders/application/tests/options/subresource-integrity_spec.ts index e846053e64c4..ca9212b0d3e3 100644 --- a/packages/angular/build/src/builders/application/tests/options/subresource-integrity_spec.ts +++ b/packages/angular/build/src/builders/application/tests/options/subresource-integrity_spec.ts @@ -238,5 +238,21 @@ describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => { .withContext('importmap must precede the first module script tag') .toBeLessThan(moduleScriptIdx); }); + + it(`preserves integrity and crossorigin in autoCsp loader when autoCsp is also enabled`, async () => { + harness.useTarget('build', { + ...BASE_OPTIONS, + subresourceIntegrity: true, + security: { autoCsp: true }, + }); + + const { result } = await harness.executeOnce(); + expect(result?.success).toBeTrue(); + + const indexHtml = harness.readFile('dist/browser/index.html'); + expect(indexHtml).toMatch( + /const scripts = \[\[(?:'[^']+', 'module', false, false, "sha384-[^"]+", "anonymous"(?:, )?)+\]\];/, + ); + }); }); }); diff --git a/packages/angular/build/src/builders/dev-server/internal.ts b/packages/angular/build/src/builders/dev-server/internal.ts index 4e5e97e5cf14..96587acb5cff 100644 --- a/packages/angular/build/src/builders/dev-server/internal.ts +++ b/packages/angular/build/src/builders/dev-server/internal.ts @@ -13,7 +13,7 @@ export { getFeatureSupport, isZonelessApp } from '../../tools/esbuild/utils'; export { type IndexHtmlTransform } from '../../utils/index-file/index-html-generator'; export { purgeStaleBuildCache } from '../../utils/purge-cache'; export { getSupportedBrowsers } from '../../utils/supported-browsers'; -export { transformSupportedBrowsersToTargets } from '../../tools/esbuild/utils'; +export { transformSupportedBrowsersToTargets } from '../../tools/esbuild/target'; export { buildApplicationInternal } from '../../builders/application'; export type { ApplicationBuilderInternalOptions } from '../../builders/application/options'; export type { ExternalResultMetadata } from '../../tools/esbuild/bundler-execution-result'; 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 c616e865a68b..868590edab95 100644 --- a/packages/angular/build/src/builders/dev-server/vite/server.ts +++ b/packages/angular/build/src/builders/dev-server/vite/server.ts @@ -104,6 +104,7 @@ function createSsrConfig( prebundleLoaderExtensions: RolldownLoaderOption | undefined, thirdPartySourcemaps: boolean, define: ApplicationBuilderInternalOptions['define'], + target: string[], ): Vite.SSROptions { return { // Note: `true` and `/.*/` have different sematics. When true, the `external` option is ignored. @@ -111,6 +112,7 @@ function createSsrConfig( // Exclude any Node.js built in module and provided dependencies (currently build defined externals) external: externalMetadata.explicitServer, optimizeDeps: getDepOptimizationConfig({ + target, // Only enable with caching since it causes prebundle dependencies to be cached disabled: serverOptions.prebundle === false, // Exclude any explicitly defined dependencies (currently build defined externals and node.js built-ins) @@ -214,6 +216,7 @@ export async function setupServer( prebundleLoaderExtensions, thirdPartySourcemaps, define, + target, ), plugins: [ createAngularSetupMiddlewaresPlugin({ @@ -239,6 +242,7 @@ export async function setupServer( ], // Browser only optimizeDeps. (This does not run for SSR dependencies). optimizeDeps: getDepOptimizationConfig({ + target, // Only enable with caching since it causes prebundle dependencies to be cached disabled: serverOptions.prebundle === false, // Exclude any explicitly defined dependencies (currently build defined externals) diff --git a/packages/angular/build/src/builders/karma/application_builder.ts b/packages/angular/build/src/builders/karma/application_builder.ts index b9a28e1bf0b0..d0adb6c3cf0e 100644 --- a/packages/angular/build/src/builders/karma/application_builder.ts +++ b/packages/angular/build/src/builders/karma/application_builder.ts @@ -11,7 +11,6 @@ import type { Config, ConfigOptions, FilePattern, InlinePluginDef, Server } from import { randomUUID } from 'node:crypto'; import { rmSync } from 'node:fs'; import * as fs from 'node:fs/promises'; -import { createRequire } from 'node:module'; import path from 'node:path'; import { ReadableStream } from 'node:stream/web'; import { createVirtualModulePlugin } from '../../tools/esbuild/virtual-module-plugin'; @@ -66,8 +65,14 @@ export function execute( init = await initializeApplication(normalizedOptions, context, karmaOptions, transforms); } catch (err) { if (err instanceof ApplicationBuildError) { - controller.enqueue({ success: false, message: err.message }); - controller.close(); + if (controller.desiredSize !== null) { + try { + controller.enqueue({ success: false, message: err.message }); + controller.close(); + } catch { + // Stream controller may already be closed or cancelled + } + } return; } @@ -85,8 +90,14 @@ export function execute( // Close the stream once the Karma server returns. karmaServer = new karma.Server(karmaConfig as Config, (exitCode) => { - controller.enqueue({ success: exitCode === 0 }); - controller.close(); + if (controller.desiredSize !== null) { + try { + controller.enqueue({ success: exitCode === 0 }); + controller.close(); + } catch { + // Stream controller may already be closed or cancelled + } + } }); await karmaServer.start(); diff --git a/packages/angular/build/src/builders/karma/progress-reporter.ts b/packages/angular/build/src/builders/karma/progress-reporter.ts index 16824badd095..6fc92b6c74c8 100644 --- a/packages/angular/build/src/builders/karma/progress-reporter.ts +++ b/packages/angular/build/src/builders/karma/progress-reporter.ts @@ -59,8 +59,18 @@ export function injectKarmaReporter( break; } + if (controller.desiredSize === null) { + break; + } + if (buildOutput.kind === ResultKind.Failure) { - controller.enqueue({ success: false, message: 'Build failed' }); + if (controller.desiredSize !== null) { + try { + controller.enqueue({ success: false, message: 'Build failed' }); + } catch { + // Stream controller may already be closed or cancelled + } + } } else if ( buildOutput.kind === ResultKind.Incremental || buildOutput.kind === ResultKind.Full @@ -81,10 +91,12 @@ export function injectKarmaReporter( } onRunComplete = function (_browsers: unknown, results: RunCompleteInfo): void { - if (results.exitCode === 0) { - controller.enqueue({ success: true }); - } else { - controller.enqueue({ success: false }); + if (controller.desiredSize !== null) { + try { + controller.enqueue({ success: results.exitCode === 0 }); + } catch { + // Stream controller may already be closed or cancelled + } } }; } diff --git a/packages/angular/build/src/builders/karma/tests/behavior/errors_spec.ts b/packages/angular/build/src/builders/karma/tests/behavior/errors_spec.ts index 366cc2aa20a1..a69698b8d743 100644 --- a/packages/angular/build/src/builders/karma/tests/behavior/errors_spec.ts +++ b/packages/angular/build/src/builders/karma/tests/behavior/errors_spec.ts @@ -28,5 +28,18 @@ describeKarmaBuilder(execute, KARMA_BUILDER_INFO, (harness, setupTarget) => { expect(result?.success).toBeFalse(); }); + + it('handles stream cancellation gracefully in watch mode', async () => { + harness.useTarget('test', { + ...BASE_OPTIONS, + watch: true, + }); + + const { result } = await harness.executeOnce({ + outputLogsOnFailure: false, + }); + + expect(result?.success).toBeTrue(); + }); }); }); diff --git a/packages/angular/build/src/builders/unit-test/options.ts b/packages/angular/build/src/builders/unit-test/options.ts index d3402b090e0f..44f6b6b9208b 100644 --- a/packages/angular/build/src/builders/unit-test/options.ts +++ b/packages/angular/build/src/builders/unit-test/options.ts @@ -10,7 +10,7 @@ import { type BuilderContext, targetFromTargetString } from '@angular-devkit/arc import { constants, promises as fs } from 'node:fs'; import path from 'node:path'; import { normalizeCacheOptions } from '../../utils/normalize-cache'; -import { canonicalizePath } from '../../utils/path'; +import { canonicalizePath, toPosixPath } from '../../utils/path'; import { getProjectRootPaths } from '../../utils/project-metadata'; import { isTTY } from '../../utils/tty'; import { Runner, type Schema as UnitTestBuilderOptions } from './schema'; @@ -58,7 +58,7 @@ export async function normalizeOptions( : process.execArgv.includes('--preserve-symlinks'); // Setup base paths based on workspace root and project information - const workspaceRoot = canonicalizePath(context.workspaceRoot, preserveSymlinks); + const workspaceRoot = canonicalizePath(context.workspaceRoot); const projectMetadata = await context.getProjectMetadata(projectName); const { projectRoot, projectSourceRoot } = getProjectRootPaths(workspaceRoot, projectMetadata); @@ -67,8 +67,17 @@ export async function normalizeOptions( const cacheOptions = normalizeCacheOptions(projectMetadata, workspaceRoot); cacheOptions.path = path.join(cacheOptions.path, projectName); - const { runner, browsers, progress, filter, browserViewport, ui, runnerConfig, isolate } = - options; + const { + runner, + browsers, + progress, + filter, + browserViewport, + ui, + runnerConfig, + isolate, + splitting = true, + } = options; if (ui && runner !== Runner.Vitest) { throw new Error('The "ui" option is only available for the "vitest" runner.'); @@ -140,10 +149,11 @@ export async function normalizeOptions( debug: options.debug ?? false, ui: process.env['CI'] ? false : ui, isolate, + splitting, quiet: options.quiet ?? (process.env['CI'] ? false : true), providersFile: options.providersFile && path.join(workspaceRoot, options.providersFile), setupFiles: options.setupFiles - ? options.setupFiles.map((setupFile) => path.join(workspaceRoot, setupFile)) + ? options.setupFiles.map((setupFile) => toPosixPath(path.join(workspaceRoot, setupFile))) : [], dumpVirtualFiles: options.dumpVirtualFiles, listTests: options.listTests, diff --git a/packages/angular/build/src/builders/unit-test/runners/vitest/build-options.ts b/packages/angular/build/src/builders/unit-test/runners/vitest/build-options.ts index 7f0f67fc0c2e..9c5abb9386bf 100644 --- a/packages/angular/build/src/builders/unit-test/runners/vitest/build-options.ts +++ b/packages/angular/build/src/builders/unit-test/runners/vitest/build-options.ts @@ -256,7 +256,12 @@ export async function getVitestBuildOptions( sourceMap: { scripts: true, vendor: false, styles: false }, outputHashing: adjustOutputHashing(baseBuildOptions.outputHashing), optimization: false, + namedChunks: false, entryPoints, + // Vitest's Node-based module loading emulation (vite-node) is not fully spec compliant and lacks + // live ESM bindings across chunk boundaries. This can cause uninitialized exports or break mocking. + // Disabling code splitting avoids shared chunks, but increases build and coverage memory/time. + disableCodeSplitting: !options.splitting, // Enable support for vitest browser prebundling. Excludes can be controlled with a runnerConfig // and the `optimizeDeps.exclude` option. externalPackages: true, diff --git a/packages/angular/build/src/builders/unit-test/schema.json b/packages/angular/build/src/builders/unit-test/schema.json index 0c6c819392f3..5e9a62cf495d 100644 --- a/packages/angular/build/src/builders/unit-test/schema.json +++ b/packages/angular/build/src/builders/unit-test/schema.json @@ -77,6 +77,11 @@ "type": "boolean", "description": "Enables isolation for test execution. When true, Vitest runs tests in separate threads or processes. This option is only available for the Vitest runner. Defaults to false to align with the Karma/Jasmine experience." }, + "splitting": { + "type": "boolean", + "description": "Enables code splitting for test execution. When enabled, shared code between test files is split into separate chunks. Issues with live ESM bindings in Node.js environments (such as uninitialized exports or mocking failures) can be resolved by disabling splitting. This option is only available for the Vitest runner.", + "default": true + }, "quiet": { "type": "boolean", "description": "Suppresses the verbose build summary and stats table on each rebuild. Defaults to `true` locally and `false` in CI environments." diff --git a/packages/angular/build/src/builders/unit-test/tests/behavior/vitest-barrel-side-effects_spec.ts b/packages/angular/build/src/builders/unit-test/tests/behavior/vitest-barrel-side-effects_spec.ts new file mode 100644 index 000000000000..7a59f09eeaa0 --- /dev/null +++ b/packages/angular/build/src/builders/unit-test/tests/behavior/vitest-barrel-side-effects_spec.ts @@ -0,0 +1,134 @@ +/** + * @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 { execute } from '../../index'; +import { BASE_OPTIONS, describeBuilder, UNIT_TEST_BUILDER_INFO } from '../setup'; + +describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { + describe('Behavior: "Vitest barrel sideEffects"', () => { + // Regression test for https://github.com/angular/angular-cli/issues/33910. + it('should retain barrel-exported components when package.json has sideEffects: false', async () => { + harness.withBuilderTarget( + 'build', + async () => ({ success: true }), + { + project: 'src/lib/ng-package.json', + }, + { + builderName: '@angular/build:ng-packagr', + }, + ); + + await harness.modifyFile('tsconfig.json', (content) => { + const tsconfig = JSON.parse(content); + tsconfig.compilerOptions ??= {}; + tsconfig.compilerOptions.paths = { + '@lib': ['./src/lib/public-api.ts'], + '@lib/sub': ['./src/lib/sub/public-api.ts'], + }; + + return JSON.stringify(tsconfig); + }); + + await harness.writeFiles({ + 'src/lib/package.json': JSON.stringify({ + name: '@lib', + version: '0.0.1', + sideEffects: false, + }), + 'src/lib/ng-package.json': JSON.stringify({ + lib: { + entryFile: 'public-api.ts', + }, + }), + 'src/lib/public-api.ts': ` + export * from './components/public-api-components'; + export * from './other/other.component'; + `, + 'src/lib/components/public-api-components.ts': `export * from './foo/foo.component';`, + 'src/lib/components/foo/foo.component.ts': ` + import { Component } from '@angular/core'; + + @Component({ + selector: 'lib-foo', + standalone: true, + template: '

foo

', + }) + export class FooComponent {} + `, + 'src/lib/other/other.component.ts': ` + import { Component } from '@angular/core'; + + @Component({ + selector: 'lib-other', + standalone: true, + template: '

other

', + }) + export class OtherComponent {} + `, + 'src/lib/other/other.component.spec.ts': ` + import { TestBed } from '@angular/core/testing'; + import { describe, it, expect } from 'vitest'; + import { OtherComponent } from '@lib'; + + describe('OtherComponent', () => { + it('creates', () => { + TestBed.configureTestingModule({ + imports: [OtherComponent], + }); + const fixture = TestBed.createComponent(OtherComponent); + expect(fixture).toBeTruthy(); + }); + }); + `, + 'src/lib/sub/ng-package.json': JSON.stringify({ + lib: { + entryFile: 'public-api.ts', + }, + }), + 'src/lib/sub/public-api.ts': `export * from './bar/bar.component';`, + 'src/lib/sub/bar/bar.component.ts': ` + import { Component } from '@angular/core'; + import { FooComponent } from '@lib'; + + @Component({ + selector: 'lib-bar', + standalone: true, + imports: [FooComponent], + template: '', + }) + export class BarComponent {} + `, + 'src/lib/sub/bar/bar.component.spec.ts': ` + import { TestBed } from '@angular/core/testing'; + import { describe, it, expect } from 'vitest'; + import { BarComponent } from './bar.component'; + + describe('BarComponent', () => { + it('creates', () => { + TestBed.configureTestingModule({ + imports: [BarComponent], + }); + const fixture = TestBed.createComponent(BarComponent); + expect(fixture).toBeTruthy(); + }); + }); + `, + }); + + harness.useTarget('test', { + ...BASE_OPTIONS, + include: ['lib/**/*.spec.ts'], + }); + + const { result } = await harness.executeOnce(); + + expect(result?.success).toBeTrue(); + }); + }); +}); diff --git a/packages/angular/build/src/builders/unit-test/tests/behavior/vitest-shared-chunk-init_spec.ts b/packages/angular/build/src/builders/unit-test/tests/behavior/vitest-shared-chunk-init_spec.ts new file mode 100644 index 000000000000..afccfc2c06e1 --- /dev/null +++ b/packages/angular/build/src/builders/unit-test/tests/behavior/vitest-shared-chunk-init_spec.ts @@ -0,0 +1,173 @@ +/** + * @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 { execute } from '../../index'; +import { + BASE_OPTIONS, + describeBuilder, + UNIT_TEST_BUILDER_INFO, + setupApplicationTarget, +} from '../setup'; + +describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { + describe('Behavior: "Vitest shared chunk initialization"', () => { + // Regression test for https://github.com/angular/angular-cli/issues/33728. + // + // Without `disableCodeSplitting`, esbuild hoists a module imported by more than one spec + // entry point into a shared chunk behind a lazy `__esm` initializer, and a class-field + // initializer in another chunk reads the exported value as `undefined` under the jsdom + // runner. All four trigger conditions are required and encoded below: + // 1. two spec entry points import the shared module (so it lands in a shared chunk); + // 2. a component in one entry reads the export during class-field initialization; + // 3. that component's spec file contains an `async` test callback (no `await` needed); + // 4. zone.js is in the polyfills (the `setupApplicationTarget` default), which downlevels + // async and makes esbuild emit the spec entry CommonJS-wrapped. + // + // NOTE: the failure this guards against is sensitive to inert content — adding a top-level + // side effect (even a `console.log`) to the shared or importing module below defused it + // during reduction. Mirror https://github.com/jonmarozick/ng-shared-chunk-repro when + // modifying these fixtures. + it('should provide shared-module exports to class-field initializers in async specs', async () => { + setupApplicationTarget(harness); + + harness.useTarget('test', { + ...BASE_OPTIONS, + splitting: false, + }); + + // Keep the default project's spec deterministic; a third spec entry that does not touch + // the shared module does not affect the reproduction (verified in a fresh workspace). + await harness.writeFile( + 'src/app/app.component.spec.ts', + ` + import { describe, it, expect } from 'vitest'; + + describe('AppComponent placeholder', () => { + it('runs', () => { + expect(1 + 1).toBe(2); + }); + }); + `, + ); + + // The shared `const`. Reached from both spec entry points, so it is hoisted into a chunk + // shared between them. + await harness.writeFile( + 'src/environments/env-config.ts', + ` + export interface DealerConfig { + dealerId: string; + clientKey: string; + } + + export const DEALERS: DealerConfig[] = [ + { dealerId: 'dealer-one', clientKey: 'KEY-ONE' }, + { dealerId: 'dealer-two', clientKey: 'KEY-TWO' }, + { dealerId: 'dealer-three', clientKey: 'KEY-THREE' }, + { dealerId: 'dealer-four', clientKey: 'KEY-FOUR' }, + ]; + `, + ); + + // Reached by both spec entries, so it and env-config.ts land in the shared chunk. Reads the + // const inside a method — after module initialization — and is the passing control. + await harness.writeFile( + 'src/app/features/lead-generator/services/lead.service.ts', + ` + import { Injectable } from '@angular/core'; + + import { DEALERS } from '../../../../environments/env-config'; + + @Injectable({ providedIn: 'root' }) + export class LeadService { + resolveClientKey(dealerId: string, clientKey?: string): string { + return clientKey ?? DEALERS.find((d) => d.dealerId === dealerId)?.clientKey ?? ''; + } + } + `, + ); + + await harness.writeFile( + 'src/app/features/lead-generator/services/index.ts', + `export * from './lead.service';\n`, + ); + + // Spec entry point 1 — the second importer that causes the chunk to be shared at all. + await harness.writeFile( + 'src/app/features/lead-generator/services/lead.service.spec.ts', + ` + import { describe, it, expect } from 'vitest'; + import { TestBed } from '@angular/core/testing'; + + import { LeadService } from './lead.service'; + + describe('LeadService', () => { + it('reads DEALERS inside a method', () => { + TestBed.configureTestingModule({ providers: [LeadService] }); + + expect(TestBed.inject(LeadService).resolveClientKey('dealer-one')).toBe('KEY-ONE'); + }); + }); + `, + ); + + // In the other chunk; reads the shared export eagerly during class-field initialization. + await harness.writeFile( + 'src/app/features/lead-generator/lead-generator.container.ts', + ` + import { Component, inject } from '@angular/core'; + + import { LeadService } from './services'; + import { DEALERS, DealerConfig } from '../../../environments/env-config'; + + @Component({ + selector: 'app-lead-generator', + standalone: true, + template: '', + }) + export class LeadGeneratorContainer { + private readonly leadService = inject(LeadService); + + readonly dealers: DealerConfig[] = DEALERS; + readonly dealerOptions = this.dealers.map((d) => d.dealerId); + + hasService(): boolean { + return this.leadService != null; + } + } + `, + ); + + // Spec entry point 2 — the failing case without the fix. The `async` is load-bearing: + // zone.js makes the builder downlevel it, the spec then imports the `__async` helper, and + // esbuild emits this entry CommonJS-wrapped with the component module behind a lazy + // `__esm` initializer. No `await` is needed; a synchronous callback hides the defect. + await harness.writeFile( + 'src/app/features/lead-generator/lead-generator.container.spec.ts', + ` + import { describe, it, expect } from 'vitest'; + import { TestBed } from '@angular/core/testing'; + + import { LeadGeneratorContainer } from './lead-generator.container'; + + describe('LeadGeneratorContainer', () => { + it('reads DEALERS in a class-field initialiser', async () => { + const fixture = TestBed.createComponent(LeadGeneratorContainer); + + expect(fixture.componentInstance.dealers.length).toBe(4); + }); + }); + `, + ); + + const { result } = await harness.executeOnce(); + + expect(result?.success).toBeTrue(); + }); + }); +}); diff --git a/packages/angular/build/src/builders/unit-test/tests/options/splitting_spec.ts b/packages/angular/build/src/builders/unit-test/tests/options/splitting_spec.ts new file mode 100644 index 000000000000..133c54ca21e9 --- /dev/null +++ b/packages/angular/build/src/builders/unit-test/tests/options/splitting_spec.ts @@ -0,0 +1,132 @@ +/** + * @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 { execute } from '../../index'; +import { + BASE_OPTIONS, + describeBuilder, + UNIT_TEST_BUILDER_INFO, + setupApplicationTarget, + expectLog, + expectNoLog, +} from '../setup'; + +describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { + describe('Option: "splitting"', () => { + beforeEach(async () => { + setupApplicationTarget(harness); + }); + + it('should default to true and run tests successfully', async () => { + harness.useTarget('test', { + ...BASE_OPTIONS, + }); + + const { result } = await harness.executeOnce(); + expect(result?.success).toBeTrue(); + }); + + it('should run tests successfully when splitting is true', async () => { + harness.useTarget('test', { + ...BASE_OPTIONS, + splitting: true, + }); + + const { result } = await harness.executeOnce(); + expect(result?.success).toBeTrue(); + }); + + it('should run tests successfully when splitting is false', async () => { + harness.useTarget('test', { + ...BASE_OPTIONS, + splitting: false, + }); + + const { result } = await harness.executeOnce(); + expect(result?.success).toBeTrue(); + }); + + it('should split shared code into a separate chunk when splitting is true', async () => { + await harness.writeFile( + 'src/app/shared.ts', + `export const SHARED_DATA = 'shared-data-value';`, + ); + + await harness.writeFile( + 'src/app/first.spec.ts', + ` + import { SHARED_DATA } from './shared'; + + it('tests first', () => { + expect(SHARED_DATA).toBe('shared-data-value'); + }); + `, + ); + + await harness.writeFile( + 'src/app/second.spec.ts', + ` + import { SHARED_DATA } from './shared'; + + it('tests second', () => { + expect(SHARED_DATA).toBe('shared-data-value'); + }); + `, + ); + + harness.useTarget('test', { + ...BASE_OPTIONS, + splitting: true, + quiet: false, + }); + + const { result, logs } = await harness.executeOnce(); + expect(result?.success).toBeTrue(); + expectLog(logs, /chunk-[a-z0-9]+\.js/i); + }); + + it('should not split shared code into a separate chunk when splitting is false', async () => { + await harness.writeFile( + 'src/app/shared.ts', + `export const SHARED_DATA = 'shared-data-value';`, + ); + + await harness.writeFile( + 'src/app/first.spec.ts', + ` + import { SHARED_DATA } from './shared'; + + it('tests first', () => { + expect(SHARED_DATA).toBe('shared-data-value'); + }); + `, + ); + + await harness.writeFile( + 'src/app/second.spec.ts', + ` + import { SHARED_DATA } from './shared'; + + it('tests second', () => { + expect(SHARED_DATA).toBe('shared-data-value'); + }); + `, + ); + + harness.useTarget('test', { + ...BASE_OPTIONS, + splitting: false, + quiet: false, + }); + + const { result, logs } = await harness.executeOnce(); + expect(result?.success).toBeTrue(); + expectNoLog(logs, /chunk-[a-z0-9]+\.js/i); + }); + }); +}); diff --git a/packages/angular/build/src/private.ts b/packages/angular/build/src/private.ts index 50d57d0e5a01..7618ca1e3dcb 100644 --- a/packages/angular/build/src/private.ts +++ b/packages/angular/build/src/private.ts @@ -35,7 +35,7 @@ export { export * from './tools/babel/plugins'; export type { ExternalResultMetadata } from './tools/esbuild/bundler-execution-result'; export { emitFilesToDisk } from './tools/esbuild/utils'; -export { transformSupportedBrowsersToTargets } from './tools/esbuild/utils'; +export { transformSupportedBrowsersToTargets } from './tools/esbuild/target'; export { SassWorkerImplementation } from './tools/sass/sass-service'; export { SourceFileCache } from './tools/esbuild/angular/source-file-cache'; diff --git a/packages/angular/build/src/tools/babel/plugins/adjust-static-class-members_oxc_spec.ts b/packages/angular/build/src/tools/babel/plugins/adjust-static-class-members_oxc_spec.ts index af28ab66b264..7fe8c68030fc 100644 --- a/packages/angular/build/src/tools/babel/plugins/adjust-static-class-members_oxc_spec.ts +++ b/packages/angular/build/src/tools/babel/plugins/adjust-static-class-members_oxc_spec.ts @@ -998,4 +998,106 @@ describe('adjust-static-class-members oxc-transform implementation', () => { `, }), ); + + it( + 'wraps adjacent class declarations without interleaving', + testCase({ + input: 'class A{static s=[1]}class B{static s=[2]}', + expected: ` + let A = /*#__PURE__*/ (() => { + class A { + static s = [1] + } + return A; + })(); + let B = /*#__PURE__*/ (() => { + class B { + static s = [2] + } + return B; + })(); + `, + }), + ); + + it( + 'wraps adjacent exported class declarations without interleaving', + testCase({ + input: 'export class A{static s=[1]}export class B{static s=[2]}', + expected: ` + export let A = /*#__PURE__*/ (() => { + class A { + static s = [1] + } + return A; + })(); + export let B = /*#__PURE__*/ (() => { + class B { + static s = [2] + } + return B; + })(); + `, + }), + ); + + it( + 'wraps adjacent default export and class declarations without interleaving', + testCase({ + input: 'export default class A{static s=[1]}class B{static s=[2]}', + expected: ` + let A = /*#__PURE__*/ (() => { + class A { + static s = [1] + } + return A; + })(); + export { A as default }; + let B = /*#__PURE__*/ (() => { + class B { + static s = [2] + } + return B; + })(); + `, + }), + ); + + it( + 'splits default export without interleaving with adjacent class declaration', + testCase({ + input: 'export default class A{}class B{static s=[2]}', + expected: ` + class A {} + export { A as default }; + let B = /*#__PURE__*/ (() => { + class B { + static s = [2] + } + return B; + })(); + `, + }), + ); + + it( + 'wraps adjacent variable class declarations without interleaving', + testCase({ + input: 'let A=class A{static s=[1]};class B{static s=[2]}', + expected: ` + let A = /*#__PURE__*/ (() => { + let A = class A { + static s = [1] + }; + return A; + })(); + let B = /*#__PURE__*/ (() => { + class B { + static s = [2] + } + return B; + })(); + `, + }), + ); }); diff --git a/packages/angular/build/src/tools/babel/plugins/adjust-typescript-enums_oxc_spec.ts b/packages/angular/build/src/tools/babel/plugins/adjust-typescript-enums_oxc_spec.ts index fc01eecf991a..82877cb3b2e3 100644 --- a/packages/angular/build/src/tools/babel/plugins/adjust-typescript-enums_oxc_spec.ts +++ b/packages/angular/build/src/tools/babel/plugins/adjust-typescript-enums_oxc_spec.ts @@ -280,4 +280,103 @@ describe('adjust-typescript-enums oxc-transform implementation', () => { `, }), ); + + it( + 'handles TypeScript enums with chained exports assignment (angular-split / shared-docs pattern)', + testCase({ + input: ` + var Area; + (function (a1) { + a1[a1["areaAfter"] = 0] = "areaAfter"; + a1[a1["preserveOtherCategoryOrder"] = 1] = "preserveOtherCategoryOrder"; + })(Area || (Area = exports.Area = {})); + `, + expected: ` + var Area = /*#__PURE__*/ (function (a1) { + a1[(a1["areaAfter"] = 0)] = "areaAfter"; + a1[(a1["preserveOtherCategoryOrder"] = 1)] = "preserveOtherCategoryOrder"; + return a1; + })(Area || (exports.Area = {})); + `, + }), + ); + + it( + 'handles TypeScript enums wrapped in parentheses', + testCase({ + input: ` + var ChangeDetectionStrategy; + ((function (ChangeDetectionStrategy) { + ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush"; + ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default"; + })(ChangeDetectionStrategy || (ChangeDetectionStrategy = {}))); + `, + expected: ` + var ChangeDetectionStrategy = /*#__PURE__*/ (function (ChangeDetectionStrategy) { + ChangeDetectionStrategy[(ChangeDetectionStrategy["OnPush"] = 0)] = "OnPush"; + ChangeDetectionStrategy[(ChangeDetectionStrategy["Default"] = 1)] = "Default"; + return ChangeDetectionStrategy; + })(ChangeDetectionStrategy || {}); + `, + }), + ); + + it( + 'wraps Crockford-style TypeScript enum IIFE without leaving dangling parentheses', + testCase({ + input: ` + var HDirection; + (function (HDirection) { + HDirection[HDirection['Backwards'] = -1] = 'Backwards'; + HDirection[HDirection['Forwards'] = 1] = 'Forwards'; + }(HDirection || (HDirection = {}))); + const nextStatement = true; + `, + expected: ` + var HDirection = /*#__PURE__*/ (function (HDirection) { + HDirection[(HDirection['Backwards'] = -1)] = 'Backwards'; + HDirection[(HDirection['Forwards'] = 1)] = 'Forwards'; + return HDirection; + }(HDirection || {})); + + const nextStatement = true; + `, + }), + ); + + it( + 'wraps TypeScript enum IIFE with multiple nested parentheses', + testCase({ + input: ` + var Foo; + (((function (Foo) { + Foo[Foo['A'] = 0] = 'A'; + }(Foo || (Foo = {}))))); + `, + expected: ` + var Foo = /*#__PURE__*/ (function (Foo) { + Foo[(Foo['A'] = 0)] = 'A'; + return Foo; + }(Foo || {})); + `, + }), + ); + + it( + 'wraps Crockford-style TypeScript enum IIFE with chained export assignments', + testCase({ + input: ` + var Foo; + (function (Foo) { + Foo[Foo['A'] = 0] = 'A'; + }(Foo || (Foo = exports.Foo = {}))); + `, + expected: ` + var Foo = /*#__PURE__*/ (function (Foo) { + Foo[(Foo['A'] = 0)] = 'A'; + return Foo; + }(Foo || (exports.Foo = {}))); + `, + }), + ); }); diff --git a/packages/angular/build/src/tools/babel/plugins/oxc-transform.ts b/packages/angular/build/src/tools/babel/plugins/oxc-transform.ts index 2c69d98cdf1a..569db927f45a 100644 --- a/packages/angular/build/src/tools/babel/plugins/oxc-transform.ts +++ b/packages/angular/build/src/tools/babel/plugins/oxc-transform.ts @@ -414,27 +414,30 @@ export function transform(filename: string, code: string, options: OxcTransformO continue; } - // 1. Remove only the trailing characters/semicolon of the expression statement + // 1. Remove leading/trailing characters/parentheses of the expression statement + s.remove(nextStatement.start, nextExpr.start); s.remove(nextExpr.end, nextStatement.end); - markEdited(nextExpr.end, nextStatement.end); + markEdited(nextStatement.start, nextStatement.end); // 2. Add return statement inside IIFE body s.appendRight(callee.body.end - 1, `; return ${paramName};`); // 3. Remove `Name = ` assignment in arguments if it's a simple identifier if (rightCallArgument.left.type === 'Identifier') { - s.overwrite( - arg.right.start, - arg.right.end, - code.substring(rightCallArgument.right.start, rightCallArgument.right.end), + let replacement = code.substring( + rightCallArgument.right.start, + rightCallArgument.right.end, ); + if (unwrapParentheses(rightCallArgument.right).type === 'AssignmentExpression') { + replacement = `(${replacement})`; + } + s.overwrite(arg.right.start, arg.right.end, replacement); markEdited(arg.right.start, arg.right.end); } // 4. Move IIFE to the var initializer s.move(nextExpr.start, nextExpr.end, decl.id.end); s.appendLeft(decl.id.end, ' = /*#__PURE__*/ '); - markEdited(nextExpr.start, nextExpr.end); } } @@ -584,25 +587,25 @@ export function transform(filename: string, code: string, options: OxcTransformO // 1. Remove `export default ` s.overwrite(statement.start, classNode.start, ''); // 2. Wrap in IIFE - s.appendLeft(classNode.start, `let ${classIdName} = /*#__PURE__*/ (() => {\n`); - s.appendRight( + s.appendRight(classNode.start, `let ${classIdName} = /*#__PURE__*/ (() => {\n`); + s.appendLeft( lastStatement.end, `\nreturn ${classIdName};\n})();\nexport { ${classIdName} as default };`, ); } else if (isExportNamed) { // 1. Export is kept, turn `class` into `let ClassName = IIFE` - s.appendLeft(classNode.start, `let ${classIdName} = /*#__PURE__*/ (() => {\n`); - s.appendRight(lastStatement.end, `\nreturn ${classIdName};\n})();`); + s.appendRight(classNode.start, `let ${classIdName} = /*#__PURE__*/ (() => {\n`); + s.appendLeft(lastStatement.end, `\nreturn ${classIdName};\n})();`); } else if (isVariableClass) { // Wrap class inside init: `/*#__PURE__*/ (() => { let ClassName = class ClassName {}; return ClassName; })()` - s.appendLeft(classNode.start, `/*#__PURE__*/ (() => {\nlet ${classIdName} = `); + s.appendRight(classNode.start, `/*#__PURE__*/ (() => {\nlet ${classIdName} = `); const terminator = activeWrapPaths.length === 0 ? ';' : ''; const iifeClosing = activeWrapPaths.length === 0 ? '})()' : '})();'; - s.appendRight(lastStatement.end, `${terminator}\nreturn ${classIdName};\n${iifeClosing}`); + s.appendLeft(lastStatement.end, `${terminator}\nreturn ${classIdName};\n${iifeClosing}`); } else { // Standard ClassDeclaration - s.appendLeft(classNode.start, `let ${classIdName} = /*#__PURE__*/ (() => {\n`); - s.appendRight(lastStatement.end, `\nreturn ${classIdName};\n})();`); + s.appendRight(classNode.start, `let ${classIdName} = /*#__PURE__*/ (() => {\n`); + s.appendLeft(lastStatement.end, `\nreturn ${classIdName};\n})();`); } markEdited(statement.start, lastStatement.end); @@ -612,7 +615,7 @@ export function transform(filename: string, code: string, options: OxcTransformO } else if (isExportDefault && !hasPotentialSideEffects) { // Splitting default export even when not wrapped s.overwrite(statement.start, classNode.start, ''); - s.appendRight(classNode.end, `\nexport { ${classIdName} as default };`); + s.appendLeft(classNode.end, `\nexport { ${classIdName} as default };`); markEdited(statement.start, classNode.end); } } diff --git a/packages/angular/build/src/tools/esbuild/angular/compilation-state.ts b/packages/angular/build/src/tools/esbuild/angular/compilation-state.ts index 79fb9715bdbd..286411a06057 100644 --- a/packages/angular/build/src/tools/esbuild/angular/compilation-state.ts +++ b/packages/angular/build/src/tools/esbuild/angular/compilation-state.ts @@ -46,13 +46,14 @@ export class AngularCompilationContext { this.#pendingCompilation = true; } - #disposed = false; + #disposal: Promise | undefined; - async dispose(): Promise { - if (this.#disposed) { - return; - } - this.#disposed = true; + dispose(): Promise { + // Reuse any in progress disposal to ensure all callers can await completion + return (this.#disposal ??= this.#close()); + } + + async #close(): Promise { this.markAsReady(true); try { await this.#compilation.close?.(); diff --git a/packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts b/packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts index 131547f78366..15537cc2508a 100644 --- a/packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts +++ b/packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts @@ -459,7 +459,7 @@ export function createCompilerPlugin( if (!requiresAngularCompiler(directContents)) { return { warnings: [createMissingFileDiagnostic(request, args.path, diangosticRoot, false)], - contents, + contents: directContents, loader: 'ts', resolveDir: path.dirname(request), }; @@ -549,9 +549,7 @@ export function createCompilerPlugin( const replacement = pluginOptions.fileReplacements?.[path.normalize(args.path)]; if (replacement) { return { - contents: await import('node:fs/promises').then(({ readFile }) => - readFile(path.normalize(replacement)), - ), + contents: await readFile(path.normalize(replacement)), loader: 'json' as const, watchFiles: [replacement], }; diff --git a/packages/angular/build/src/tools/esbuild/angular/rewrite-bazel-paths.ts b/packages/angular/build/src/tools/esbuild/angular/rewrite-bazel-paths.ts index 8a6fb6aa82a4..b7cd376d560e 100644 --- a/packages/angular/build/src/tools/esbuild/angular/rewrite-bazel-paths.ts +++ b/packages/angular/build/src/tools/esbuild/angular/rewrite-bazel-paths.ts @@ -6,25 +6,55 @@ * found in the LICENSE file at https://angular.dev/license */ -import { join, relative } from 'node:path'; +import { join, relative, sep } from 'node:path'; const bazelBinDirectory = process.env['BAZEL_BINDIR']; const bazelExecRoot = process.env['JS_BINARY__EXECROOT']; +const execRootMarker = `${sep}execroot${sep}`; + +/** + * Sandboxed actions run in a copy of the execroot whose absolute path differs from + * `JS_BINARY__EXECROOT`, so the effective execroot is derived from the working directory. + */ +function effectiveExecRoot(): string | undefined { + const cwd = process.cwd(); + const markerIndex = cwd.indexOf(execRootMarker); + if (markerIndex === -1) { + return bazelExecRoot; + } + + const workspaceEnd = cwd.indexOf(sep, markerIndex + execRootMarker.length); + + return workspaceEnd === -1 ? cwd : cwd.slice(0, workspaceEnd); +} export function rewriteForBazel(path: string): string { if (!bazelBinDirectory || !bazelExecRoot) { return path; } - const fromExecRoot = relative(bazelExecRoot, path); + const execRoot = effectiveExecRoot() ?? bazelExecRoot; + + const fromExecRoot = relative(execRoot, path); if (!fromExecRoot.startsWith('..')) { return path; } const fromBinDirectory = relative(bazelBinDirectory, path); - if (fromBinDirectory.startsWith('..')) { - return path; + if (!fromBinDirectory.startsWith('..')) { + return join(execRoot, fromBinDirectory); + } + + // A path that realpath resolved out of a symlink-staged sandbox into the + // unsandboxed execroot: re-anchor its execroot-relative tail. + const markerIndex = path.indexOf(execRootMarker); + if (markerIndex !== -1) { + const tail = path.slice(markerIndex + execRootMarker.length); + const workspaceEnd = tail.indexOf(sep); + if (workspaceEnd !== -1) { + return join(execRoot, tail.slice(workspaceEnd + 1)); + } } - return join(bazelExecRoot, fromBinDirectory); + return path; } diff --git a/packages/angular/build/src/tools/esbuild/angular/source-file-cache.ts b/packages/angular/build/src/tools/esbuild/angular/source-file-cache.ts index 2bc38bd12a89..a408650a4f4f 100644 --- a/packages/angular/build/src/tools/esbuild/angular/source-file-cache.ts +++ b/packages/angular/build/src/tools/esbuild/angular/source-file-cache.ts @@ -25,6 +25,19 @@ export class SourceFileCache extends Map { super(); } + /** + * Releases all cached content. The cached data is only needed for incremental + * rebuilds and can include the emitted contents of every TypeScript file in the + * program. The cache is repopulated if a build is performed after this is called. + */ + override clear(): void { + super.clear(); + this.modifiedFiles.clear(); + this.typeScriptFileCache.clear(); + this.loadResultCache.clear(); + this.referencedFiles = undefined; + } + invalidate(files: Iterable): boolean { if (files !== this.modifiedFiles) { this.modifiedFiles.clear(); diff --git a/packages/angular/build/src/tools/esbuild/application-code-bundle.ts b/packages/angular/build/src/tools/esbuild/application-code-bundle.ts index 37ff846c7400..3e7d65a1bc53 100644 --- a/packages/angular/build/src/tools/esbuild/application-code-bundle.ts +++ b/packages/angular/build/src/tools/esbuild/application-code-bundle.ts @@ -71,6 +71,15 @@ export function createBrowserCodeBundleOptions( supported: getFeatureSupport(zoneless), }; + if (options.disableCodeSplitting) { + // Splitting emits shared chunks that are read across chunk boundaries as live ESM bindings, + // which the unit-test runners' module loading does not reliably preserve. + buildOptions.splitting = false; + // In unit test builds, package.json "sideEffects": false annotations can cause esbuild + // to incorrectly elide statically-referenced barrel module bodies across multiple entry points. + buildOptions.ignoreAnnotations = true; + } + buildOptions.plugins ??= []; buildOptions.plugins.push( createWasmPlugin({ allowAsync: zoneless, cache: loadCache }), diff --git a/packages/angular/build/src/tools/esbuild/bundler-context.ts b/packages/angular/build/src/tools/esbuild/bundler-context.ts index 58f2df2a05c8..d3f3ca567a0f 100644 --- a/packages/angular/build/src/tools/esbuild/bundler-context.ts +++ b/packages/angular/build/src/tools/esbuild/bundler-context.ts @@ -17,9 +17,7 @@ import { context, } from 'esbuild'; import assert from 'node:assert'; -import { realpathSync } from 'node:fs'; -import { basename, extname, join, relative, resolve } from 'node:path'; -import { toPosixPath } from '../../utils/path'; +import { basename, extname, join, relative } from 'node:path'; import { SERVER_GENERATED_EXTERNALS } from '../../utils/server-rendering/manifest'; import { type BuildOutputFile, @@ -66,7 +64,6 @@ export class BundlerContext { #optionsFactory: BundlerOptionsFactory; #shouldCacheResult: boolean; #loadCache?: MemoryLoadResultCache; - #realWorkspaceRoot?: string; readonly watchFiles = new Set(); constructor( @@ -264,17 +261,6 @@ export class BundlerContext { } } - // esbuild always resolves its working directory through symbolic links (including - // Windows directory junctions) and generates metafile paths relative to the resolved - // path. When `preserveSymlinks` is enabled, the workspace root is intentionally not - // resolved, and the metafile paths are then relative to a different base directory. - // The paths are remapped so that all downstream consumers can rely on the documented - // invariant that metafile paths are relative to the workspace root. - this.#realWorkspaceRoot ??= realpathSync(this.workspaceRoot); - if (this.#realWorkspaceRoot !== this.workspaceRoot) { - remapMetafileBasePath(result.metafile, this.#realWorkspaceRoot, this.workspaceRoot); - } - // Update files that should be watched. // While this should technically not be linked to incremental mode, incremental is only // currently enabled with watch mode where watch files are needed. @@ -501,71 +487,6 @@ export class BundlerContext { } } -/** - * Remaps all relative paths within an esbuild metafile from one base directory to another. - * Virtual files (e.g., `angular:` namespaced or bundler generated), external imports, and - * non-relative paths are left unmodified. - * - * @param metafile The metafile to update in place. - * @param fromBase The absolute base directory the metafile paths are currently relative to. - * @param toBase The absolute base directory the metafile paths should be made relative to. - */ -export function remapMetafileBasePath(metafile: Metafile, fromBase: string, toBase: string): void { - const remapped = new Map(); - const remap = (value: string): string => { - // Skip virtual files and paths with a scheme-like or namespace prefix (e.g., `angular:`) - if ( - isInternalAngularFile(value) || - isInternalBundlerFile(value) || - /^[^\\/.]{2,}:/.test(value) - ) { - return value; - } - - let result = remapped.get(value); - if (result === undefined) { - // esbuild metafile paths always use POSIX path separators - result = toPosixPath(relative(toBase, resolve(fromBase, value))); - remapped.set(value, result); - } - - return result; - }; - - const inputs: Metafile['inputs'] = {}; - for (const [key, value] of Object.entries(metafile.inputs)) { - for (const importRecord of value.imports) { - if (!importRecord.external) { - importRecord.path = remap(importRecord.path); - } - } - inputs[remap(key)] = value; - } - metafile.inputs = inputs; - - const outputs: Metafile['outputs'] = {}; - for (const [key, value] of Object.entries(metafile.outputs)) { - if (value.entryPoint !== undefined) { - value.entryPoint = remap(value.entryPoint); - } - if (value.cssBundle !== undefined) { - value.cssBundle = remap(value.cssBundle); - } - for (const importRecord of value.imports) { - if (!importRecord.external) { - importRecord.path = remap(importRecord.path); - } - } - const outputInputs: (typeof value)['inputs'] = {}; - for (const [inputKey, inputValue] of Object.entries(value.inputs)) { - outputInputs[remap(inputKey)] = inputValue; - } - value.inputs = outputInputs; - outputs[remap(key)] = value; - } - metafile.outputs = outputs; -} - function isInternalAngularFile(file: string) { return file.startsWith('angular:'); } diff --git a/packages/angular/build/src/tools/esbuild/bundler-context_spec.ts b/packages/angular/build/src/tools/esbuild/bundler-context_spec.ts deleted file mode 100644 index 8806f1d90406..000000000000 --- a/packages/angular/build/src/tools/esbuild/bundler-context_spec.ts +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @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 { Metafile } from 'esbuild'; -import { join, relative } from 'node:path'; -import { remapMetafileBasePath } from './bundler-context'; - -describe('remapMetafileBasePath', () => { - // Simulates a workspace root accessed through a symbolic link or Windows - // directory junction (`toBase`) that resolves to a different real path - // (`fromBase`), as esbuild resolves its working directory through links. - const fromBase = join('/real', 'projects', 'demo'); - const toBase = join('/linked', 'demo'); - - /** Creates a metafile path as esbuild would: relative to the resolved (real) base. */ - const fromBaseRelative = (filePath: string): string => relative(fromBase, join(toBase, filePath)); - - it('remaps input and output paths onto the target base directory', () => { - const metafile: Metafile = { - inputs: { - [fromBaseRelative('src/main.ts')]: { bytes: 10, imports: [] }, - }, - outputs: { - [fromBaseRelative('main.js')]: { - bytes: 100, - inputs: { [fromBaseRelative('src/main.ts')]: { bytesInOutput: 10 } }, - imports: [{ path: fromBaseRelative('chunk-ABC.js'), kind: 'import-statement' }], - exports: [], - entryPoint: fromBaseRelative('src/main.ts'), - cssBundle: fromBaseRelative('main.css'), - }, - }, - }; - - remapMetafileBasePath(metafile, fromBase, toBase); - - expect(Object.keys(metafile.inputs)).toEqual(['src/main.ts']); - expect(Object.keys(metafile.outputs)).toEqual(['main.js']); - - const output = metafile.outputs['main.js']; - expect(output.entryPoint).toBe('src/main.ts'); - expect(output.cssBundle).toBe('main.css'); - expect(Object.keys(output.inputs)).toEqual(['src/main.ts']); - expect(output.imports[0].path).toBe('chunk-ABC.js'); - }); - - it('does not modify virtual and namespaced files', () => { - const metafile: Metafile = { - inputs: { - 'angular:polyfills': { - bytes: 10, - imports: [{ path: '', kind: 'import-statement' }], - }, - }, - outputs: { - [fromBaseRelative('polyfills.js')]: { - bytes: 100, - inputs: { 'angular:polyfills': { bytesInOutput: 10 } }, - imports: [], - exports: [], - entryPoint: 'angular:polyfills', - }, - }, - }; - - remapMetafileBasePath(metafile, fromBase, toBase); - - expect(Object.keys(metafile.inputs)).toEqual(['angular:polyfills']); - expect(metafile.inputs['angular:polyfills'].imports[0].path).toBe(''); - - const output = metafile.outputs['polyfills.js']; - expect(output.entryPoint).toBe('angular:polyfills'); - expect(Object.keys(output.inputs)).toEqual(['angular:polyfills']); - }); - - it('does not modify external imports', () => { - const externalPath = 'https://example.com/module.js'; - const metafile: Metafile = { - inputs: {}, - outputs: { - [fromBaseRelative('main.js')]: { - bytes: 100, - inputs: {}, - imports: [{ path: externalPath, kind: 'import-statement', external: true }], - exports: [], - }, - }, - }; - - remapMetafileBasePath(metafile, fromBase, toBase); - - expect(metafile.outputs['main.js'].imports[0].path).toBe(externalPath); - }); -}); diff --git a/packages/angular/build/src/tools/esbuild/bundler-execution-result.ts b/packages/angular/build/src/tools/esbuild/bundler-execution-result.ts index bebfd6a3eedd..53e17e7e427c 100644 --- a/packages/angular/build/src/tools/esbuild/bundler-execution-result.ts +++ b/packages/angular/build/src/tools/esbuild/bundler-execution-result.ts @@ -194,11 +194,21 @@ export class ExecutionResult { return changed; } - async dispose(): Promise { - await Promise.allSettled([ - ...this.rebuildContexts.typescriptContexts.map((context) => context.dispose()), - ...this.rebuildContexts.otherContexts.map((context) => context.dispose()), - this.componentStyleBundler.dispose(), - ]); + #disposal?: Promise; + + dispose(): Promise { + return (this.#disposal ??= this.#dispose()); + } + + async #dispose(): Promise { + try { + await Promise.allSettled([ + ...this.rebuildContexts.typescriptContexts.map((context) => context.dispose()), + ...this.rebuildContexts.otherContexts.map((context) => context.dispose()), + this.componentStyleBundler.dispose(), + ]); + } finally { + this.codeBundleCache?.clear(); + } } } diff --git a/packages/angular/build/src/tools/esbuild/i18n-inliner-worker.ts b/packages/angular/build/src/tools/esbuild/i18n-inliner-worker.ts index 71a055cea676..7d230f479c11 100644 --- a/packages/angular/build/src/tools/esbuild/i18n-inliner-worker.ts +++ b/packages/angular/build/src/tools/esbuild/i18n-inliner-worker.ts @@ -6,11 +6,13 @@ * found in the LICENSE file at https://angular.dev/license */ -import remapping, { type EncodedSourceMap, type SourceMapInput } from '@ampproject/remapping'; +import remapping, { type DecodedSourceMap, type SourceMapInput } from '@ampproject/remapping'; +import type { Node } from '@oxc-project/types'; import { MagicString } from 'magic-string'; import assert from 'node:assert'; +import { deserialize } from 'node:v8'; import { workerData } from 'node:worker_threads'; -import { Visitor, parseSync } from 'oxc-parser'; +import { parseSync, visitorKeys } from 'oxc-parser'; /** * The options passed to the inliner for each file request @@ -28,9 +30,11 @@ interface InlineFileRequest { locale: string; /** - * The translation messages for the locale that should be used during the inlining process of the file. + * The serialized translation messages for the locale that should be used during the inlining + * process of the file. A Blob is used so that the messages are shared with the Worker by + * reference instead of being copied into it for every request. */ - translation?: Record; + translation?: Blob; } /** @@ -53,19 +57,55 @@ interface InlineCodeRequest { locale: string; /** - * The translation messages for the locale that should be used during the inlining process of the file. + * The serialized translation messages for the locale that should be used during the inlining + * process of the file. A Blob is used so that the messages are shared with the Worker by + * reference instead of being copied into it for every request. */ - translation?: Record; + translation?: Blob; } // Extract the application files and common options used for inline requests from the Worker context -// TODO: Evaluate overall performance difference of passing translations here as well const { files, missingTranslation, shouldOptimize } = (workerData || {}) as { files: ReadonlyMap; missingTranslation: 'error' | 'warning' | 'ignore'; shouldOptimize: boolean; }; +/** + * The translation messages deserialized for the locale most recently requested of this Worker. + * Locales are inlined one at a time, so retaining only the active locale is enough to avoid + * deserializing the messages once per file while holding at most one set of messages in memory. + */ +let activeTranslation: { locale: string; messages: Promise> } | undefined; + +/** + * Deserializes the translation messages for an inline request, reusing the result for any + * subsequent request that targets the same locale. + * @param request An inline request containing the locale and its serialized messages. + * @returns The translation messages, or undefined if the locale has no translations. + */ +function loadTranslation( + request: InlineFileRequest | InlineCodeRequest, +): Promise> | undefined { + const { locale, translation } = request; + if (!translation) { + return undefined; + } + + if (activeTranslation?.locale !== locale) { + activeTranslation = { + locale, + // Deserializing within the stored promise ensures that concurrent requests for a locale + // share the one deserialization instead of each performing their own. + messages: translation + .arrayBuffer() + .then((buffer) => deserialize(new Uint8Array(buffer)) as Record), + }; + } + + return activeTranslation.messages; +} + /** * Inlines the provided locale and translation into a JavaScript file that contains `$localize` usage. * This function is the main entry for the Worker's action that is called by the worker pool. @@ -80,7 +120,12 @@ export default async function inlineFile(request: InlineFileRequest) { const code = await data.text(); const map = await files.get(request.filename + '.map')?.text(); - const result = await transformWithOxc(code, map && (JSON.parse(map) as SourceMapInput), request); + const result = await transformWithOxc( + code, + map && (JSON.parse(map) as SourceMapInput), + request, + await loadTranslation(request), + ); return { file: request.filename, @@ -98,7 +143,12 @@ export default async function inlineFile(request: InlineFileRequest) { * @returns An object containing the inlined code. */ export async function inlineCode(request: InlineCodeRequest) { - const result = await transformWithOxc(request.code, undefined, request); + const result = await transformWithOxc( + request.code, + undefined, + request, + await loadTranslation(request), + ); return { output: result.code, @@ -131,17 +181,68 @@ async function loadLocalizeTools(): Promise { return localizeToolsModule; } +/** + * Traverses ESTree AST nodes in post-order (bottom-up) without recursion. + * Bottom-up traversal ensures that nested `$localize` expressions are transformed and + * written to MagicString before outer containing templates are evaluated. + * + * @param root The root AST node to traverse. + * @param onExit Callback invoked on each AST node in post-order. + */ +function walkAstPostOrder(root: Node, onExit: (node: Node) => void): void { + const traverseStack: Node[] = [root]; + const postOrderNodes: Node[] = []; + + while (traverseStack.length > 0) { + const current = traverseStack.pop(); + if (!current) { + continue; + } + + postOrderNodes.push(current); + + const keys = visitorKeys[current.type]; + if (!keys) { + continue; + } + + for (let i = 0; i < keys.length; i++) { + const child = (current as unknown as Record)[keys[i]]; + if (!child) { + continue; + } + + if (Array.isArray(child)) { + for (const item of child) { + if (item) { + traverseStack.push(item); + } + } + } else { + traverseStack.push(child); + } + } + } + + // Process collected nodes in reverse order to achieve bottom-up (post-order) traversal + for (let i = postOrderNodes.length - 1; i >= 0; i--) { + onExit(postOrderNodes[i]); + } +} + /** * Transforms a JavaScript file using OXC and Magic-String to inline the request locale and translation. * @param code A string containing the JavaScript code to transform. * @param map A sourcemap object for the provided JavaScript code. * @param options The inline request options to use. + * @param translation The translation messages to inline, or undefined for an untranslated locale. * @returns An object containing the code, map, and diagnostics from the transformation. */ async function transformWithOxc( code: string, map: SourceMapInput | undefined, options: InlineFileRequest, + translation: Record | undefined, ) { const { program } = parseSync(options.filename, code, { sourceType: 'unambiguous', @@ -155,13 +256,12 @@ async function transformWithOxc( const { Diagnostics, translate } = await loadLocalizeTools(); const diagnostics = new Diagnostics(); - const visitor = new Visitor({ - Literal(node) { + walkAstPostOrder(program, (node) => { + if (node.type === 'Literal') { if (typeof node.value === 'string' && node.value === '___NG_LOCALE_INSERT___') { magicString.overwrite(node.start, node.end, JSON.stringify(options.locale)); } - }, - 'TaggedTemplateExpression:exit'(node) { + } else if (node.type === 'TaggedTemplateExpression') { if (node.tag.type === 'Identifier' && node.tag.name === '$localize') { const cooked = node.quasi.quasis.map((q) => q.value.cooked); const raw = node.quasi.quasis.map((q) => q.value.raw); @@ -169,10 +269,10 @@ async function transformWithOxc( const [translatedParts, translatedSubstitutions] = translate( diagnostics, - options.translation || {}, + translation || {}, messageParts, node.quasi.expressions.map((_, index) => index), - options.translation === undefined ? 'ignore' : missingTranslation, + translation === undefined ? 'ignore' : missingTranslation, ); // Reconstruct the new template/string literal replacement @@ -201,20 +301,21 @@ async function transformWithOxc( magicString.overwrite(node.start, node.end, replacement); } - }, + } }); - visitor.visit(program); - const outputCode = magicString.toString(); let outputMap; if (map && magicString.hasChanged()) { - const rawMap = magicString.generateMap({ + // A decoded map is generated here rather than an encoded one because remapping decodes its + // inputs. Encoding the mappings only for remapping to immediately decode them again doubles + // the peak memory of the largest structure involved in inlining a file. + const rawMap = magicString.generateDecodedMap({ source: options.filename, includeContent: true, hires: 'boundary', }); - outputMap = remapping([rawMap as EncodedSourceMap, map], () => null); + outputMap = remapping([{ ...rawMap, version: 3 } satisfies DecodedSourceMap, map], () => null); } return { diff --git a/packages/angular/build/src/tools/esbuild/i18n-inliner.ts b/packages/angular/build/src/tools/esbuild/i18n-inliner.ts index af13226a68d4..071097315e5b 100644 --- a/packages/angular/build/src/tools/esbuild/i18n-inliner.ts +++ b/packages/angular/build/src/tools/esbuild/i18n-inliner.ts @@ -9,6 +9,7 @@ import assert from 'node:assert'; import { createHash } from 'node:crypto'; import { extname, join } from 'node:path'; +import { serialize } from 'node:v8'; import { WorkerPool } from '../../utils/worker-pool'; import { type BuildOutputFile, BuildOutputFileType, createOutputFile } from './bundler-files'; import { type PersistentCacheStore, createPersistentCacheStore } from './cache'; @@ -19,6 +20,20 @@ import { type PersistentCacheStore, createPersistentCacheStore } from './cache'; */ const LOCALIZE_KEYWORD = '$localize'; +/** + * Serializes the translation messages for a locale for transfer to an inliner Worker. + * + * A Blob is used because cloning one shares its data by reference, whereas sending the messages + * themselves copies them into a Worker for every request that carries them. A locale can contain + * tens of thousands of messages, which makes that copy the dominant cost of inlining a locale. + * + * @param translation The translation messages for a locale, if the locale has any. + * @returns A Blob containing the serialized messages, or undefined if the locale has none. + */ +function serializeTranslation(translation: Record | undefined): Blob | undefined { + return translation && new Blob([serialize(translation)]); +} + /** * Inlining options that should apply to all transformed code. */ @@ -125,6 +140,10 @@ export class I18nInliner { await this.initCache(); const { shouldOptimize, missingTranslation } = this.options; + + // Serialized once here and then shared by the request for every file of this locale + const translationBlob = serializeTranslation(translation); + // Request inlining for each file that contains localize calls const requests = []; @@ -138,10 +157,12 @@ export class I18nInliner { let cacheResultPromise = Promise.resolve(null); if (this.#cache) { - fileCacheKeyBase ??= Buffer.from( - JSON.stringify({ locale, translation, missingTranslation, shouldOptimize }), - 'utf-8', - ); + // The options are digested here so that each file's key is derived from a fixed number + // of bytes. Hashing the options directly would re-hash the full set of messages, which + // can be several megabytes, once for every file. + fileCacheKeyBase ??= createHash('sha256') + .update(JSON.stringify({ locale, translation, missingTranslation, shouldOptimize })) + .digest(); // NOTE: If additional options are added, this may need to be updated. // TODO: Consider xxhash or similar instead of SHA256 @@ -160,7 +181,11 @@ export class I18nInliner { return cachedResult; } - const result = await this.#workerPool.run({ filename, locale, translation }); + const result = await this.#workerPool.run({ + filename, + locale, + translation: translationBlob, + }); if (this.#cache && cacheKey) { try { // Failure to set the value should not fail the transform @@ -227,7 +252,12 @@ export class I18nInliner { } const { output, messages } = await this.#workerPool.run( - { code: templateCode, filename: templateId, locale, translation }, + { + code: templateCode, + filename: templateId, + locale, + translation: serializeTranslation(translation), + }, { name: 'inlineCode' }, ); @@ -252,8 +282,8 @@ export class I18nInliner { * Stops all active transformation tasks and shuts down all workers. * @returns A void promise that resolves when closing is complete. */ - close(): Promise { - return this.#workerPool.destroy(); + async close(): Promise { + await Promise.allSettled([this.#cache?.close(), this.#workerPool.destroy()]); } /** diff --git a/packages/angular/build/src/tools/esbuild/i18n-inliner_spec.ts b/packages/angular/build/src/tools/esbuild/i18n-inliner_spec.ts new file mode 100644 index 000000000000..e89acc41c161 --- /dev/null +++ b/packages/angular/build/src/tools/esbuild/i18n-inliner_spec.ts @@ -0,0 +1,298 @@ +/** + * @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 { transform } from 'esbuild'; +import { type BuildOutputFile, BuildOutputFileType, createOutputFile } from './bundler-files'; +import { I18nInliner } from './i18n-inliner'; + +/** + * A module that uses a `$localize` message with an explicit message identifier so that the + * translations for a test can be keyed by a known name. + */ +const GREETING_SOURCE = 'export const greeting = $localize`:@@greeting:Hello`;\n'; + +/** + * Creates the parsed translation form that `@angular/localize` expects for a message without + * placeholders. + */ +function translationFor(message: string): Record { + return { messageParts: [message], placeholderNames: [], text: message }; +} + +function browserFile(path: string, contents: string): BuildOutputFile { + return createOutputFile(path, contents, BuildOutputFileType.Browser); +} + +function findFile(outputFiles: BuildOutputFile[], path: string): BuildOutputFile { + const file = outputFiles.find((output) => output.path === path); + if (!file) { + throw new Error(`Expected output files to contain '${path}'.`); + } + + return file; +} + +describe('I18nInliner', () => { + let inliner: I18nInliner | undefined; + + // A single thread is used throughout so that every file of every locale is inlined by the same + // Worker. Any translation state that a Worker retains between requests is then observable. + function createInliner(outputFiles: BuildOutputFile[]): I18nInliner { + inliner = new I18nInliner({ missingTranslation: 'warning', outputFiles }, 1); + + return inliner; + } + + afterEach(async () => { + await inliner?.close(); + inliner = undefined; + }); + + it('inlines the translations of a locale', async () => { + const { outputFiles, errors, warnings } = await createInliner([ + browserFile('main.js', GREETING_SOURCE), + ]).inlineForLocale('fr', { greeting: translationFor('Bonjour') }); + + expect(errors).toEqual([]); + expect(warnings).toEqual([]); + expect(findFile(outputFiles, 'main.js').text).toContain('"Bonjour"'); + expect(findFile(outputFiles, 'main.js').text).not.toContain('$localize'); + }); + + it('inlines the translations of each locale when several are inlined in sequence', async () => { + const localeInliner = createInliner([browserFile('main.js', GREETING_SOURCE)]); + + const french = await localeInliner.inlineForLocale('fr', { + greeting: translationFor('Bonjour'), + }); + const german = await localeInliner.inlineForLocale('de', { greeting: translationFor('Hallo') }); + // Repeats the first locale to cover a locale being inlined again after another has been. + const frenchAgain = await localeInliner.inlineForLocale('fr', { + greeting: translationFor('Bonjour'), + }); + + expect(findFile(french.outputFiles, 'main.js').text).toContain('"Bonjour"'); + expect(findFile(german.outputFiles, 'main.js').text).toContain('"Hallo"'); + expect(findFile(frenchAgain.outputFiles, 'main.js').text).toContain('"Bonjour"'); + }); + + it('inlines the translations of a locale into every file that uses them', async () => { + const { outputFiles } = await createInliner([ + browserFile('main.js', GREETING_SOURCE), + browserFile('chunk.js', GREETING_SOURCE), + ]).inlineForLocale('fr', { greeting: translationFor('Bonjour') }); + + expect(findFile(outputFiles, 'main.js').text).toContain('"Bonjour"'); + expect(findFile(outputFiles, 'chunk.js').text).toContain('"Bonjour"'); + }); + + it('retains the original messages for a locale without translations', async () => { + const { outputFiles, errors, warnings } = await createInliner([ + browserFile('main.js', GREETING_SOURCE), + ]).inlineForLocale('en-US', undefined); + + // A locale without translations is the source locale, so its messages are not missing. + expect(errors).toEqual([]); + expect(warnings).toEqual([]); + expect(findFile(outputFiles, 'main.js').text).toContain('"Hello"'); + }); + + it('warns and retains the original message when a locale is missing a translation', async () => { + const { outputFiles, errors, warnings } = await createInliner([ + browserFile('main.js', GREETING_SOURCE), + ]).inlineForLocale('fr', { unrelated: translationFor('Sans rapport') }); + + expect(errors).toEqual([]); + expect(warnings.length).toBe(1); + expect(warnings[0]).toContain('greeting'); + expect(findFile(outputFiles, 'main.js').text).toContain('"Hello"'); + }); + + it('replaces the locale placeholder with the locale being inlined', async () => { + // The placeholder is only inlined for files that use `$localize`, which is where the build + // inserts it, so the message is present alongside it here. + const { outputFiles } = await createInliner([ + browserFile('main.js', `export const locale = "___NG_LOCALE_INSERT___";\n${GREETING_SOURCE}`), + ]).inlineForLocale('fr', { greeting: translationFor('Bonjour') }); + + expect(findFile(outputFiles, 'main.js').text).toContain('"fr"'); + expect(findFile(outputFiles, 'main.js').text).not.toContain('___NG_LOCALE_INSERT___'); + }); + + it('remaps the source map of a file it modifies', async () => { + // esbuild provides a map from the emitted code back to an original file, matching what the + // inliner receives during a build. + const { code, map } = await transform(GREETING_SOURCE, { + sourcefile: 'greeting.ts', + loader: 'ts', + sourcemap: 'external', + }); + + const { outputFiles } = await createInliner([ + browserFile('main.js', code), + browserFile('main.js.map', map), + ]).inlineForLocale('fr', { greeting: translationFor('Bonjour') }); + + const outputMap = JSON.parse(findFile(outputFiles, 'main.js.map').text) as { + version: number; + sources: string[]; + mappings: string; + }; + + expect(outputMap.version).toBe(3); + // The map must still resolve to the original file rather than to the inliner's input. + expect(outputMap.sources).toContain('greeting.ts'); + expect(outputMap.mappings.length).toBeGreaterThan(0); + }); + + describe('inlineTemplateUpdate', () => { + it('inlines the translations of a locale into a template update', async () => { + const { code, errors, warnings } = await createInliner([]).inlineTemplateUpdate( + 'fr', + { greeting: translationFor('Bonjour') }, + GREETING_SOURCE, + 'template-id', + ); + + expect(errors).toEqual([]); + expect(warnings).toEqual([]); + expect(code).toContain('"Bonjour"'); + expect(code).not.toContain('$localize'); + }); + + it('retains the original messages for a locale without translations', async () => { + const { code, errors, warnings } = await createInliner([]).inlineTemplateUpdate( + 'en-US', + undefined, + GREETING_SOURCE, + 'template-id', + ); + + expect(errors).toEqual([]); + expect(warnings).toEqual([]); + expect(code).toContain('"Hello"'); + }); + + it('returns the code untouched when it has no localize calls', async () => { + const source = 'export const answer = 42;\n'; + const { code } = await createInliner([]).inlineTemplateUpdate( + 'fr', + { greeting: translationFor('Bonjour') }, + source, + 'template-id', + ); + + expect(code).toBe(source); + }); + }); + + it('safely inlines translations containing special characters, quotes, and newlines', async () => { + const { outputFiles, errors, warnings } = await createInliner([ + browserFile('main.js', GREETING_SOURCE), + ]).inlineForLocale('fr', { + greeting: translationFor('Bonjour "mon ami" \\ \' \n '), + }); + + expect(errors).toEqual([]); + expect(warnings).toEqual([]); + expect(findFile(outputFiles, 'main.js').text).toBe( + 'export const greeting = "Bonjour \\"mon ami\\" \\\\ \' \\n ";\n', + ); + }); + + it('inlines translations containing placeholders', async () => { + const source = 'export const welcome = (name) => $localize`:@@welcome:Hello ${name}!`;\n'; + const { outputFiles, errors, warnings } = await createInliner([ + browserFile('main.js', source), + ]).inlineForLocale('fr', { + welcome: { + messageParts: ['Bonjour ', ' !'], + placeholderNames: ['PH'], + text: 'Bonjour {$PH} !', + }, + }); + + expect(errors).toEqual([]); + expect(warnings).toEqual([]); + expect(findFile(outputFiles, 'main.js').text).toBe( + 'export const welcome = (name) => `Bonjour ${name} !`;\n', + ); + }); + + it('inlines multiple localize calls within the same file', async () => { + const source = + 'export const a = $localize`:@@greeting:Hello`;\nexport const b = $localize`:@@farewell:Goodbye`;\n'; + const { outputFiles, errors, warnings } = await createInliner([ + browserFile('main.js', source), + ]).inlineForLocale('fr', { + greeting: translationFor('Bonjour'), + farewell: translationFor('Au revoir'), + }); + + expect(errors).toEqual([]); + expect(warnings).toEqual([]); + expect(findFile(outputFiles, 'main.js').text).toBe( + 'export const a = "Bonjour";\nexport const b = "Au revoir";\n', + ); + }); + + it('inlines translations across multiple files using multiple worker threads in parallel', async () => { + inliner = new I18nInliner( + { + missingTranslation: 'warning', + outputFiles: [ + browserFile('main.js', GREETING_SOURCE), + browserFile('chunk1.js', GREETING_SOURCE), + browserFile('chunk2.js', GREETING_SOURCE), + browserFile('chunk3.js', GREETING_SOURCE), + ], + }, + 4, + ); + + const { outputFiles, errors, warnings } = await inliner.inlineForLocale('fr', { + greeting: translationFor('Bonjour'), + }); + + expect(errors).toEqual([]); + expect(warnings).toEqual([]); + for (const name of ['main.js', 'chunk1.js', 'chunk2.js', 'chunk3.js']) { + expect(findFile(outputFiles, name).text).toBe('export const greeting = "Bonjour";\n'); + } + }); + + it('leaves files without localize calls unmodified', async () => { + const { outputFiles } = await createInliner([ + browserFile('main.js', GREETING_SOURCE), + browserFile('other.js', 'export const answer = 42;\n'), + ]).inlineForLocale('fr', { greeting: translationFor('Bonjour') }); + + expect(findFile(outputFiles, 'other.js').text).toBe('export const answer = 42;\n'); + }); + + it('inlines nested $localize calls in post-order', async () => { + const source = + 'export const msg = $localize`:@@outer:You selected ${$localize`:@@inner:Apple`} for delivery.`;\n'; + const { outputFiles, errors, warnings } = await createInliner([ + browserFile('main.js', source), + ]).inlineForLocale('fr', { + inner: translationFor('Pomme'), + outer: { + messageParts: ['Vous avez sélectionné ', ' pour la livraison.'], + placeholderNames: ['PH'], + text: 'Vous avez sélectionné {$PH} pour la livraison.', + }, + }); + + expect(errors).toEqual([]); + expect(warnings).toEqual([]); + expect(findFile(outputFiles, 'main.js').text).toBe( + 'export const msg = `Vous avez sélectionné ${"Pomme"} pour la livraison.`;\n', + ); + }); +}); diff --git a/packages/angular/build/src/tools/esbuild/license-extractor.ts b/packages/angular/build/src/tools/esbuild/license-extractor.ts index 6629bbc387bf..890ebdd9826f 100644 --- a/packages/angular/build/src/tools/esbuild/license-extractor.ts +++ b/packages/angular/build/src/tools/esbuild/license-extractor.ts @@ -7,7 +7,7 @@ */ import type { Metafile } from 'esbuild'; -import { readFile } from 'node:fs/promises'; +import { readFile, readdir } from 'node:fs/promises'; import path from 'node:path'; /** @@ -30,9 +30,9 @@ const NODE_MODULE_SEGMENT = 'node_modules'; const CUSTOM_LICENSE_TEXT = 'SEE LICENSE IN '; /** - * A list of commonly named license files found within packages. + * A regular expression for commonly named license files found within packages. */ -const LICENSE_FILES = ['LICENSE', 'LICENSE.txt', 'LICENSE.md']; +const LICENSE_FILE_REGEXP = /^(?:mit-)?licen[cs]e(?:$|[-._])/i; /** * Header text that will be added to the top of the output license extraction file. @@ -64,6 +64,7 @@ export async function extractLicenses(metafile: Metafile, rootDirectory: string) let extractedLicenseContent = `${EXTRACTION_FILE_HEADER}\n${EXTRACTION_FILE_SEPARATOR}`; const seenPaths = new Set(); + const seenPackageDirectories = new Set(); const seenPackages = new Set(); for (const entry of Object.values(metafile.outputs)) { @@ -110,6 +111,11 @@ export async function extractLicenses(metafile: Metafile, rootDirectory: string) : nameOrScope; const packageDirectory = path.join(baseDirectory, packageName); + if (seenPackageDirectories.has(packageDirectory)) { + continue; + } + seenPackageDirectories.add(packageDirectory); + // Load the package's metadata to find the package's name, version, and license type const packageJsonPath = path.join(packageDirectory, 'package.json'); let packageJson; @@ -136,12 +142,12 @@ export async function extractLicenses(metafile: Metafile, rootDirectory: string) let licenseText = ''; if ( typeof packageJson.license === 'string' && - packageJson.license.toLowerCase().startsWith(CUSTOM_LICENSE_TEXT) + packageJson.license.toUpperCase().startsWith(CUSTOM_LICENSE_TEXT) ) { // Attempt to load the package's custom license let customLicensePath; const customLicenseFile = path.normalize( - packageJson.license.slice(CUSTOM_LICENSE_TEXT.length + 1).trim(), + packageJson.license.slice(CUSTOM_LICENSE_TEXT.length).trim(), ); if (customLicenseFile.startsWith('..') || path.isAbsolute(customLicenseFile)) { // Path is attempting to access files outside of the package @@ -150,17 +156,20 @@ export async function extractLicenses(metafile: Metafile, rootDirectory: string) customLicensePath = path.join(packageDirectory, customLicenseFile); try { licenseText = await readFile(customLicensePath, 'utf-8'); - break; } catch {} } } else { // Search for a license file within the root of the package - for (const potentialLicense of LICENSE_FILES) { - const packageLicensePath = path.join(packageDirectory, potentialLicense); - try { - licenseText = await readFile(packageLicensePath, 'utf-8'); - break; - } catch {} + const entries = await readdir(packageDirectory, { withFileTypes: true }).catch(() => []); + + for (const entry of entries) { + if ((entry.isFile() || entry.isSymbolicLink()) && LICENSE_FILE_REGEXP.test(entry.name)) { + const packageLicensePath = path.join(packageDirectory, entry.name); + try { + licenseText = await readFile(packageLicensePath, 'utf-8'); + break; + } catch {} + } } } diff --git a/packages/angular/build/src/tools/esbuild/load-result-cache.ts b/packages/angular/build/src/tools/esbuild/load-result-cache.ts index 30067486a384..40936c6a87d1 100644 --- a/packages/angular/build/src/tools/esbuild/load-result-cache.ts +++ b/packages/angular/build/src/tools/esbuild/load-result-cache.ts @@ -48,12 +48,26 @@ export function createCachedLoad( export class MemoryLoadResultCache implements LoadResultCache { #loadResults = new Map(); #fileDependencies = new Map>(); + #watchFilesPerKey = new Map>(); get(path: string): OnLoadResult | undefined { return this.#loadResults.get(path); } async put(path: string, result: OnLoadResult): Promise { + if (result.errors && result.errors.length > 0) { + const previousWatchFiles = this.#watchFilesPerKey.get(path); + if (previousWatchFiles) { + result.watchFiles = Array.from( + new Set([...(result.watchFiles ?? []), ...previousWatchFiles]), + ); + } + } else if (result.watchFiles && result.watchFiles.length > 0) { + this.#watchFilesPerKey.set(path, [...result.watchFiles]); + } else { + this.#watchFilesPerKey.delete(path); + } + this.#loadResults.set(path, result); if (result.watchFiles) { for (const watchFile of result.watchFiles) { @@ -90,4 +104,10 @@ export class MemoryLoadResultCache implements LoadResultCache { // are namespaced request paths and not disk-based file paths. return [...this.#fileDependencies.keys()]; } + + clear(): void { + this.#loadResults.clear(); + this.#fileDependencies.clear(); + this.#watchFilesPerKey.clear(); + } } diff --git a/packages/angular/build/src/tools/esbuild/load-result-cache_spec.ts b/packages/angular/build/src/tools/esbuild/load-result-cache_spec.ts new file mode 100644 index 000000000000..fb0396aea829 --- /dev/null +++ b/packages/angular/build/src/tools/esbuild/load-result-cache_spec.ts @@ -0,0 +1,85 @@ +/** + * @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 { MemoryLoadResultCache } from './load-result-cache'; + +describe('MemoryLoadResultCache', () => { + let cache: MemoryLoadResultCache; + + beforeEach(() => { + cache = new MemoryLoadResultCache(); + }); + + it('should store and retrieve results', async () => { + const result = { + contents: 'body { color: red; }', + loader: 'css' as const, + }; + + await cache.put('file:/test/styles.css', result); + const cached = cache.get('file:/test/styles.css'); + + expect(cached).toBe(result); + }); + + it('should track watch files in fileDependencies', async () => { + const result = { + contents: 'body { color: red; }', + loader: 'css' as const, + watchFiles: ['/test/styles.css', '/test/theme.json'], + }; + + await cache.put('file:/test/styles.css', result); + + expect(cache.watchFiles).toContain('/test/styles.css'); + expect(cache.watchFiles).toContain('/test/theme.json'); + }); + + it('should invalidate cached results when a dependency changes', async () => { + const result = { + contents: 'body { color: red; }', + loader: 'css' as const, + watchFiles: ['/test/styles.css', '/test/theme.json'], + }; + + await cache.put('file:/test/styles.css', result); + expect(cache.get('file:/test/styles.css')).toBe(result); + + const invalidated = cache.invalidate('/test/theme.json'); + expect(invalidated).toBeTrue(); + expect(cache.get('file:/test/styles.css')).toBeUndefined(); + }); + + it('should preserve previous watch files when caching an error result', async () => { + const successResult = { + contents: 'body { color: red; }', + loader: 'css' as const, + watchFiles: ['/test/styles.css', '/test/theme.json'], + }; + + await cache.put('file:/test/styles.css', successResult); + cache.invalidate('/test/theme.json'); + + // Simulate an incremental rebuild error result that only has the entry file in watchFiles + const errorResult = { + errors: [{ text: 'Syntax error in theme.json' }], + watchFiles: ['/test/styles.css'], + }; + + await cache.put('file:/test/styles.css', errorResult); + + // Both the entry file and the previous dependency should be tracked + expect(cache.watchFiles).toContain('/test/styles.css'); + expect(cache.watchFiles).toContain('/test/theme.json'); + + // Invalidating the dependency should clear the cached error result + const invalidated = cache.invalidate('/test/theme.json'); + expect(invalidated).toBeTrue(); + expect(cache.get('file:/test/styles.css')).toBeUndefined(); + }); +}); diff --git a/packages/angular/build/src/tools/esbuild/sqlite-cache-store.ts b/packages/angular/build/src/tools/esbuild/sqlite-cache-store.ts index 3d594668d44f..cbd51d345ddd 100644 --- a/packages/angular/build/src/tools/esbuild/sqlite-cache-store.ts +++ b/packages/angular/build/src/tools/esbuild/sqlite-cache-store.ts @@ -7,14 +7,25 @@ */ import { DatabaseSync, StatementSync } from 'node:sqlite'; +import { deserialize, serialize } from 'node:v8'; import { Cache, PersistentCacheStore } from './cache'; +/** + * A persistent cache store backed by SQLite. + * + * Values are persisted with the V8 structured clone serialization API instead of JSON. Cached + * values include binary data such as the `Uint8Array` output of the JavaScript transformer and + * the `contents` of an esbuild load result. A JSON round-trip converts those into plain objects + * (`{"0":105,"1":109,...}`), which breaks consumers on any build that reads them back from disk. + */ export class SqliteCacheStore implements PersistentCacheStore { #db: DatabaseSync | undefined; #getStmt: StatementSync | undefined; #hasStmt: StatementSync | undefined; #setStmt: StatementSync | undefined; #updateAccessedStmt: StatementSync | undefined; + readonly #pendingAccessedKeys = new Set(); + #flushTimeout: NodeJS.Timeout | undefined; constructor( readonly cachePath: string, @@ -29,8 +40,11 @@ export class SqliteCacheStore implements PersistentCacheStore { this.#db.exec('PRAGMA auto_vacuum = FULL;'); this.#db.exec('PRAGMA journal_mode = WAL;'); this.#db.exec('PRAGMA synchronous = NORMAL;'); + this.#db.exec('PRAGMA busy_timeout = 5000;'); + this.#db.exec('PRAGMA temp_store = MEMORY;'); + this.#db.exec('PRAGMA mmap_size = 268435456;'); this.#db.exec( - 'CREATE TABLE IF NOT EXISTS cache (key TEXT PRIMARY KEY, value TEXT, last_accessed INTEGER NOT NULL) WITHOUT ROWID;', + 'CREATE TABLE IF NOT EXISTS cache (key TEXT PRIMARY KEY, value BLOB, last_accessed INTEGER NOT NULL) WITHOUT ROWID;', ); this.#getStmt = this.#db.prepare('SELECT value FROM cache WHERE key = ?'); @@ -46,18 +60,59 @@ export class SqliteCacheStore implements PersistentCacheStore { return this.#db; } + #queueAccessUpdate(key: string): void { + this.#pendingAccessedKeys.add(key); + + if (this.#pendingAccessedKeys.size >= 100) { + this.#flushAccessUpdates(); + } else if (!this.#flushTimeout) { + this.#flushTimeout = setTimeout(() => this.#flushAccessUpdates(), 500); + this.#flushTimeout.unref?.(); + } + } + + #flushAccessUpdates(): void { + if (this.#flushTimeout) { + clearTimeout(this.#flushTimeout); + this.#flushTimeout = undefined; + } + + if (!this.#db || this.#pendingAccessedKeys.size === 0 || !this.#updateAccessedStmt) { + return; + } + + try { + this.#db.exec('BEGIN IMMEDIATE TRANSACTION;'); + for (const key of this.#pendingAccessedKeys) { + this.#updateAccessedStmt.run(key); + } + this.#db.exec('COMMIT;'); + } catch { + try { + this.#db.exec('ROLLBACK;'); + } catch { + // Ignore rollback errors if transaction was not active + } + } finally { + this.#pendingAccessedKeys.clear(); + } + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any async get(key: string): Promise { this.#ensureDb(); - const row = this.#getStmt?.get(key) as { value: string } | undefined; + // SQLite column types are dynamic, so the stored value is only known at runtime. + const row = this.#getStmt?.get(key) as { value: unknown } | undefined; if (row) { - this.#updateAccessedStmt?.run(key); - - try { - return JSON.parse(row.value); - } catch { - return undefined; + this.#queueAccessUpdate(key); + + if (row.value instanceof Uint8Array) { + try { + return deserialize(row.value); + } catch { + // Treat corrupt or unparseable cached payloads as a cache miss. + } } } @@ -72,7 +127,8 @@ export class SqliteCacheStore implements PersistentCacheStore { async set(key: string, value: unknown): Promise { this.#ensureDb(); - this.#setStmt?.run(key, JSON.stringify(value)); + this.#pendingAccessedKeys.delete(key); + this.#setStmt?.run(key, serialize(value)); return this; } @@ -84,6 +140,9 @@ export class SqliteCacheStore implements PersistentCacheStore { close(): void { if (this.#db) { try { + // Flush any pending access updates in one transaction before pruning + this.#flushAccessUpdates(); + // 1. Delete items older than N days this.#db .prepare("DELETE FROM cache WHERE last_accessed < unixepoch('now', ?);") @@ -103,6 +162,12 @@ export class SqliteCacheStore implements PersistentCacheStore { } catch { // Pruning errors should not block build success } finally { + if (this.#flushTimeout) { + clearTimeout(this.#flushTimeout); + this.#flushTimeout = undefined; + } + this.#pendingAccessedKeys.clear(); + this.#getStmt = undefined; this.#hasStmt = undefined; this.#setStmt = undefined; diff --git a/packages/angular/build/src/tools/esbuild/sqlite-cache-store_spec.ts b/packages/angular/build/src/tools/esbuild/sqlite-cache-store_spec.ts index 679bff21de20..75ab1a358573 100644 --- a/packages/angular/build/src/tools/esbuild/sqlite-cache-store_spec.ts +++ b/packages/angular/build/src/tools/esbuild/sqlite-cache-store_spec.ts @@ -36,6 +36,81 @@ describe('SqliteCacheStore', () => { expect(result).toEqual(data); }); + it('should preserve binary values', async () => { + const data = new TextEncoder().encode('export const value = 1;\n'); + await store.set('binary-key', data); + + const result = await store.get('binary-key'); + expect(result).toBeInstanceOf(Uint8Array); + expect(result).toEqual(data); + }); + + it('should preserve binary values nested within an object', async () => { + const data = { + contents: new TextEncoder().encode('export const value = 1;\n'), + loader: 'js', + watchFiles: ['/some/file.js'], + }; + await store.set('nested-binary-key', data); + + const result = await store.get('nested-binary-key'); + expect(result.contents).toBeInstanceOf(Uint8Array); + expect(result).toEqual(data); + }); + + it('should preserve binary values across store instances', async () => { + const data = new TextEncoder().encode('export const value = 1;\n'); + await store.set('persisted-binary-key', data); + store.close(); + + const reopenedStore = new SqliteCacheStore(cachePath); + try { + const result = await reopenedStore.get('persisted-binary-key'); + expect(result).toBeInstanceOf(Uint8Array); + expect(result).toEqual(data); + } finally { + reopenedStore.close(); + } + }); + + it('should treat a corrupt payload as a cache miss', async () => { + await store.set('corrupt-key', 'value'); + store.close(); + + // Simulate an entry with an invalid/corrupt payload that fails deserialization. + const { DatabaseSync } = await import('node:sqlite'); + const directDb = new DatabaseSync(cachePath); + directDb + .prepare('UPDATE cache SET value = ? WHERE key = ?') + .run(new Uint8Array([0x00, 0x01, 0x02]), 'corrupt-key'); + directDb.close(); + + const reopenedStore = new SqliteCacheStore(cachePath); + try { + expect(await reopenedStore.get('corrupt-key')).toBeUndefined(); + } finally { + reopenedStore.close(); + } + }); + + it('should treat a non-binary payload as a cache miss', async () => { + await store.set('text-key', 'value'); + store.close(); + + // SQLite column types are dynamic, so a stored value is not guaranteed to be binary. + const { DatabaseSync } = await import('node:sqlite'); + const directDb = new DatabaseSync(cachePath); + directDb.prepare('UPDATE cache SET value = ? WHERE key = ?').run('"value"', 'text-key'); + directDb.close(); + + const reopenedStore = new SqliteCacheStore(cachePath); + try { + expect(await reopenedStore.get('text-key')).toBeUndefined(); + } finally { + reopenedStore.close(); + } + }); + it('should return undefined for non-existent key', async () => { const result = await store.get('missing-key'); expect(result).toBeUndefined(); @@ -89,8 +164,8 @@ describe('SqliteCacheStore', () => { store.close(); // Create a store with a tiny size limit (e.g. 25 bytes) - // Keys 'k1', 'k2', 'k3' are small (each is 10 bytes: key + JSON.stringify(value)). - // Total size of k1 + k2 + k3 is 30 bytes, which exceeds the 25 bytes limit. + // Keys 'k1', 'k2', 'k3' are small (each is 12 bytes: 2 byte key + 10 byte serialized value). + // Total size of k1 + k2 + k3 is 36 bytes, which exceeds the 25 bytes limit. const sizeStore = new SqliteCacheStore(cachePath, 25); // Set k1, then k2, then k3. diff --git a/packages/angular/build/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.ts b/packages/angular/build/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.ts index 78925f35835e..2c40e007350e 100644 --- a/packages/angular/build/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.ts +++ b/packages/angular/build/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.ts @@ -427,6 +427,7 @@ async function compileString( }, }, ], + watchFiles: error.file && error.file !== filename ? [filename, error.file] : [filename], }; } else { assertIsError(error); diff --git a/packages/angular/build/src/tools/esbuild/target.ts b/packages/angular/build/src/tools/esbuild/target.ts new file mode 100644 index 000000000000..2925905276b7 --- /dev/null +++ b/packages/angular/build/src/tools/esbuild/target.ts @@ -0,0 +1,116 @@ +/** + * @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 { coerce, compare, minVersion } from 'semver'; + +/** + * Compares two target version strings. + * + * This function is used to determine the lowest version for a given browser target. + * + * @param a The first version string. + * @param b The second version string. + * @returns A negative value if `a` is lower than `b`, a positive value if `a` is higher than `b`, and 0 if they are equal. + */ +function compareTargetVersions(a: string, b: string): number { + const aVersion = coerce(a); + const bVersion = coerce(b); + + if (!aVersion || !bVersion) { + return aVersion ? -1 : bVersion ? 1 : 0; + } + + return compare(aVersion, bVersion); +} + +// https://esbuild.github.io/api/#target +const ESBUILD_SUPPORTED_BROWSERS: ReadonlySet = new Set([ + 'chrome', + 'edge', + 'firefox', + 'ie', + 'ios', + 'node', + 'opera', + 'safari', +]); + +/** + * Transform browserlists result to esbuild target. + * + * Only the lowest version for each browser is returned to avoid issues with esbuild and rolldown + * when multiple versions of the same target engine are specified. + * + * @see https://esbuild.github.io/api/#target + * @see https://github.com/evanw/esbuild/issues/4509 + * @see https://github.com/rolldown/rolldown/issues/10633 + */ +export function transformSupportedBrowsersToTargets(supportedBrowsers: string[]): string[] { + const browsers = new Map(); + + for (const browser of supportedBrowsers) { + let [browserName, version] = browser.toLowerCase().split(' '); + if (!browserName || !version) { + continue; + } + + // browserslist uses the name `ios_saf` for iOS Safari whereas esbuild uses `ios` + if (browserName === 'ios_saf') { + browserName = 'ios'; + } + + if (!ESBUILD_SUPPORTED_BROWSERS.has(browserName)) { + continue; + } + + // browserslist uses ranges `15.2-15.3` versions but only the lowest is required + // to perform minimum supported feature checks. esbuild also expects a single version. + [version] = version.split('-'); + + if (browserName === 'safari' && version === 'tp') { + // esbuild only supports numeric versions so `TP` is converted to a high number (999) since + // a Technology Preview (TP) of Safari is assumed to support all currently known features. + version = '999'; + } else if (!version.includes('.')) { + // A lone major version is considered by esbuild to include all minor versions. However, + // browserslist does not and is also inconsistent in its `.0` version naming. For example, + // Safari 15.0 is named `safari 15` but Safari 16.0 is named `safari 16.0`. + version += '.0'; + } + + const current = browsers.get(browserName); + if (!current || compareTargetVersions(version, current) < 0) { + browsers.set(browserName, version); + } + } + + return Array.from(browsers, ([browserName, version]) => browserName + version); +} + +const SUPPORTED_NODE_VERSIONS = '0.0.0-ENGINES-NODE'; + +/** + * Transform supported Node.js versions to esbuild target. + * + * Only the lowest Node.js version is returned to avoid issues with esbuild and rolldown + * when multiple versions of the same target engine are specified. + * + * @see https://esbuild.github.io/api/#target + * @see https://github.com/evanw/esbuild/issues/4509 + * @see https://github.com/rolldown/rolldown/issues/10633 + */ +export function getSupportedNodeTargets(): string[] { + if (SUPPORTED_NODE_VERSIONS.charAt(0) === '0') { + // Unlike `pkg_npm`, `ts_library` which is used to run unit tests does not support substitutions. + return []; + } + + const parsed = minVersion(SUPPORTED_NODE_VERSIONS); + + return parsed ? ['node' + parsed.version] : []; +} diff --git a/packages/angular/build/src/tools/esbuild/target_spec.ts b/packages/angular/build/src/tools/esbuild/target_spec.ts new file mode 100644 index 000000000000..e5a375a1412b --- /dev/null +++ b/packages/angular/build/src/tools/esbuild/target_spec.ts @@ -0,0 +1,80 @@ +/** + * @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 { getSupportedNodeTargets, transformSupportedBrowsersToTargets } from './target'; + +describe('esbuild target', () => { + describe('transformSupportedBrowsersToTargets', () => { + it('should return the smallest version for each browser', () => { + const targets = transformSupportedBrowsersToTargets([ + 'chrome 122', + 'chrome 120', + 'chrome 121', + 'firefox 116', + 'firefox 115', + 'safari 17.0', + 'safari 16.4', + ]); + + expect(targets).toEqual(['chrome120.0', 'firefox115.0', 'safari16.4']); + }); + + it('should handle version ranges and pick the lowest version', () => { + const targets = transformSupportedBrowsersToTargets([ + 'ios_saf 15.4', + 'ios_saf 15.2-15.3', + 'ios_saf 16.0', + ]); + + expect(targets).toEqual(['ios15.2']); + }); + + it('should handle Safari TP (Technology Preview)', () => { + const targetsWithOlderSafari = transformSupportedBrowsersToTargets([ + 'safari TP', + 'safari 16.4', + ]); + expect(targetsWithOlderSafari).toEqual(['safari16.4']); + + const targetsWithOnlyTP = transformSupportedBrowsersToTargets(['safari TP']); + expect(targetsWithOnlyTP).toEqual(['safari999']); + }); + + it('should ignore browsers not supported by esbuild', () => { + const targets = transformSupportedBrowsersToTargets([ + 'android 4.4', + 'samsung 22', + 'kaios 2.5', + 'chrome 115', + ]); + + expect(targets).toEqual(['chrome115.0']); + }); + + it('should return empty array for empty supportedBrowsers', () => { + const targets = transformSupportedBrowsersToTargets([]); + expect(targets).toEqual([]); + }); + + it('should handle malformed or incomplete browser strings gracefully', () => { + const targets = transformSupportedBrowsersToTargets(['chrome', 'firefox ', '']); + expect(targets).toEqual([]); + }); + + it('should handle single major versions by appending .0', () => { + const targets = transformSupportedBrowsersToTargets(['chrome 120', 'edge 120']); + expect(targets).toEqual(['chrome120.0', 'edge120.0']); + }); + }); + + describe('getSupportedNodeTargets', () => { + it('should return empty array when node versions are not stamped', () => { + expect(getSupportedNodeTargets()).toEqual([]); + }); + }); +}); diff --git a/packages/angular/build/src/tools/esbuild/utils.ts b/packages/angular/build/src/tools/esbuild/utils.ts index 6d76623f1493..e4881e184862 100644 --- a/packages/angular/build/src/tools/esbuild/utils.ts +++ b/packages/angular/build/src/tools/esbuild/utils.ts @@ -12,7 +12,6 @@ import { Listr } from 'listr2'; import { basename, join } from 'node:path'; import { pathToFileURL } from 'node:url'; import { brotliCompress } from 'node:zlib'; -import { coerce } from 'semver'; import { NormalizedApplicationBuildOptions } from '../../builders/application/options'; import { OutputMode } from '../../builders/application/schema'; import { BudgetCalculatorResult } from '../../utils/bundle-calculator'; @@ -213,7 +212,7 @@ export async function emitFilesToDisk( writeFileCallback: (file: T) => Promise, ): Promise { // Write files in groups of MAX_CONCURRENT_WRITES to avoid too many open files - for (let fileIndex = 0; fileIndex < files.length; ) { + for (let fileIndex = 0; fileIndex < files.length;) { const groupMax = Math.min(fileIndex + MAX_CONCURRENT_WRITES, files.length); const actions = []; @@ -225,71 +224,6 @@ export async function emitFilesToDisk( } } -/** - * Transform browserlists result to esbuild target. - * @see https://esbuild.github.io/api/#target - */ -export function transformSupportedBrowsersToTargets(supportedBrowsers: string[]): string[] { - const transformed: string[] = []; - - // https://esbuild.github.io/api/#target - const esBuildSupportedBrowsers = new Set([ - 'chrome', - 'edge', - 'firefox', - 'ie', - 'ios', - 'node', - 'opera', - 'safari', - ]); - - for (const browser of supportedBrowsers) { - let [browserName, version] = browser.toLowerCase().split(' '); - - // browserslist uses the name `ios_saf` for iOS Safari whereas esbuild uses `ios` - if (browserName === 'ios_saf') { - browserName = 'ios'; - } - - // browserslist uses ranges `15.2-15.3` versions but only the lowest is required - // to perform minimum supported feature checks. esbuild also expects a single version. - [version] = version.split('-'); - - if (esBuildSupportedBrowsers.has(browserName)) { - if (browserName === 'safari' && version === 'tp') { - // esbuild only supports numeric versions so `TP` is converted to a high number (999) since - // a Technology Preview (TP) of Safari is assumed to support all currently known features. - version = '999'; - } else if (!version.includes('.')) { - // A lone major version is considered by esbuild to include all minor versions. However, - // browserslist does not and is also inconsistent in its `.0` version naming. For example, - // Safari 15.0 is named `safari 15` but Safari 16.0 is named `safari 16.0`. - version += '.0'; - } - - transformed.push(browserName + version); - } - } - - return transformed; -} - -const SUPPORTED_NODE_VERSIONS = '0.0.0-ENGINES-NODE'; - -/** - * Transform supported Node.js versions to esbuild target. - * @see https://esbuild.github.io/api/#target - */ -export function getSupportedNodeTargets(): string[] { - if (SUPPORTED_NODE_VERSIONS.charAt(0) === '0') { - // Unlike `pkg_npm`, `ts_library` which is used to run unit tests does not support substitutions. - return []; - } - - return SUPPORTED_NODE_VERSIONS.split('||').map((v) => 'node' + coerce(v)?.version); -} - interface BuildManifest { errors: string[]; warnings: string[]; diff --git a/packages/angular/build/src/tools/vite/utils.ts b/packages/angular/build/src/tools/vite/utils.ts index f2b54d403334..dc7094b8ffe4 100644 --- a/packages/angular/build/src/tools/vite/utils.ts +++ b/packages/angular/build/src/tools/vite/utils.ts @@ -48,6 +48,7 @@ export type RolldownLoaderOption = Exclude< >['moduleTypes']; export function getDepOptimizationConfig({ + target, disabled, exclude, include, @@ -56,6 +57,7 @@ export function getDepOptimizationConfig({ thirdPartySourcemaps, define = {}, }: { + target: string[]; disabled: boolean; exclude: string[]; include: string[]; @@ -73,6 +75,7 @@ export function getDepOptimizationConfig({ noDiscovery: disabled, rolldownOptions: { transform: { + target, define, }, moduleTypes: loader, diff --git a/packages/angular/build/src/utils/bundle-calculator.ts b/packages/angular/build/src/utils/bundle-calculator.ts index 3349a8a40830..71a75dafde02 100644 --- a/packages/angular/build/src/utils/bundle-calculator.ts +++ b/packages/angular/build/src/utils/bundle-calculator.ts @@ -152,6 +152,8 @@ function calculateSizes(budget: BudgetEntry, stats: BudgetStats): Size[] { } abstract class Calculator { + private assetMap?: ReadonlyMap; + constructor( protected budget: BudgetEntry, protected chunks: BudgetChunk[], @@ -167,15 +169,24 @@ abstract class Calculator { return 0; } + if (!this.assetMap) { + const map = new Map(); + for (const asset of this.assets) { + map.set(asset.name, asset.size); + } + this.assetMap = map; + } + const assetMap = this.assetMap; + return chunk.files .filter((file) => !file.endsWith('.map')) .map((file) => { - const asset = this.assets.find((asset) => asset.name === file); - if (!asset) { + const assetSize = assetMap.get(file); + if (assetSize === undefined) { throw new Error(`Could not find asset for file: ${file}`); } - return asset.size; + return assetSize; }) .reduce((l, r) => l + r, 0); } diff --git a/packages/angular/build/src/utils/index-file/auto-csp.ts b/packages/angular/build/src/utils/index-file/auto-csp.ts index 0e1dfe3ed916..df33f0766607 100644 --- a/packages/angular/build/src/utils/index-file/auto-csp.ts +++ b/packages/angular/build/src/utils/index-file/auto-csp.ts @@ -22,6 +22,8 @@ interface SrcScriptTag { type?: string; async: boolean; defer: boolean; + integrity?: string; + crossOrigin?: string; } /** @@ -106,11 +108,14 @@ export async function autoCsp(html: string, unsafeEval = false): Promise // If there are any interesting attributes, note them down. const scriptType = getScriptAttributeValue(tag, 'type'); if (shouldDynamicallyLoadScriptTagBasedOnType(scriptType)) { + const crossOrigin = getScriptAttributeValue(tag, 'crossorigin'); scriptContent.push({ src: src, type: scriptType, async: getScriptAttributeValue(tag, 'async') !== undefined, defer: getScriptAttributeValue(tag, 'defer') !== undefined, + integrity: getScriptAttributeValue(tag, 'integrity'), + crossOrigin: crossOrigin === '' ? 'anonymous' : crossOrigin, }); return; // Skip writing my script tag until we've read it all. @@ -267,36 +272,52 @@ function createLoaderScript(srcList: SrcScriptTag[], enableTrustedTypes = false) const srcAttr = encodeURI(s.src).replaceAll("'", "\\'"); // Can only be 'module' or a JS MIME type or an empty string. const typeAttr = s.type ? "'" + s.type + "'" : "''"; - const asyncAttr = s.async ? 'true' : 'false'; - const deferAttr = s.defer ? 'true' : 'false'; + const asyncAttr = !!s.async; + const deferAttr = !!s.defer; + const integrityAttr = JSON.stringify(s.integrity ?? null).replaceAll('<', '\\u003c'); + const crossOriginAttr = JSON.stringify(s.crossOrigin ?? null).replaceAll('<', '\\u003c'); - return `['${srcAttr}', ${typeAttr}, ${asyncAttr}, ${deferAttr}]`; + return `['${srcAttr}', ${typeAttr}, ${asyncAttr}, ${deferAttr}, ${integrityAttr}, ${crossOriginAttr}]`; }) .join(); return enableTrustedTypes - ? ` - var scripts = [${srcListFormatted}]; - var policy = self.trustedTypes && self.trustedTypes.createPolicy ? + ? `(() => { + const scripts = [${srcListFormatted}]; + const policy = self.trustedTypes && self.trustedTypes.createPolicy ? self.trustedTypes.createPolicy('angular#auto-csp', {createScriptURL: function(u) { - return scripts.includes(u) ? u : null; + return scripts.some(function(s) { return s[0] === u; }) ? u : null; }}) : { createScriptURL: function(u) { return u; } }; scripts.forEach(function(scriptUrl) { - var s = document.createElement('script'); + const s = document.createElement('script'); s.src = policy.createScriptURL(scriptUrl[0]); s.type = scriptUrl[1]; - s.async = !!scriptUrl[2]; - s.defer = !!scriptUrl[3]; + s.async = scriptUrl[2]; + s.defer = scriptUrl[3]; + if (scriptUrl[4]) { + s.integrity = scriptUrl[4]; + } + if (scriptUrl[5]) { + s.crossOrigin = scriptUrl[5]; + } document.lastElementChild.appendChild(s); - });\n` - : ` - var scripts = [${srcListFormatted}]; + }); +})();\n` + : `(() => { + const scripts = [${srcListFormatted}]; scripts.forEach(function(scriptUrl) { - var s = document.createElement('script'); + const s = document.createElement('script'); s.src = scriptUrl[0]; s.type = scriptUrl[1]; - s.async = !!scriptUrl[2]; - s.defer = !!scriptUrl[3]; + s.async = scriptUrl[2]; + s.defer = scriptUrl[3]; + if (scriptUrl[4]) { + s.integrity = scriptUrl[4]; + } + if (scriptUrl[5]) { + s.crossOrigin = scriptUrl[5]; + } document.lastElementChild.appendChild(s); - });\n`; + }); +})();\n`; } diff --git a/packages/angular/build/src/utils/index-file/auto-csp_spec.ts b/packages/angular/build/src/utils/index-file/auto-csp_spec.ts index efbd338233ad..29e9bff68074 100644 --- a/packages/angular/build/src/utils/index-file/auto-csp_spec.ts +++ b/packages/angular/build/src/utils/index-file/auto-csp_spec.ts @@ -58,7 +58,7 @@ describe('auto-csp', () => { const csps = getCsps(result); expect(csps).toHaveSize(1); expect(csps[0]).toMatch(CSP_SINGLE_HASH_REGEX); - expect(result).toContain(`var scripts = [['./main.js', '', false, false]];`); + expect(result).toContain(`const scripts = [['./main.js', '', false, false, null, null]];`); }); it('should rewrite a single source script in place', async () => { @@ -78,7 +78,7 @@ describe('auto-csp', () => { expect(csps[0]).toMatch(CSP_SINGLE_HASH_REGEX); // Our loader script appears after the HTML text content. expect(result).toMatch( - /Some text<\/div>\s*`); @@ -166,12 +166,12 @@ describe('auto-csp', () => { // Loader script for main.js and main2.js appear after 'foo' and before 'bar'. expect(result).toMatch( // eslint-disable-next-line max-len - /console.log\('foo'\);<\/script>\s* +
Some text
+ + + `); + + const csps = getCsps(result); + expect(csps).toHaveSize(1); + expect(csps[0]).toMatch(CSP_SINGLE_HASH_REGEX); + expect(result).toContain( + `const scripts = [['./main.js', 'module', false, false, "sha384-xyz123", "anonymous"]];`, + ); + }); + + it('should preserve only integrity attribute when crossorigin is omitted', async () => { + const result = await autoCsp(` + + + + + +
Some text
+ + + `); + + const csps = getCsps(result); + expect(csps).toHaveSize(1); + expect(csps[0]).toMatch(CSP_SINGLE_HASH_REGEX); + expect(result).toContain( + `const scripts = [['./main.js', '', false, false, "sha384-xyz123", null]];`, + ); + }); + + it('should map empty crossorigin attribute to anonymous', async () => { + const result = await autoCsp(` + + + + + +
Some text
+ + + `); + + const csps = getCsps(result); + expect(csps).toHaveSize(1); + expect(csps[0]).toMatch(CSP_SINGLE_HASH_REGEX); + expect(result).toContain( + `const scripts = [['./main.js', '', false, false, null, "anonymous"]];`, + ); + }); }); diff --git a/packages/angular/build/src/utils/path.ts b/packages/angular/build/src/utils/path.ts index 4056972f790c..a236878d134e 100644 --- a/packages/angular/build/src/utils/path.ts +++ b/packages/angular/build/src/utils/path.ts @@ -6,7 +6,6 @@ * found in the LICENSE file at https://angular.dev/license */ -import { realpathSync } from 'node:fs'; import { isAbsolute, posix, relative, resolve } from 'node:path'; import { platform } from 'node:process'; @@ -53,18 +52,15 @@ export function isSubDirectory(parent: string, child: string): boolean { } /** - * Canonicalizes a file path by normalising Windows drive-letter casing to uppercase - * and optionally resolving symbolic links. + * Canonicalizes a file path by normalising Windows drive-letter casing to uppercase. * * @param pathString - The file path to canonicalize. - * @param preserveSymlinks - If true, symbolic links will not be resolved. * @returns The canonicalized file path. */ -export function canonicalizePath(pathString: string, preserveSymlinks = false): string { - const resolved = preserveSymlinks ? pathString : realpathSync(pathString); - if (platform === 'win32' && /^[a-z]:/.test(resolved)) { - return resolved[0].toUpperCase() + resolved.slice(1); +export function canonicalizePath(pathString: string): string { + if (platform === 'win32' && /^[a-z]:/.test(pathString)) { + return pathString[0].toUpperCase() + pathString.slice(1); } - return resolved; + return pathString; } diff --git a/packages/angular/build/src/utils/path_spec.ts b/packages/angular/build/src/utils/path_spec.ts index 84c7d8ac31c4..cd8ca3372433 100644 --- a/packages/angular/build/src/utils/path_spec.ts +++ b/packages/angular/build/src/utils/path_spec.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ -import { isSubDirectory } from './path'; +import { canonicalizePath, isSubDirectory } from './path'; describe('isSubDirectory', () => { it('should return true for a direct child', () => { @@ -39,3 +39,17 @@ describe('isSubDirectory', () => { expect(isSubDirectory('/foo/bar', '/foo/bar/..baz/qux')).toBeTrue(); }); }); + +describe('canonicalizePath', () => { + it('should return the path unmodified on POSIX systems', () => { + expect(canonicalizePath('/foo/bar/baz')).toBe('/foo/bar/baz'); + }); + + if (process.platform === 'win32') { + it('should uppercase Windows drive-letter casing', () => { + expect(canonicalizePath('c:/foo/bar')).toBe('C:/foo/bar'); + expect(canonicalizePath('d:\\foo\\bar')).toBe('D:\\foo\\bar'); + expect(canonicalizePath('C:/foo/bar')).toBe('C:/foo/bar'); + }); + } +}); diff --git a/packages/angular/build/src/utils/server-rendering/esm-in-memory-loader/loader-hooks.ts b/packages/angular/build/src/utils/server-rendering/esm-in-memory-loader/loader-hooks.ts index 1d0d9df32d30..6f21bfbc739b 100644 --- a/packages/angular/build/src/utils/server-rendering/esm-in-memory-loader/loader-hooks.ts +++ b/packages/angular/build/src/utils/server-rendering/esm-in-memory-loader/loader-hooks.ts @@ -16,6 +16,7 @@ import { fileURLToPath, pathToFileURL } from 'node:url'; * @note For some unknown reason, setting `globalThis.ngServerMode = true` does not work when using ESM loader hooks. */ const NG_SERVER_MODE_INIT_BYTES = new TextEncoder().encode('var ngServerMode=true;'); +const UTF8_DECODER = new TextDecoder(); /** * Node.js ESM loader to redirect imports to in memory files. @@ -25,12 +26,12 @@ const NG_SERVER_MODE_INIT_BYTES = new TextEncoder().encode('var ngServerMode=tru const MEMORY_URL_SCHEME = 'memory://'; export interface ESMInMemoryFileLoaderWorkerData { - outputFiles: Record; + outputFiles: Record; workspaceRoot: string; } let memoryVirtualRootUrl: string; -let outputFiles: Record; +let outputFiles: Record; export function initialize(data: ESMInMemoryFileLoaderWorkerData) { // This path does not actually exist but is used to overlay the in memory files with the @@ -84,7 +85,7 @@ export function resolve( } catch {} if ( - specifierUrl?.pathname && + specifierUrl?.href.startsWith(memoryVirtualRootUrl) && Object.hasOwn(outputFiles, specifierUrl.href.slice(memoryVirtualRootUrl.length)) ) { return { @@ -114,12 +115,14 @@ export async function load(url: string, context: { format?: string | null }, nex // Load the file from memory if the URL is based in the virtual root if (url.startsWith(memoryVirtualRootUrl)) { - const source = outputFiles[url.slice(memoryVirtualRootUrl.length)]; - assert(source !== undefined, 'Resolved in-memory ESM file should always exist: ' + url); + const rawSource = outputFiles[url.slice(memoryVirtualRootUrl.length)]; + assert(rawSource !== undefined, 'Resolved in-memory ESM file should always exist: ' + url); + + const source = typeof rawSource === 'string' ? rawSource : UTF8_DECODER.decode(rawSource); // In-memory files have already been transformer during bundling and can be returned directly return { - format, + format: format ?? 'module', shortCircuit: true, source, }; @@ -128,14 +131,15 @@ export async function load(url: string, context: { format?: string | null }, nex // Only module files potentially require transformation. Angular libraries that would // need linking are ESM only. if (format === 'module' && isFileProtocol(url)) { - const filePath = fileURLToPath(url); - let source = await readFile(filePath); - - if (filePath.includes('@angular/')) { - // Prepend 'var ngServerMode=true;' to the source. - source = Buffer.concat([NG_SERVER_MODE_INIT_BYTES, source]); + // Check url instead of filePath so the check is robust across Windows and POSIX path separators. + if (!url.includes('/@angular/')) { + return nextLoad(url, context); } + const filePath = fileURLToPath(url); + const fileBytes = await readFile(filePath); + const source = Buffer.concat([NG_SERVER_MODE_INIT_BYTES, fileBytes]); + return { format, shortCircuit: true, diff --git a/packages/angular/build/src/utils/server-rendering/esm-in-memory-loader/loader-hooks_spec.ts b/packages/angular/build/src/utils/server-rendering/esm-in-memory-loader/loader-hooks_spec.ts new file mode 100644 index 000000000000..2b7622145378 --- /dev/null +++ b/packages/angular/build/src/utils/server-rendering/esm-in-memory-loader/loader-hooks_spec.ts @@ -0,0 +1,246 @@ +/** + * @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 { initialize, load, resolve } from './loader-hooks'; +import { createSharedServerFiles } from './utils'; + +describe('esm-in-memory-loader loader-hooks', () => { + const workspaceRoot = '/mock/workspace/root'; + const sharedFiles = createSharedServerFiles({ + 'main.server.mjs': 'export const main = true;', + 'chunk-abc.mjs': 'export const chunk = "abc";', + 'nested/chunk-sub.mjs': 'export const sub = "sub";', + 'utf8.mjs': 'export const text = "🔥 UTF-8 🚀";', + 'empty.mjs': '', + }); + + beforeEach(() => { + initialize({ + workspaceRoot, + outputFiles: sharedFiles, + }); + }); + + describe('resolve', () => { + it('should resolve memory:// URLs into virtual filesystem URLs', () => { + const nextResolve = jasmine.createSpy('nextResolve'); + const memoryUrl = new URL('./main.server.mjs', 'memory://').href; + const result = resolve(memoryUrl, { parentURL: undefined }, nextResolve); + + expect(nextResolve).not.toHaveBeenCalled(); + expect(result.format).toBe('module'); + expect(result.shortCircuit).toBeTrue(); + expect(result.url).toContain('/.angular/prerender-root/'); + expect(result.url).toContain('/main.server.mjs'); + }); + + it('should fail when memory:// URL is malformed', () => { + const nextResolve = jasmine.createSpy('nextResolve'); + expect(() => { + resolve('memory://::invalid', { parentURL: undefined }, nextResolve); + }).toThrowMatching((err: Error) => + err.message.includes('External code attempted to use malformed memory scheme'), + ); + expect(nextResolve).not.toHaveBeenCalled(); + }); + + it('should resolve relative specifiers within in-memory files', () => { + const memoryUrl = new URL('./main.server.mjs', 'memory://').href; + const rootResolve = resolve(memoryUrl, { parentURL: undefined }, () => {}); + const parentURL = rootResolve.url; + + const nextResolve = jasmine.createSpy('nextResolve'); + const result = resolve('./chunk-abc.mjs', { parentURL }, nextResolve); + + expect(nextResolve).not.toHaveBeenCalled(); + expect(result.format).toBe('module'); + expect(result.shortCircuit).toBeTrue(); + expect(result.url).toContain('/chunk-abc.mjs'); + }); + + it('should resolve relative specifiers navigating parent directories within in-memory files', () => { + const memoryUrl = new URL('./nested/chunk-sub.mjs', 'memory://').href; + const rootResolve = resolve(memoryUrl, { parentURL: undefined }, () => {}); + const parentURL = rootResolve.url; + + const nextResolve = jasmine.createSpy('nextResolve'); + const result = resolve('../chunk-abc.mjs', { parentURL }, nextResolve); + + expect(nextResolve).not.toHaveBeenCalled(); + expect(result.format).toBe('module'); + expect(result.shortCircuit).toBeTrue(); + expect(result.url).toContain('/chunk-abc.mjs'); + }); + + it('should fail when relative specifier from in-memory file does not exist', () => { + const memoryUrl = new URL('./main.server.mjs', 'memory://').href; + const rootResolve = resolve(memoryUrl, { parentURL: undefined }, () => {}); + const parentURL = rootResolve.url; + + const nextResolve = jasmine.createSpy('nextResolve'); + expect(() => { + resolve('./non-existent.mjs', { parentURL }, nextResolve); + }).toThrowMatching((err: Error) => + err.message.includes('In-memory ESM relative file should always exist'), + ); + expect(nextResolve).not.toHaveBeenCalled(); + }); + + it('should rewrite parentURL to index.js in virtual root for bare package specifiers', () => { + const memoryUrl = new URL('./main.server.mjs', 'memory://').href; + const rootResolve = resolve(memoryUrl, { parentURL: undefined }, () => {}); + const parentURL = rootResolve.url; + + const nextResolve = jasmine + .createSpy('nextResolve') + .and.returnValue({ url: 'file:///some/node_modules/@angular/core/index.js' }); + const result = resolve('@angular/core', { parentURL }, nextResolve); + + expect(nextResolve).toHaveBeenCalledWith( + '@angular/core', + jasmine.objectContaining({ + parentURL: jasmine.stringMatching(/\/\.angular\/prerender-root\/[^/]+\/index\.js$/), + }), + ); + expect(result.url).toBe('file:///some/node_modules/@angular/core/index.js'); + }); + + it('should delegate to nextResolve for external non-memory URLs', () => { + const nextResolve = jasmine + .createSpy('nextResolve') + .and.returnValue({ url: 'file:///some/ext/pkg' }); + const result = resolve('some-pkg', { parentURL: 'file:///some/ext/file.js' }, nextResolve); + + expect(nextResolve).toHaveBeenCalledWith('some-pkg', { + parentURL: 'file:///some/ext/file.js', + }); + expect(result.url).toBe('file:///some/ext/pkg'); + }); + }); + + describe('load', () => { + it('should load in-memory file source from SharedArrayBuffer backed Uint8Array', async () => { + const memoryUrl = new URL('./main.server.mjs', 'memory://').href; + const rootResolve = resolve(memoryUrl, { parentURL: undefined }, () => {}); + const nextLoad = jasmine.createSpy('nextLoad'); + + const result = await load(rootResolve.url, { format: 'module' }, nextLoad); + + expect(nextLoad).not.toHaveBeenCalled(); + expect(result.format).toBe('module'); + expect(result.shortCircuit).toBeTrue(); + expect(result.source).toBe('export const main = true;'); + }); + + it('should load in-memory file with multi-byte UTF-8 characters', async () => { + const memoryUrl = new URL('./utf8.mjs', 'memory://').href; + const rootResolve = resolve(memoryUrl, { parentURL: undefined }, () => {}); + const nextLoad = jasmine.createSpy('nextLoad'); + + const result = await load(rootResolve.url, { format: 'module' }, nextLoad); + + expect(nextLoad).not.toHaveBeenCalled(); + expect(result.format).toBe('module'); + expect(result.shortCircuit).toBeTrue(); + expect(result.source).toBe('export const text = "🔥 UTF-8 🚀";'); + }); + + it('should load in-memory file with empty content', async () => { + const memoryUrl = new URL('./empty.mjs', 'memory://').href; + const rootResolve = resolve(memoryUrl, { parentURL: undefined }, () => {}); + const nextLoad = jasmine.createSpy('nextLoad'); + + const result = await load(rootResolve.url, { format: 'module' }, nextLoad); + + expect(nextLoad).not.toHaveBeenCalled(); + expect(result.format).toBe('module'); + expect(result.shortCircuit).toBeTrue(); + expect(result.source).toBe(''); + }); + + it('should load in-memory file source with non-zero byteOffset in Uint8Array', async () => { + const target = 'export const sliced = 42;'; + const fullBuffer = Buffer.from(`__PADDING__${target}__MORE__`); + const offset = Buffer.byteLength('__PADDING__', 'utf-8'); + const length = Buffer.byteLength(target, 'utf-8'); + const subView = new Uint8Array(fullBuffer.buffer, fullBuffer.byteOffset + offset, length); + + initialize({ + workspaceRoot, + outputFiles: { + 'sliced.mjs': subView, + }, + }); + + const memoryUrl = new URL('./sliced.mjs', 'memory://').href; + const rootResolve = resolve(memoryUrl, { parentURL: undefined }, () => {}); + const nextLoad = jasmine.createSpy('nextLoad'); + + const result = await load(rootResolve.url, { format: 'module' }, nextLoad); + + expect(nextLoad).not.toHaveBeenCalled(); + expect(result.format).toBe('module'); + expect(result.shortCircuit).toBeTrue(); + expect(result.source).toBe(target); + }); + + it('should load in-memory file source when outputFiles contain string values', async () => { + initialize({ + workspaceRoot, + outputFiles: { + 'string-file.mjs': 'export const fromString = 1;', + }, + }); + + const memoryUrl = new URL('./string-file.mjs', 'memory://').href; + const rootResolve = resolve(memoryUrl, { parentURL: undefined }, () => {}); + const nextLoad = jasmine.createSpy('nextLoad'); + + const result = await load(rootResolve.url, { format: 'module' }, nextLoad); + + expect(nextLoad).not.toHaveBeenCalled(); + expect(result.format).toBe('module'); + expect(result.shortCircuit).toBeTrue(); + expect(result.source).toBe('export const fromString = 1;'); + }); + + it('should reject when in-memory file does not exist in outputFiles', async () => { + const memoryUrl = new URL('./main.server.mjs', 'memory://').href; + const rootResolve = resolve(memoryUrl, { parentURL: undefined }, () => {}); + const nonExistentVirtualUrl = rootResolve.url.replace('main.server.mjs', 'missing.mjs'); + const nextLoad = jasmine.createSpy('nextLoad'); + + await expectAsync( + load(nonExistentVirtualUrl, { format: 'module' }, nextLoad), + ).toBeRejectedWithError(/Resolved in-memory ESM file should always exist/); + expect(nextLoad).not.toHaveBeenCalled(); + }); + + it('should delegate to nextLoad for non-angular file URLs', async () => { + const nextLoad = jasmine.createSpy('nextLoad').and.resolveTo({ format: 'module' }); + const result = await load( + 'file:///workspace/node_modules/rxjs/index.js', + { format: 'module' }, + nextLoad, + ); + + expect(nextLoad).toHaveBeenCalledWith('file:///workspace/node_modules/rxjs/index.js', { + format: 'module', + }); + expect(result.format).toBe('module'); + }); + + it('should delegate to nextLoad for non-memory non-file URLs', async () => { + const nextLoad = jasmine.createSpy('nextLoad').and.resolveTo({ format: 'builtin' }); + const result = await load('node:fs', { format: 'builtin' }, nextLoad); + + expect(nextLoad).toHaveBeenCalledWith('node:fs'); + expect(result.format).toBe('builtin'); + }); + }); +}); diff --git a/packages/angular/build/src/utils/server-rendering/esm-in-memory-loader/utils.ts b/packages/angular/build/src/utils/server-rendering/esm-in-memory-loader/utils.ts index 3af354f6ba0f..7eb2bd1f5c49 100644 --- a/packages/angular/build/src/utils/server-rendering/esm-in-memory-loader/utils.ts +++ b/packages/angular/build/src/utils/server-rendering/esm-in-memory-loader/utils.ts @@ -11,3 +11,41 @@ import { pathToFileURL } from 'node:url'; export const IMPORT_EXEC_ARGV = '--import=' + pathToFileURL(join(__dirname, 'register-hooks.js')).href; + +/** + * Creates a shared zero-copy `Uint8Array` backed by a `SharedArrayBuffer` for the given file content. + */ +export function createSharedFile(content: string | Uint8Array): Uint8Array { + if (typeof content === 'string') { + const byteLength = Buffer.byteLength(content, 'utf-8'); + const sab = new SharedArrayBuffer(byteLength); + Buffer.from(sab).write(content, 'utf-8'); + + return new Uint8Array(sab); + } + + if (content.buffer instanceof SharedArrayBuffer) { + return content; + } + + const sab = new SharedArrayBuffer(content.byteLength); + const view = new Uint8Array(sab); + view.set(content); + + return view; +} + +/** + * Creates shared zero-copy `Uint8Array` views backed by `SharedArrayBuffer` for all output files. + */ +export function createSharedServerFiles( + outputFiles: Record, +): Record { + const sharedFiles: Record = {}; + + for (const [key, value] of Object.entries(outputFiles)) { + sharedFiles[key] = createSharedFile(value); + } + + return sharedFiles; +} diff --git a/packages/angular/build/src/utils/server-rendering/esm-in-memory-loader/utils_spec.ts b/packages/angular/build/src/utils/server-rendering/esm-in-memory-loader/utils_spec.ts new file mode 100644 index 000000000000..b7bb2844b66e --- /dev/null +++ b/packages/angular/build/src/utils/server-rendering/esm-in-memory-loader/utils_spec.ts @@ -0,0 +1,147 @@ +/** + * @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 { createSharedFile, createSharedServerFiles } from './utils'; + +describe('server-rendering shared file utilities', () => { + describe('createSharedFile', () => { + it('should create a Uint8Array backed by SharedArrayBuffer from string', () => { + const text = 'console.log("hello world");'; + const shared = createSharedFile(text); + + expect(shared instanceof Uint8Array).toBeTrue(); + expect(shared.buffer instanceof SharedArrayBuffer).toBeTrue(); + expect(shared.byteLength).toBe(Buffer.byteLength(text, 'utf-8')); + + const decoded = Buffer.from(shared.buffer, shared.byteOffset, shared.byteLength).toString( + 'utf-8', + ); + expect(decoded).toBe(text); + }); + + it('should correctly handle multi-byte UTF-8 characters', () => { + const text = 'export const greeting = "🚀 Привет, мир! 🌍";'; + const shared = createSharedFile(text); + + expect(shared.buffer instanceof SharedArrayBuffer).toBeTrue(); + const decoded = Buffer.from(shared.buffer, shared.byteOffset, shared.byteLength).toString( + 'utf-8', + ); + expect(decoded).toBe(text); + }); + + it('should handle empty string', () => { + const shared = createSharedFile(''); + + expect(shared.buffer instanceof SharedArrayBuffer).toBeTrue(); + expect(shared.byteLength).toBe(0); + const decoded = Buffer.from(shared.buffer, shared.byteOffset, shared.byteLength).toString( + 'utf-8', + ); + expect(decoded).toBe(''); + }); + + it('should handle empty Uint8Array', () => { + const shared = createSharedFile(new Uint8Array(0)); + + expect(shared.buffer instanceof SharedArrayBuffer).toBeTrue(); + expect(shared.byteLength).toBe(0); + }); + + it('should return the same Uint8Array if already backed by SharedArrayBuffer', () => { + const text = 'export default 42;'; + const shared1 = createSharedFile(text); + const shared2 = createSharedFile(shared1); + + expect(shared2).toBe(shared1); + expect(shared2.buffer).toBe(shared1.buffer); + }); + + it('should return existing Uint8Array view if already backed by SharedArrayBuffer with non-zero byteOffset', () => { + const text = '0123456789abcdef'; + const shared1 = createSharedFile(text); + const subView = new Uint8Array(shared1.buffer, 4, 8); + const shared2 = createSharedFile(subView); + + expect(shared2).toBe(subView); + expect(shared2.byteOffset).toBe(4); + expect(shared2.byteLength).toBe(8); + + const decoded = Buffer.from(shared2.buffer, shared2.byteOffset, shared2.byteLength).toString( + 'utf-8', + ); + expect(decoded).toBe('456789ab'); + }); + + it('should convert standard Uint8Array to SharedArrayBuffer backed Uint8Array', () => { + const regularBuffer = Buffer.from('export const test = true;'); + expect(regularBuffer.buffer instanceof SharedArrayBuffer).toBeFalse(); + + const shared = createSharedFile(regularBuffer); + expect(shared.buffer instanceof SharedArrayBuffer).toBeTrue(); + + const decoded = Buffer.from(shared.buffer, shared.byteOffset, shared.byteLength).toString( + 'utf-8', + ); + expect(decoded).toBe('export const test = true;'); + }); + + it('should handle Uint8Array slice with non-zero byteOffset from standard ArrayBuffer', () => { + const target = 'export const data = 123;'; + const fullBuffer = Buffer.from(`__PREFIX__${target}__SUFFIX__`); + const offset = Buffer.byteLength('__PREFIX__', 'utf-8'); + const length = Buffer.byteLength(target, 'utf-8'); + const subView = new Uint8Array(fullBuffer.buffer, fullBuffer.byteOffset + offset, length); + + const shared = createSharedFile(subView); + expect(shared.buffer instanceof SharedArrayBuffer).toBeTrue(); + expect(shared.byteLength).toBe(length); + + const decoded = Buffer.from(shared.buffer, shared.byteOffset, shared.byteLength).toString( + 'utf-8', + ); + expect(decoded).toBe(target); + }); + }); + + describe('createSharedServerFiles', () => { + it('should convert all entries in a record to SharedArrayBuffer backed Uint8Arrays', () => { + const files: Record = { + 'main.server.mjs': 'export default function() {}', + 'chunk-1.mjs': 'export const x = 1;', + 'render-utils.mjs': Buffer.from('export const helper = () => true;'), + }; + + const sharedFiles = createSharedServerFiles(files); + + expect(Object.keys(sharedFiles)).toEqual([ + 'main.server.mjs', + 'chunk-1.mjs', + 'render-utils.mjs', + ]); + + for (const [key, shared] of Object.entries(sharedFiles)) { + expect(shared instanceof Uint8Array).toBeTrue(); + expect(shared.buffer instanceof SharedArrayBuffer).toBeTrue(); + + const expectedText = + typeof files[key] === 'string' ? files[key] : (files[key] as Buffer).toString('utf-8'); + + const decoded = Buffer.from(shared.buffer, shared.byteOffset, shared.byteLength).toString( + 'utf-8', + ); + expect(decoded).toBe(expectedText); + } + }); + + it('should handle empty file map', () => { + const sharedFiles = createSharedServerFiles({}); + expect(Object.keys(sharedFiles).length).toBe(0); + }); + }); +}); diff --git a/packages/angular/build/src/utils/server-rendering/manifest.ts b/packages/angular/build/src/utils/server-rendering/manifest.ts index bd294b1e7e4b..1ee430a76333 100644 --- a/packages/angular/build/src/utils/server-rendering/manifest.ts +++ b/packages/angular/build/src/utils/server-rendering/manifest.ts @@ -7,8 +7,8 @@ */ import type { Metafile } from 'esbuild'; +import { Buffer } from 'node:buffer'; import { extname } from 'node:path'; -import { runInThisContext } from 'node:vm'; import { NormalizedApplicationBuildOptions } from '../../builders/application/options'; import { type BuildOutputFile, @@ -174,9 +174,14 @@ export function generateAngularServerAppManifest( ), ); - // This is needed because JavaScript engines script parser convert `\r\n` to `\n` in template literals, - // which can result in an incorrect byte length. - const size = runInThisContext(`new TextEncoder().encode(\`${escapedContent}\`).byteLength`); + // JavaScript engine script parsers normalize `\r\n` (2 bytes in UTF-8) to `\n` (1 byte in UTF-8) in template literals. + // Subtracting the count of `\r\n` occurrences avoids allocating any temporary strings or match arrays for large assets. + let size = Buffer.byteLength(file.text); + let pos = file.text.indexOf('\r\n'); + while (pos !== -1) { + size--; + pos = file.text.indexOf('\r\n', pos + 2); + } serverAssets[file.path] = `{size: ${size}, hash: '${file.hash}', text: () => import('./${jsChunkFilePath}').then(m => m.default)}`; diff --git a/packages/angular/build/src/utils/server-rendering/prerender.ts b/packages/angular/build/src/utils/server-rendering/prerender.ts index b4f81f03a800..37e29f02385b 100644 --- a/packages/angular/build/src/utils/server-rendering/prerender.ts +++ b/packages/angular/build/src/utils/server-rendering/prerender.ts @@ -16,7 +16,11 @@ import { assertIsError } from '../error'; import { toPosixPath } from '../path'; import { addLeadingSlash, addTrailingSlash, joinUrlParts, stripLeadingSlash } from '../url'; import { WorkerPool } from '../worker-pool'; -import { IMPORT_EXEC_ARGV } from './esm-in-memory-loader/utils'; +import { + IMPORT_EXEC_ARGV, + createSharedFile, + createSharedServerFiles, +} from './esm-in-memory-loader/utils'; import { SERVER_APP_MANIFEST_FILENAME } from './manifest'; import { RouteRenderMode, @@ -25,7 +29,7 @@ import { SerializableRouteTreeNode, WritableSerializableRouteTreeNode, } from './models'; -import type { RenderWorkerData } from './render-worker'; +import type { RenderResult, RenderWorkerData } from './render-worker'; import { generateRedirectStaticPage } from './utils'; type PrerenderOptions = NormalizedApplicationBuildOptions['prerenderOptions']; @@ -63,7 +67,7 @@ export async function prerenderPages( errors: string[]; serializableRouteTreeNode: SerializableRouteTreeNode; }> { - const outputFilesForWorker: Record = {}; + const rawOutputFiles: Record = {}; const serverBundlesSourceMaps = new Map(); const warnings: string[] = []; const errors: string[] = []; @@ -77,23 +81,25 @@ export async function prerenderPages( if (extname(path) === '.map') { serverBundlesSourceMaps.set(path.slice(0, -4), text); } else { - outputFilesForWorker[path] = text; + rawOutputFiles[path] = text; } } // Inline sourcemap into JS file. This is needed to make Node.js resolve sourcemaps // when using `--enable-source-maps` when using in memory files. for (const [filePath, map] of serverBundlesSourceMaps) { - const jsContent = outputFilesForWorker[filePath]; + const jsContent = rawOutputFiles[filePath]; if (jsContent) { - outputFilesForWorker[filePath] = + rawOutputFiles[filePath] = jsContent + - `\n//# sourceMappingURL=` + + '\n//# sourceMappingURL=' + `data:application/json;base64,${Buffer.from(map).toString('base64')}`; } } serverBundlesSourceMaps.clear(); + const outputFilesForWorker = createSharedServerFiles(rawOutputFiles); + const assetsReversed: Record = {}; for (const { source, destination } of assets) { // Assets are not stored with baseHref when using i18n, @@ -169,9 +175,13 @@ export async function prerenderPages( // We could re-generate it from the start, but that would require a number of options to be passed down. const manifest = outputFilesForWorker[SERVER_APP_MANIFEST_FILENAME]; if (manifest) { - outputFilesForWorker[SERVER_APP_MANIFEST_FILENAME] = manifest.replace( - 'routes: undefined,', - `routes: ${JSON.stringify(serializableRouteTreeNodeForPrerender, undefined, 2)},`, + const manifestText = new TextDecoder().decode(manifest); + + outputFilesForWorker[SERVER_APP_MANIFEST_FILENAME] = createSharedFile( + manifestText.replace( + 'routes: undefined,', + `routes: ${JSON.stringify(serializableRouteTreeNodeForPrerender, undefined, 2)},`, + ), ); } @@ -204,7 +214,7 @@ async function renderPages( serializableRouteTreeNode: SerializableRouteTreeNode, maxThreads: number, workspaceRoot: string, - outputFilesForWorker: Record, + outputFilesForWorker: Record, assetFilesForWorker: Record, outputMode: OutputMode | undefined, appShellRoute: string | undefined, @@ -214,15 +224,59 @@ async function renderPages( }> { const output: PrerenderOutput = {}; const errors: string[] = []; - const workerExecArgv = [IMPORT_EXEC_ARGV]; + const baseHrefPathnameWithLeadingSlash = new URL(baseHref, 'http://localhost').pathname; + const appShellRouteWithoutBaseHref = appShellRoute + ? addTrailingSlash(appShellRoute).startsWith(baseHrefPathnameWithLeadingSlash) + ? addLeadingSlash(appShellRoute.slice(baseHrefPathnameWithLeadingSlash.length)) + : addLeadingSlash(appShellRoute) + : undefined; + + const routesToRender: { route: string; outPath: string; isAppShell: boolean }[] = []; + + for (const { route, redirectTo } of serializableRouteTreeNode) { + // Remove the base href from the file output path. + const routeWithoutBaseHref = addTrailingSlash(route).startsWith( + baseHrefPathnameWithLeadingSlash, + ) + ? addLeadingSlash(route.slice(baseHrefPathnameWithLeadingSlash.length)) + : route; + + const outPath = stripLeadingSlash(posix.join(routeWithoutBaseHref, 'index.html')); + + if (typeof redirectTo === 'string') { + output[outPath] = { content: generateRedirectStaticPage(redirectTo), appShellRoute: false }; + + continue; + } + + routesToRender.push({ + route, + outPath, + isAppShell: appShellRouteWithoutBaseHref === routeWithoutBaseHref, + }); + } + + if (routesToRender.length === 0) { + return { + errors, + output, + }; + } + + // Batch routes to reduce IPC overhead while ensuring enough batches exist for load balancing across worker threads. + const batchSize = Math.max(1, Math.min(50, Math.ceil(routesToRender.length / (maxThreads * 4)))); + const numBatches = Math.ceil(routesToRender.length / batchSize); + const effectiveMaxThreads = Math.min(numBatches, maxThreads); + + const workerExecArgv = [IMPORT_EXEC_ARGV]; if (sourcemap) { workerExecArgv.push('--enable-source-maps'); } const renderWorker = new WorkerPool({ filename: require.resolve('./render-worker'), - maxThreads: Math.min(serializableRouteTreeNode.length, maxThreads), + maxThreads: effectiveMaxThreads, workerData: { workspaceRoot, outputFiles: outputFilesForWorker, @@ -238,45 +292,46 @@ async function renderPages( }); try { - const renderingPromises: Promise[] = []; - const appShellRouteWithLeadingSlash = appShellRoute && addLeadingSlash(appShellRoute); - const baseHrefPathnameWithLeadingSlash = new URL(baseHref, 'http://localhost').pathname; - - for (const { route, redirectTo } of serializableRouteTreeNode) { - // Remove the base href from the file output path. - const routeWithoutBaseHref = addTrailingSlash(route).startsWith( - baseHrefPathnameWithLeadingSlash, - ) - ? addLeadingSlash(route.slice(baseHrefPathnameWithLeadingSlash.length)) - : route; - - const outPath = stripLeadingSlash(posix.join(routeWithoutBaseHref, 'index.html')); - - if (typeof redirectTo === 'string') { - output[outPath] = { content: generateRedirectStaticPage(redirectTo), appShellRoute: false }; + const routeOutPathMap = new Map(); + for (const item of routesToRender) { + routeOutPathMap.set(item.route, item); + } - continue; - } + const renderingPromises: Promise[] = []; - const render: Promise = renderWorker.run({ url: route }); - const renderResult: Promise = render - .then((content) => { - if (content !== null) { - output[outPath] = { - content, - appShellRoute: appShellRouteWithLeadingSlash === routeWithoutBaseHref, - }; + for (let i = 0; i < routesToRender.length; i += batchSize) { + const batch = routesToRender.slice(i, i + batchSize); + const urls = batch.map((item) => item.route); + const renderBatchPromise: Promise = renderWorker.run(urls); + const batchResultPromise = renderBatchPromise + .then((results) => { + for (const { url, content, error } of results) { + if (error) { + errors.push(`An error occurred while prerendering route '${url}'.\n\n${error}`); + continue; + } + + if (content !== null) { + const routeInfo = routeOutPathMap.get(url); + if (routeInfo) { + output[routeInfo.outPath] = { + content, + appShellRoute: routeInfo.isAppShell, + }; + } + } } }) .catch((err) => { assertIsError(err); - errors.push( - `An error occurred while prerendering route '${route}'.\n\n${err.stack ?? err.message ?? err.code ?? err}`, - ); - void renderWorker.destroy(); + for (const url of urls) { + errors.push( + `An error occurred while prerendering route '${url}'.\n\n${err.stack ?? err.message ?? err.code ?? err}`, + ); + } }); - renderingPromises.push(renderResult); + renderingPromises.push(batchResultPromise); } await Promise.all(renderingPromises); @@ -293,7 +348,7 @@ async function renderPages( async function getAllRoutes( workspaceRoot: string, baseHref: string, - outputFilesForWorker: Record, + outputFilesForWorker: Record, assetFilesForWorker: Record, appShellOptions: AppShellOptions | undefined, prerenderOptions: PrerenderOptions | undefined, diff --git a/packages/angular/build/src/utils/server-rendering/render-worker.ts b/packages/angular/build/src/utils/server-rendering/render-worker.ts index 7ded0550b826..b8f01c440c4b 100644 --- a/packages/angular/build/src/utils/server-rendering/render-worker.ts +++ b/packages/angular/build/src/utils/server-rendering/render-worker.ts @@ -8,6 +8,7 @@ import { workerData } from 'node:worker_threads'; import type { OutputMode } from '../../builders/application/schema'; +import { assertIsError } from '../error'; import type { ESMInMemoryFileLoaderWorkerData } from './esm-in-memory-loader/loader-hooks'; import { patchFetchToLoadInMemoryAssets } from './fetch-patch'; import { DEFAULT_URL, launchServer } from './launch-server'; @@ -20,10 +21,14 @@ export interface RenderWorkerData extends ESMInMemoryFileLoaderWorkerData { hasSsrEntry: boolean; } -export interface RenderOptions { +export interface RenderResultItem { url: string; + content: string | null; + error?: string; } +export type RenderResult = RenderResultItem[]; + /** * This is passed as workerData when setting up the worker via the `piscina` package. */ @@ -35,16 +40,12 @@ const { outputMode, hasSsrEntry } = workerData as { let serverURL = DEFAULT_URL; /** - * Renders each route in routes and writes them to //index.html. + * Renders a single route URL. */ -async function renderPage({ url }: RenderOptions): Promise { - const { ɵgetOrCreateAngularServerApp: getOrCreateAngularServerApp } = - await loadEsmModuleFromMemory('./main.server.mjs'); - - const angularServerApp = getOrCreateAngularServerApp({ - allowStaticRouteRender: true, - }); - +async function renderPage( + url: string, + angularServerApp: { handle: (request: Request) => Promise }, +): Promise { const response = await angularServerApp.handle( new Request(new URL(url, serverURL), { signal: AbortSignal.timeout(30_000) }), ); @@ -58,6 +59,35 @@ async function renderPage({ url }: RenderOptions): Promise { return location ? generateRedirectStaticPage(location) : response.text(); } +/** + * Renders routes in batch or individual URL. + */ +async function renderPages(urls: string[]): Promise { + const { ɵgetOrCreateAngularServerApp: getOrCreateAngularServerApp } = + await loadEsmModuleFromMemory('./main.server.mjs'); + + const angularServerApp = getOrCreateAngularServerApp({ + allowStaticRouteRender: true, + }); + + const results: RenderResult = []; + for (const currentUrl of urls) { + try { + const content = await renderPage(currentUrl, angularServerApp); + results.push({ url: currentUrl, content }); + } catch (err) { + assertIsError(err); + results.push({ + url: currentUrl, + content: null, + error: err.stack ?? err.message ?? err.code ?? `${err}`, + }); + } + } + + return results; +} + async function initialize() { // Load the compiler because `@angular/ssr/node` depends on `@angular/` packages, // which must be processed by the runtime linker, even if they are not used. @@ -69,7 +99,7 @@ async function initialize() { patchFetchToLoadInMemoryAssets(serverURL); - return renderPage; + return renderPages; } export default initialize(); diff --git a/packages/angular/build/src/utils/source-map.ts b/packages/angular/build/src/utils/source-map.ts index 3b91bfb5b5ad..9ce5e838987b 100644 --- a/packages/angular/build/src/utils/source-map.ts +++ b/packages/angular/build/src/utils/source-map.ts @@ -21,7 +21,12 @@ import { fileURLToPath } from 'node:url'; * @returns The code with top-level sourcemap comments removed. */ export function removeSourceMappingURL(code: string): string { + if (!code.includes('//# sourceMappingURL=')) { + return code; + } + const result: string[] = []; + let lastCopiedIndex = 0; let i = 0; const len = code.length; @@ -30,7 +35,6 @@ export function removeSourceMappingURL(code: string): string { let currentState: 'normal' | 'string_double' | 'string_single' | 'template' | 'comment_block' | 'comment_line' = 'normal'; - let isStrippingComment = false; while (i < len) { const char = code[i]; @@ -39,20 +43,19 @@ export function removeSourceMappingURL(code: string): string { if (currentState === 'normal') { if (char === '/' && nextChar === '*') { currentState = 'comment_block'; - result.push('/*'); i += 2; continue; } if (char === '/' && nextChar === '/') { // Detect if the comment is escaped (e.g. inside a regex literal like `/\/\/#/`). let isEscaped = false; - let prevIdx = result.length - 1; - while (prevIdx >= 0 && /\s/.test(result[prevIdx])) { + let prevIdx = i - 1; + while (prevIdx >= 0 && /\s/.test(code[prevIdx])) { prevIdx--; } - if (prevIdx >= 0 && result[prevIdx] === '\\') { + if (prevIdx >= 0 && code[prevIdx] === '\\') { let bsCount = 0; - while (prevIdx >= 0 && result[prevIdx] === '\\') { + while (prevIdx >= 0 && code[prevIdx] === '\\') { bsCount++; prevIdx--; } @@ -62,34 +65,35 @@ export function removeSourceMappingURL(code: string): string { } if (!isEscaped && code.startsWith('//# sourceMappingURL=', i)) { - currentState = 'comment_line'; - isStrippingComment = true; - i += 21; // Skip the '//# sourceMappingURL=' prefix + if (i > lastCopiedIndex) { + result.push(code.slice(lastCopiedIndex, i)); + } + // Skip the rest of the comment line up to the newline + i += 21; + while (i < len && code[i] !== '\n' && code[i] !== '\r') { + i++; + } + lastCopiedIndex = i; continue; } else { currentState = 'comment_line'; - isStrippingComment = false; - result.push('//'); i += 2; continue; } } if (char === '"') { currentState = 'string_double'; - result.push('"'); i++; continue; } if (char === "'") { currentState = 'string_single'; - result.push("'"); i++; continue; } if (char === '`') { currentState = 'template'; stack.push({ type: 'template', braceDepth: 0 }); - result.push('`'); i++; continue; } @@ -98,7 +102,6 @@ export function removeSourceMappingURL(code: string): string { if (top) { top.braceDepth++; } - result.push('{'); i++; continue; } @@ -110,43 +113,35 @@ export function removeSourceMappingURL(code: string): string { // Exiting a template literal interpolation ${ ... } stack.pop(); currentState = 'template'; - result.push('}'); i++; continue; } } - result.push('}'); i++; continue; } - result.push(char); i++; } else if (currentState === 'string_double') { if (char === '\\') { - result.push(char, nextChar || ''); i += 2; continue; } if (char === '"') { currentState = 'normal'; } - result.push(char); i++; } else if (currentState === 'string_single') { if (char === '\\') { - result.push(char, nextChar || ''); i += 2; continue; } if (char === "'") { currentState = 'normal'; } - result.push(char); i++; } else if (currentState === 'template') { if (char === '\\') { - result.push(char, nextChar || ''); i += 2; continue; } @@ -154,7 +149,6 @@ export function removeSourceMappingURL(code: string): string { // Entering template literal interpolation context currentState = 'normal'; stack.push({ type: 'template', braceDepth: 0 }); - result.push('${'); i += 2; continue; } @@ -162,32 +156,30 @@ export function removeSourceMappingURL(code: string): string { stack.pop(); currentState = 'normal'; } - result.push(char); i++; } else if (currentState === 'comment_block') { if (char === '*' && nextChar === '/') { currentState = 'normal'; - result.push('*/'); i += 2; continue; } - result.push(char); i++; } else if (currentState === 'comment_line') { if (char === '\n' || char === '\r') { currentState = 'normal'; - isStrippingComment = false; - result.push(char); - i++; - continue; - } - if (!isStrippingComment) { - result.push(char); } i++; } } + if (lastCopiedIndex === 0) { + return code; + } + + if (lastCopiedIndex < len) { + result.push(code.slice(lastCopiedIndex)); + } + return result.join(''); } diff --git a/packages/angular/build/src/utils/source-map_spec.ts b/packages/angular/build/src/utils/source-map_spec.ts index 7b424b019403..b34d5bc57a98 100644 --- a/packages/angular/build/src/utils/source-map_spec.ts +++ b/packages/angular/build/src/utils/source-map_spec.ts @@ -87,4 +87,14 @@ describe('removeSourceMappingURL', () => { const code = '// # sourceMappingURL=main.js.map\n//# sourceMappingURL=main.js.map'; expect(removeSourceMappingURL(code)).toBe('// # sourceMappingURL=main.js.map\n'); }); + + it('should return the exact input string when no sourcemap comment is present', () => { + const code = 'const x = 1;\nconsole.log(x);'; + expect(removeSourceMappingURL(code)).toBe(code); + }); + + it('should handle sourcemap comments with CRLF newlines', () => { + const code = 'console.log("hello");\r\n//# sourceMappingURL=main.js.map\r\nconst next = 2;'; + expect(removeSourceMappingURL(code)).toBe('console.log("hello");\r\n\r\nconst next = 2;'); + }); }); diff --git a/packages/angular/cli/lib/init.ts b/packages/angular/cli/lib/init.ts index cd324b6df69b..97d410890955 100644 --- a/packages/angular/cli/lib/init.ts +++ b/packages/angular/cli/lib/init.ts @@ -10,8 +10,6 @@ import { readFile } from 'node:fs/promises'; import { createRequire } from 'node:module'; import * as path from 'node:path'; import { SemVer, major } from 'semver'; -import { colors } from '../src/utilities/color'; -import { isWarningEnabled } from '../src/utilities/config'; import { disableVersionCheck } from '../src/utilities/environment-options'; import { VERSION } from '../src/utilities/version'; @@ -24,6 +22,26 @@ import { VERSION } from '../src/utilities/version'; let forceExit = false; (async (): Promise => { + /** + * On Windows, ensure process.cwd() uses uppercase drive letter casing. + * Windows cmd.exe and VS Code terminals often preserve lowercase drive letters (e.g. c:\...), + * which causes ESM module duplication in Node.js (e.g. loading "vitest" twice) and path + * lookup mismatches in tools like Vite and esbuild. + */ + if (process.platform === 'win32') { + const cwd = process.cwd(); + if (/^[a-z]:/.test(cwd)) { + try { + process.chdir(cwd[0].toUpperCase() + cwd.slice(1)); + } catch { + // Ignore failure to change directory + } + } + + // Ensure Windows CreateProcess does not search the current directory for bare executable names. + process.env['NoDefaultCurrentDirectoryInExePath'] = '1'; + } + /** * Disable Browserslist old data warning as otherwise with every release we'd need to update this dependency * which is cumbersome considering we pin versions and the warning is not user actionable. @@ -31,6 +49,7 @@ let forceExit = false; * See: https://github.com/browserslist/browserslist/blob/819c4337456996d19db6ba953014579329e9c6e1/node.js#L324 */ process.env.BROWSERSLIST_IGNORE_OLD_DATA = '1'; + const rawCommandName = process.argv[2]; /** @@ -104,15 +123,23 @@ let forceExit = false; cli.VERSION.major - globalVersion.major <= 1 ) { cli = await import('./cli'); - } else if (await isWarningEnabled('versionMismatch')) { - // Otherwise, use local version and warn if global is newer than local - const warning = - `Your global Angular CLI version (${globalVersion}) is greater than your local ` + - `version (${localVersion}). The local Angular CLI version is used.\n\n` + - 'To disable this warning use "ng config -g cli.warnings.versionMismatch false".'; + } else { + try { + const { isWarningEnabled } = await import('../src/utilities/config'); + if (await isWarningEnabled('versionMismatch')) { + // Otherwise, use local version and warn if global is newer than local + const warning = + `Your global Angular CLI version (${globalVersion}) is greater than your local ` + + `version (${localVersion}). The local Angular CLI version is used.\n\n` + + 'To disable this warning use "ng config -g cli.warnings.versionMismatch false".'; - // eslint-disable-next-line no-console - console.error(colors.yellow(warning)); + const { colors } = await import('../src/utilities/color'); + // eslint-disable-next-line no-console + console.error(colors.yellow(warning)); + } + } catch { + // Ignore errors during warning check to avoid falling back to global CLI + } } } } catch { diff --git a/packages/angular/cli/package.json b/packages/angular/cli/package.json index 1d458f516d06..a210a0a411fd 100644 --- a/packages/angular/cli/package.json +++ b/packages/angular/cli/package.json @@ -16,15 +16,15 @@ "@angular-devkit/core": "workspace:0.0.0-PLACEHOLDER", "@angular-devkit/schematics": "workspace:0.0.0-PLACEHOLDER", "@inquirer/prompts": "8.5.2", - "@listr2/prompt-adapter-inquirer": "4.2.4", - "@modelcontextprotocol/sdk": "1.29.0", + "@listr2/prompt-adapter-inquirer": "4.2.5", + "@modelcontextprotocol/sdk": "1.30.0", "@schematics/angular": "workspace:0.0.0-PLACEHOLDER", "jsonc-parser": "3.3.1", - "listr2": "10.2.2", + "listr2": "11.0.0", "npm-package-arg": "14.0.0", "parse5-html-rewriting-stream": "8.0.1", "semver": "7.8.5", - "yargs": "18.0.0", + "yargs": "18.1.0", "zod": "4.4.3" }, "ng-update": { diff --git a/packages/angular/cli/src/commands/add/cli.ts b/packages/angular/cli/src/commands/add/cli.ts index a3a3d6f7ecd2..bc95f33ff8e7 100644 --- a/packages/angular/cli/src/commands/add/cli.ts +++ b/packages/angular/cli/src/commands/add/cli.ts @@ -243,9 +243,7 @@ export default class AddCommandModule }, // TODO: Rework schematic execution as a task and insert here ], - { - /* options */ - }, + {/* options */}, ); try { @@ -263,6 +261,9 @@ export default class AddCommandModule if (localManifest['ng-add']?.save === false) { shouldCleanUp = true; } + } else { + await this.cleanUpTemporaryDependency(result.collectionName); + shouldCleanUp = false; } } catch {} } 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 dca61eb700b3..0b40c5c0c207 100644 --- a/packages/angular/cli/src/commands/mcp/tools/best-practices.ts +++ b/packages/angular/cli/src/commands/mcp/tools/best-practices.ts @@ -20,6 +20,7 @@ import { createRequire } from 'node:module'; import { dirname, isAbsolute, join, relative, resolve } from 'node:path'; import { z } from 'zod'; import { VERSION } from '../../../utilities/version'; +import { isAllowedWorkspacePath } from '../workspace-utils'; import { type McpToolContext, declareTool } from './tool-registry'; const bestPracticesInputSchema = z.object({ @@ -86,13 +87,36 @@ async function getBundledBestPractices(): Promise { * * @param workspacePath The absolute path to the user's `angular.json` file. * @param logger The MCP tool context logger for reporting warnings. + * @param server The MCP server context, used to enforce the client's declared roots. * @returns A promise that resolves to an object containing the guide's content and source, * or `undefined` if the guide could not be resolved. */ async function getVersionSpecificBestPractices( workspacePath: string, logger: McpToolContext['logger'], + server: McpToolContext['server'], ): Promise<{ content: string; source: string } | undefined> { + if (server) { + let isAllowed: boolean; + try { + isAllowed = await isAllowedWorkspacePath(server, workspacePath); + } catch (e) { + logger.warn( + `Failed to verify workspace path '${workspacePath}': ` + + `${e instanceof Error ? e.message : e}. Falling back to the bundled guide.`, + ); + + return undefined; + } + + if (!isAllowed) { + throw new Error( + `Workspace path is outside the allowed MCP roots: ${workspacePath}. ` + + "You can use 'list_projects' to find available workspaces.", + ); + } + } + // 1. Resolve the path to package.json let pkgJsonPath: string; try { @@ -175,7 +199,7 @@ async function getVersionSpecificBestPractices( * @param context The MCP tool context, containing the logger. * @returns An async function that serves as the tool's executor. */ -function createBestPracticesHandler({ logger }: McpToolContext) { +function createBestPracticesHandler({ logger, server }: McpToolContext) { let bundledBestPractices: Promise; return async (input: BestPracticesInput) => { @@ -184,7 +208,11 @@ function createBestPracticesHandler({ logger }: McpToolContext) { // First, try to get the version-specific guide. if (input.workspacePath) { - const versionSpecific = await getVersionSpecificBestPractices(input.workspacePath, logger); + const versionSpecific = await getVersionSpecificBestPractices( + input.workspacePath, + logger, + server, + ); if (versionSpecific) { content = versionSpecific.content; source = versionSpecific.source; diff --git a/packages/angular/cli/src/commands/mcp/tools/devserver/devserver-start.ts b/packages/angular/cli/src/commands/mcp/tools/devserver/devserver-start.ts index 4e2155f500b7..72bf5440adcb 100644 --- a/packages/angular/cli/src/commands/mcp/tools/devserver/devserver-start.ts +++ b/packages/angular/cli/src/commands/mcp/tools/devserver/devserver-start.ts @@ -119,7 +119,7 @@ the first build completes. * **Consistent Ports**: If making multiple calls, it is recommended to reuse the port you got from the first call for subsequent ones. `, - isReadOnly: true, + isReadOnly: false, isLocalOnly: true, inputSchema: devserverStartToolInputSchema.shape, outputSchema: devserverStartToolOutputSchema.shape, diff --git a/packages/angular/cli/src/commands/mcp/tools/devserver/devserver-stop.ts b/packages/angular/cli/src/commands/mcp/tools/devserver/devserver-stop.ts index 669160695194..32b7d90269d2 100644 --- a/packages/angular/cli/src/commands/mcp/tools/devserver/devserver-stop.ts +++ b/packages/angular/cli/src/commands/mcp/tools/devserver/devserver-stop.ts @@ -69,7 +69,7 @@ Stops a running Angular development server ("ng serve") that was started with th time after this is called. However note that this is not a blocker for starting a new devserver. `, - isReadOnly: true, + isReadOnly: false, isLocalOnly: true, inputSchema: devserverStopToolInputSchema.shape, outputSchema: devserverStopToolOutputSchema.shape, diff --git a/packages/angular/cli/src/commands/mcp/tools/run-target/build-target-strategy.ts b/packages/angular/cli/src/commands/mcp/tools/run-target/build-target-strategy.ts index 1fbd8f83e47a..2e280927f466 100644 --- a/packages/angular/cli/src/commands/mcp/tools/run-target/build-target-strategy.ts +++ b/packages/angular/cli/src/commands/mcp/tools/run-target/build-target-strategy.ts @@ -29,7 +29,7 @@ export class BuildTargetStrategy implements TargetStrategy { ): Promise { const args = ['build', input.projectName]; if (input.configuration) { - args.push('-c', input.configuration); + args.push(`--configuration=${input.configuration}`); } args.push(...serializeOptions(input.options)); diff --git a/packages/angular/cli/src/commands/mcp/tools/run-target/generic-target-strategy.ts b/packages/angular/cli/src/commands/mcp/tools/run-target/generic-target-strategy.ts index e2cbc816c330..365253131248 100644 --- a/packages/angular/cli/src/commands/mcp/tools/run-target/generic-target-strategy.ts +++ b/packages/angular/cli/src/commands/mcp/tools/run-target/generic-target-strategy.ts @@ -46,7 +46,7 @@ export class GenericTargetStrategy implements TargetStrategy { } if (input.configuration) { - args.push('-c', input.configuration); + args.push(`--configuration=${input.configuration}`); } let options = input.options; diff --git a/packages/angular/cli/src/commands/mcp/tools/run-target/run-target_spec.ts b/packages/angular/cli/src/commands/mcp/tools/run-target/run-target_spec.ts index 67b1fffef27e..91ccbac4584a 100644 --- a/packages/angular/cli/src/commands/mcp/tools/run-target/run-target_spec.ts +++ b/packages/angular/cli/src/commands/mcp/tools/run-target/run-target_spec.ts @@ -42,7 +42,7 @@ describe('Run Target Tool', () => { mockContext.workspace.extensions['defaultProject'] = 'my-app'; await runTarget({ target: 'build', configuration: 'production' }, mockContext); expect(mockHost.executeNgCommand).toHaveBeenCalledWith( - ['build', 'my-app', '-c', 'production'], + ['build', 'my-app', '--configuration=production'], { cwd: '/test', }, @@ -53,7 +53,7 @@ describe('Run Target Tool', () => { mockContext.workspace.extensions['defaultProject'] = 'my-app'; await runTarget({ target: 'storybook', configuration: 'docs' }, mockContext); expect(mockHost.executeNgCommand).toHaveBeenCalledWith( - ['run', 'my-app:storybook', '-c', 'docs'], + ['run', 'my-app:storybook', '--configuration=docs'], { cwd: '/test' }, ); }); diff --git a/packages/angular/cli/src/commands/mcp/tools/run-target/unit-test-strategy.ts b/packages/angular/cli/src/commands/mcp/tools/run-target/unit-test-strategy.ts index 77ca5797e71c..1023cdd7956c 100644 --- a/packages/angular/cli/src/commands/mcp/tools/run-target/unit-test-strategy.ts +++ b/packages/angular/cli/src/commands/mcp/tools/run-target/unit-test-strategy.ts @@ -28,7 +28,7 @@ export class UnitTestTargetStrategy implements TargetStrategy { ): Promise { const args = ['test', input.projectName]; if (input.configuration) { - args.push('-c', input.configuration); + args.push(`--configuration=${input.configuration}`); } const builder = input.targetDefinition?.builder; diff --git a/packages/angular/cli/src/commands/mcp/tools/run-target/unit-test-strategy_spec.ts b/packages/angular/cli/src/commands/mcp/tools/run-target/unit-test-strategy_spec.ts index f1467f0002c9..4e63eed148a0 100644 --- a/packages/angular/cli/src/commands/mcp/tools/run-target/unit-test-strategy_spec.ts +++ b/packages/angular/cli/src/commands/mcp/tools/run-target/unit-test-strategy_spec.ts @@ -65,7 +65,15 @@ describe('UnitTestTargetStrategy', () => { ); expect(mockHost.executeNgCommand).toHaveBeenCalledWith( - ['test', 'my-app', '-c', 'ci', '--browsers', 'ChromeHeadless', '--watch', 'false'], + [ + 'test', + 'my-app', + '--configuration=ci', + '--browsers', + 'ChromeHeadless', + '--watch', + 'false', + ], { cwd: '/test' }, ); }); diff --git a/packages/angular/cli/src/commands/mcp/workspace-utils.ts b/packages/angular/cli/src/commands/mcp/workspace-utils.ts index 6cc245ff1dbc..94c4c55655c0 100644 --- a/packages/angular/cli/src/commands/mcp/workspace-utils.ts +++ b/packages/angular/cli/src/commands/mcp/workspace-utils.ts @@ -110,7 +110,7 @@ async function getAllowedWorkspaceRoots(server: McpToolContext['server']): Promi .filter((root): root is string => root !== null); } -async function isAllowedWorkspacePath( +export async function isAllowedWorkspacePath( server: McpToolContext['server'], workspacePath: string, ): Promise { diff --git a/packages/angular/cli/src/commands/update/cli.ts b/packages/angular/cli/src/commands/update/cli.ts index b886c287f2ec..005df998b501 100644 --- a/packages/angular/cli/src/commands/update/cli.ts +++ b/packages/angular/cli/src/commands/update/cli.ts @@ -634,7 +634,7 @@ export default class UpdateCommandModule extends CommandModule/package.json` after installation, + * we ensure that any migration collections defined by the package are discovered and queued. + */ +export async function resolveFallbackMigrations( + workspaceRoot: string, + plan: UpdatePlan, +): Promise<{ package: string; collection: string; from: string; to: string }[]> { + const migrations = [...plan.migrationsToRun]; + const existingMigrationPackages = new Set(migrations.map((m) => m.package)); + + for (const [packageName, targetVersion] of plan.packagesToUpdate) { + if (existingMigrationPackages.has(packageName)) { + continue; + } + + const packageJsonPath = findPackageJson(workspaceRoot, packageName); + if (packageJsonPath) { + try { + const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8')); + const ngUpdate = packageJson?.['ng-update']; + if (ngUpdate && typeof ngUpdate === 'object' && typeof ngUpdate.migrations === 'string') { + const installedVersion = plan.packageInfoMap.get(packageName)?.installed.version; + if (installedVersion) { + migrations.push({ + package: packageName, + collection: ngUpdate.migrations, + from: installedVersion, + to: targetVersion, + }); + } + } + } catch { + // Ignore read/parse errors for optional fallback + } + } + } + + return migrations; +} diff --git a/packages/angular/cli/src/commands/update/cli_spec.ts b/packages/angular/cli/src/commands/update/cli_spec.ts new file mode 100644 index 000000000000..bae00d3dba24 --- /dev/null +++ b/packages/angular/cli/src/commands/update/cli_spec.ts @@ -0,0 +1,133 @@ +/** + * @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 assert from 'node:assert'; +import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises'; +import path from 'path'; +import { resolveFallbackMigrations } from './cli'; +import type { PackageVersionInfo, UpdatePlan } from './update-resolver'; + +describe('resolveFallbackMigrations', () => { + let tempRoot: string; + let pkgDir: string; + beforeEach(async () => { + const baseTmpDir = process.env['TEST_TMPDIR']; + assert(baseTmpDir, 'TEST_TMPDIR is not set'); + tempRoot = await mkdtemp(path.join(baseTmpDir, 'angular-cli-update-cli-test-')); + pkgDir = path.join(tempRoot, 'node_modules/@company/library-name'); + await mkdir(pkgDir, { recursive: true }); + }); + + afterEach(async () => { + await rm(tempRoot, { recursive: true, force: true }); + }); + + it('discovers migrations from installed package.json when omitted from plan.migrationsToRun', async () => { + await writeFile( + path.join(pkgDir, 'package.json'), + JSON.stringify({ + name: '@company/library-name', + version: '21.2.0-next.1', + 'ng-update': { + migrations: './schematics/migration.json', + }, + }), + 'utf8', + ); + + const plan: UpdatePlan = { + packagesToUpdate: new Map([['@company/library-name', '21.2.0-next.1']]), + migrationsToRun: [], + packageInfoMap: new Map([ + [ + '@company/library-name', + { + name: '@company/library-name', + npmPackageJson: { + name: '@company/library-name', + versions: ['21.1.0', '21.2.0-next.1'], + 'dist-tags': {}, + }, + installed: { + version: '21.1.0' as unknown as PackageVersionInfo['version'], + packageJson: { name: '@company/library-name', version: '21.1.0' }, + updateMetadata: { packageGroup: {}, requirements: {} }, + }, + packageJsonRange: '^21.1.0', + }, + ], + ]), + registryClient: undefined as unknown as UpdatePlan['registryClient'], + }; + + const migrations = await resolveFallbackMigrations(tempRoot, plan); + + expect(migrations).toEqual([ + { + package: '@company/library-name', + collection: './schematics/migration.json', + from: '21.1.0', + to: '21.2.0-next.1', + }, + ]); + }); + + it('does not duplicate migration if package is already in plan.migrationsToRun', async () => { + await writeFile( + path.join(pkgDir, 'package.json'), + JSON.stringify({ + name: '@company/library-name', + version: '21.2.0-next.1', + 'ng-update': { + migrations: './schematics/migration.json', + }, + }), + 'utf8', + ); + + const plan: UpdatePlan = { + packagesToUpdate: new Map([['@company/library-name', '21.2.0-next.1']]), + migrationsToRun: [ + { + package: '@company/library-name', + collection: './schematics/migration.json', + from: '21.1.0', + to: '21.2.0-next.1', + }, + ], + packageInfoMap: new Map(), + registryClient: undefined as unknown as UpdatePlan['registryClient'], + }; + + const migrations = await resolveFallbackMigrations(tempRoot, plan); + + expect(migrations).toHaveSize(1); + }); + + it('returns unchanged migrations when package has no ng-update field on disk', async () => { + await writeFile( + path.join(pkgDir, 'package.json'), + JSON.stringify({ + name: '@company/library-name', + version: '21.2.0-next.1', + }), + 'utf8', + ); + + const plan: UpdatePlan = { + packagesToUpdate: new Map([['@company/library-name', '21.2.0-next.1']]), + migrationsToRun: [], + packageInfoMap: new Map(), + registryClient: undefined as unknown as UpdatePlan['registryClient'], + }; + + const migrations = await resolveFallbackMigrations(tempRoot, plan); + + expect(migrations).toHaveSize(0); + }); +}); diff --git a/packages/angular/cli/src/commands/update/update-resolver.ts b/packages/angular/cli/src/commands/update/update-resolver.ts index 7b75ab7a9e20..995762d92bc9 100644 --- a/packages/angular/cli/src/commands/update/update-resolver.ts +++ b/packages/angular/cli/src/commands/update/update-resolver.ts @@ -942,11 +942,7 @@ export async function resolveUserUpdatePlan( }; if (packages.size === 0) { - await Promise.all( - Array.from(npmDeps.keys()).map(async (depName) => { - await getOrFetchPackageMetadata(depName); - }), - ); + await Promise.all(Array.from(npmDeps.keys(), (depName) => getOrFetchPackageMetadata(depName))); } else { let lastPackagesSize; do { @@ -999,12 +995,13 @@ export async function resolveUserUpdatePlan( } while (packages.size > lastPackagesSize); } + const isListingUpdates = packages.size === 0; const packageInfoEntries = await Promise.all( Array.from(npmDeps.keys(), async (depName) => { const isUpdating = packages.has(depName); const localPkgJson = getInstalledPackageJson(depName, workspaceRoot); - if (isUpdating || !localPkgJson) { + if (isListingUpdates || isUpdating || !localPkgJson) { const metadata = await getOrFetchPackageMetadata(depName); if (metadata) { const info = await _buildPackageInfo( diff --git a/packages/angular/cli/src/commands/update/update-resolver_spec.ts b/packages/angular/cli/src/commands/update/update-resolver_spec.ts index e18cba641016..9ced5829587e 100644 --- a/packages/angular/cli/src/commands/update/update-resolver_spec.ts +++ b/packages/angular/cli/src/commands/update/update-resolver_spec.ts @@ -289,6 +289,29 @@ describe('UpdateResolver', () => { expect(plan.packagesToUpdate.size).toBe(0); }); + it('includes registry metadata when listing updates with locked dependency versions in package.json', async () => { + createMockWorkspace( + { + name: 'blah', + dependencies: { + '@angular-devkit-tests/update-base': '1.0.0', + }, + }, + { + '@angular-devkit-tests/update-base': { version: '1.0.0' }, + }, + ); + + const plan = await resolvePlan({ + packages: [], + workspaceRoot: tempRoot, + }); + + const info = plan.packageInfoMap.get('@angular-devkit-tests/update-base'); + expect(info?.npmPackageJson['dist-tags']?.['latest']).toBe('1.1.0'); + expect(info?.npmPackageJson.versions).toContain('1.1.0'); + }); + it('should not error with yarn 2.0 protocols', async () => { createMockWorkspace( { diff --git a/packages/angular/cli/src/commands/update/utilities/git.ts b/packages/angular/cli/src/commands/update/utilities/git.ts index 0998c9c61fff..1714846117d9 100644 --- a/packages/angular/cli/src/commands/update/utilities/git.ts +++ b/packages/angular/cli/src/commands/update/utilities/git.ts @@ -60,7 +60,7 @@ export function checkCleanGit(root: string): boolean { return false; } } - } catch {} // eslint-disable-line no-empty + } catch {} return true; } diff --git a/packages/angular/cli/src/package-managers/parsers.ts b/packages/angular/cli/src/package-managers/parsers.ts index 03774a0f2478..9fa915ed9ee9 100644 --- a/packages/angular/cli/src/package-managers/parsers.ts +++ b/packages/angular/cli/src/package-managers/parsers.ts @@ -262,13 +262,26 @@ function isValidManifest(obj: unknown): obj is PackageManifest { return false; } - const record = obj as Record; - const name = record.name; - const version = record.version; + const { name, version } = obj as Record; return typeof name === 'string' && typeof version === 'string' && valid(version) !== null; } +function isValidMetadata(obj: unknown): obj is PackageMetadata { + if (typeof obj !== 'object' || obj === null) { + return false; + } + + const { name, versions, 'dist-tags': distTags } = obj as Record; + + return ( + typeof name === 'string' && + Array.isArray(versions) && + typeof distTags === 'object' && + distTags !== null + ); +} + /** * Parses the output of `npm view` or a compatible command to get a package manifest. * @param stdout The standard output of the command. @@ -340,7 +353,28 @@ export function parseNpmLikeMetadata(stdout: string, logger?: Logger): PackageMe return null; } - return JSON.parse(stdout); + const result = JSON.parse(stdout); + + // npm 12+ `npm view --json` always returns an array of objects. + if (Array.isArray(result)) { + for (const item of result) { + if (isValidMetadata(item)) { + return item; + } + } + + logger?.debug(' No valid metadata found in the array.'); + + return null; + } + + if (!isValidMetadata(result)) { + logger?.debug(' Parsed JSON is not valid metadata (missing name, versions, or dist-tags).'); + + return null; + } + + return result; } /** @@ -479,9 +513,16 @@ export function parseNpmLikeError(output: string, logger?: Logger): ErrorInfo | return null; } - // Attempt to parse as JSON first (common for pnpm, modern yarn, bun) + // Attempt to parse as JSON first (common for pnpm, modern yarn, bun, npm 12) try { - const jsonError = JSON.parse(output); + let jsonError = JSON.parse(output); + if (Array.isArray(jsonError)) { + jsonError = jsonError[0]; + } + if (jsonError && typeof jsonError === 'object' && 'error' in jsonError) { + jsonError = jsonError.error; + } + if ( jsonError && typeof jsonError.code === 'string' && diff --git a/packages/angular/cli/src/package-managers/parsers_spec.ts b/packages/angular/cli/src/package-managers/parsers_spec.ts index dff0adfc2726..049aeaec9129 100644 --- a/packages/angular/cli/src/package-managers/parsers_spec.ts +++ b/packages/angular/cli/src/package-managers/parsers_spec.ts @@ -12,6 +12,7 @@ import { parseNpmLikeDependencies, parseNpmLikeError, parseNpmLikeManifest, + parseNpmLikeMetadata, parsePnpmReleaseAge, parseYarnClassicDependencies, parseYarnClassicError, @@ -231,6 +232,56 @@ describe('parsers', () => { const error = parseNpmLikeError('An unexpected error occurred.'); expect(error).toBeNull(); }); + + it('should parse a structured JSON error wrapped in an error property (npm 12+ format)', () => { + const stdout = JSON.stringify({ + error: { + code: 'E404', + summary: 'Not Found', + detail: 'Package not found.', + }, + }); + const error = parseNpmLikeError(stdout); + expect(error).toEqual({ + code: 'E404', + summary: 'Not Found', + detail: 'Package not found.', + }); + }); + + it('should parse a structured JSON error wrapped in an array', () => { + const stdout = JSON.stringify([ + { + code: 'E404', + summary: 'Not Found', + detail: 'Package not found.', + }, + ]); + const error = parseNpmLikeError(stdout); + expect(error).toEqual({ + code: 'E404', + summary: 'Not Found', + detail: 'Package not found.', + }); + }); + + it('should parse a structured JSON error wrapped in both an array and an error property', () => { + const stdout = JSON.stringify([ + { + error: { + code: 'E404', + summary: 'Not Found', + detail: 'Package not found.', + }, + }, + ]); + const error = parseNpmLikeError(stdout); + expect(error).toEqual({ + code: 'E404', + summary: 'Not Found', + detail: 'Package not found.', + }); + }); }); describe('parseNpmLikeManifest', () => { @@ -295,6 +346,66 @@ describe('parsers', () => { }); }); + describe('parseNpmLikeMetadata', () => { + it('should parse a single metadata object', () => { + const stdout = JSON.stringify({ + name: 'foo', + 'dist-tags': { latest: '1.0.0' }, + versions: ['1.0.0'], + }); + expect(parseNpmLikeMetadata(stdout)).toEqual({ + name: 'foo', + 'dist-tags': { latest: '1.0.0' }, + versions: ['1.0.0'], + }); + }); + + it('should parse metadata from an array (npm 12+ format)', () => { + const stdout = JSON.stringify([ + { + name: 'foo', + 'dist-tags': { latest: '1.0.0' }, + versions: ['1.0.0'], + }, + ]); + expect(parseNpmLikeMetadata(stdout)).toEqual({ + name: 'foo', + 'dist-tags': { latest: '1.0.0' }, + versions: ['1.0.0'], + }); + }); + + it('should return the first valid metadata from an array', () => { + const stdout = JSON.stringify([ + { name: 'foo' }, // Invalid (missing versions and dist-tags) + { + name: 'foo', + 'dist-tags': { latest: '1.0.0' }, + versions: ['1.0.0'], + }, + ]); + expect(parseNpmLikeMetadata(stdout)).toEqual({ + name: 'foo', + 'dist-tags': { latest: '1.0.0' }, + versions: ['1.0.0'], + }); + }); + + it('should return null if no valid metadata is found in an array', () => { + const stdout = JSON.stringify([{ name: 'foo' }, { versions: ['1.0.0'] }]); + expect(parseNpmLikeMetadata(stdout)).toBeNull(); + }); + + it('should return null for invalid single object', () => { + const stdout = JSON.stringify({ name: 'foo' }); // Missing versions and dist-tags + expect(parseNpmLikeMetadata(stdout)).toBeNull(); + }); + + it('should return null for empty stdout', () => { + expect(parseNpmLikeMetadata('')).toBeNull(); + }); + }); + describe('parseYarnClassicManifest', () => { it('should parse a valid manifest', () => { const stdout = JSON.stringify({ diff --git a/packages/angular/ssr/node/src/common-engine/common-engine.ts b/packages/angular/ssr/node/src/common-engine/common-engine.ts index 8db528f30f34..6af1c0f2727c 100644 --- a/packages/angular/ssr/node/src/common-engine/common-engine.ts +++ b/packages/angular/ssr/node/src/common-engine/common-engine.ts @@ -10,7 +10,7 @@ import { ApplicationRef, StaticProvider, Type } from '@angular/core'; import { BootstrapContext } from '@angular/platform-browser'; import { renderApplication, renderModule, ɵSERVER_CONTEXT } from '@angular/platform-server'; import * as fs from 'node:fs'; -import { dirname, join, normalize, resolve } from 'node:path'; +import { dirname, isAbsolute, join, relative, resolve } from 'node:path'; import { URL } from 'node:url'; import { validateUrl } from '../../../src/utils/validation'; import { getAllowedHostsFromEnv } from '../environment-options'; @@ -155,16 +155,18 @@ export class CommonEngine { // See: https://portswigger.net/web-security/file-path-traversal const pagePath = join(publicPath, pathname, 'index.html'); + const relativePath = relative(publicPath, pagePath); + const isOutside = + relativePath === '..' || relativePath.startsWith('../') || relativePath.startsWith('..\\'); + if (isOutside || isAbsolute(relativePath)) { + return undefined; + } + if (this.pageIsSSG.get(pagePath)) { // Serve pre-rendered page. return fs.promises.readFile(pagePath, 'utf-8'); } - if (!pagePath.startsWith(normalize(publicPath))) { - // Potential path traversal detected. - return undefined; - } - if (pagePath === resolve(documentFilePath) || !(await exists(pagePath))) { // View matches with prerender path or file does not exist. return undefined; diff --git a/packages/angular/ssr/node/src/request.ts b/packages/angular/ssr/node/src/request.ts index 4bd754b268cc..4f604b6a9d0e 100644 --- a/packages/angular/ssr/node/src/request.ts +++ b/packages/angular/ssr/node/src/request.ts @@ -55,9 +55,18 @@ export function createWebRequestFromNodeRequest( const { headers, method = 'GET' } = nodeRequest; const withBody = method !== 'GET' && method !== 'HEAD'; const referrer = headers.referer && URL.canParse(headers.referer) ? headers.referer : undefined; + const controller = new AbortController(); + if (nodeRequest.aborted) { + controller.abort(); + } else { + const onAbort = () => controller.abort(); + nodeRequest.once('aborted', onAbort); + nodeRequest.once('close', () => nodeRequest.off('aborted', onAbort)); + } return new Request(createRequestUrl(nodeRequest, trustProxyHeadersNormalized), { method, + signal: controller.signal, headers: createRequestHeaders(headers), body: withBody ? nodeRequest : undefined, duplex: withBody ? 'half' : undefined, diff --git a/packages/angular/ssr/node/src/response.ts b/packages/angular/ssr/node/src/response.ts index 56f091deed5f..d3b0cf403090 100644 --- a/packages/angular/ssr/node/src/response.ts +++ b/packages/angular/ssr/node/src/response.ts @@ -9,6 +9,22 @@ import type { ServerResponse } from 'node:http'; import type { Http2ServerResponse } from 'node:http2'; +/** + * Checks whether a Node.js `ServerResponse` or `Http2ServerResponse` is destroyed, closed, or ended. + * + * @param destination - The HTTP/1.1 or HTTP/2 server response to check. + * @returns `true` if the response or its underlying stream is destroyed, closed, or ended; otherwise `false`. + */ +function isResponseDestroyedOrClosed(destination: ServerResponse | Http2ServerResponse): boolean { + return ( + destination.destroyed || + destination.closed || + destination.writableEnded || + ('stream' in destination && + (!destination.stream || destination.stream.destroyed || destination.stream.closed)) + ); +} + /** * Streams a web-standard `Response` into a Node.js `ServerResponse` * or `Http2ServerResponse`. @@ -24,6 +40,10 @@ export async function writeResponseToNodeResponse( source: Response, destination: ServerResponse | Http2ServerResponse, ): Promise { + if (isResponseDestroyedOrClosed(destination)) { + return; + } + const { status, headers, body } = source; destination.statusCode = status; @@ -48,27 +68,52 @@ export async function writeResponseToNodeResponse( } if (!body) { - destination.end(); + if (!isResponseDestroyedOrClosed(destination)) { + destination.end(); + } return; } - try { - const reader = body.getReader(); - - destination.on('close', () => { - reader.cancel().catch((error) => { - // eslint-disable-next-line no-console - console.error( - `An error occurred while writing the response body for: ${destination.req.url}.`, - error, - ); - }); + let isClosed = isResponseDestroyedOrClosed(destination); + const isDestroyedOrClosed = () => isClosed || isResponseDestroyedOrClosed(destination); + + let readerCancelled = false; + const reader = body.getReader(); + const cancelReader = (error?: unknown) => { + if (readerCancelled) { + return; + } + readerCancelled = true; + isClosed = true; + destination.off('close', cancelReader); + destination.off('error', cancelReader); + reader.cancel(error).catch((err) => { + // eslint-disable-next-line no-console + console.error( + `An error occurred while writing the response body for: ${destination.req.url}.`, + err, + ); }); + }; + + destination.once('close', cancelReader); + destination.once('error', cancelReader); + try { // eslint-disable-next-line no-constant-condition while (true) { + if (isDestroyedOrClosed()) { + cancelReader(); + break; + } + const { done, value } = await reader.read(); + if (isDestroyedOrClosed()) { + cancelReader(); + break; + } + if (done) { destination.end(); break; @@ -78,10 +123,39 @@ export async function writeResponseToNodeResponse( if (canContinue === false) { // Explicitly check for `false`, as AWS may return `undefined` even though this is not valid. // See: https://github.com/CodeGenieApp/serverless-express/issues/683 - await new Promise((resolve) => destination.once('drain', resolve)); + await new Promise((resolve) => { + if (isDestroyedOrClosed()) { + resolve(); + + return; + } + + const onDrain = () => { + destination.off('close', onClose); + destination.off('error', onClose); + resolve(); + }; + + const onClose = () => { + destination.off('drain', onDrain); + destination.off('close', onClose); + destination.off('error', onClose); + cancelReader(); + resolve(); + }; + + destination.once('drain', onDrain); + destination.once('close', onClose); + destination.once('error', onClose); + }); } } } catch { - destination.end('Internal server error.'); + if (!isDestroyedOrClosed()) { + destination.end('Internal server error.'); + } + } finally { + destination.off('close', cancelReader); + destination.off('error', cancelReader); } } diff --git a/packages/angular/ssr/node/test/request_http1_spec.ts b/packages/angular/ssr/node/test/request_http1_spec.ts index 87f25f918ef7..9f11fe390ed4 100644 --- a/packages/angular/ssr/node/test/request_http1_spec.ts +++ b/packages/angular/ssr/node/test/request_http1_spec.ts @@ -189,4 +189,42 @@ describe('createWebRequestFromNodeRequest (HTTP/1.1)', () => { expect(await webRequest.text()).toBe(''); }); }); + + describe('abort handling', () => { + it('should abort the web request signal when the node request is aborted', async () => { + const nodeRequest = await extractNodeRequest(() => { + request({ + hostname: 'localhost', + port, + path: '/abort', + method: 'GET', + }).end(); + }); + + const webRequest = createWebRequestFromNodeRequest(nodeRequest); + expect(webRequest.signal.aborted).toBeFalse(); + + nodeRequest.emit('aborted'); + + expect(webRequest.signal.aborted).toBeTrue(); + }); + + it('should create an aborted web request signal when the node request is already aborted', async () => { + const nodeRequest = await extractNodeRequest(() => { + request({ + hostname: 'localhost', + port, + path: '/already-aborted', + method: 'GET', + }).end(); + }); + + Object.defineProperty(nodeRequest, 'aborted', { get: () => true, configurable: true }); + + const webRequest = createWebRequestFromNodeRequest(nodeRequest); + expect(webRequest.signal.aborted).toBeTrue(); + + delete (nodeRequest as { aborted?: boolean }).aborted; + }); + }); }); diff --git a/packages/angular/ssr/node/test/request_http2_spec.ts b/packages/angular/ssr/node/test/request_http2_spec.ts index 7079a385daaf..e652c59f6461 100644 --- a/packages/angular/ssr/node/test/request_http2_spec.ts +++ b/packages/angular/ssr/node/test/request_http2_spec.ts @@ -188,4 +188,42 @@ describe('createWebRequestFromNodeRequest (HTTP/2)', () => { expect(await webRequest.text()).toBe(''); }); }); + + describe('abort handling', () => { + it('should abort the web request signal when the node request is aborted', async () => { + const nodeRequest = await extractNodeRequest(() => { + client + .request({ + ':path': '/abort', + ':method': 'GET', + }) + .end(); + }); + + const webRequest = createWebRequestFromNodeRequest(nodeRequest); + expect(webRequest.signal.aborted).toBeFalse(); + + nodeRequest.emit('aborted'); + + expect(webRequest.signal.aborted).toBeTrue(); + }); + + it('should create an aborted web request signal when the node request is already aborted', async () => { + const nodeRequest = await extractNodeRequest(() => { + client + .request({ + ':path': '/already-aborted', + ':method': 'GET', + }) + .end(); + }); + + Object.defineProperty(nodeRequest, 'aborted', { get: () => true, configurable: true }); + + const webRequest = createWebRequestFromNodeRequest(nodeRequest); + expect(webRequest.signal.aborted).toBeTrue(); + + delete (nodeRequest as { aborted?: boolean }).aborted; + }); + }); }); diff --git a/packages/angular/ssr/node/test/response_http1_spec.ts b/packages/angular/ssr/node/test/response_http1_spec.ts index 8deae2b7e3b4..c7648f03a627 100644 --- a/packages/angular/ssr/node/test/response_http1_spec.ts +++ b/packages/angular/ssr/node/test/response_http1_spec.ts @@ -107,4 +107,48 @@ describe('writeResponseToNodeResponse (HTTP/1.1)', () => { expect(response.headers['set-cookie']).toEqual(cookieValue); }); + + it('should resolve and cancel reader when client disconnects while response is backpressured', async () => { + let writePromise!: Promise; + let readerCancelled = false; + const largeChunk = 'x'.repeat(1024 * 1024 * 4); // 4MB to ensure backpressure + const stream = new ReadableStream({ + start(controller) { + controller.enqueue(largeChunk); + controller.enqueue(largeChunk); + }, + cancel() { + readerCancelled = true; + }, + }); + + server.once('request', (_, nodeResponse) => { + writePromise = writeResponseToNodeResponse(new Response(stream), nodeResponse); + }); + + await new Promise((resolve) => { + const { port } = server.address() as AddressInfo; + const clientRequest = requestCb( + { + host: 'localhost', + port, + }, + (response) => { + response.once('data', () => { + clientRequest.destroy(); + resolve(); + }); + }, + ); + + clientRequest.on('error', () => { + // Expected when destroying the socket + }); + + clientRequest.end(); + }); + + await writePromise; + expect(readerCancelled).toBeTrue(); + }); }); diff --git a/packages/angular/ssr/node/test/response_http2_spec.ts b/packages/angular/ssr/node/test/response_http2_spec.ts index c2de8e977561..431bc9de0c38 100644 --- a/packages/angular/ssr/node/test/response_http2_spec.ts +++ b/packages/angular/ssr/node/test/response_http2_spec.ts @@ -116,4 +116,48 @@ describe('writeResponseToNodeResponse (HTTP/2)', () => { expect(resHeaders['set-cookie']).toEqual(cookieValue); }); + + it('should resolve and cancel reader when client disconnects while response is backpressured', async () => { + let writePromise!: Promise; + let readerCancelled = false; + const largeChunk = 'x'.repeat(1024 * 1024); // 1MB to exceed HTTP/2 flow control window + const stream = new ReadableStream({ + start(controller) { + controller.enqueue(largeChunk); + controller.enqueue(largeChunk); + }, + cancel() { + readerCancelled = true; + }, + }); + + server.once('request', (_, nodeResponse) => { + writePromise = writeResponseToNodeResponse(new Response(stream), nodeResponse); + }); + + await new Promise((resolve) => { + const { port } = server.address() as AddressInfo; + const client = connect(`http://localhost:${port}`); + const req = client.request({ + ':path': '/', + }); + + req.once('response', () => { + req.once('data', () => { + req.destroy(); + client.destroy(); + resolve(); + }); + }); + + req.on('error', () => { + // Expected when destroying/closing the stream + }); + + req.end(); + }); + + await writePromise; + expect(readerCancelled).toBeTrue(); + }); }); diff --git a/packages/angular/ssr/package.json b/packages/angular/ssr/package.json index 3ffa71cd9fe5..399278629c13 100644 --- a/packages/angular/ssr/package.json +++ b/packages/angular/ssr/package.json @@ -37,12 +37,12 @@ }, "devDependencies": { "@angular-devkit/schematics": "workspace:*", - "@angular/common": "22.1.0-rc.0", - "@angular/compiler": "22.1.0-rc.0", - "@angular/core": "22.1.0-rc.0", - "@angular/platform-browser": "22.1.0-rc.0", - "@angular/platform-server": "22.1.0-rc.0", - "@angular/router": "22.1.0-rc.0", + "@angular/common": "22.1.4", + "@angular/compiler": "22.1.4", + "@angular/core": "22.1.4", + "@angular/platform-browser": "22.1.4", + "@angular/platform-server": "22.1.4", + "@angular/router": "22.1.4", "@schematics/angular": "workspace:*", "beasties": "0.4.3" }, diff --git a/packages/angular/ssr/src/app.ts b/packages/angular/ssr/src/app.ts index a9ca7dd05fe3..3e0f33be8ba7 100644 --- a/packages/angular/ssr/src/app.ts +++ b/packages/angular/ssr/src/app.ts @@ -366,10 +366,18 @@ export class AngularServerApp { // Use a stream to send the response before finishing rendering and inling critical CSS, improving performance via header flushing. const stream = new ReadableStream({ start: async (controller) => { - const renderedHtml = await result.content(); - const finalHtml = await this.inlineCriticalCssWithCache(renderedHtml, url); - controller.enqueue(finalHtml); - controller.close(); + try { + const renderedHtml = await result.content(); + const finalHtml = await this.inlineCriticalCssWithCache(renderedHtml, url); + controller.enqueue(finalHtml); + controller.close(); + } catch (error) { + result.destroy(); + controller.error(error); + } + }, + cancel: () => { + result.destroy(); }, }); diff --git a/packages/angular/ssr/src/utils/ng.ts b/packages/angular/ssr/src/utils/ng.ts index 55d054bd2387..4ae3a7f4ed0f 100644 --- a/packages/angular/ssr/src/utils/ng.ts +++ b/packages/angular/ssr/src/utils/ng.ts @@ -34,8 +34,7 @@ import { addTrailingSlash, joinUrlParts, stripIndexHtmlFromURL, stripTrailingSla * - A function that returns a `Promise`, which resolves with the root application reference. */ export type AngularBootstrap = - | Type - | ((context: BootstrapContext) => Promise); + Type | ((context: BootstrapContext) => Promise); /** * Renders an Angular application or module to an HTML string. @@ -60,7 +59,12 @@ export async function renderAngular( serverContext: string, ): Promise< | { hasNavigationError: true } - | { hasNavigationError: boolean; redirectTo?: string; content: () => Promise } + | { + hasNavigationError: boolean; + redirectTo?: string; + content: () => Promise; + destroy: () => void; + } > { // A request to `http://www.example.com/page/index.html` will render the Angular route corresponding to `http://www.example.com/page`. const urlToRender = stripIndexHtmlFromURL(url); @@ -134,6 +138,7 @@ export async function renderAngular( } return { + destroy: () => void asyncDestroyPlatform(platformRef), hasNavigationError, redirectTo, content: () => @@ -177,6 +182,10 @@ export function isNgModule(value: AngularBootstrap): value is Type { * @param platformRef - The platform reference to be destroyed. */ function asyncDestroyPlatform(platformRef: PlatformRef): Promise { + if (platformRef.destroyed) { + return Promise.resolve(); + } + return new Promise((resolve) => { setTimeout(() => { if (!platformRef.destroyed) { diff --git a/packages/angular/ssr/src/utils/validation.ts b/packages/angular/ssr/src/utils/validation.ts index 714042b52f76..73e6c712d80b 100644 --- a/packages/angular/ssr/src/utils/validation.ts +++ b/packages/angular/ssr/src/utils/validation.ts @@ -88,7 +88,7 @@ export function validateUrl(url: URL, allowedHosts: ReadonlySet): void { /** * Sanitizes the proxy headers of a request by removing unallowed `X-Forwarded-*` headers. - * If no headers need to be removed, the original request is returned without cloning. + * If no headers need to be removed, the original request is returned unchanged. * * @param request - The incoming `Request` object to sanitize. * @param trustProxyHeaders - A set of allowed proxy headers. @@ -117,8 +117,7 @@ export function sanitizeRequestHeaders( } return headersDeleted - ? new Request(request.clone(), { - signal: request.signal, + ? new Request(request, { headers, }) : request; diff --git a/packages/angular/ssr/test/app_spec.ts b/packages/angular/ssr/test/app_spec.ts index de4b1bcb988e..1e3d40d3ede8 100644 --- a/packages/angular/ssr/test/app_spec.ts +++ b/packages/angular/ssr/test/app_spec.ts @@ -14,6 +14,7 @@ import '@angular/compiler'; import { APP_BASE_HREF } from '@angular/common'; import { Component, PlatformRef, REQUEST, RESPONSE_INIT, inject } from '@angular/core'; import { ActivatedRoute, CanActivateFn, Router } from '@angular/router'; +import { setTimeout } from 'node:timers/promises'; import { AngularServerApp } from '../src/app'; import { RenderMode } from '../src/routes/route-config'; import { setAngularAppTestingManifest } from './testing-utils'; @@ -365,6 +366,16 @@ describe('AngularServerApp', () => { expect(await response?.text()).toContain('Home works'); }); + it('should destroy the platform when the response stream is cancelled', async () => { + const destroySpy = spyOn(PlatformRef.prototype, 'destroy').and.callThrough(); + const response = await app.handle(new Request('http://localhost/home')); + expect(response?.body).toBeInstanceOf(ReadableStream); + await response?.body?.cancel(); + // Wait for the macrotask queue to clear since destroy is called asynchronously + await setTimeout(0); + expect(destroySpy).toHaveBeenCalled(); + }); + describe('APP_BASE_HREF / X-Forwarded-Prefix', () => { const headers = new Headers({ 'X-Forwarded-Prefix': '/base/' }); diff --git a/packages/angular/ssr/test/utils/validation_spec.ts b/packages/angular/ssr/test/utils/validation_spec.ts index 0f44f8067aeb..c9986a9bd73a 100644 --- a/packages/angular/ssr/test/utils/validation_spec.ts +++ b/packages/angular/ssr/test/utils/validation_spec.ts @@ -493,5 +493,40 @@ describe('Validation Utils', () => { expect(secured.headers.get('host')).toBe('example.com'); expect(secured.headers.get('forwarded')).toBe('host=proxy.com;proto=https'); }); + + it('should transfer request body without teeing when removing unallowed headers', async () => { + const req = new Request('http://example.com', { + method: 'POST', + body: 'test body', + headers: { + 'host': 'example.com', + 'x-forwarded-host': 'evil.com', + }, + }); + + const secured = sanitizeRequestHeaders(req, normalizeTrustProxyHeaders(undefined)); + + // In the Fetch specification, calling `request.clone()` tees the body stream and leaves + // `req.bodyUsed` as `false`. Passing `req` directly to `new Request(req, ...)` transfers the + // underlying stream without teeing, immediately marking `req.bodyUsed` as `true`. + expect(req.bodyUsed).toBeTrue(); + expect(await secured.text()).toBe('test body'); + }); + + it('should preserve abort signal when removing unallowed headers', () => { + const controller = new AbortController(); + const req = new Request('http://example.com', { + signal: controller.signal, + headers: { + 'host': 'example.com', + 'x-forwarded-host': 'evil.com', + }, + }); + + const secured = sanitizeRequestHeaders(req, normalizeTrustProxyHeaders(undefined)); + + controller.abort(); + expect(secured.signal.aborted).toBeTrue(); + }); }); }); diff --git a/packages/angular_devkit/build_angular/package.json b/packages/angular_devkit/build_angular/package.json index 73dc6012ad22..810fafbee30f 100644 --- a/packages/angular_devkit/build_angular/package.json +++ b/packages/angular_devkit/build_angular/package.json @@ -28,12 +28,12 @@ "browserslist": "^4.26.0", "copy-webpack-plugin": "14.0.0", "css-loader": "7.1.4", - "esbuild-wasm": "0.28.1", + "esbuild-wasm": "0.28.2", "http-proxy-middleware": "4.2.0", "istanbul-lib-instrument": "6.0.3", "jsonc-parser": "3.3.1", "karma-source-map-support": "1.4.0", - "less": "4.6.7", + "less": "4.9.0", "less-loader": "13.0.0", "license-webpack-plugin": "4.0.2", "loader-utils": "3.3.1", @@ -42,7 +42,7 @@ "ora": "9.4.1", "picomatch": "4.0.5", "piscina": "5.2.0", - "postcss": "8.5.19", + "postcss": "8.5.25", "postcss-loader": "8.2.1", "resolve-url-loader": "5.0.0", "rxjs": "7.8.2", @@ -54,19 +54,19 @@ "terser": "5.49.0", "tinyglobby": "0.2.17", "tslib": "2.8.1", - "webpack": "5.108.4", + "webpack": "5.109.2", "webpack-dev-middleware": "8.0.3", "webpack-dev-server": "5.2.6", "webpack-merge": "6.0.1", "webpack-subresource-integrity": "5.1.0" }, "optionalDependencies": { - "esbuild": "0.28.1" + "esbuild": "0.28.2" }, "devDependencies": { "@angular/ssr": "workspace:*", "browser-sync": "3.0.4", - "ng-packagr": "22.1.0-next.3", + "ng-packagr": "22.1.1", "undici": "8.7.0" }, "peerDependencies": { diff --git a/packages/angular_devkit/build_webpack/package.json b/packages/angular_devkit/build_webpack/package.json index 67cebb40bf7c..33fc2ad137b2 100644 --- a/packages/angular_devkit/build_webpack/package.json +++ b/packages/angular_devkit/build_webpack/package.json @@ -22,7 +22,7 @@ "devDependencies": { "@angular-devkit/core": "workspace:0.0.0-PLACEHOLDER", "@ngtools/webpack": "workspace:0.0.0-PLACEHOLDER", - "webpack": "5.108.4", + "webpack": "5.109.2", "webpack-dev-server": "5.2.6" }, "peerDependencies": { diff --git a/packages/ngtools/webpack/package.json b/packages/ngtools/webpack/package.json index 52995d53d86b..e0a1ec9150f8 100644 --- a/packages/ngtools/webpack/package.json +++ b/packages/ngtools/webpack/package.json @@ -17,9 +17,9 @@ }, "devDependencies": { "@angular-devkit/core": "workspace:0.0.0-PLACEHOLDER", - "@angular/compiler": "22.1.0-rc.0", - "@angular/compiler-cli": "22.1.0-rc.0", + "@angular/compiler": "22.1.4", + "@angular/compiler-cli": "22.1.4", "typescript": "6.0.3", - "webpack": "5.108.4" + "webpack": "5.109.2" } } diff --git a/packages/schematics/angular/BUILD.bazel b/packages/schematics/angular/BUILD.bazel index b4fc4e885c30..34d730f2aa6d 100644 --- a/packages/schematics/angular/BUILD.bazel +++ b/packages/schematics/angular/BUILD.bazel @@ -3,7 +3,6 @@ # 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 -load("@bazel_skylib//rules:copy_file.bzl", "copy_file") load("@npm//:defs.bzl", "npm_link_all_packages") load("//tools:defaults.bzl", "copy_to_bin", "jasmine_test", "npm_package", "ts_project") load("//tools:ts_json_schema.bzl", "ts_json_schema") @@ -46,10 +45,11 @@ copy_to_bin( srcs = glob(["**/schema.json"]), ) -copy_file( +genrule( name = "angular_best_practices", - src = "//:node_modules/@angular/core/resources/best-practices.md", - out = "ai-config/files/__bestPracticesName__.template", + srcs = ["//:node_modules/@angular/core/dir"], + outs = ["ai-config/files/__bestPracticesName__.template"], + cmd = "cp $(execpath //:node_modules/@angular/core/dir)/resources/best-practices.md $@", ) RUNTIME_ASSETS = [ diff --git a/packages/schematics/angular/ai-config/index.ts b/packages/schematics/angular/ai-config/index.ts index 7dab2fccbdef..6da0214f5f36 100644 --- a/packages/schematics/angular/ai-config/index.ts +++ b/packages/schematics/angular/ai-config/index.ts @@ -19,7 +19,11 @@ const AGENTS_MD_CFG: ContextFileInfo = { const AI_TOOLS: { [key in Exclude]: ContextFileInfo[] } = { ['claude-code']: [ - AGENTS_MD_CFG, + { + type: ContextFileType.BestPracticesMd, + name: 'CLAUDE.md', + directory: '.', + }, { type: ContextFileType.McpConfig, name: '.mcp.json', diff --git a/packages/schematics/angular/ai-config/index_spec.ts b/packages/schematics/angular/ai-config/index_spec.ts index f4408e96444c..b2eae216246f 100644 --- a/packages/schematics/angular/ai-config/index_spec.ts +++ b/packages/schematics/angular/ai-config/index_spec.ts @@ -32,9 +32,9 @@ describe('AI Config Schematic', () => { workspaceTree = await schematicRunner.runSchematic('workspace', workspaceOptions); }); - it('should create Angular MCP server config and AGENTS.md for Claude Code', async () => { + it('should create Angular MCP server config and CLAUDE.md for Claude Code', async () => { const tree = await runAiConfigSchematic([ConfigTool.ClaudeCode]); - expect(tree.exists('AGENTS.md')).toBeTruthy(); + expect(tree.exists('CLAUDE.md')).toBeTruthy(); expect(tree.exists('.mcp.json')).toBeTruthy(); }); @@ -89,7 +89,7 @@ describe('AI Config Schematic', () => { it('should omit best practices creation, if the file already exists', async () => { const customContent = 'custom user content'; - workspaceTree.create('AGENTS.md', customContent); + workspaceTree.create('CLAUDE.md', customContent); const messages: string[] = []; const loggerSubscription = schematicRunner.logger.subscribe((x) => messages.push(x.message)); @@ -97,9 +97,9 @@ describe('AI Config Schematic', () => { try { const tree = await runAiConfigSchematic([ConfigTool.ClaudeCode]); - expect(tree.readContent('AGENTS.md')).toBe(customContent); + expect(tree.readContent('CLAUDE.md')).toBe(customContent); expect(messages).toContain( - `Skipping configuration file for 'ClaudeCode' at './AGENTS.md' because it already exists.\n` + + `Skipping configuration file for 'ClaudeCode' at './CLAUDE.md' because it already exists.\n` + 'This is to prevent overwriting a potentially customized file. ' + 'If you want to regenerate it with Angular recommended defaults, please delete the existing file and re-run the command.\n' + 'You can review the latest recommendations at https://angular.dev/ai/develop-with-ai.\n', diff --git a/packages/schematics/angular/ai-config/schema.json b/packages/schematics/angular/ai-config/schema.json index 4cb63468ae53..66818095d68d 100644 --- a/packages/schematics/angular/ai-config/schema.json +++ b/packages/schematics/angular/ai-config/schema.json @@ -4,7 +4,7 @@ "title": "Angular AI Config File Options Schema", "type": "object", "additionalProperties": false, - "description": "Generates AI configuration files for Angular projects. This schematic creates AGENTS.md file and Angular MCP server configuration, improving the quality of AI-generated code and suggestions.", + "description": "Generates AI configuration files for Angular projects. This schematic creates instruction files (e.g. AGENTS.md, CLAUDE.md) and Angular MCP server configuration, improving the quality of AI-generated code and suggestions.", "properties": { "tool": { "type": "array", @@ -20,7 +20,7 @@ }, { "value": "claude-code", - "label": "Claude Code [ `AGENTS.md` + Angular MCP server config ]" + "label": "Claude Code [ `CLAUDE.md` + Angular MCP server config ]" }, { "value": "cursor", @@ -40,7 +40,7 @@ } ] }, - "description": "Specifies which AI tools to generate configuration files (AGENTS.md, MCP server config) for.", + "description": "Specifies which AI tools to generate configuration files (AGENTS.md, CLAUDE.md, MCP server config) for.", "items": { "type": "string", "enum": ["none", "claude-code", "cursor", "gemini-cli", "open-ai-codex", "vscode"] diff --git a/packages/schematics/angular/application/files/module-files/src/app/app__suffix__.spec.ts.template b/packages/schematics/angular/application/files/module-files/src/app/app__suffix__.spec.ts.template index dfe31b1010c6..b12a559c7068 100644 --- a/packages/schematics/angular/application/files/module-files/src/app/app__suffix__.spec.ts.template +++ b/packages/schematics/angular/application/files/module-files/src/app/app__suffix__.spec.ts.template @@ -11,7 +11,8 @@ describe('App', () => { declarations: [ App ], - }).compileComponents(); + }) + .compileComponents(); }); it('should create the app', () => { @@ -20,7 +21,7 @@ describe('App', () => { expect(app).toBeTruthy(); }); - it('should render title', <% if(zoneless) { %>async <% } %>() => { + it('should render title', <% if (zoneless) { %>async <% } %>() => { const fixture = TestBed.createComponent(App); <%= zoneless ? 'await fixture.whenStable();' : 'fixture.detectChanges();' %> const compiled = fixture.nativeElement as HTMLElement; diff --git a/packages/schematics/angular/application/files/module-files/src/app/app__suffix__.ts.template b/packages/schematics/angular/application/files/module-files/src/app/app__suffix__.ts.template index 055586955b75..ef9aebaa0e14 100644 --- a/packages/schematics/angular/application/files/module-files/src/app/app__suffix__.ts.template +++ b/packages/schematics/angular/application/files/module-files/src/app/app__suffix__.ts.template @@ -1,7 +1,10 @@ import { Component, signal } from '@angular/core'; @Component({ - selector: '<%= selector %>',<% if(inlineTemplate) { %> + selector: '<%= selector %>', + standalone: false,<% if (inlineStyle) { %> + styles: [],<% } else { %> + styleUrl: './app<%= suffix %>.<%= style %>',<% } %><% if (inlineTemplate) { %> template: `

Hello, {{ title() }}

Congratulations! Your app is running. 🎉

@@ -11,9 +14,6 @@ import { Component, signal } from '@angular/core'; } %> `,<% } else { %> templateUrl: './app<%= suffix %>.html',<% } %> - standalone: false,<% if(inlineStyle) { %> - styles: []<% } else { %> - styleUrl: './app<%= suffix %>.<%= style %>'<% } %> }) export class App { protected readonly title = signal('<%= name %>'); diff --git a/packages/schematics/angular/application/files/module-files/src/app/app__typeSeparator__module.ts.template b/packages/schematics/angular/application/files/module-files/src/app/app__typeSeparator__module.ts.template index f7ad6f2cb515..1efc27f522e6 100644 --- a/packages/schematics/angular/application/files/module-files/src/app/app__typeSeparator__module.ts.template +++ b/packages/schematics/angular/application/files/module-files/src/app/app__typeSeparator__module.ts.template @@ -1,6 +1,5 @@ -import { NgModule, provideBrowserGlobalErrorListeners<% if(!zoneless) { %>, provideZoneChangeDetection<% } %> } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; -<% if (routing) { %> +import { NgModule, provideBrowserGlobalErrorListeners<% if (!zoneless) { %>, provideZoneChangeDetection<% } %> } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser';<% if (routing) { %> import { AppRoutingModule } from './app-routing<%= typeSeparator %>module';<% } %> import { App } from './app<%= suffix %>'; @@ -13,7 +12,7 @@ import { App } from './app<%= suffix %>'; AppRoutingModule<% } %> ], providers: [ - provideBrowserGlobalErrorListeners(),<% if(!zoneless) { %> + provideBrowserGlobalErrorListeners(),<% if (!zoneless) { %> provideZoneChangeDetection({ eventCoalescing: true }),<% } %> ], bootstrap: [App] diff --git a/packages/schematics/angular/application/files/module-files/src/main.ts.template b/packages/schematics/angular/application/files/module-files/src/main.ts.template index f74887b16867..0fcb878b1e23 100644 --- a/packages/schematics/angular/application/files/module-files/src/main.ts.template +++ b/packages/schematics/angular/application/files/module-files/src/main.ts.template @@ -1,8 +1,8 @@ -<% if(!!viewEncapsulation) { %>import { ViewEncapsulation } from '@angular/core'; -<% }%>import { platformBrowser } from '@angular/platform-browser'; +<% if (!!viewEncapsulation) { %>import { ViewEncapsulation } from '@angular/core'; +<% } %>import { platformBrowser } from '@angular/platform-browser'; import { AppModule } from './app/app<%= typeSeparator %>module'; platformBrowser().bootstrapModule(AppModule, { - <% if(!!viewEncapsulation) { %> defaultEncapsulation: ViewEncapsulation.<%= viewEncapsulation %><% } %> + <% if (!!viewEncapsulation) { %> defaultEncapsulation: ViewEncapsulation.<%= viewEncapsulation %><% } %> }) .catch(err => console.error(err)); diff --git a/packages/schematics/angular/application/files/standalone-files/src/app/app.config.ts.template b/packages/schematics/angular/application/files/standalone-files/src/app/app.config.ts.template index 8f0e1b0dc23a..20201fdb80ca 100644 --- a/packages/schematics/angular/application/files/standalone-files/src/app/app.config.ts.template +++ b/packages/schematics/angular/application/files/standalone-files/src/app/app.config.ts.template @@ -1,12 +1,11 @@ -import { ApplicationConfig, provideBrowserGlobalErrorListeners<% if(!zoneless) { %>, provideZoneChangeDetection<% } %> } from '@angular/core';<% if (routing) { %> +import { ApplicationConfig, provideBrowserGlobalErrorListeners<% if (!zoneless) { %>, provideZoneChangeDetection<% } %> } from '@angular/core';<% if (routing) { %> import { provideRouter } from '@angular/router'; - import { routes } from './app.routes';<% } %> export const appConfig: ApplicationConfig = { providers: [ - provideBrowserGlobalErrorListeners(),<% if(!zoneless) { %> + provideBrowserGlobalErrorListeners(),<% if (!zoneless) { %> provideZoneChangeDetection({ eventCoalescing: true }),<% } %> - <% if (routing) {%>provideRouter(routes)<% } %> + <% if (routing) { %>provideRouter(routes)<% } %> ] }; diff --git a/packages/schematics/angular/application/files/standalone-files/src/app/app__suffix__.spec.ts.template b/packages/schematics/angular/application/files/standalone-files/src/app/app__suffix__.spec.ts.template index e6944dc73ccd..306911a0f500 100644 --- a/packages/schematics/angular/application/files/standalone-files/src/app/app__suffix__.spec.ts.template +++ b/packages/schematics/angular/application/files/standalone-files/src/app/app__suffix__.spec.ts.template @@ -5,7 +5,8 @@ describe('App', () => { beforeEach(async () => { await TestBed.configureTestingModule({ imports: [App], - }).compileComponents(); + }) + .compileComponents(); }); it('should create the app', () => { @@ -14,7 +15,7 @@ describe('App', () => { expect(app).toBeTruthy(); }); - it('should render title', <% if(zoneless) { %>async <% } %>() => { + it('should render title', <% if (zoneless) { %>async <% } %>() => { const fixture = TestBed.createComponent(App); <%= zoneless ? 'await fixture.whenStable();' : 'fixture.detectChanges();' %> const compiled = fixture.nativeElement as HTMLElement; diff --git a/packages/schematics/angular/application/files/standalone-files/src/app/app__suffix__.ts.template b/packages/schematics/angular/application/files/standalone-files/src/app/app__suffix__.ts.template index ce8010ecfbce..dfdb04abcb76 100644 --- a/packages/schematics/angular/application/files/standalone-files/src/app/app__suffix__.ts.template +++ b/packages/schematics/angular/application/files/standalone-files/src/app/app__suffix__.ts.template @@ -1,9 +1,11 @@ -import { Component, signal } from '@angular/core';<% if(routing) { %> +import { Component, signal } from '@angular/core';<% if (routing) { %> import { RouterOutlet } from '@angular/router';<% } %> @Component({ - selector: '<%= selector %>', - imports: [<% if(routing) { %>RouterOutlet<% } %>],<% if(inlineTemplate) { %> + imports: [<% if (routing) { %>RouterOutlet<% } %>], + selector: '<%= selector %>',<% if (inlineStyle) { %> + styles: [],<% } else { %> + styleUrl: './app<%= suffix %>.<%= style %>',<% } %><% if (inlineTemplate) { %> template: `

Hello, {{ title() }}

@@ -11,9 +13,7 @@ import { RouterOutlet } from '@angular/router';<% } %> %><% } %> `,<% } else { %> - templateUrl: './app<%= suffix %>.html',<% } if(inlineStyle) { %> - styles: [],<% } else { %> - styleUrl: './app<%= suffix %>.<%= style %>'<% } %> + templateUrl: './app<%= suffix %>.html',<% } %> }) export class App { protected readonly title = signal('<%= name %>'); diff --git a/packages/schematics/angular/component/files/__name@dasherize@if-flat__/__name@dasherize__.__type@dasherize__.__style__.template b/packages/schematics/angular/component/files/__name@dasherize@if-flat__/__name@dasherize__.__type@dasherize__.__style__.template index 2ccecd1220b9..4f8512fa3752 100644 --- a/packages/schematics/angular/component/files/__name@dasherize@if-flat__/__name@dasherize__.__type@dasherize__.__style__.template +++ b/packages/schematics/angular/component/files/__name@dasherize@if-flat__/__name@dasherize__.__type@dasherize__.__style__.template @@ -1,4 +1,4 @@ -<% if(displayBlock){ if(style != 'sass') { %>:host { +<% if (displayBlock) { if (style != 'sass') { %>:host { display: block; } <% } else { %>\:host diff --git a/packages/schematics/angular/component/files/__name@dasherize@if-flat__/__name@dasherize__.__type@dasherize__.spec.ts.template b/packages/schematics/angular/component/files/__name@dasherize@if-flat__/__name@dasherize__.__type@dasherize__.spec.ts.template index 74d858ea1e64..13be0cdf9856 100644 --- a/packages/schematics/angular/component/files/__name@dasherize@if-flat__/__name@dasherize__.__type@dasherize__.spec.ts.template +++ b/packages/schematics/angular/component/files/__name@dasherize@if-flat__/__name@dasherize__.__type@dasherize__.spec.ts.template @@ -1,6 +1,5 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import <% if(!exportDefault) { %>{ <% }%><%= classifiedName %> <% if(!exportDefault) {%>} <% }%>from './<%= dasherize(name) %><%= type ? '.' + dasherize(type): '' %>'; +import <% if (!exportDefault) { %>{ <% } %><%= classifiedName %> <% if (!exportDefault) { %>} <% } %>from './<%= dasherize(name) %><%= type ? '.' + dasherize(type): '' %>'; describe('<%= classifiedName %>', () => { let component: <%= classifiedName %>; @@ -10,7 +9,7 @@ describe('<%= classifiedName %>', () => { await TestBed.configureTestingModule({ <%= standalone ? 'imports' : 'declarations' %>: [<%= classifiedName %>] }) - .compileComponents(); + .compileComponents(); fixture = TestBed.createComponent(<%= classifiedName %>); component = fixture.componentInstance; diff --git a/packages/schematics/angular/component/files/__name@dasherize@if-flat__/__name@dasherize__.__type@dasherize__.ts.template b/packages/schematics/angular/component/files/__name@dasherize@if-flat__/__name@dasherize__.__type@dasherize__.ts.template index d46cd8233862..7b3424c5be17 100644 --- a/packages/schematics/angular/component/files/__name@dasherize@if-flat__/__name@dasherize__.__type@dasherize__.ts.template +++ b/packages/schematics/angular/component/files/__name@dasherize@if-flat__/__name@dasherize__.__type@dasherize__.ts.template @@ -1,24 +1,23 @@ -import { <% if(changeDetection !== 'OnPush') { %>ChangeDetectionStrategy, <% }%>Component<% if(!!viewEncapsulation) { %>, ViewEncapsulation<% }%> } from '@angular/core'; +import { <% if (changeDetection !== 'OnPush') { %>ChangeDetectionStrategy, <% } %>Component<% if (!!viewEncapsulation) { %>, ViewEncapsulation<% } %> } from '@angular/core'; -@Component({<% if(!skipSelector) {%> - selector: '<%= selector %>',<%}%><% if(standalone) {%> - imports: [],<%} else { %> - standalone: false,<% }%><% if(inlineTemplate) { %> +@Component({<% if (changeDetection !== 'OnPush') { %> + changeDetection: ChangeDetectionStrategy.<%= changeDetection %>,<% } %><% if (!!viewEncapsulation) { %> + encapsulation: ViewEncapsulation.<%= viewEncapsulation %>,<% } %><% if (standalone) { %> + imports: [],<% } %><% if (!skipSelector) { %> + selector: '<%= selector %>',<% } %><% if (!standalone) { %> + standalone: false,<% } %><% if (inlineStyle) { %> + styles: `<% if (displayBlock) { %> + :host { + display: block; + } + <% } %>`,<% } else if (style !== 'none') { %> + styleUrl: './<%= dasherize(name) %><%= type ? '.' + dasherize(type): '' %>.<%= style %>',<% } %><% if (inlineTemplate) { %> template: `

<%= dasherize(name) %> works!

`,<% } else { %> - templateUrl: './<%= dasherize(name) %><%= type ? '.' + dasherize(type): '' %><%= ngext %>.html',<% } if(inlineStyle) { %> - styles: `<% if(displayBlock){ %> - :host { - display: block; - } - <% } %>`,<% } else if (style !== 'none') { %> - styleUrl: './<%= dasherize(name) %><%= type ? '.' + dasherize(type): '' %>.<%= style %>',<% } %><% if(!!viewEncapsulation) { %> - encapsulation: ViewEncapsulation.<%= viewEncapsulation %>,<% } if (changeDetection !== 'OnPush') { %> - changeDetection: ChangeDetectionStrategy.<%= changeDetection %>,<% } %> + templateUrl: './<%= dasherize(name) %><%= type ? '.' + dasherize(type): '' %><%= ngext %>.html',<% } %> }) -export <% if(exportDefault) {%>default <%}%>class <%= classifiedName %> { - +export <% if (exportDefault) { %>default <% } %>class <%= classifiedName %> { } diff --git a/packages/schematics/angular/directive/files/__name@dasherize__.__type@dasherize__.ts.template b/packages/schematics/angular/directive/files/__name@dasherize__.__type@dasherize__.ts.template index eff23c7e350a..d932838b1f8e 100644 --- a/packages/schematics/angular/directive/files/__name@dasherize__.__type@dasherize__.ts.template +++ b/packages/schematics/angular/directive/files/__name@dasherize__.__type@dasherize__.ts.template @@ -1,8 +1,8 @@ import { Directive } from '@angular/core'; @Directive({ - selector: '[<%= selector %>]',<% if(!standalone) {%> - standalone: false,<%}%> + selector: '[<%= selector %>]',<% if (!standalone) { %> + standalone: false,<% } %> }) export class <%= classifiedName %> { } diff --git a/packages/schematics/angular/guard/implements-files/__name@dasherize____typeSeparator__guard.spec.ts.template b/packages/schematics/angular/guard/implements-files/__name@dasherize____typeSeparator__guard.spec.ts.template index fefa3afee2b0..0bea60fdd710 100644 --- a/packages/schematics/angular/guard/implements-files/__name@dasherize____typeSeparator__guard.spec.ts.template +++ b/packages/schematics/angular/guard/implements-files/__name@dasherize____typeSeparator__guard.spec.ts.template @@ -1,5 +1,4 @@ import { TestBed } from '@angular/core/testing'; - import { <%= classify(name) %>Guard } from './<%= dasherize(name) %><%= typeSeparator %>guard'; describe('<%= classify(name) %>Guard', () => { diff --git a/packages/schematics/angular/guard/index.ts b/packages/schematics/angular/guard/index.ts index 467fe6198935..8e8d5c75610c 100644 --- a/packages/schematics/angular/guard/index.ts +++ b/packages/schematics/angular/guard/index.ts @@ -34,7 +34,7 @@ export default function (options: GuardOptions): Rule { const routerNamedImports: string[] = [...options.implements, 'MaybeAsync', 'GuardResult']; if (options.implements.includes(GuardInterface.CanMatch)) { - routerNamedImports.push('Route', 'subPath'); + routerNamedImports.push('Route', 'UrlSegment'); if (options.implements.length > 1) { routerNamedImports.push(...commonRouterNameImports); diff --git a/packages/schematics/angular/guard/index_spec.ts b/packages/schematics/angular/guard/index_spec.ts index 3b0c0da2059b..79689f8c71f8 100644 --- a/packages/schematics/angular/guard/index_spec.ts +++ b/packages/schematics/angular/guard/index_spec.ts @@ -165,7 +165,7 @@ describe('Guard Schematic', () => { const options = { ...defaultOptions, implements: implementationOptions, functional: false }; const tree = await schematicRunner.runSchematic('guard', options, appTree); const fileString = tree.readContent('/projects/bar/src/app/foo-guard.ts'); - const expectedImports = `import { CanMatch, GuardResult, MaybeAsync, Route, subPath } from '@angular/router';`; + const expectedImports = `import { CanMatch, GuardResult, MaybeAsync, Route, UrlSegment } from '@angular/router';`; expect(fileString).toContain(expectedImports); }); @@ -198,7 +198,7 @@ describe('Guard Schematic', () => { const fileString = tree.readContent('/projects/bar/src/app/foo-guard.ts'); const expectedImports = `import { ActivatedRouteSnapshot, CanActivate, CanActivateChild, CanMatch, GuardResult, ` + - `MaybeAsync, Route, RouterStateSnapshot, subPath } from '@angular/router';`; + `MaybeAsync, Route, RouterStateSnapshot, UrlSegment } from '@angular/router';`; expect(fileString).toContain(expectedImports); }); diff --git a/packages/schematics/angular/guard/type-files/__name@dasherize____typeSeparator__guard.spec.ts.template b/packages/schematics/angular/guard/type-files/__name@dasherize____typeSeparator__guard.spec.ts.template index 9bad0a553eb4..a9420dc90d56 100644 --- a/packages/schematics/angular/guard/type-files/__name@dasherize____typeSeparator__guard.spec.ts.template +++ b/packages/schematics/angular/guard/type-files/__name@dasherize____typeSeparator__guard.spec.ts.template @@ -1,6 +1,5 @@ import { TestBed } from '@angular/core/testing'; import { <%= guardType %> } from '@angular/router'; - import { <%= camelize(name) %>Guard } from './<%= dasherize(name) %><%= typeSeparator %>guard'; describe('<%= camelize(name) %>Guard', () => { diff --git a/packages/schematics/angular/interceptor/class-files/__name@dasherize____typeSeparator__interceptor.spec.ts.template b/packages/schematics/angular/interceptor/class-files/__name@dasherize____typeSeparator__interceptor.spec.ts.template index 9af595489571..b836eb209e36 100755 --- a/packages/schematics/angular/interceptor/class-files/__name@dasherize____typeSeparator__interceptor.spec.ts.template +++ b/packages/schematics/angular/interceptor/class-files/__name@dasherize____typeSeparator__interceptor.spec.ts.template @@ -1,5 +1,4 @@ import { TestBed } from '@angular/core/testing'; - import { <%= classify(name) %>Interceptor } from './<%= dasherize(name) %><%= typeSeparator %>interceptor'; describe('<%= classify(name) %>Interceptor', () => { diff --git a/packages/schematics/angular/interceptor/class-files/__name@dasherize____typeSeparator__interceptor.ts.template b/packages/schematics/angular/interceptor/class-files/__name@dasherize____typeSeparator__interceptor.ts.template index fffab4ddf988..427ddd774765 100755 --- a/packages/schematics/angular/interceptor/class-files/__name@dasherize____typeSeparator__interceptor.ts.template +++ b/packages/schematics/angular/interceptor/class-files/__name@dasherize____typeSeparator__interceptor.ts.template @@ -9,9 +9,6 @@ import { Observable } from 'rxjs'; @Injectable() export class <%= classify(name) %>Interceptor implements HttpInterceptor { - - constructor() {} - intercept(request: HttpRequest, next: HttpHandler): Observable> { return next.handle(request); } diff --git a/packages/schematics/angular/interceptor/functional-files/__name@dasherize____typeSeparator__interceptor.spec.ts.template b/packages/schematics/angular/interceptor/functional-files/__name@dasherize____typeSeparator__interceptor.spec.ts.template index ee1662c6530f..a01d79325e01 100755 --- a/packages/schematics/angular/interceptor/functional-files/__name@dasherize____typeSeparator__interceptor.spec.ts.template +++ b/packages/schematics/angular/interceptor/functional-files/__name@dasherize____typeSeparator__interceptor.spec.ts.template @@ -1,6 +1,5 @@ import { TestBed } from '@angular/core/testing'; import { HttpInterceptorFn } from '@angular/common/http'; - import { <%= camelize(name) %>Interceptor } from './<%= dasherize(name) %><%= typeSeparator %>interceptor'; describe('<%= camelize(name) %>Interceptor', () => { diff --git a/packages/schematics/angular/library/files/README.md.template b/packages/schematics/angular/library/files/README.md.template index 661e8958b9f6..d0c32c07f678 100644 --- a/packages/schematics/angular/library/files/README.md.template +++ b/packages/schematics/angular/library/files/README.md.template @@ -43,7 +43,7 @@ Once the project is built, you can publish your library by following these steps ## Running unit tests -To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command: +To execute unit tests with the [Vitest](https://vitest.dev/) test runner, use the following command: ```bash ng test diff --git a/packages/schematics/angular/ng-new/index_spec.ts b/packages/schematics/angular/ng-new/index_spec.ts index a9a6b4a1b6b2..8023c9b08531 100644 --- a/packages/schematics/angular/ng-new/index_spec.ts +++ b/packages/schematics/angular/ng-new/index_spec.ts @@ -109,7 +109,7 @@ describe('Ng New Schematic', () => { const tree = await schematicRunner.runSchematic('ng-new', options); const files = tree.files; - expect(files).toContain('/bar/AGENTS.md'); + expect(files).toContain('/bar/CLAUDE.md'); expect(files).toContain('/bar/.mcp.json'); expect(files).toContain('/bar/.gemini/GEMINI.md'); expect(files).toContain('/bar/.gemini/settings.json'); diff --git a/packages/schematics/angular/pipe/files/__name@dasherize____typeSeparator__pipe.ts.template b/packages/schematics/angular/pipe/files/__name@dasherize____typeSeparator__pipe.ts.template index 57765121531e..3348a8225ee9 100644 --- a/packages/schematics/angular/pipe/files/__name@dasherize____typeSeparator__pipe.ts.template +++ b/packages/schematics/angular/pipe/files/__name@dasherize____typeSeparator__pipe.ts.template @@ -1,13 +1,11 @@ import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ - name: '<%= camelize(name) %>',<% if(!standalone) {%> - standalone: false,<%}%> + name: '<%= camelize(name) %>',<% if (!standalone) { %> + standalone: false,<% } %> }) export class <%= classify(name) %>Pipe implements PipeTransform { - transform(value: unknown, ...args: unknown[]): unknown { return null; } - } diff --git a/packages/schematics/angular/refactor/jasmine-vitest/test-file-transformer.integration_spec.ts b/packages/schematics/angular/refactor/jasmine-vitest/test-file-transformer.integration_spec.ts index 5b30e9f24f4b..ce667dce1afc 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/test-file-transformer.integration_spec.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/test-file-transformer.integration_spec.ts @@ -392,14 +392,14 @@ describe('Jasmine to Vitest Transformer - Integration Tests', () => { it('should handle fail()', () => { if (true) { - throw new Error('This should not have happened'); + expect.fail('This should not have happened'); } }); it('should handle fail() with a specific error', () => { try { expect(1).toBe(2); - throw new Error('Expected test to fail'); + expect.fail('Expected test to fail'); } catch (err) { expect(err.message).toBe('1 !== 2'); } diff --git a/packages/schematics/angular/refactor/jasmine-vitest/test-file-transformer.ts b/packages/schematics/angular/refactor/jasmine-vitest/test-file-transformer.ts index f652368b03f7..e436434f134a 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/test-file-transformer.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/test-file-transformer.ts @@ -144,6 +144,7 @@ const callExpressionTransformers = [ // **Stage 3: Global Functions & Cleanup** // These handle global Jasmine functions and catch-alls for unsupported APIs. + transformFail, transformTimerMocks, transformUnsupportedGlobalFunctions, transformUnsupportedJasmineCalls, @@ -168,7 +169,6 @@ const expressionStatementTransformers = [ transformCalledOnceWith, transformArrayWithExactContents, transformExpectNothing, - transformFail, transformJasmineMembers, ]; @@ -227,18 +227,16 @@ export function transformJasmineToVitest( } for (const transformer of callExpressionTransformers) { - if ( - !( - (options.browserMode && transformer === transformToHaveClass) || - (options.fakeAsync === false && - [ - transformFakeAsyncFlush, - transformFakeAsyncFlushMicrotasks, - transformFakeAsyncTick, - transformFakeAsyncTest, - ].includes(transformer)) - ) - ) { + if (!( + (options.browserMode && transformer === transformToHaveClass) || + (options.fakeAsync === false && + [ + transformFakeAsyncFlush, + transformFakeAsyncFlushMicrotasks, + transformFakeAsyncTick, + transformFakeAsyncTest, + ].includes(transformer)) + )) { transformedNode = transformer(transformedNode, refactorCtx); } } diff --git a/packages/schematics/angular/refactor/jasmine-vitest/test-file-transformer_add-imports_spec.ts b/packages/schematics/angular/refactor/jasmine-vitest/test-file-transformer_add-imports_spec.ts index f4b10d485920..cbe05226ef7b 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/test-file-transformer_add-imports_spec.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/test-file-transformer_add-imports_spec.ts @@ -178,4 +178,24 @@ describe('Jasmine to Vitest Transformer - addImports option', () => { `; await expectTransformation(input, expected, true); }); + + it('should add import for `expect` when `fail()` is used and addImports is true', async () => { + const input = ` + describe('My Suite', () => { + it('fails', () => { + fail('Something went wrong'); + }); + }); + `; + const expected = ` + import { describe, expect, it } from 'vitest'; + + describe('My Suite', () => { + it('fails', () => { + expect.fail('Something went wrong'); + }); + }); + `; + await expectTransformation(input, expected, true); + }); }); diff --git a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-misc.ts b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-misc.ts index f71353cc9783..fe7e944e53e1 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-misc.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-misc.ts @@ -90,29 +90,53 @@ export function transformTimerMocks(node: ts.Node, ctx: RefactorContext): ts.Nod return node; } -export function transformFail(node: ts.Node, { sourceFile, reporter }: RefactorContext): ts.Node { +export function transformFail( + node: ts.Node, + { sourceFile, reporter, pendingVitestValueImports }: RefactorContext, +): ts.Node { if ( - ts.isExpressionStatement(node) && - ts.isCallExpression(node.expression) && - ts.isIdentifier(node.expression.expression) && - node.expression.expression.text === 'fail' + ts.isCallExpression(node) && + ts.isIdentifier(node.expression) && + node.expression.text === 'fail' ) { - reporter.reportTransformation(sourceFile, node, 'Transformed `fail()` to `throw new Error()`.'); - - const arg = node.expression.arguments[0]; - let throwExpression: ts.Expression; - - if (arg && ts.isNewExpression(arg)) { - throwExpression = arg; - } else { - throwExpression = ts.factory.createNewExpression( - ts.factory.createIdentifier('Error'), - undefined, - arg ? [arg] : [], - ); + addVitestValueImport(pendingVitestValueImports, 'expect'); + reporter.reportTransformation(sourceFile, node, 'Transformed `fail()` to `expect.fail()`.'); + + const arg = node.arguments[0]; + let replacementArg: ts.Expression | undefined = arg; + let hasNonStringArg = false; + + if (arg) { + if (ts.isNewExpression(arg)) { + replacementArg = arg.arguments && arg.arguments.length > 0 ? arg.arguments[0] : undefined; + } else if ( + !ts.isStringLiteral(arg) && + !ts.isNoSubstitutionTemplateLiteral(arg) && + !ts.isTemplateExpression(arg) + ) { + replacementArg = ts.factory.createCallExpression( + ts.factory.createIdentifier('String'), + undefined, + [arg], + ); + hasNonStringArg = true; + } } - const replacement = ts.factory.createThrowStatement(throwExpression); + const replacement = ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier('expect'), + ts.factory.createIdentifier('fail'), + ), + undefined, + replacementArg ? [replacementArg] : [], + ); + + if (hasNonStringArg) { + const category = 'fail-non-string-argument'; + reporter.recordTodo(category, sourceFile, node); + addTodoComment(replacement, category); + } return ts.setOriginalNode(ts.setTextRange(replacement, node), node); } @@ -197,11 +221,7 @@ const UNSUPPORTED_GLOBAL_FUNCTION_CATEGORIES = new Set([ function isUnsupportedGlobalFunction( methodName: string, ): methodName is - | 'setSpecProperty' - | 'setSuiteProperty' - | 'throwUnless' - | 'throwUnlessAsync' - | 'getSpecProperty' { + 'setSpecProperty' | 'setSuiteProperty' | 'throwUnless' | 'throwUnlessAsync' | 'getSpecProperty' { return UNSUPPORTED_GLOBAL_FUNCTION_CATEGORIES.has(methodName as TodoCategory); } diff --git a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-misc_spec.ts b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-misc_spec.ts index a5b29f2d2b6a..49cb2d54475a 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-misc_spec.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-misc_spec.ts @@ -59,19 +59,31 @@ jasmine.clock().withMock(noop);`, describe('transformFail', () => { const testCases = [ { - description: 'should transform fail() to throw new Error()', + description: 'should transform fail() to expect.fail()', input: `fail('This should not happen');`, - expected: `throw new Error('This should not happen');`, + expected: `expect.fail('This should not happen');`, }, { - description: 'should transform fail() without a message to throw new Error()', + description: 'should transform fail() without a message to expect.fail()', input: `fail();`, - expected: `throw new Error();`, + expected: `expect.fail();`, }, { description: 'should transform fail() with an Error object', input: `fail(new TypeError('Invalid input'));`, - expected: `throw new TypeError('Invalid input');`, + expected: `expect.fail('Invalid input');`, + }, + { + description: 'should transform fail() with an empty Error object', + input: `fail(new Error());`, + expected: `expect.fail();`, + }, + { + description: 'should transform fail() with a non-string argument and add a TODO note', + input: `fail(err);`, + // eslint-disable-next-line max-len + expected: `// TODO: vitest-migration: expect.fail() only accepts a string message. Verify that converting this argument with String() produces the expected failure output. See: https://vitest.dev/api/expect.html#expect-fail +expect.fail(String(err));`, }, ]; diff --git a/packages/schematics/angular/refactor/jasmine-vitest/utils/todo-notes.ts b/packages/schematics/angular/refactor/jasmine-vitest/utils/todo-notes.ts index 598606d7bde6..0179a0314277 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/utils/todo-notes.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/utils/todo-notes.ts @@ -64,6 +64,12 @@ export const TODO_NOTES = { message: 'expect().nothing() has been removed because it is redundant in Vitest. Tests without assertions pass by default.', }, + 'fail-non-string-argument': { + message: + 'expect.fail() only accepts a string message. ' + + 'Verify that converting this argument with String() produces the expected failure output.', + url: 'https://vitest.dev/api/expect.html#expect-fail', + }, 'unsupported-jasmine-member': { message: (context: { name: string }): string => `jasmine.${context.name} is not supported.`, }, diff --git a/packages/schematics/angular/resolver/class-files/__name@dasherize____typeSeparator__resolver.spec.ts.template b/packages/schematics/angular/resolver/class-files/__name@dasherize____typeSeparator__resolver.spec.ts.template index af27433460e5..42e600625d0b 100644 --- a/packages/schematics/angular/resolver/class-files/__name@dasherize____typeSeparator__resolver.spec.ts.template +++ b/packages/schematics/angular/resolver/class-files/__name@dasherize____typeSeparator__resolver.spec.ts.template @@ -1,5 +1,4 @@ import { TestBed } from '@angular/core/testing'; - import { <%= classify(name) %>Resolver } from './<%= dasherize(name) %><%= typeSeparator %>resolver'; describe('<%= classify(name) %>Resolver', () => { diff --git a/packages/schematics/angular/resolver/functional-files/__name@dasherize____typeSeparator__resolver.spec.ts.template b/packages/schematics/angular/resolver/functional-files/__name@dasherize____typeSeparator__resolver.spec.ts.template index c9f42a1a0bd5..c5a62b14b577 100644 --- a/packages/schematics/angular/resolver/functional-files/__name@dasherize____typeSeparator__resolver.spec.ts.template +++ b/packages/schematics/angular/resolver/functional-files/__name@dasherize____typeSeparator__resolver.spec.ts.template @@ -1,6 +1,5 @@ import { TestBed } from '@angular/core/testing'; import { ResolveFn } from '@angular/router'; - import { <%= camelize(name) %>Resolver } from './<%= dasherize(name) %><%= typeSeparator %>resolver'; describe('<%= camelize(name) %>Resolver', () => { diff --git a/packages/schematics/angular/server/files/server-builder/ngmodule-src/app/app.module.server.ts.template b/packages/schematics/angular/server/files/server-builder/ngmodule-src/app/app.module.server.ts.template index eeffba7f902b..5e79f7aa57ad 100644 --- a/packages/schematics/angular/server/files/server-builder/ngmodule-src/app/app.module.server.ts.template +++ b/packages/schematics/angular/server/files/server-builder/ngmodule-src/app/app.module.server.ts.template @@ -1,6 +1,5 @@ import { NgModule } from '@angular/core'; import { ServerModule } from '@angular/platform-server'; - import { <%= appModuleName %> } from '<%= appModulePath %>'; import { <%= appComponentName %> } from '<%= appComponentPath %>'; diff --git a/packages/schematics/angular/service/files/__name@dasherize__.__type@dasherize__.spec.ts.template b/packages/schematics/angular/service/files/__name@dasherize__.__type@dasherize__.spec.ts.template index 168bb9ef23f2..0a85fae12489 100644 --- a/packages/schematics/angular/service/files/__name@dasherize__.__type@dasherize__.spec.ts.template +++ b/packages/schematics/angular/service/files/__name@dasherize__.__type@dasherize__.spec.ts.template @@ -1,5 +1,4 @@ import { TestBed } from '@angular/core/testing'; - import { <%= classifiedName %> } from './<%= dasherize(name) %><%= type ? '.' + dasherize(type) : '' %>'; describe('<%= classifiedName %>', () => { diff --git a/packages/schematics/angular/service/files/__name@dasherize__.__type@dasherize__.ts.template b/packages/schematics/angular/service/files/__name@dasherize__.__type@dasherize__.ts.template index 3b9a10da6ce4..0c9620cb0bcd 100644 --- a/packages/schematics/angular/service/files/__name@dasherize__.__type@dasherize__.ts.template +++ b/packages/schematics/angular/service/files/__name@dasherize__.__type@dasherize__.ts.template @@ -4,5 +4,4 @@ import { <%= injectable ? 'Injectable' : 'Service' %> } from '@angular/core'; providedIn: 'root', })<% } else { %>@Service()<% } %> export class <%= classifiedName %> { - } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a4a7dbe23065..9b1866762625 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,8 +14,8 @@ importers: .: dependencies: '@angular/compiler-cli': - specifier: 22.1.0-rc.0 - version: 22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(typescript@6.0.3) + specifier: 22.1.4 + version: 22.1.4(@angular/compiler@22.1.4)(typescript@6.0.3) typescript: specifier: 6.0.3 version: 6.0.3 @@ -26,44 +26,44 @@ importers: built: true devDependencies: '@angular/animations': - specifier: 22.1.0-rc.0 - version: 22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)) + specifier: 22.1.4 + version: 22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)) '@angular/cdk': - specifier: 22.1.0-next.4 - version: 22.1.0-next.4(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.0-rc.0(@angular/animations@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) + specifier: 22.1.4 + version: 22.1.4(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.4(@angular/animations@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) '@angular/common': - specifier: 22.1.0-rc.0 - version: 22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + specifier: 22.1.4 + version: 22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) '@angular/compiler': - specifier: 22.1.0-rc.0 - version: 22.1.0-rc.0 + specifier: 22.1.4 + version: 22.1.4 '@angular/core': - specifier: 22.1.0-rc.0 - version: 22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2) + specifier: 22.1.4 + version: 22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2) '@angular/forms': - specifier: 22.1.0-rc.0 - version: 22.1.0-rc.0(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.0-rc.0(@angular/animations@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) + specifier: 22.1.4 + version: 22.1.4(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.4(@angular/animations@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) '@angular/localize': - specifier: 22.1.0-rc.0 - version: 22.1.0-rc.0(@angular/compiler-cli@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(typescript@6.0.3))(@angular/compiler@22.1.0-rc.0) + specifier: 22.1.4 + version: 22.1.4(@angular/compiler-cli@22.1.4(@angular/compiler@22.1.4)(typescript@6.0.3))(@angular/compiler@22.1.4) '@angular/material': - specifier: 22.1.0-next.4 - version: 22.1.0-next.4(4ff7080c77e2fe320ac430b9737f79ee) + specifier: 22.1.4 + version: 22.1.4(37c77e13676b90a7dcd0d6f9cc058167) '@angular/ng-dev': - specifier: https://github.com/angular/dev-infra-private-ng-dev-builds.git#7a67d5221a9efec2b69b102759d04223a3fc8552 - version: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/7a67d5221a9efec2b69b102759d04223a3fc8552(@modelcontextprotocol/sdk@1.29.0(supports-color@10.2.2)(zod@4.4.3)) + specifier: https://github.com/angular/dev-infra-private-ng-dev-builds.git#beec8fe17573a33c9934487ce99ce9cce3e3f6bf + version: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/beec8fe17573a33c9934487ce99ce9cce3e3f6bf(@modelcontextprotocol/sdk@1.30.0(supports-color@11.0.0)(zod@4.4.3)) '@angular/platform-browser': - specifier: 22.1.0-rc.0 - version: 22.1.0-rc.0(@angular/animations@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)) + specifier: 22.1.4 + version: 22.1.4(@angular/animations@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)) '@angular/platform-server': - specifier: 22.1.0-rc.0 - version: 22.1.0-rc.0(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/compiler@22.1.0-rc.0)(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.0-rc.0(@angular/animations@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) + specifier: 22.1.4 + version: 22.1.4(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/compiler@22.1.4)(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.4(@angular/animations@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) '@angular/router': - specifier: 22.1.0-rc.0 - version: 22.1.0-rc.0(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.0-rc.0(@angular/animations@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) + specifier: 22.1.4 + version: 22.1.4(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.4(@angular/animations@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) '@angular/service-worker': - specifier: 22.1.0-rc.0 - version: 22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + specifier: 22.1.4 + version: 22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) '@babel/core': specifier: 8.0.1 version: 8.0.1 @@ -78,13 +78,13 @@ importers: version: 0.28.0 '@eslint/compat': specifier: 2.1.0 - version: 2.1.0(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2)) + version: 2.1.0(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0)) '@eslint/eslintrc': specifier: 3.3.6 - version: 3.3.6(supports-color@10.2.2) + version: 3.3.6(supports-color@11.0.0) '@eslint/js': specifier: 10.0.1 - version: 10.0.1(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2)) + version: 10.0.1(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0)) '@rollup/plugin-alias': specifier: ^6.0.0 version: 6.0.0(rollup@4.62.2) @@ -102,10 +102,10 @@ importers: version: 4.62.2 '@stylistic/eslint-plugin': specifier: ^5.0.0 - version: 5.10.0(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2)) + version: 5.10.0(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0)) '@tony.ganchev/eslint-plugin-header': specifier: ~3.4.0 - version: 3.4.4(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2)) + version: 3.4.4(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0)) '@types/babel__core': specifier: 7.20.5 version: 7.20.5 @@ -129,16 +129,16 @@ importers: version: 2.5.3 '@types/karma': specifier: ^6.3.0 - version: 6.3.9(supports-color@10.2.2) + version: 6.3.9(supports-color@11.0.0) '@types/less': specifier: ^3.0.3 version: 3.0.8 '@types/loader-utils': specifier: ^3.0.0 - version: 3.0.0(esbuild@0.28.1) + version: 3.0.0(esbuild@0.28.2) '@types/lodash': specifier: ^4.17.0 - version: 4.17.24 + version: 4.17.25 '@types/node': specifier: ^22.12.0 version: 22.20.1 @@ -153,7 +153,7 @@ importers: version: 2.0.7 '@types/semver': specifier: ^7.3.12 - version: 7.7.1 + version: 7.8.0 '@types/watchpack': specifier: ^2.4.4 version: 2.4.5 @@ -165,10 +165,10 @@ importers: version: 21.0.3 '@typescript-eslint/eslint-plugin': specifier: 8.64.0 - version: 8.64.0(@typescript-eslint/parser@8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + version: 8.64.0(@typescript-eslint/parser@8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3))(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3) '@typescript-eslint/parser': specifier: 8.64.0 - version: 8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + version: 8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3) ajv: specifier: 8.20.0 version: 8.20.0 @@ -176,23 +176,23 @@ importers: specifier: 6.0.3 version: 6.0.3 esbuild: - specifier: 0.28.1 - version: 0.28.1 + specifier: 0.28.2 + version: 0.28.2 esbuild-wasm: - specifier: 0.28.1 - version: 0.28.1 + specifier: 0.28.2 + version: 0.28.2 eslint: specifier: 10.7.0 - version: 10.7.0(jiti@2.7.0)(supports-color@10.2.2) + version: 10.7.0(jiti@2.7.0)(supports-color@11.0.0) eslint-config-prettier: specifier: 10.1.8 - version: 10.1.8(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2)) + version: 10.1.8(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0)) eslint-plugin-import: specifier: 2.32.0 - version: 2.32.0(@typescript-eslint/parser@8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2) + version: 2.32.0(@typescript-eslint/parser@8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3))(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0) express: specifier: 5.2.1 - version: 5.2.1(supports-color@10.2.2) + version: 5.2.1(supports-color@11.0.0) fast-glob: specifier: 3.3.3 version: 3.3.3 @@ -201,10 +201,10 @@ importers: version: 17.7.0 http-proxy: specifier: ^1.18.1 - version: 1.18.1(debug@4.4.3(supports-color@10.2.2)) + version: 1.18.1(debug@4.4.3(supports-color@11.0.0)) http-proxy-middleware: specifier: 4.2.0 - version: 4.2.0(supports-color@10.2.2) + version: 4.2.0(supports-color@11.0.0) husky: specifier: 9.1.7 version: 9.1.7 @@ -222,19 +222,19 @@ importers: version: 7.0.0 karma: specifier: ~6.4.0 - version: 6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6) + version: 6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6) karma-chrome-launcher: specifier: ~3.2.0 version: 3.2.0 karma-coverage: specifier: ~2.2.0 - version: 2.2.1(supports-color@10.2.2) + version: 2.2.1(supports-color@11.0.0) karma-jasmine: specifier: ~5.1.0 - version: 5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6)) + version: 5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6)) karma-jasmine-html-reporter: specifier: ~2.2.0 - version: 2.2.0(jasmine-core@6.3.0)(karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6)))(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6)) + version: 2.2.0(jasmine-core@6.3.0)(karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6)))(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6)) karma-source-map-support: specifier: 1.4.0 version: 1.4.0 @@ -282,10 +282,10 @@ importers: version: 1.10.0 verdaccio: specifier: 6.8.0 - version: 6.8.0(encoding@0.1.13)(supports-color@10.2.2) + version: 6.8.0(encoding@0.1.13)(supports-color@11.0.0) verdaccio-auth-memory: specifier: ^13.0.0 - version: 13.0.3(supports-color@10.2.2) + version: 13.1.2(supports-color@11.0.0) zone.js: specifier: ^0.16.0 version: 0.16.2 @@ -309,22 +309,22 @@ importers: version: 4.1.10(vitest@4.1.10) browser-sync: specifier: 3.0.4 - version: 3.0.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6) + version: 3.0.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6) istanbul-lib-instrument: specifier: 6.0.3 - version: 6.0.3(supports-color@10.2.2) + version: 6.0.3(supports-color@11.0.0) jsdom: specifier: 29.1.1 version: 29.1.1 ng-packagr: - specifier: 22.1.0-next.3 - version: 22.1.0-next.3(@angular/compiler-cli@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(typescript@6.0.3))(tslib@2.8.1)(typescript@6.0.3) + specifier: 22.1.1 + version: 22.1.1(@angular/compiler-cli@22.1.4(@angular/compiler@22.1.4)(typescript@6.0.3))(supports-color@11.0.0)(tslib@2.8.1)(typescript@6.0.3) rxjs: specifier: 7.8.2 version: 7.8.2 vitest: specifier: 4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/coverage-v8@4.1.10)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(less@4.6.7)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(@vitest/coverage-v8@4.1.10)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@29.1.1)(less@4.9.0(supports-color@11.0.0))(sass@1.101.0)(terser@5.49.0)(tsx@4.23.12)(yaml@2.9.0) packages/angular/build: dependencies: @@ -345,28 +345,28 @@ importers: version: 7.24.7 '@inquirer/confirm': specifier: 6.1.1 - version: 6.1.1(@types/node@24.13.3) + version: 6.1.1(@types/node@22.20.1) '@vitejs/plugin-basic-ssl': specifier: 2.3.0 - version: 2.3.0(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.7)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0)) + version: 2.3.0(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.0(supports-color@11.0.0))(sass@1.101.0)(terser@5.49.0)(tsx@4.23.12)(yaml@2.9.0)) beasties: specifier: 0.4.3 version: 0.4.3 browserslist: specifier: ^4.26.0 - version: 4.28.7 + version: 4.28.8 esbuild: - specifier: 0.28.1 - version: 0.28.1 + specifier: 0.28.2 + version: 0.28.2 https-proxy-agent: specifier: 9.1.0 - version: 9.1.0(supports-color@10.2.2) + version: 9.1.0(supports-color@11.0.0) jsonc-parser: specifier: 3.3.1 version: 3.3.1 listr2: - specifier: 10.2.2 - version: 10.2.2 + specifier: 11.0.0 + version: 11.0.0 magic-string: specifier: 1.0.0 version: 1.0.0 @@ -374,8 +374,8 @@ importers: specifier: 2.0.1 version: 2.0.1 oxc-parser: - specifier: 0.140.0 - version: 0.140.0 + specifier: 0.142.0 + version: 0.142.0 parse5-html-rewriting-stream: specifier: 8.0.1 version: 8.0.1 @@ -402,7 +402,7 @@ importers: version: 0.2.17 vite: specifier: 8.1.5 - version: 8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.7)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0) + version: 8.1.5(@types/node@22.20.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.0(supports-color@11.0.0))(sass@1.101.0)(terser@5.49.0)(tsx@4.23.12)(yaml@2.9.0) watchpack: specifier: 2.5.2 version: 2.5.2 @@ -418,19 +418,19 @@ importers: version: 0.140.0 istanbul-lib-instrument: specifier: 6.0.3 - version: 6.0.3(supports-color@10.2.2) + version: 6.0.3(supports-color@11.0.0) jsdom: specifier: 29.1.1 version: 29.1.1 less: - specifier: 4.6.7 - version: 4.6.7 + specifier: 4.9.0 + version: 4.9.0(supports-color@11.0.0) ng-packagr: - specifier: 22.1.0-next.3 - version: 22.1.0-next.3(@angular/compiler-cli@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(typescript@6.0.3))(tslib@2.8.1)(typescript@6.0.3) + specifier: 22.1.1 + version: 22.1.1(@angular/compiler-cli@22.1.4(@angular/compiler@22.1.4)(typescript@6.0.3))(supports-color@11.0.0)(tslib@2.8.1)(typescript@6.0.3) postcss: - specifier: 8.5.19 - version: 8.5.19 + specifier: 8.5.25 + version: 8.5.25 rollup: specifier: 4.62.2 version: 4.62.2 @@ -439,7 +439,7 @@ importers: version: 7.8.2 vitest: specifier: 4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/coverage-v8@4.1.10)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(less@4.6.7)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(@vitest/coverage-v8@4.1.10)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@29.1.1)(less@4.9.0(supports-color@11.0.0))(sass@1.101.0)(terser@5.49.0)(tsx@4.23.12)(yaml@2.9.0) optionalDependencies: lmdb: specifier: 3.5.6 @@ -458,13 +458,13 @@ importers: version: link:../../angular_devkit/schematics '@inquirer/prompts': specifier: 8.5.2 - version: 8.5.2(@types/node@24.13.3) + version: 8.5.2(@types/node@22.20.1) '@listr2/prompt-adapter-inquirer': - specifier: 4.2.4 - version: 4.2.4(@inquirer/prompts@8.5.2(@types/node@24.13.3))(@types/node@24.13.3)(listr2@10.2.2) + specifier: 4.2.5 + version: 4.2.5(@inquirer/prompts@8.5.2(@types/node@22.20.1))(@types/node@22.20.1)(listr2@11.0.0) '@modelcontextprotocol/sdk': - specifier: 1.29.0 - version: 1.29.0(supports-color@10.2.2)(zod@4.4.3) + specifier: 1.30.0 + version: 1.30.0(supports-color@11.0.0)(zod@4.4.3) '@schematics/angular': specifier: workspace:0.0.0-PLACEHOLDER version: link:../../schematics/angular @@ -472,8 +472,8 @@ importers: specifier: 3.3.1 version: 3.3.1 listr2: - specifier: 10.2.2 - version: 10.2.2 + specifier: 11.0.0 + version: 11.0.0 npm-package-arg: specifier: 14.0.0 version: 14.0.0 @@ -484,8 +484,8 @@ importers: specifier: 7.8.5 version: 7.8.5 yargs: - specifier: 18.0.0 - version: 18.0.0 + specifier: 18.1.0 + version: 18.1.0 zod: specifier: 4.4.3 version: 4.4.3 @@ -512,23 +512,23 @@ importers: specifier: workspace:* version: link:../../angular_devkit/schematics '@angular/common': - specifier: 22.1.0-rc.0 - version: 22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + specifier: 22.1.4 + version: 22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) '@angular/compiler': - specifier: 22.1.0-rc.0 - version: 22.1.0-rc.0 + specifier: 22.1.4 + version: 22.1.4 '@angular/core': - specifier: 22.1.0-rc.0 - version: 22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2) + specifier: 22.1.4 + version: 22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2) '@angular/platform-browser': - specifier: 22.1.0-rc.0 - version: 22.1.0-rc.0(@angular/animations@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)) + specifier: 22.1.4 + version: 22.1.4(@angular/animations@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)) '@angular/platform-server': - specifier: 22.1.0-rc.0 - version: 22.1.0-rc.0(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/compiler@22.1.0-rc.0)(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.0-rc.0(@angular/animations@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) + specifier: 22.1.4 + version: 22.1.4(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/compiler@22.1.4)(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.4(@angular/animations@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) '@angular/router': - specifier: 22.1.0-rc.0 - version: 22.1.0-rc.0(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.0-rc.0(@angular/animations@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) + specifier: 22.1.4 + version: 22.1.4(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.4(@angular/animations@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) '@schematics/angular': specifier: workspace:* version: link:../../schematics/angular @@ -600,28 +600,28 @@ importers: version: 4.1.3 autoprefixer: specifier: 10.5.4 - version: 10.5.4(postcss@8.5.19) + version: 10.5.4(postcss@8.5.25) babel-loader: specifier: 10.1.1 - version: 10.1.1(@babel/core@8.0.1)(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)) + version: 10.1.1(@babel/core@8.0.1)(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)) browserslist: specifier: ^4.26.0 - version: 4.28.7 + version: 4.28.8 copy-webpack-plugin: specifier: 14.0.0 - version: 14.0.0(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)) + version: 14.0.0(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)) css-loader: specifier: 7.1.4 - version: 7.1.4(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)) + version: 7.1.4(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)) esbuild-wasm: - specifier: 0.28.1 - version: 0.28.1 + specifier: 0.28.2 + version: 0.28.2 http-proxy-middleware: specifier: 4.2.0 - version: 4.2.0(supports-color@10.2.2) + version: 4.2.0(supports-color@11.0.0) istanbul-lib-instrument: specifier: 6.0.3 - version: 6.0.3(supports-color@10.2.2) + version: 6.0.3(supports-color@11.0.0) jsonc-parser: specifier: 3.3.1 version: 3.3.1 @@ -629,20 +629,20 @@ importers: specifier: 1.4.0 version: 1.4.0 less: - specifier: 4.6.7 - version: 4.6.7 + specifier: 4.9.0 + version: 4.9.0(supports-color@11.0.0) less-loader: specifier: 13.0.0 - version: 13.0.0(less@4.6.7)(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)) + version: 13.0.0(less@4.9.0(supports-color@11.0.0))(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)) license-webpack-plugin: specifier: 4.0.2 - version: 4.0.2(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)) + version: 4.0.2(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)) loader-utils: specifier: 3.3.1 version: 3.3.1 mini-css-extract-plugin: specifier: 2.10.2 - version: 2.10.2(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)) + version: 2.10.2(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)) open: specifier: 11.0.0 version: 11.0.0 @@ -656,11 +656,11 @@ importers: specifier: 5.2.0 version: 5.2.0 postcss: - specifier: 8.5.19 - version: 8.5.19 + specifier: 8.5.25 + version: 8.5.25 postcss-loader: specifier: 8.2.1 - version: 8.2.1(postcss@8.5.19)(typescript@6.0.3)(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)) + version: 8.2.1(postcss@8.5.25)(typescript@6.0.3)(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)) resolve-url-loader: specifier: 5.0.0 version: 5.0.0 @@ -672,13 +672,13 @@ importers: version: 1.101.0 sass-loader: specifier: 17.0.0 - version: 17.0.0(sass@1.101.0)(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)) + version: 17.0.0(sass@1.101.0)(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)) semver: specifier: 7.8.5 version: 7.8.5 source-map-loader: specifier: 5.0.0 - version: 5.0.0(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)) + version: 5.0.0(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)) source-map-support: specifier: 0.5.21 version: 0.5.21 @@ -692,37 +692,37 @@ importers: specifier: 2.8.1 version: 2.8.1 webpack: - specifier: 5.108.4 - version: 5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3) + specifier: 5.109.2 + version: 5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3) webpack-dev-middleware: specifier: 8.0.3 - version: 8.0.3(tslib@2.8.1)(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)) + version: 8.0.3(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)) webpack-dev-server: specifier: 5.2.6 - version: 5.2.6(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(tslib@2.8.1)(utf-8-validate@6.0.6)(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)) + version: 5.2.6(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6)(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)) webpack-merge: specifier: 6.0.1 version: 6.0.1 webpack-subresource-integrity: specifier: 5.1.0 - version: 5.1.0(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)) + version: 5.1.0(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)) devDependencies: '@angular/ssr': specifier: workspace:* version: link:../../angular/ssr browser-sync: specifier: 3.0.4 - version: 3.0.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6) + version: 3.0.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6) ng-packagr: - specifier: 22.1.0-next.3 - version: 22.1.0-next.3(@angular/compiler-cli@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(typescript@6.0.3))(tslib@2.8.1)(typescript@6.0.3) + specifier: 22.1.1 + version: 22.1.1(@angular/compiler-cli@22.1.4(@angular/compiler@22.1.4)(typescript@6.0.3))(supports-color@11.0.0)(tslib@2.8.1)(typescript@6.0.3) undici: specifier: 8.7.0 version: 8.7.0 optionalDependencies: esbuild: - specifier: 0.28.1 - version: 0.28.1 + specifier: 0.28.2 + version: 0.28.2 packages/angular_devkit/build_webpack: dependencies: @@ -740,11 +740,11 @@ importers: specifier: workspace:0.0.0-PLACEHOLDER version: link:../../ngtools/webpack webpack: - specifier: 5.108.4 - version: 5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3) + specifier: 5.109.2 + version: 5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3) webpack-dev-server: specifier: 5.2.6 - version: 5.2.6(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(tslib@2.8.1)(utf-8-validate@6.0.6)(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)) + version: 5.2.6(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6)(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)) packages/angular_devkit/core: dependencies: @@ -799,7 +799,7 @@ importers: version: link:../schematics '@inquirer/prompts': specifier: 8.5.2 - version: 8.5.2(@types/node@24.13.3) + version: 8.5.2(@types/node@22.20.1) packages/ngtools/webpack: devDependencies: @@ -807,17 +807,17 @@ importers: specifier: workspace:0.0.0-PLACEHOLDER version: link:../../angular_devkit/core '@angular/compiler': - specifier: 22.1.0-rc.0 - version: 22.1.0-rc.0 + specifier: 22.1.4 + version: 22.1.4 '@angular/compiler-cli': - specifier: 22.1.0-rc.0 - version: 22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(typescript@6.0.3) + specifier: 22.1.4 + version: 22.1.4(@angular/compiler@22.1.4)(typescript@6.0.3) typescript: specifier: 6.0.3 version: 6.0.3 webpack: - specifier: 5.108.4 - version: 5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3) + specifier: 5.109.2 + version: 5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3) packages/schematics/angular: dependencies: @@ -864,48 +864,48 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@angular/animations@22.1.0-rc.0': - resolution: {integrity: sha512-marmWKKbvY5Y7epi2THZnIdeW9fkgimgoWOs/Ld5tKnCDTjN0NiyykjYzSQGu47hSJjAIfkk8a0sdaW1XGF7Kg==} + '@angular/animations@22.1.4': + resolution: {integrity: sha512-DZqSHhmSRBVfLlrFxNLQj6PYVhu1w8vj1iUdD6fmlhfGGafuiw/VcUpBgYmy2YNcXmGmwbZsKr1oeJP7fT8zNQ==} engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0} deprecated: '@angular/animations is deprecated. Use `animate.enter` and `animate.leave` instead. For more information see: https://v22.angular.dev/guide/animations.' peerDependencies: - '@angular/core': 22.1.0-rc.0 + '@angular/core': 22.1.4 - '@angular/cdk@22.1.0-next.4': - resolution: {integrity: sha512-lWsn9LIWr1E7R7DoMoorxnLjLUc5tQ47QI6Zn1TNNWoPvKa7Hh89mMwLwvUo0sDvu/rhCw6mwENQCyLbl0kP/g==} + '@angular/cdk@22.1.4': + resolution: {integrity: sha512-//KICh/rxeLbYLgNj8HawaliVAPNlSV0aRmki45Tf/YhoXVhzon9DfFqCs5u1cLvmMkMTHdFm5ghGTB8SUv3DA==} peerDependencies: - '@angular/common': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 - '@angular/core': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 - '@angular/platform-browser': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 + '@angular/common': ^22.0.0 || ^23.0.0 + '@angular/core': ^22.0.0 || ^23.0.0 + '@angular/platform-browser': ^22.0.0 || ^23.0.0 rxjs: ^6.5.3 || ^7.4.0 - '@angular/common@22.1.0-rc.0': - resolution: {integrity: sha512-UWNaHg3tlFkHvsj5SedcsKVSoRO9RHN6tHaKvW2XTFLoDUlKvgKE1VciKbuut5LzKtSzu622Ag1bxD77MN4QWA==} + '@angular/common@22.1.4': + resolution: {integrity: sha512-UtWCloA/d0I5twV9Lu/Fcc7T6uQb40f/k0Hj5HLohIsiLTyvXVxWINBfa7LWWLtcq/0UOIY/yCs9Zq9Sj4dWqA==} engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0} peerDependencies: - '@angular/core': 22.1.0-rc.0 + '@angular/core': 22.1.4 rxjs: ^6.5.3 || ^7.4.0 - '@angular/compiler-cli@22.1.0-rc.0': - resolution: {integrity: sha512-DfNHPjLxBS7mNqSUZVEjYWHHGaQ1ItjRty4WfcD+7R9hrfSCK3L9nSoQQa9okfBg+6edcR1Q8Dl7M7syfh3swA==} + '@angular/compiler-cli@22.1.4': + resolution: {integrity: sha512-h9CcVG614TJLbk+dswlzSjYARYJh2MLOEwcnpt9zUGtOffhrrSS9BFJGjSwzdDSVM3J5mvf5ZuW+0hPAuRRoOA==} engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0} hasBin: true peerDependencies: - '@angular/compiler': 22.1.0-rc.0 + '@angular/compiler': 22.1.4 typescript: '>=6.0 <6.1' peerDependenciesMeta: typescript: optional: true - '@angular/compiler@22.1.0-rc.0': - resolution: {integrity: sha512-wzQo9qMsw85QXi6IauJPKNcbRHuTXQCW/BeMF+UkqXbUrTIez9YdV2Ly+XMZI5r3JUgkly0Z/8t3Rci6CdvybA==} + '@angular/compiler@22.1.4': + resolution: {integrity: sha512-o+W0shjR5KmPPWchFmqN9bLINYAy14zIW//g9T5WqKDMOqjt4IbeY6AKOoE1db/dXffprLEH9nyPOmi19iKNxg==} engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0} - '@angular/core@22.1.0-rc.0': - resolution: {integrity: sha512-gXH8srb4B1VshzwYxJrTFO/z+RpydlWf/kVXtFfY7eID0bWqpHwTKvIXyEtpUgUmqTN4MIr0w9vUdaHB3LJmwg==} + '@angular/core@22.1.4': + resolution: {integrity: sha512-0dW+lw8nHo6RGBUOXtjs02vjHIPJ8rEbw4fd0NH3Dii4p+gIB4ZaTw+o7Se3Nf4m1oZ8+2qAYmWVHXlfhKcCDg==} engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0} peerDependencies: - '@angular/compiler': 22.1.0-rc.0 + '@angular/compiler': 22.1.4 rxjs: ^6.5.3 || ^7.4.0 zone.js: ~0.15.0 || ~0.16.0 peerDependenciesMeta: @@ -914,74 +914,74 @@ packages: zone.js: optional: true - '@angular/forms@22.1.0-rc.0': - resolution: {integrity: sha512-f7Rb5idCYw5pliQumI0o3PUA0NBUpNArq1hesNcdkMux2foKKKDOmXHCnbIt3VvRqOyBknKugXRT8UUA+fCJzA==} + '@angular/forms@22.1.4': + resolution: {integrity: sha512-w8ZXe4oURrb/DS5zAFrR4AmGXC84sdLeOKXRM76ndRRgSCzyRLEe4wDU1KHnDejNVIGvoSZYJJjOajG1lpj8TA==} engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0} peerDependencies: - '@angular/common': 22.1.0-rc.0 - '@angular/core': 22.1.0-rc.0 - '@angular/platform-browser': 22.1.0-rc.0 + '@angular/common': 22.1.4 + '@angular/core': 22.1.4 + '@angular/platform-browser': 22.1.4 rxjs: ^6.5.3 || ^7.4.0 - '@angular/localize@22.1.0-rc.0': - resolution: {integrity: sha512-FXOGYRqnv/7cyVPFTNbd5XSxE75vtncyypuaB6zH3sAgpHfBU8x/EWf3IDS8piOE0DG1zmw6fsc0e7hX2n8IYQ==} + '@angular/localize@22.1.4': + resolution: {integrity: sha512-U9Kq6b/JuSQBEmkpwlspbPHb5/Z2ZOEOBbgeZWOytmAud2FIYR9kW6mcyXbYNRbB4Jnv3GzNrP8avbCMG984PQ==} engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0} hasBin: true peerDependencies: - '@angular/compiler': 22.1.0-rc.0 - '@angular/compiler-cli': 22.1.0-rc.0 + '@angular/compiler': 22.1.4 + '@angular/compiler-cli': 22.1.4 - '@angular/material@22.1.0-next.4': - resolution: {integrity: sha512-DFbQUTYF6ur0QgyHyOi9YuPQKwGYKXyWU6CEVREgwKZJVW+1PJ1BIoAtdiCA13ymMoqIuum7EAu2BwkXOHKZ3A==} + '@angular/material@22.1.4': + resolution: {integrity: sha512-d4+uajpIYmyjar/4dypd5L+z8pbgkaCOsSxsrslmE0o0wK7mfFvXCkn0wwfucey5yUHXjswlKu1X5RzJZLOZ+w==} peerDependencies: - '@angular/cdk': 22.1.0-next.4 - '@angular/common': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 - '@angular/core': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 - '@angular/forms': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 - '@angular/platform-browser': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 + '@angular/cdk': 22.1.4 + '@angular/common': ^22.0.0 || ^23.0.0 + '@angular/core': ^22.0.0 || ^23.0.0 + '@angular/forms': ^22.0.0 || ^23.0.0 + '@angular/platform-browser': ^22.0.0 || ^23.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/7a67d5221a9efec2b69b102759d04223a3fc8552': - resolution: {gitHosted: true, integrity: sha512-DQnETQLANEERiT5UIcBj1D4S1WYlYVOuwtog4JpslthLq0JqSkKXCp7o+1roasNfBrFLaOYMD7wqZiRhsxbNSw==, tarball: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/7a67d5221a9efec2b69b102759d04223a3fc8552} - version: 0.0.0-7365173626bd7f475d30ba010bfb0e485233b199 + '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/beec8fe17573a33c9934487ce99ce9cce3e3f6bf': + resolution: {gitHosted: true, integrity: sha512-ELGv/rsp5iaQw1+viAhn5IlLrodz7g7rPm6Ea06sEsBpQ2kSamcpZnXWf+j4SPzGvK+td+DtFCrgbkX+ihFiZQ==, tarball: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/beec8fe17573a33c9934487ce99ce9cce3e3f6bf} + version: 0.0.0-8fb164f40c9776c41771785c6d9facbd9ea63b73 hasBin: true - '@angular/platform-browser@22.1.0-rc.0': - resolution: {integrity: sha512-HHtTB6vJ8jtIq+pN3zOpwA2R7KItVpjpK0AxLEk1E+6Yg8jyuQdtGBpbet61V9ndOyqFh4XyBWMx02+g2DrVcg==} + '@angular/platform-browser@22.1.4': + resolution: {integrity: sha512-zhEWnRShG6GjnEvCVROD68XfnrV6+HJ9bPjwZx4LsAz7spX823Nhiml8Uqpvijsa1w7UdWLU7nK/magr9IEMOQ==} engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0} peerDependencies: - '@angular/animations': 22.1.0-rc.0 - '@angular/common': 22.1.0-rc.0 - '@angular/core': 22.1.0-rc.0 + '@angular/animations': 22.1.4 + '@angular/common': 22.1.4 + '@angular/core': 22.1.4 peerDependenciesMeta: '@angular/animations': optional: true - '@angular/platform-server@22.1.0-rc.0': - resolution: {integrity: sha512-yE5H9GLBZ0n9VDzvEMixtMz9RDUHwAMgyWRAzHj7gVmj/bbFrJ3waw3Pc2sJY9hhY+asA4q4FdYDchXcxgZXqA==} + '@angular/platform-server@22.1.4': + resolution: {integrity: sha512-ZhCIT+Iu2dpTOtM9BAy8jEt9yTMV2XpEZjh9wUM+/JGfkZfm9e12ZEx0n5VbAHJNnufw3qulEyfdF8yG19tN/g==} engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0} peerDependencies: - '@angular/common': 22.1.0-rc.0 - '@angular/compiler': 22.1.0-rc.0 - '@angular/core': 22.1.0-rc.0 - '@angular/platform-browser': 22.1.0-rc.0 + '@angular/common': 22.1.4 + '@angular/compiler': 22.1.4 + '@angular/core': 22.1.4 + '@angular/platform-browser': 22.1.4 rxjs: ^6.5.3 || ^7.4.0 - '@angular/router@22.1.0-rc.0': - resolution: {integrity: sha512-nJRUfPqhYbUygYlpFtrGW2ymotpSNojkPNIVNnIMLmbQHl498jOEuYKK6ZpD10mDihBqNiuxBB0yUQNNTlp1fA==} + '@angular/router@22.1.4': + resolution: {integrity: sha512-vCwJLRnFBSRH5LxSF8OXKBhdmJ526hVGb/5sfeLTQW/oWCdcfXb2RvHfB077m5cdqKX9sBwFVlkJ8Z8kgx/pLQ==} engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0} peerDependencies: - '@angular/common': 22.1.0-rc.0 - '@angular/core': 22.1.0-rc.0 - '@angular/platform-browser': 22.1.0-rc.0 + '@angular/common': 22.1.4 + '@angular/core': 22.1.4 + '@angular/platform-browser': 22.1.4 rxjs: ^6.5.3 || ^7.4.0 - '@angular/service-worker@22.1.0-rc.0': - resolution: {integrity: sha512-TOgMekeFEk6MSA5oIW33b6SAxZeas+1FoGtYVRbTuQdLbzpO77Xugt3LixRq2MP88oJg1Z+nYLKkmKj0HjYsyQ==} + '@angular/service-worker@22.1.4': + resolution: {integrity: sha512-UKRtwePIiZtrKFNn8Uc/I8TNu0941K7Z56klSXaP6F0xaS2U4FsOcqIdWxDBIL6CEnyxjjX1n4v71v2hbSkXQQ==} engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0} hasBin: true peerDependencies: - '@angular/core': 22.1.0-rc.0 + '@angular/core': 22.1.4 rxjs: ^6.5.3 || ^7.4.0 '@asamuzakjp/css-color@5.1.11': @@ -1023,8 +1023,8 @@ packages: resolution: {integrity: sha512-5FgxM4dLQpMJHSiVATk8foW263dVHQHBVpXYiimNECVWG01f4nFyEbQixeT6Mwvg7TayREJ2gpKl3o2RoMdnqw==} engines: {node: ^22.18.0 || >=24.11.0} - '@babel/generator@7.29.7': - resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==} + '@babel/generator@7.29.8': + resolution: {integrity: sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==} engines: {node: '>=6.9.0'} '@babel/generator@8.0.0': @@ -1159,8 +1159,8 @@ packages: resolution: {integrity: sha512-wfbi91pM3py96oIiJEz7qIpyXDytgr9zQC1HEWwlGNVRAEmItuU/0a41ZUKu1sJGyhhOIpc4t5vk4PYzt8wpsg==} engines: {node: ^22.18.0 || >=24.11.0} - '@babel/parser@7.29.7': - resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==} + '@babel/parser@7.29.8': + resolution: {integrity: sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==} engines: {node: '>=6.0.0'} hasBin: true @@ -1539,16 +1539,16 @@ packages: resolution: {integrity: sha512-eAD0QW/AlbamBbw0FeGiwasbCVPq5ncW0HNVyLP3B9czqLyh4gvw+5JTSNt6le9+ziAU7mqDZsKTHf3jTb4chQ==} engines: {node: ^22.18.0 || >=24.11.0} - '@babel/traverse@7.29.7': - resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==} + '@babel/traverse@7.29.8': + resolution: {integrity: sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==} engines: {node: '>=6.9.0'} '@babel/traverse@8.0.4': resolution: {integrity: sha512-bZnmqzGG8UZneG1lLxBoWIH0G6Gr1D846Yu4/3XnY6FhCndMR49u26nTY08u/dAxWmLWF9vGQOuC+84FfIUoeg==} engines: {node: ^22.18.0 || >=24.11.0} - '@babel/types@7.29.7': - resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} + '@babel/types@7.29.8': + resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} engines: {node: '>=6.9.0'} '@babel/types@8.0.4': @@ -1579,31 +1579,31 @@ packages: resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} - '@conventional-changelog/git-client@3.1.0': - resolution: {integrity: sha512-Tqa/gHco2WJWa740NRjOrfKVvzIqxkZpecb8bemaQ8sKM5PXb1UK4uTyTb/1wIqNuOVaDOFxyBdhTIQZn6gdjQ==} + '@conventional-changelog/git-client@3.1.2': + resolution: {integrity: sha512-jZqwnJwf7nboIlAcw/mkOjVa6DexCcUOgT2oOQgkoi3z9vR8tGFkcMy2BFcYwjhL9sYcDDXkRQDayiDieCoW7A==} engines: {node: '>=22'} peerDependencies: conventional-commits-filter: ^6.0.1 - conventional-commits-parser: ^7.0.1 + conventional-commits-parser: ^7.1.2 peerDependenciesMeta: conventional-commits-filter: optional: true conventional-commits-parser: optional: true - '@csstools/color-helpers@6.1.0': - resolution: {integrity: sha512-064IFJdjTfUqnjpCVpMOdbr8FLQBhinbZj6yRv2An2E41O/pLEXqfFRWqGq/SxlE5PEUYTlvWsG2r8MswAVvkg==} + '@csstools/color-helpers@6.1.1': + resolution: {integrity: sha512-gLNsunvwf3mCi5u5o46/Z/JcJMnhbHSaZ69rkgPzNM3J4s8hWwpPUQB6/tt0EDFyCiWzxANlx+2LJwpYj4zS1w==} engines: {node: '>=20.19.0'} - '@csstools/css-calc@3.2.1': - resolution: {integrity: sha512-DtdHlgXh5ZkA43cwBcAm+huzgJiwx3ZTWVjBs94kwz2xKqSimDA3lBgCjphYgwgVUMWatSM0pDd8TILB1yrVVg==} + '@csstools/css-calc@3.3.0': + resolution: {integrity: sha512-c5ihYsPkdG6JCkU2zTMm4+k6r7RXuGxtWYhu5DHMIiF1FHzrfmHL5so11AoFpUv/tu61xfcmT4AmKoFfMPoqdQ==} engines: {node: '>=20.19.0'} peerDependencies: '@csstools/css-parser-algorithms': ^4.0.0 '@csstools/css-tokenizer': ^4.0.0 - '@csstools/css-color-parser@4.1.9': - resolution: {integrity: sha512-paQcIaOO53Rk5+YrBaBjm/SgrV4INImjo2BT1DtQRYr+XeTRbeAYlS+jxXp9drqvKmtFnWRJKIalDLhZZDu42A==} + '@csstools/css-color-parser@4.2.0': + resolution: {integrity: sha512-5+5LEmFuY1AjXdYhmgjTJogtQnP1evJ1zrBZGUNZ0thkpwnnmKxcHdAMn/OtFjAb25zA+jKDVYVRl+5G7rjv1A==} engines: {node: '>=20.19.0'} peerDependencies: '@csstools/css-parser-algorithms': ^4.0.0 @@ -1615,8 +1615,8 @@ packages: peerDependencies: '@csstools/css-tokenizer': ^4.0.0 - '@csstools/css-syntax-patches-for-csstree@1.1.6': - resolution: {integrity: sha512-TcJCWFbXLPpJYq6z7bfOyjWYJDiDg2/I4gyUC9pqPNqHFRIey0EB0q0L5cSnQDfWJg8Jd6VadakxdIez/3zkqQ==} + '@csstools/css-syntax-patches-for-csstree@1.1.8': + resolution: {integrity: sha512-CpMLjAvwQg3BL5S0IeqsZNMH7EQrEWi0kLKOC13ZBF0ZwERiLWlibNPJr8G1kdU3Ms/r2KiNrF81pUh2HwAHdg==} peerDependencies: css-tree: ^3.2.1 peerDependenciesMeta: @@ -1650,158 +1650,158 @@ packages: '@emnapi/wasi-threads@1.2.2': resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} - '@esbuild/aix-ppc64@0.28.1': - resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==} + '@esbuild/aix-ppc64@0.28.2': + resolution: {integrity: sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.28.1': - resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==} + '@esbuild/android-arm64@0.28.2': + resolution: {integrity: sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.28.1': - resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==} + '@esbuild/android-arm@0.28.2': + resolution: {integrity: sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.28.1': - resolution: {integrity: sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==} + '@esbuild/android-x64@0.28.2': + resolution: {integrity: sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.28.1': - resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==} + '@esbuild/darwin-arm64@0.28.2': + resolution: {integrity: sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.28.1': - resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==} + '@esbuild/darwin-x64@0.28.2': + resolution: {integrity: sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.28.1': - resolution: {integrity: sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==} + '@esbuild/freebsd-arm64@0.28.2': + resolution: {integrity: sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.28.1': - resolution: {integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==} + '@esbuild/freebsd-x64@0.28.2': + resolution: {integrity: sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.28.1': - resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==} + '@esbuild/linux-arm64@0.28.2': + resolution: {integrity: sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.28.1': - resolution: {integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==} + '@esbuild/linux-arm@0.28.2': + resolution: {integrity: sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.28.1': - resolution: {integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==} + '@esbuild/linux-ia32@0.28.2': + resolution: {integrity: sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.28.1': - resolution: {integrity: sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==} + '@esbuild/linux-loong64@0.28.2': + resolution: {integrity: sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.28.1': - resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==} + '@esbuild/linux-mips64el@0.28.2': + resolution: {integrity: sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.28.1': - resolution: {integrity: sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==} + '@esbuild/linux-ppc64@0.28.2': + resolution: {integrity: sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.28.1': - resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==} + '@esbuild/linux-riscv64@0.28.2': + resolution: {integrity: sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.28.1': - resolution: {integrity: sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==} + '@esbuild/linux-s390x@0.28.2': + resolution: {integrity: sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.28.1': - resolution: {integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==} + '@esbuild/linux-x64@0.28.2': + resolution: {integrity: sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.28.1': - resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==} + '@esbuild/netbsd-arm64@0.28.2': + resolution: {integrity: sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.28.1': - resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==} + '@esbuild/netbsd-x64@0.28.2': + resolution: {integrity: sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.28.1': - resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==} + '@esbuild/openbsd-arm64@0.28.2': + resolution: {integrity: sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.28.1': - resolution: {integrity: sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==} + '@esbuild/openbsd-x64@0.28.2': + resolution: {integrity: sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.28.1': - resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==} + '@esbuild/openharmony-arm64@0.28.2': + resolution: {integrity: sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.28.1': - resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==} + '@esbuild/sunos-x64@0.28.2': + resolution: {integrity: sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.28.1': - resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==} + '@esbuild/win32-arm64@0.28.2': + resolution: {integrity: sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.28.1': - resolution: {integrity: sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==} + '@esbuild/win32-ia32@0.28.2': + resolution: {integrity: sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.28.1': - resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==} + '@esbuild/win32-x64@0.28.2': + resolution: {integrity: sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -1867,30 +1867,32 @@ packages: '@noble/hashes': optional: true - '@firebase/ai@2.13.1': - resolution: {integrity: sha512-RhT/VViTPBSplhQSuEp62HhLvfsV+LowMh8ZUo5MMRDzG7oFtSget4Kmg5oHP50hDVyWQuQj6to9iPFEZk08Tw==} + '@firebase/ai@2.14.0': + resolution: {integrity: sha512-TYEQqCQUTyVHuG/HVi9vau6F9kvEaS49o/hmdn/yUuN6ZXQkwIml2nNJTIBfjNl/r9LOxwUNILgcOY16nxObug==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app': 0.x '@firebase/app-types': 0.x - '@firebase/analytics-compat@0.2.28': - resolution: {integrity: sha512-lIAlqUUbBu93FJMlQfslryQtBwwzdzvp23ePC6FNgymXk6Ook5v4Uvc0vdutvoIeqmyA3LfP0ZeRFK8+11kOOQ==} + '@firebase/analytics-compat@0.2.29': + resolution: {integrity: sha512-allztvCvCUlItZzD97TiRAtGoFJzR1FQFmLxbaLc6PvgscqD9cl5NdKPTtka6keShVYXvCZJpzWcRoH4TME8rw==} peerDependencies: + '@firebase/app': 0.x '@firebase/app-compat': 0.x '@firebase/analytics-types@0.8.4': resolution: {integrity: sha512-zQ+XTgkwH6CY/eUSHJRP7e4LxM30RCxlCmob5sy2axs25GE3Ny0XdgpDscMTHHQIGqWkxPXad4w2Mw9sCgT8zQ==} - '@firebase/analytics@0.10.22': - resolution: {integrity: sha512-8BSaq/QRGU1+xyi8L2PTLTJU7MH9aMA72RQdIxrbhWFauOZY9OXo8f2YDN/972xA8d588tlnNVEQ2Mo69pT9Ow==} + '@firebase/analytics@0.10.23': + resolution: {integrity: sha512-34ALWXzWA6PTRUA5hipZmsm1RKzeecw5J1+qTCXsiMzwLqONC+GuTIQSdmm91MmTAEA+wG1Q5t0IFahcYQOqAA==} peerDependencies: '@firebase/app': 0.x - '@firebase/app-check-compat@0.4.5': - resolution: {integrity: sha512-JI17mVcZs34zO6ZeSCrw4U2iohqy+n6GIzkbmsA+TbVjmvFLkUKt3bs5M+qRBteQm/0IWzqSHYFzEQLzDTQebg==} + '@firebase/app-check-compat@0.4.6': + resolution: {integrity: sha512-2pzNEZEkX84jSqy6TH6FI1HSLA1lc7kakRUybBbKjg9YhIttPlW/XX3N9CDtChji2PTTPWVPZiWhB10exHfA+A==} engines: {node: '>=20.0.0'} peerDependencies: + '@firebase/app': 0.x '@firebase/app-compat': 0.x '@firebase/app-check-interop-types@0.3.4': @@ -1899,27 +1901,28 @@ packages: '@firebase/app-check-types@0.5.4': resolution: {integrity: sha512-xV7JsIyzVr15aA7f3Pi0rB9gdBuVubs89FGA8VkRYA4g0l78poADgdfrScgf7NndSg9mm7cR7PJyY0+t22KaGw==} - '@firebase/app-check@0.12.0': - resolution: {integrity: sha512-wMeT6HLWRAuW7Cp/5UjWBGKgjPNxWNOoNf4PRIv0weljoGMZVeqbUY7wNBWTI2/31cX1NlXx8gQruDLsUShB3Q==} + '@firebase/app-check@0.13.0': + resolution: {integrity: sha512-AbMttBKazQvGVXBZhQdVAdPzRhwHyJAY3Ghu5y2C7IZKIDIppzNYz0shTZ1mP4FBJa+28BuC4t+5h1Q6pT3Asg==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app': 0.x - '@firebase/app-compat@0.5.15': - resolution: {integrity: sha512-HaiSM9TwbGIR4b7F6+UncHWlqdH89eeY7VUskaOGOlI2PxHS5Z+6hHsYGvNLy0SHDE6zyXO+3QSA6a4aqQxsqA==} + '@firebase/app-compat@0.5.16': + resolution: {integrity: sha512-shQq37O8qELDzvsVwYPlDXwD1zlcrZ0m2bpBF5ov2HSbY8x+AHsnL5TtJ2e1JAfkQN05qHao1AfabS69PN6GiA==} engines: {node: '>=20.0.0'} '@firebase/app-types@0.9.5': resolution: {integrity: sha512-YevqTjvo7Iujsa9Dwowmd6dSoElhzmD63ZSrq6bzjvQ6POjYgNjOFHLmNIgJs48eNO093NCERibuFnxbfOvU7A==} - '@firebase/app@0.15.1': - resolution: {integrity: sha512-iD9+Z5HcPo0Uop5f72/VYMeXwKucBhW7iFrISkJFvQ+lSZikTNgTz0FgAtaaTkAG0pEZSnCymA2Fu49n0rcufQ==} + '@firebase/app@0.16.0': + resolution: {integrity: sha512-G+ZGEyVP8YTb3ay6A+XpcYgFH3sTESHcnHU/EyTktodqhz2BHkLq+QEP7IVwjiMX0cxYwpVKip0/wC0KZcn9vQ==} engines: {node: '>=20.0.0'} - '@firebase/auth-compat@0.6.8': - resolution: {integrity: sha512-llcBREUC4iSNKZ6rvwud7Oz9Q7aAWU6KuQLa6pdu7Q+QAQsy4JLw6yFgxwtmzabsgznHmmcsX2UjHLLzqUxi3Q==} + '@firebase/auth-compat@0.6.9': + resolution: {integrity: sha512-/hHeTBmQ61+N5J1RECls+WfskZTY78JXr7aO5EMOfUpqJvDqvoS+568k0rp6Ss/4UWwBjadILs+H+SGy1zCS3A==} engines: {node: '>=20.0.0'} peerDependencies: + '@firebase/app': 0.x '@firebase/app-compat': 0.x '@firebase/auth-interop-types@0.2.5': @@ -1931,8 +1934,8 @@ packages: '@firebase/app-types': 0.x '@firebase/util': 1.x - '@firebase/auth@1.13.3': - resolution: {integrity: sha512-bqiq4uubDN2YyQkdvSWPQeJyXAv2O76ImF41En9b6UhV5JuBVYDoHYrrrE3NzIuGkpFMKagfhMRP4Vz6t+yQSQ==} + '@firebase/auth@1.13.4': + resolution: {integrity: sha512-s+NS1aV0DDyyfoIMeSz53HXnVTv7ufJjJfrP63XyaWHweJ5vOoxKWrTm5tO7S7PDqvyOa/Wi3oP0dgAo6JTMMA==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app': 0.x @@ -1941,30 +1944,39 @@ packages: '@react-native-async-storage/async-storage': optional: true - '@firebase/component@0.7.3': - resolution: {integrity: sha512-wFofIaa2879ogD/WvkjYXJxRmfnL0scen6ORgaC3na1FNOR9ASIUANQdhqQcmWu/h77/pVHY7ch5flewa5Bcew==} + '@firebase/component@0.7.4': + resolution: {integrity: sha512-tLpOaaCol9ugUIYp2R3CbWPPA8Ajg/papX/XHEy8U52b/QXH3BbX8tTJX9aShDCjp+9sMAxMLD94i7lresdugQ==} engines: {node: '>=20.0.0'} - '@firebase/data-connect@0.7.1': - resolution: {integrity: sha512-2LbUU8mmSA63HknxQMmWHjpzuNLBKflvVwQc2tpoVKg0biWleNEJX031ELks0vzFs+dDjOUkCJR72RP6mQHFOg==} + '@firebase/data-connect@0.7.3': + resolution: {integrity: sha512-nHBFk3Ntl+NZCRIUG2d5j7I69P0otjyQ/duhVKLbw4+5cNke/F6RK1pdE5Jnf831/QOTs2Bd00LlxlZ+jNsb9w==} peerDependencies: '@firebase/app': 0.x - '@firebase/database-compat@2.1.4': - resolution: {integrity: sha512-3pK35F1MAgmqFJQlf2nhQl44vtAXQO1uaCaQOEUI9kCRtLFqi7N+QRKR7lFZPg+xIZIyubgxQaxY69YgfZRZWg==} + '@firebase/database-compat@2.1.6': + resolution: {integrity: sha512-mu7S/75UIajB1A5M9Vfojk69LttW55uABp9nHEtWrV/mIaSEwvoaIe9GySsEzS2EKFK5/3f5okcAuUbihhYeJg==} engines: {node: '>=20.0.0'} + peerDependencies: + '@firebase/app': 0.x + '@firebase/app-compat': 0.x + peerDependenciesMeta: + '@firebase/app': + optional: true + '@firebase/app-compat': + optional: true - '@firebase/database-types@1.0.20': - resolution: {integrity: sha512-kegbOk/w8iU64pr0q6k2ItyNGjnQBMHFhwS7ohdWI4W+pc0/zhhdGXTdFj6X1oxItRjPoYOsSQmERgBkn/ihxw==} + '@firebase/database-types@1.0.21': + resolution: {integrity: sha512-SX1jUqhttKgg/m9dYRTvqU9QvucBooziWfA986r4cpsbi4zlsvewe424j3Vpduwd6DG1MSAMfBVT2VqA61FnkA==} - '@firebase/database@1.1.3': - resolution: {integrity: sha512-XwWCa+E4TvNGpGwXrycLRNfdogADwFcvuhyow6wDWma9W54roaQIhe+4PM0KiLsIftBdSCGI7OKCXrdSRHbIhw==} + '@firebase/database@1.1.4': + resolution: {integrity: sha512-D+j4+8uhGtNd1tVD+X+c8JrC4ppStGJKyujSQt2NPwdN26QcCk0BeIxue+UqspHkHiFHyQOimwlzjLewGq6S+A==} engines: {node: '>=20.0.0'} - '@firebase/firestore-compat@0.4.11': - resolution: {integrity: sha512-W7o1WdwWq5aABK5Up2ncSvTQs/QGLR/fy7cVpFBNqhsXtxoMtflHf2xBIG6+aoptcuGAobddq4g2Sq27wqHaYw==} + '@firebase/firestore-compat@0.4.12': + resolution: {integrity: sha512-k2uX81Ao/S0jnFcWGPOQpKK1cPlJHvD9WIqh/RE1XBDP2yg5zhE4rHhSg1rtB11k39q3nKon9XLNDDrPjGclag==} engines: {node: '>=20.0.0'} peerDependencies: + '@firebase/app': 0.x '@firebase/app-compat': 0.x '@firebase/firestore-types@3.0.4': @@ -1973,30 +1985,32 @@ packages: '@firebase/app-types': 0.x '@firebase/util': 1.x - '@firebase/firestore@4.16.0': - resolution: {integrity: sha512-qdHMHMvMr0nRMuZyWNR/ArWa0YlPE3C4eAbmxTASJMYXAesKPL0Y54p70moggrNPzaK7MSIIq5RDJJyntQyIYA==} + '@firebase/firestore@4.17.0': + resolution: {integrity: sha512-P9tof6pyO1bnLlMWbux+5O7WFJqlb7OTPMKxxOiXKYiQl7mxykAvxr1BFCgWeEXUU7DZxQncyJ040B0IhFVZCg==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app': 0.x - '@firebase/functions-compat@0.4.5': - resolution: {integrity: sha512-10qlUXGY25G5/1g9UihqksPp2po+ZqSE7LEizsrdUP7vrTmkysXxGSZCDyojSEp6mQe/ecRDdDDI+z4XRdb4wQ==} + '@firebase/functions-compat@0.4.6': + resolution: {integrity: sha512-dj9sOet+FIU91jeU4A3vGJoXHty7NqkSfjRLCwLgJXPDk1m72KFuxD3nlFgw/yXx/Fr7UjqzbxZ0LrIOdpx7+w==} engines: {node: '>=20.0.0'} peerDependencies: + '@firebase/app': 0.x '@firebase/app-compat': 0.x '@firebase/functions-types@0.6.4': resolution: {integrity: sha512-zV6kgqtduR4rUAdC/ilS7kmb93XD7bEZoJDlVBZqlOw2uGGGCNBQBuleww2rr0Ulr3L9o2TDjumEt68/l1f9DQ==} - '@firebase/functions@0.13.5': - resolution: {integrity: sha512-bWCx713f4kE/uFV7gdFOLBS7lDoiZj48MRkbAqe35gkXcCeWF4QjRNO07Jhmve7EJIoQOBczL29y2r8VRuN1kw==} + '@firebase/functions@0.13.6': + resolution: {integrity: sha512-9obLnzeQUivK5lmtGFOU2ucQ38BjTp+jpPtbfFp/mDsdVCvEpRqdWNvMMQ6aQwR4vcVc/utsvngm5BRkXbc7ZA==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app': 0.x - '@firebase/installations-compat@0.2.22': - resolution: {integrity: sha512-C/zpAuTP5S9OgKSPvXRupw3hoY/JZSlA1wFjD/Sb7LIQE0FNbcMdO8Y4KXVEkjVzma/DDDDIAzxEXqKMAzc88w==} + '@firebase/installations-compat@0.2.23': + resolution: {integrity: sha512-isaXmjb9roM83eVeXAe+ZRNKYNsSo2s0aNM+cy04AAGEyVL/d8Aa11GwEXovRFeYjl9+1yRAOxRDTOukZRwTxA==} peerDependencies: + '@firebase/app': 0.x '@firebase/app-compat': 0.x '@firebase/installations-types@0.5.4': @@ -2004,8 +2018,8 @@ packages: peerDependencies: '@firebase/app-types': 0.x - '@firebase/installations@0.6.22': - resolution: {integrity: sha512-ef6nn3GGQTdReCfotRMG77PJZu8CqEbiK5pEoBnM0gTu/Z9v0i/az2p3HABsa/1beQmmyh1OsOjf7P5+pgwdZw==} + '@firebase/installations@0.6.23': + resolution: {integrity: sha512-MBkbcQfd+3qHjW+slsH4s7jH5qTdGlYpwqmxEZ7QcIpgDxu1SKyU0f+mCZhCt1BCacLNiOWF5L0R06N0LtlfMg==} peerDependencies: '@firebase/app': 0.x @@ -2013,49 +2027,53 @@ packages: resolution: {integrity: sha512-vZKLsqE1ABOy8OjQiE7cUTFn4gvaqlk88yp8N94Pk/sDpq61YqZGqmVFZTvOyflTwuYFcWirBdYGoJgbDaXKYQ==} engines: {node: '>=20.0.0'} - '@firebase/messaging-compat@0.2.27': - resolution: {integrity: sha512-JNOiu1PPgdHzEPEtoFiNxQuu0x9bm4bfETSQCpGfcTlgWkhlSK7uh7nlsjC10TQLUNgYetLmuutaYTh8aeYLVA==} + '@firebase/messaging-compat@0.2.28': + resolution: {integrity: sha512-/AmMqHRnSQhPsdeED3ocs+s30/tpFvZDiiwIYY2uXFRvLujo1fnbPOeCFoe4Y+dRy1LCSjpvJf+dy5ZTsxi1yg==} peerDependencies: + '@firebase/app': 0.x '@firebase/app-compat': 0.x '@firebase/messaging-interop-types@0.2.5': resolution: {integrity: sha512-tUEKnaAP2Y/MNIqgnriPpV6e5l13Vs/+p2yrd6NGlncPJT9O3a8muYZtdnWe+IJ4fgKLHJVC79n/asxk/N5Msw==} - '@firebase/messaging@0.13.0': - resolution: {integrity: sha512-GZoo0uGRvEbszo83xcgbjJp4FpkmBEr4l8Z4hi8gl+P1Spn/MTK3HapanMzSX4yUHuTEiF5hasWRxOaz+o5sxQ==} + '@firebase/messaging@0.13.1': + resolution: {integrity: sha512-kL8fdjbNBI7hprlXJrUjktDWosrpT4JtfwXtVVevImPF/rBRAsC+LS/jIs+kgQVuotnvMhaBCgAFipBoY9YU9g==} peerDependencies: '@firebase/app': 0.x - '@firebase/performance-compat@0.2.25': - resolution: {integrity: sha512-q6NjTXpIPoFuUmCmMN/maCdTgzT6aExs9xZo+PxfVLj6uLVGvpyAD6XWjmcrb7jChsFBYbq7E5dyNDF7Zhy9kA==} + '@firebase/performance-compat@0.2.26': + resolution: {integrity: sha512-jgoocXLN6ao26xWQ8pzosmzQ33uLzGBJQPNK0NTbVy1XvIHr5pfgBf9hWLOxsWe+R7sJq5bjD+8ybXprmt61mA==} peerDependencies: + '@firebase/app': 0.x '@firebase/app-compat': 0.x '@firebase/performance-types@0.2.4': resolution: {integrity: sha512-kJSEk7b0uhpcPRyL4SQ/GPujLqk52XNKcXlnsKDbWGAb9vugcLvOU3u6zfEdwd+d8hWJb5S5ZizV1JFFI0nkKg==} - '@firebase/performance@0.7.12': - resolution: {integrity: sha512-fe7nV8teUU3OBHlMUZ9Lw4gLhCW2k4m5Uc3pfWGV+fl8uwJQBGp9Q3lqsJ+HSrFu3Q2pJyLAgrClPGSKyDeYgQ==} + '@firebase/performance@0.7.13': + resolution: {integrity: sha512-1u6fuXP9cj0s+lkTFAspr/ttfPebPbEdpx+5Wdr4mPZbp8qH2KCMxOddEAR1ZMRa5GI0E7hDYSnolEmbqOFOAg==} peerDependencies: '@firebase/app': 0.x - '@firebase/remote-config-compat@0.2.27': - resolution: {integrity: sha512-FYwYWwSbUdza/pRX4NpSBm/Pimntum3jEIBpnDn5Ey1jHNWgjxrE8Z5SB4mCHd5wGCoYd3koJzxARl/VWIEx0Q==} + '@firebase/remote-config-compat@0.2.28': + resolution: {integrity: sha512-kEO9Gn6fbmVj7eNUtZ6d59mLgUDUD0qo7aCicGOWNfuRWTaUv3CF9DMYychO61zaEQ3cfA+CEny4V1E8A1gRGA==} peerDependencies: + '@firebase/app': 0.x '@firebase/app-compat': 0.x '@firebase/remote-config-types@0.5.1': resolution: {integrity: sha512-cX/1LT6KQwkXzck2eSzeKnuvXZCyr8qaPpDcikoJs7jmI+oBOXixpDLeDtWj1U6GNMkIoXrEDNoyT2Ypcyp5/A==} - '@firebase/remote-config@0.9.0': - resolution: {integrity: sha512-aNn6/eJhsSC+gXSToiXiYPv3ypLP9lFtzl+/q9kSOBPB7D6rae0Rt2uENZZLXGYbEgHYKQblOhijJAXGbbJjtQ==} + '@firebase/remote-config@0.9.1': + resolution: {integrity: sha512-nzQUSJnk1zAZEl2Q5O3I7Z61cYLK5JI4H6wyyOiHkVZ+bmgy1YXNNMptNbVjixMQ/eCzgA6nZRaC+1eBcJGUFA==} peerDependencies: '@firebase/app': 0.x - '@firebase/storage-compat@0.4.3': - resolution: {integrity: sha512-gruVqjtUGX8tEoeNbaWXZm0Zfcfcb7fvmDmBxV8yPAbWvExRnZYLO2+qw9idxNE7BvPXt5csyjSYHy//dAizxw==} + '@firebase/storage-compat@0.4.4': + resolution: {integrity: sha512-qSRgCB9f2R/nCp8t/8OC101cIFBFeUazlRInOMdzbnLzvrQBzEfx19SrR4pvdj/0+M+P/y8AK/a2s+3EB+B1Pw==} engines: {node: '>=20.0.0'} peerDependencies: + '@firebase/app': 0.x '@firebase/app-compat': 0.x '@firebase/storage-types@0.8.4': @@ -2064,14 +2082,14 @@ packages: '@firebase/app-types': 0.x '@firebase/util': 1.x - '@firebase/storage@0.14.3': - resolution: {integrity: sha512-YX4/YL6P6/fufSSeGnVhjWddcIXbFq2cWIhMKFTZo1E/Rtcl2mJj/BYUQTwJfcE1Tl8un1FOya4L05jcSLN/Eg==} + '@firebase/storage@0.14.4': + resolution: {integrity: sha512-jfzEWZb3Fpsq3FwAB2ifoc8mcSh935qXdDou3TpyjDWa45hhNcZUv8/w28/10njByhfK7snbakKN30nwnzQ3/w==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app': 0.x - '@firebase/util@1.15.1': - resolution: {integrity: sha512-LUdM4Wg7YM9Pq/49nGYySJA0CSQEKnGffFzWV8+6gXN7mGxn+FL1IqvFbuZUtAQcfZgHYDwCE1wwlK7rB7gl2g==} + '@firebase/util@1.15.2': + resolution: {integrity: sha512-974pWIZVLDMc5GW5YAsj8y0XxULxIy/sPUy7tsxmWbF93KRIyh9xpuHlh0zDL+shUcf5nHDjFOg9YLiQ763eiA==} engines: {node: '>=20.0.0'} '@firebase/webchannel-wrapper@1.0.6': @@ -2080,20 +2098,20 @@ packages: '@glideapps/ts-necessities@2.2.3': resolution: {integrity: sha512-gXi0awOZLHk3TbW55GZLCPP6O+y/b5X1pBXKBVckFONSwF1z1E5ND2BGJsghQFah+pW7pkkyFb2VhUQI2qhL5w==} - '@google-cloud/common@6.0.1': - resolution: {integrity: sha512-1uvKzbmAWUdchIYRsg0f4rUmezOamWuVBSWAPAhnYoUE5OiPEx6v6JOxFIdr3MsrqV+6fyLV3EI1vMPlHoeRvw==} + '@google-cloud/common@6.1.0': + resolution: {integrity: sha512-Ohjxjvusr65+SiEVBrilpyn1ir9CM8ZqWjcf7bA8ph1GCunxI6bbwtcl7iGl67A7Lr4Nz7WpNzITNETwggc7pw==} engines: {node: '>=18'} - '@google-cloud/precise-date@5.1.0': - resolution: {integrity: sha512-Z9RVpJUZR+aMF9gPel07xbLURjdT+G4HV6x7jJhreNarQGcT/ZYn1IIfo55rd+tncGvJ4qZDfZnaF6PzqgsQkw==} + '@google-cloud/precise-date@5.2.0': + resolution: {integrity: sha512-ckZ1elVT/JXbO4kxltiT8tumYnTXGIY7OFrDMAJyVWAte/rUYiCuH1YbaKLQrZpYDp522xgTfPqqW/VxfXFdgA==} engines: {node: '>=18'} '@google-cloud/projectify@4.0.0': resolution: {integrity: sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==} engines: {node: '>=14.0.0'} - '@google-cloud/projectify@5.1.0': - resolution: {integrity: sha512-61RXiUnoPBjeIXTzG+WgGLdJlnE3lS7p63rbePw0CEC0tjMGpODKHEr8vFUmuD+iEl7sUWYKbu/ZTk/N2dXw6w==} + '@google-cloud/projectify@5.2.0': + resolution: {integrity: sha512-u4lTO+UI9bwyd/qaVkhVpp57jVH0Pc7wkHE0snZkpQyoKheHDJwmfStao8cWXSF03DmrQltLLSoDjM2CGBpFJA==} engines: {node: '>=18'} '@google-cloud/promisify@4.1.0': @@ -2108,8 +2126,8 @@ packages: resolution: {integrity: sha512-IJn+8A3QZJfe7FUtWqHVNo3xJs7KFpurCWGWCiCz3oEh+BkRymKZ1QxfAbU2yGMDzTytLGQ2IV6T2r3cuo75/w==} engines: {node: '>=18'} - '@google/genai@2.12.0': - resolution: {integrity: sha512-LUr972DZosqPUhf9Mb3CIVu/B99woD3QW6ZJV1T9aNgxaoimAZARmo+IyyDsxIL+zouFiYSdA4hzfEWXc9oNIQ==} + '@google/genai@2.17.1': + resolution: {integrity: sha512-CdZ3M/titoH81hXXkvOikrOW26bC9IXh9iYT7u+r+5p7wi1LnMEnB0AbJfDeWAkjuneP4oJ299BtCt6twmORWg==} engines: {node: '>=20.0.0'} peerDependencies: '@modelcontextprotocol/sdk': ^1.25.2 @@ -2138,9 +2156,9 @@ packages: '@harperfast/extended-iterable@1.0.3': resolution: {integrity: sha512-sSAYhQca3rDWtQUHSAPeO7axFIUJOI6hn1gjRC5APVE1a90tuyT8f5WIgRsFhhWA7htNkju2veB9eWL6YHi/Lw==} - '@hono/node-server@1.19.14': - resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==} - engines: {node: '>=18.14.1'} + '@hono/node-server@2.1.1': + resolution: {integrity: sha512-ELuehkj5VCBdgEw9zs+ivkKwyzzUCSQuE96YmiPvn1ECBoZCczbFXJLeEGMTYjphP6gydh4pHMqEYPVMYUVgQg==} + engines: {node: '>=20'} peerDependencies: hono: ^4 @@ -2168,8 +2186,8 @@ packages: resolution: {integrity: sha512-3eTuUO1vH2cZm2ZKHeQxnOqlTi9EfZDGgIe3BL3I4u+rJHocr9Fz86M4fjYABPvFnQG/gGK551HqDiIcETwU6Q==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} - '@inquirer/checkbox@5.2.1': - resolution: {integrity: sha512-b6xmA/VlTe0ZgDQHDui+Nav470u7u49nRd8/iuhOcQPO9Ch7lGuogydhi2VOmNlZ+zXcM8IcPuNSwQcdJaF/kw==} + '@inquirer/checkbox@5.2.2': + resolution: {integrity: sha512-Y5/bAScMy5Y+9isCx0SKbyJebMCaXXX5em0kxkj115eZNscgV9srOHrgyfS0e5xAVymIfOh9piYBKDILktsMMg==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2195,8 +2213,17 @@ packages: '@types/node': optional: true - '@inquirer/editor@5.2.2': - resolution: {integrity: sha512-ZRVd/oD+sYsUd5zVm0NflqEzlqfYCyHNsqkHl2oWXEUHs12tCbcSFi+wVFEvD8+LGRaMUsVrE7qeo6lSG/S1Vg==} + '@inquirer/core@12.0.0': + resolution: {integrity: sha512-+nnvFEXIB08CZNVXpvW3B+zHW96QXvGUjNKJ8NJIPqAZi5Kd4WhYt2S3C234ReepG1qw2HOlEUbjYVHBowXObA==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/editor@5.3.0': + resolution: {integrity: sha512-nnsP/IdJ8s83q7ZuObmgn12QM+uLCkab9E0Oordojbn62WUg1c+v9Ou/F/057pgh0ppX0W+Hj5bO/Dp5hsxQtA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2204,8 +2231,8 @@ packages: '@types/node': optional: true - '@inquirer/expand@5.1.1': - resolution: {integrity: sha512-YmQpenjbFSHAK3sOd44puHh3V1KXXr+JiNpUztoSQ4drLh2rTVzTap/YtlAVu/5xavifIlBfNEzJ/neZJ1a/1g==} + '@inquirer/expand@5.1.2': + resolution: {integrity: sha512-OWIH1IyyWqEKIyqC9Xy+Bnga7NkGMovFdo4atYZMUOTRqf6rO2WCv9E/1MyzvOErDBCxs+9UFliRUDc50xs/jw==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2213,8 +2240,8 @@ packages: '@types/node': optional: true - '@inquirer/external-editor@3.0.3': - resolution: {integrity: sha512-6thf5I8q7lZwzGLAxPaaGEREEkZ3nyePPDQ1oyobblxmEE8mqTLguScP7pDjUTAibiyb4hfXl+qjUEJ+di/aNA==} + '@inquirer/external-editor@3.0.4': + resolution: {integrity: sha512-tZbbaK2ovq6vlrRBNQvjrypmrED/p5x2ncIHQ79cD55tei3dD96v5glMMA+6tiq7K104i/25DVYKWVPJuV6ptA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2222,12 +2249,12 @@ packages: '@types/node': optional: true - '@inquirer/figures@2.0.7': - resolution: {integrity: sha512-aJ8TBPOGB6f/2qziPfElISTCEd5XOYTFckA2SGjhNmiKzfK/u4ot3v0DUzGVdUnKjN10EqnnEPck36BkyfLnJw==} + '@inquirer/figures@2.0.8': + resolution: {integrity: sha512-tApbon79GM9ry56ja/Ud3SY2CL4TQsao9fIwDQbgTeNY55025GdMzQ2+UdegV/lx51VNGUB59M0v0nMpybYY4Q==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} - '@inquirer/input@5.1.2': - resolution: {integrity: sha512-9K/DDBSQpOyZSkt6sOVP9Vo0TR7atX2kuILsUu0x3wVcVbe97lJwIJKMLdMw25tDYuXl/qp6erT0Xs1rfmcfZg==} + '@inquirer/input@5.1.3': + resolution: {integrity: sha512-F/BZHtyEzP+HO+IGVd4AjBRgvX/ywm42bx8S0+dENk2YclzE9tJ3X/15THwtT6ehApmKvdYDMsVTuyyDod0gOQ==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2235,8 +2262,8 @@ packages: '@types/node': optional: true - '@inquirer/number@4.1.1': - resolution: {integrity: sha512-XF4IXAbPnGPgw0wsbC/i2tPcyfdZgDpUlhsqU0SfT4IRIGWha6Xm9VRgN5yYxJq+jnyXlfXI/nQ3ulfk0iEICA==} + '@inquirer/number@4.2.0': + resolution: {integrity: sha512-ew+fSDijsQ/WhD4TV3XLb+if400cDuzTzHfGR8sTNBXkK9CYDWoGE8fhaO8GbT312pNv1AJEOsDxy/z/HVettA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2244,8 +2271,8 @@ packages: '@types/node': optional: true - '@inquirer/password@5.1.1': - resolution: {integrity: sha512-3XBfF7DAsp5qeDsvN5Rd1HmbNokVvEQoUM0QLrRcybC9nX96w3Pbmu7qUsb3IT3J3jBvs2+mTXaKHOUsgHMLzg==} + '@inquirer/password@5.1.2': + resolution: {integrity: sha512-nSdufycW8xynEVssFkNQEYIzTySilog0UlfOVRwh3pXzPSk4frXUT2jZWjHnKae6RU9PaoF9wfy1pGwewQuqGw==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2262,8 +2289,8 @@ packages: '@types/node': optional: true - '@inquirer/rawlist@5.3.1': - resolution: {integrity: sha512-QqdTqQddL3qPX/PPrjobpsO25NZ4dWXgTLenrR445L2ptLEYE6Z+PD5c5CNDJNx4ugRgELAIpSIJxZaO2jJ2Og==} + '@inquirer/rawlist@5.3.2': + resolution: {integrity: sha512-oPSKrYK1X1bMkjXDzIKHUkJp195LFSfgbnVtXnjSKGFjrCbS6I+wyvfAZTwKE9BSt3HwWgfD7JfsXALBgCogzQ==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2271,8 +2298,8 @@ packages: '@types/node': optional: true - '@inquirer/search@4.2.1': - resolution: {integrity: sha512-xJj8QWKRSrfKoBIITLZK61dD3zwo0Rz11fgDImku30/Oe81zMdIdGgrLY2h6RkJ+KZ/GhNYIRMKnH/62qBTA5g==} + '@inquirer/search@4.3.0': + resolution: {integrity: sha512-HFxXE5w727ctSUcAwrDquftJGjMgu36OeV5SHEXMlr2j/ahzmRX9xSEeVolV8tzYnTf45cg6vGkdMMRdm3RPhQ==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2280,8 +2307,8 @@ packages: '@types/node': optional: true - '@inquirer/select@5.2.1': - resolution: {integrity: sha512-FlDndEUww8m7BfukO2nJa25vhD+H5jxxCv4oGioKqzyWz3nPHhhw4LKdYRSlXuAx7DsdWia7iyaBPKKS95Evfw==} + '@inquirer/select@5.2.2': + resolution: {integrity: sha512-RkI8dRHWt+bh04oLixvF1kFzKC7e5rqJoHKkzcqSHATebBXFC6GmrT8ddbVkgSzLV0HnHs2cPFuBINr8otij8Q==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2306,8 +2333,8 @@ packages: resolution: {integrity: sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==} engines: {node: '>=8'} - '@jasminejs/reporters@1.0.0': - resolution: {integrity: sha512-rM3GG4vx2H1Gp5kYCTr9aKlOEJFd43pzpiMAiy5b1+FUc2ub4e6bS6yCi/WQNDzAa5MVp9++dwcoEtcIfoEnhA==} + '@jasminejs/reporters@1.1.0': + resolution: {integrity: sha512-JIrlfaf9c6m0+GtBAgZdcFB6RIRbFBbXxZDZ0WOewq4cLIEcVKEe0RgI1FA77M39FNzeSMTAm+LK/kcQVIkfGQ==} '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -2367,50 +2394,50 @@ packages: peerDependencies: tslib: '2' - '@jsonjoy.com/fs-core@4.64.0': - resolution: {integrity: sha512-zs2TAq7Six5jgMuoMNjpspAvOP3mhtgq/k1UyQodEzCtQi/N83y2/y+zcvnZSGp/Rxq96DBN+bValOBQAyn/ew==} + '@jsonjoy.com/fs-core@4.68.1': + resolution: {integrity: sha512-V5oZ4Gt9WJKyQef0n9cAd0N9qjSkIBm3E4MYsgNIWBk5aINCDPKxMPo1i29rBxqiT4Ixf1epklqV9VJMKIxwlw==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/fs-fsa@4.64.0': - resolution: {integrity: sha512-nMWOVbkLFyEgmXZih3wyvxA9XpgyyqyfrINMHvEFqhi7uqfRl7c9ERJt6yX7vgMPrB9Uo+OJO+Spa0cFzPD01w==} + '@jsonjoy.com/fs-fsa@4.68.1': + resolution: {integrity: sha512-HCG72UioncuO7Gw09XNVG+S85e3cq2hrUC/mexBrsWsa3mI7eePkkqWie3uVYbtsb64OR9YGQs5SqaufDRYBcg==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/fs-node-builtins@4.64.0': - resolution: {integrity: sha512-/o7WRFhUWaM/fOrslwLZGnzn4RmRILykn+lAL+mNObqqRNw+CQSiij6hpCeZ+C7buhdoVo7go/OYqzaSUfDYmA==} + '@jsonjoy.com/fs-node-builtins@4.68.1': + resolution: {integrity: sha512-HK1BTksysokNZxNspqDH0yPaqN9YgR/AYIlYiIaU2Ys4BOk5CdybI7r6BgiZuiiPiV8n4sK/kZdice7Znpy2Kw==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/fs-node-to-fsa@4.64.0': - resolution: {integrity: sha512-WDD9WVs0hb7UAEKTgZW2f66WDrbj7gIIWwpP3spbLyXa0rghtUaFTB8L4gdR3ZCWwiKIsj38/CNijpVmpnuPUw==} + '@jsonjoy.com/fs-node-to-fsa@4.68.1': + resolution: {integrity: sha512-lpKmU4X9e/oh8GIuAI7EXaS5QiLNM3KD15CkdhfS6PYmrGvoJqKQcyEfnLgnnaGslh/PFUMYSIZBCf2ejJGw8g==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/fs-node-utils@4.64.0': - resolution: {integrity: sha512-k5Indsx9hWW9xSF7Y6oSKKwtCUNhzZxadub3owhIlitc+iMRVlPPdX2duTKQWBL3qNWpXya8jykgaaWpheeS4w==} + '@jsonjoy.com/fs-node-utils@4.68.1': + resolution: {integrity: sha512-/GxfW1DWm9SCdkfbvqevLO/P5duobQfmKkHXxdMIDbcZMQeAgooAstIfZhkXpATzq9QbCQsnoWFM/dGHdZfndw==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/fs-node@4.64.0': - resolution: {integrity: sha512-dO+NNkODbUli4uV42bcNrrLvq5rE7SNpdZ5TNd0dtbLsAaNK3MDiIC9lUi+brboGoIjW6vd2fB1qao60nrk5xA==} + '@jsonjoy.com/fs-node@4.68.1': + resolution: {integrity: sha512-R5D9mWtqdURzcOWj1vdXr3APCwX0xchtFT+kmW7fXLNDifWdDrnh26jSID8pdnUfFBxTyfHtFtTL/NWKzIH7kQ==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/fs-print@4.64.0': - resolution: {integrity: sha512-PHZFccchvkhWrwPWHjmVAhbC3vSHCtyZvlZfJJ3ho2bnzl450hXri6/8e6pbkWdH+SkmLXNml0sV8e5HDAfxKw==} + '@jsonjoy.com/fs-print@4.68.1': + resolution: {integrity: sha512-oGeZOGPYKK9v1CgeVeEDsLomH1lCnslSpqUN5GmPzrmAVGQlsmsdcXNA2O4lV8Y4xkuSuynx2ITBkUHJVaTbow==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/fs-snapshot@4.64.0': - resolution: {integrity: sha512-oM7UDeL83q6NBzzsfKAsYKXKVXlykKFqqOLh4xZZKAzzROTlInkPbc6LTDGThEOnPiFiUzA7tYziHG9xavd76Q==} + '@jsonjoy.com/fs-snapshot@4.68.1': + resolution: {integrity: sha512-XZfP0FDZN32bbc4t2bZN2qRrYHg5AktJnzk22HRoKGK4BprrbNRH2k5ceSNS/kupKYcofCs+O841+xaAbjnxwQ==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' @@ -2454,12 +2481,12 @@ packages: '@leichtgewicht/ip-codec@2.0.5': resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==} - '@listr2/prompt-adapter-inquirer@4.2.4': - resolution: {integrity: sha512-/KRI2DMD7JGSYaREF0Ygl7AefJ/2ase4Gc5cBiKqT5l4tFjsSJfhFGcc5nSkgl0Sp9LkCQNzl/cqbVJYP2L3dw==} + '@listr2/prompt-adapter-inquirer@4.2.5': + resolution: {integrity: sha512-pYGy9dTdTwXdasPgyohkr0HoQ4FrkAzFnsUZl/gcnadDArbpZ8e+fgr+F9WBdNEl2y00mb9bCM4WgmoBkZJ27A==} engines: {node: '>=22.13.0'} peerDependencies: '@inquirer/prompts': '>= 3 < 9' - listr2: 10.2.1 + listr2: 11.0.0 '@lmdb/lmdb-darwin-arm64@3.5.6': resolution: {integrity: sha512-mY5FG4TjPAkY4P0w+OhHaUka5mDh2TX2WKYIwuKzJ1zeW3VvRgxdam/lGJTquI+bthTx5CSHDW+BAQCnNAzkEA==} @@ -2496,8 +2523,8 @@ packages: cpu: [x64] os: [win32] - '@modelcontextprotocol/sdk@1.29.0': - resolution: {integrity: sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==} + '@modelcontextprotocol/sdk@1.30.0': + resolution: {integrity: sha512-xKd8OIzlqNzcqcNumGAa6g+PW2kjD5vrpcKOnfldAUPP3j7lnqMPwlTXQm8gF+UwH72z0lqaRbjr9hqGz0eITA==} engines: {node: '>=18'} peerDependencies: '@cfworker/json-schema': ^4.1.1 @@ -2653,11 +2680,12 @@ packages: resolution: {integrity: sha512-xJIPs+bYuc9ASBl+cvGsKbGrJmS6fAKaSZCnT0lhahT5rhA2VVy9/EcIgd2JhtEuFOJNx7UHNn/qiTPTY4nrQw==} engines: {node: '>= 10'} - '@napi-rs/wasm-runtime@1.1.6': - resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + '@napi-rs/wasm-runtime@1.2.3': + resolution: {integrity: sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==} + engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0} peerDependencies: - '@emnapi/core': ^1.7.1 - '@emnapi/runtime': ^1.7.1 + '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.4 + '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.4 '@noble/hashes@1.4.0': resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} @@ -2675,58 +2703,67 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@octokit/auth-app@8.2.0': - resolution: {integrity: sha512-vVjdtQQwomrZ4V46B9LaCsxsySxGoHsyw6IYBov/TqJVROrlYdyNgw5q6tQbB7KZt53v1l1W53RiqTvpzL907g==} + '@octokit/auth-app@8.3.0': + resolution: {integrity: sha512-/UaKmJCsOc5XBZwhnFiGNdLH/FkDF8lYtBn1QlKxtX7IpgaRB/XOXjixFtERAknyUZHxp3oDuoiG0En4VptJSg==} engines: {node: '>= 20'} - '@octokit/auth-oauth-app@9.0.3': - resolution: {integrity: sha512-+yoFQquaF8OxJSxTb7rnytBIC2ZLbLqA/yb71I4ZXT9+Slw4TziV9j/kyGhUFRRTF2+7WlnIWsePZCWHs+OGjg==} + '@octokit/auth-oauth-app@9.0.4': + resolution: {integrity: sha512-Pe3du5LrC6dlv10b0RbarBlJtIT1Urq8BFoQklK8WmBw8YKnGgrANn7cQmHiA1v8AVihgi7YutV8MncP57I4og==} engines: {node: '>= 20'} - '@octokit/auth-oauth-device@8.0.3': - resolution: {integrity: sha512-zh2W0mKKMh/VWZhSqlaCzY7qFyrgd9oTWmTmHaXnHNeQRCZr/CXy2jCgHo4e4dJVTiuxP5dLa0YM5p5QVhJHbw==} + '@octokit/auth-oauth-device@8.0.4': + resolution: {integrity: sha512-M/+34rmkxMvUnnTo/uqNeVRCXJoJ+5N34eNTbL1KMtIyJpedCTsu/iFL1cWdL+w5hQMlYt6xzXoyux2gn0OVnw==} engines: {node: '>= 20'} - '@octokit/auth-oauth-user@6.0.2': - resolution: {integrity: sha512-qLoPPc6E6GJoz3XeDG/pnDhJpTkODTGG4kY0/Py154i/I003O9NazkrwJwRuzgCalhzyIeWQ+6MDvkUmKXjg/A==} + '@octokit/auth-oauth-user@6.0.3': + resolution: {integrity: sha512-t4OKUhrI5britmpRiSzPAz1TJPyUN/Hw1HEE3Hz/uElxcmnf/YCRSKtFRNc5gy4yJFTlXgk34H1lvxiotQJQvQ==} engines: {node: '>= 20'} '@octokit/auth-token@6.0.0': resolution: {integrity: sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==} engines: {node: '>= 20'} - '@octokit/core@7.0.6': - resolution: {integrity: sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==} + '@octokit/core@7.0.7': + resolution: {integrity: sha512-DcB0M3KFgr9ECI328lhBMVsyFT2DnmNucSBTqEN3exyNKUzkkpUSCHmTRcunF41Eou2TIQKW4seewri8ON9bSA==} engines: {node: '>= 20'} - '@octokit/endpoint@11.0.3': - resolution: {integrity: sha512-FWFlNxghg4HrXkD3ifYbS/IdL/mDHjh9QcsNyhQjN8dplUoZbejsdpmuqdA76nxj2xoWPs7p8uX2SNr9rYu0Ag==} + '@octokit/endpoint@11.0.4': + resolution: {integrity: sha512-f1cOWoHPmxryJFknxbtDdjODWfV8A9tc8Aae6ermXPNgHFZ/x91AtHIz4gicEjL8hkJiip+u21QHJORfBv/qiA==} engines: {node: '>= 20'} '@octokit/graphql-schema@15.26.1': resolution: {integrity: sha512-RFDC2MpRBd4AxSRvUeBIVeBU7ojN/SxDfALUd7iVYOSeEK3gZaqR2MGOysj4Zh2xj2RY5fQAUT+Oqq7hWTraMA==} - '@octokit/graphql@9.0.3': - resolution: {integrity: sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==} + '@octokit/graphql@9.0.4': + resolution: {integrity: sha512-5s15CCiY8XXQ+FG+b1YQcl6Z2FA++nwAz/tg2VUrTmnMncP+2nnGUEYANImdnxsA2Fnq+Mbl7hDjUTw7cFAwcg==} engines: {node: '>= 20'} '@octokit/oauth-authorization-url@8.0.0': resolution: {integrity: sha512-7QoLPRh/ssEA/HuHBHdVdSgF8xNLz/Bc5m9fZkArJE5bb6NmVkDm3anKxXPmN1zh6b5WKZPRr3697xKT/yM3qQ==} engines: {node: '>= 20'} - '@octokit/oauth-methods@6.0.2': - resolution: {integrity: sha512-HiNOO3MqLxlt5Da5bZbLV8Zarnphi4y9XehrbaFMkcoJ+FL7sMxH/UlUsCVxpddVu4qvNDrBdaTVE2o4ITK8ng==} + '@octokit/oauth-methods@6.0.4': + resolution: {integrity: sha512-96RsnxS7Hk/BQhUA1Qo2pmcYP6LWQRWMdo7bVbNE7ZCkFLhSUYBXVUj9tVnvhl4jzbwHYt/dcIG+ioY427b2sg==} engines: {node: '>= 20'} '@octokit/openapi-types@27.0.0': resolution: {integrity: sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==} + '@octokit/openapi-types@28.0.0': + resolution: {integrity: sha512-0rFyLuyHvIj6uuZWuDslxkowFYdPXoNIkeAv4b27dzm2Tf4vGWXnPsMcxs7d65kLdMERgP3wc1AEPlqMz8e1cQ==} + '@octokit/plugin-paginate-rest@14.0.0': resolution: {integrity: sha512-fNVRE7ufJiAA3XUrha2omTA39M6IXIc6GIZLvlbsm8QOQCYvpq/LkMNGyFlB1d8hTDzsAXa3OKtybdMAYsV/fw==} engines: {node: '>= 20'} peerDependencies: '@octokit/core': '>=6' + '@octokit/plugin-paginate-rest@15.0.0': + resolution: {integrity: sha512-lw9A9YL5s4VPj+VEx8uMxaxQm2YTgrPDkrLEuZuu18R8TK3oPcXF4K6t52nx6xn1RcogZC9i188sAr/4XYJaQQ==} + engines: {node: '>= 20'} + peerDependencies: + '@octokit/core': '>=6' + '@octokit/plugin-request-log@6.0.0': resolution: {integrity: sha512-UkOzeEN3W91/eBq9sPZNQ7sUBvYCqYbrrD8gTbBuGtHEuycE4/awMXcYvx6sVYo7LypPhmQwwpUe4Yyu4QZN5Q==} engines: {node: '>= 20'} @@ -2739,12 +2776,18 @@ packages: peerDependencies: '@octokit/core': '>=6' - '@octokit/request-error@7.1.0': - resolution: {integrity: sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==} + '@octokit/plugin-rest-endpoint-methods@18.0.0': + resolution: {integrity: sha512-1wM02pQTHEarWYij0Bb4gu8X8fBy2FJdI4HMTSFDxtYLbOkJErGVx5ywmM6jeS8tOmC0iCiRLrn6YsSIecUeOQ==} engines: {node: '>= 20'} + peerDependencies: + '@octokit/core': '>=6' - '@octokit/request@10.0.11': - resolution: {integrity: sha512-+s7HUxjfFqOMS9VlIwDffq0MikjSAK0gSpG73W+meAvVAvX4MBrHYTK5Bj3Uot55qFT4gzUtfzE4mGWY4Br8/Q==} + '@octokit/request-error@7.1.1': + resolution: {integrity: sha512-+eaY7G2VVpSf2pc5Gn1+mph837V/d/TYTJAgWL9Tb0ogGYcpN3IlAVFgjL+Vv93F/sevrxkvsYCedtpLdcFLzA==} + engines: {node: '>= 20'} + + '@octokit/request@10.0.15': + resolution: {integrity: sha512-3CBg9aJ0hO9Pjyij8LbK/xYtEaPws9SW7xKz67daPNxQB1q5Y9OMA7DDOG0A6Hwf9ygGu3tvzusg0LXQ8/wAjA==} engines: {node: '>= 20'} '@octokit/rest@22.0.1': @@ -2754,6 +2797,9 @@ packages: '@octokit/types@16.0.0': resolution: {integrity: sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==} + '@octokit/types@17.0.0': + resolution: {integrity: sha512-ByP1v7YL5SMveFPP7+sj0/ZuWCOOg/Chs4NafOMpq6WNIM/hdGY0S7C0TCGDBWu1aGmOxmUIhMx3cO+IdwYZ1Q==} + '@open-draft/deferred-promise@2.2.0': resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==} @@ -2783,129 +2829,129 @@ packages: resolution: {integrity: sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==} engines: {node: '>=14'} - '@oxc-parser/binding-android-arm-eabi@0.140.0': - resolution: {integrity: sha512-ZfjDZ422mo7eo3b3VltqNsV9kmv1qt/sPEAMSl64iOSwhVfd0eIZ9LB79Mbs1xYXJnk7WSROwzBCKDIiVxPTvQ==} + '@oxc-parser/binding-android-arm-eabi@0.142.0': + resolution: {integrity: sha512-ZiRGDutGsv1G6bL/ozy/koC0Sv39T1DqyoC4KD1DOy9ZoACm1O5UWhEK2c02Qdk+4lfLVkvFa/mQ0fm/4h1BtQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] - '@oxc-parser/binding-android-arm64@0.140.0': - resolution: {integrity: sha512-Ia8jSvikUX6Sf+Ht+KOCUF/k1HpR0VlmqIYymubmWDebOEGtsyliHDR6JxsZ4IX3/c/GbrB1uh09aVGQv/LQmQ==} + '@oxc-parser/binding-android-arm64@0.142.0': + resolution: {integrity: sha512-WZkvGRLNQTz8lR9zP5nLjUdlroRCopBu3g9zF1p/laE6DzT1UbQo8Rdz5MWhaJUPYg/6gp+jo7HUgsyKaN1FtQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@oxc-parser/binding-darwin-arm64@0.140.0': - resolution: {integrity: sha512-G6VK0nK61pH0d0mBjUqSZbVxGqqO5uzeginLDQj+gOO6ObfJjXRwgkD/ol0w1INcnFeAb6YGGO7qc3ueGHaycQ==} + '@oxc-parser/binding-darwin-arm64@0.142.0': + resolution: {integrity: sha512-l4khS8LQOOVYsGRVARo1gSaCT/aBSceUVXgtovWc2+drnxVuDr082WA3OCHVdVzIz5JIrP/y9CWsSKxBDNmYGg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@oxc-parser/binding-darwin-x64@0.140.0': - resolution: {integrity: sha512-HazBOuZzd2pO1C2uMmp8Gv7mhzMHqKSKDS1OZfcLEvpIcgA+48J92HEtNanVHDIzRD9PRPCV6aS6fkZIWOVl8Q==} + '@oxc-parser/binding-darwin-x64@0.142.0': + resolution: {integrity: sha512-QBsNF3nqlXmcH2B1YOPqQYmCJoy4HuIjUxGbBO/k5JAJUl68ghU2psRY2zPk+RyBaWqKP/qfL4oaFgEMCdwskA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@oxc-parser/binding-freebsd-x64@0.140.0': - resolution: {integrity: sha512-9hSUU+HmTUyOe4JzMHxNGgLWNY7rrO+6ShicZwImNJacEAACDMIkuEQQkvXSL+WJN50jaNtLYJv8s4OcBdpyUQ==} + '@oxc-parser/binding-freebsd-x64@0.142.0': + resolution: {integrity: sha512-b7Q7m4Cqc6XqNhri3R+QhU+GVy646Pn+bkdhrDdWym/Fdi0ZUa+d73H9dm5H91JtbtAQ/z1d8XKMW3oOV8a4tQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@oxc-parser/binding-linux-arm-gnueabihf@0.140.0': - resolution: {integrity: sha512-RAEuQsYtS0KcDFqN0ABTjyyNlokS91JeuDuoW9tEbG0JTbRNXnpQUdbYc/16JoA6Z/2ALbNrE3KmxtqDiuIjCQ==} + '@oxc-parser/binding-linux-arm-gnueabihf@0.142.0': + resolution: {integrity: sha512-3riVS5IhdH3uCZj1Y9ftDQlR0dvLsIlw/edrRqk8JhgNd5K0XSs+UBtgh50N13CAlW9/TXj6sVGXaKNBocd0Yg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxc-parser/binding-linux-arm-musleabihf@0.140.0': - resolution: {integrity: sha512-c4CkHvPvqfojouredJ0w3e6+jiBq0SbFyhH61kr/zPb/7XsaYTNKQ54vmlSsopfdQbNDX40ZeK9Abs2Qet6wcw==} + '@oxc-parser/binding-linux-arm-musleabihf@0.142.0': + resolution: {integrity: sha512-NmXUOpgpTSkhl795TiXmWppTwmSJ92RC1qvD6e4XOF+slgmo3e6Ah+kEu+6AN8s7NAOEwqGmir58MgSQSWmBSA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxc-parser/binding-linux-arm64-gnu@0.140.0': - resolution: {integrity: sha512-yrjmLj8ixPB25yqvPGr28meGjb+keed7m1GqqY/0uqkhZIoT4t9zmfwUgFEtC33C7dtE+UQ7TU0IaVxf97SWJg==} + '@oxc-parser/binding-linux-arm64-gnu@0.142.0': + resolution: {integrity: sha512-gc0EXsKtXgerujmU2Bql3u1L1HsSQ2774R83idq/FoNMPVV/RY/1ErFsvnit7KoiP/sLvzQixeUo4Ut0ic0wmw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-arm64-musl@0.140.0': - resolution: {integrity: sha512-ggGMQTN8Agwxp2WiLMpdY671dt0qTDJWiWlJeig3HnUwTnerRl0J2JdGVghWBeDcss2D9S2V2Js6dZHEiVabVA==} + '@oxc-parser/binding-linux-arm64-musl@0.142.0': + resolution: {integrity: sha512-F2XvmWSE0uWpie+jHKKIFgdVOe9ypGhkEZxKx5DuW215K6cbAC274yYaPkcM7EqY4Df3Weyhpcz3lsURyH2LVg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@oxc-parser/binding-linux-ppc64-gnu@0.140.0': - resolution: {integrity: sha512-IgTs8xYAFgAUGNmR65tIqjlJ8vKgrfXzC515e9goSdfMyKQV4aJpd2pUUudU4u51G64H0/DSEJEXKOraxm9ZCA==} + '@oxc-parser/binding-linux-ppc64-gnu@0.142.0': + resolution: {integrity: sha512-wLMbT21U/QxknQsk+VvNF0b9D2/aGWhcaQQQ+VYlE8FwD5+GoWZIPPXNzyHmkYyhm0KB3itL+TBavjMatqNnYA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-riscv64-gnu@0.140.0': - resolution: {integrity: sha512-A1x+PMWZmSGaFVOx2YeNTFau8uD+QO14/vLP4GrcuvUPs3+nBkUOjy9Lus86ftHsDojjYMbvBelmKc3F7Rv08g==} + '@oxc-parser/binding-linux-riscv64-gnu@0.142.0': + resolution: {integrity: sha512-+G8F/4ckwT7FCJV4H2bt09xEzJbjNCfuL4Sp1AYNaFtFMVtgIGMuJlteT82U+K0UIZ/DzAR/LDlMFnEuajG7Kw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-riscv64-musl@0.140.0': - resolution: {integrity: sha512-zBqpfRo2myWPrPo5xUjeZqlnPXPXsX8BcWtWff66/eGRQdbPjhzPgXa/F+AtxT2afUViPxbuDlwscMKzQ5tg+g==} + '@oxc-parser/binding-linux-riscv64-musl@0.142.0': + resolution: {integrity: sha512-hTsHtTLxMAfCo+rpF5K3qZJKW2NpPN/CHd4mYB3y7XlSdspHkd2gehDIofP64AacA9nWQw2tY3O7wR6UY8IVOA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [musl] - '@oxc-parser/binding-linux-s390x-gnu@0.140.0': - resolution: {integrity: sha512-2M1DPm/8w9I//YzFlFC9qXw+r2tJFh5CYwRlYTq2vUJQS7qoQftEDeCZ8EnN7KHtvSiXvYj8mZI5pR7DpXmcEw==} + '@oxc-parser/binding-linux-s390x-gnu@0.142.0': + resolution: {integrity: sha512-6y7qYY3TCUDYjqswImdTGl92y+KA/80twALegQPN27kfY+bG7Ib1+L3jbmrCZQx6wrVnai9IPsEZp07I0hx7JQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-x64-gnu@0.140.0': - resolution: {integrity: sha512-8aRDbZ/U/jO8N7go1MO72jtbpb4uswV8d7vOkMvt/BPgZiyEYvl1VIWK4ESxZZhnJ4tqwVldgX7dNiP/eB1Jdg==} + '@oxc-parser/binding-linux-x64-gnu@0.142.0': + resolution: {integrity: sha512-i69kAWU+2LgoH5bR+zWiiu+UzAw7Oxkwv7COeJTeY19pn4e70nKQcr9Pm6cL2Z0Z54d+gl9qADlK/0yyuCPiBA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-x64-musl@0.140.0': - resolution: {integrity: sha512-xRqpeI8U2sQQS1W5BMWRyMTxtagkuLG2dEWruet5lFsWHTvBth11/TpSaJatHdqVVwHN0q3uuoS9zRsGinq8hg==} + '@oxc-parser/binding-linux-x64-musl@0.142.0': + resolution: {integrity: sha512-4SQs678MmjYVrmhAgCWD4o0vpaFszXw9xLX5p2Z9MMFcltxiLkA88wQjh80YHjPrXtpyZ2CWI5m+1yNKM0m2Pw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@oxc-parser/binding-openharmony-arm64@0.140.0': - resolution: {integrity: sha512-GbGRe26MqAKciFRvXeHNQJ6VAHYs9R4miP89sEAncysM3n+f4lnyLWgsa9kklJNpfnxdq2yRoNYHFqwBckVimw==} + '@oxc-parser/binding-openharmony-arm64@0.142.0': + resolution: {integrity: sha512-YHpx9N7Ln3a++Tc8rv+H7mrK1zyJQOAwCFg8LZ3lTs1T5afGWeZrLPhPT9HLnIwSjCyJqPWVMIrMxbjcmBr2oQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@oxc-parser/binding-wasm32-wasi@0.140.0': - resolution: {integrity: sha512-vFiC1hqys+hkX1GnQkIoiTQJNiUm43Z0lO35ETKXTw0YtpW7+cN58YRRXFAQQ+TgpkIi3lrhcxdlnqz+Oi3ptQ==} + '@oxc-parser/binding-wasm32-wasi@0.142.0': + resolution: {integrity: sha512-3pLDyY3+oogW73RM5uehNgAiR/Xfb7fvO2Q1Z1gIqZ2+50XDVQmBVlRkHXZTU4gKnQHpwETNsYQVsJ3joVB2iA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [wasm32] - '@oxc-parser/binding-win32-arm64-msvc@0.140.0': - resolution: {integrity: sha512-fGSQldwEYKhM+H8uLt76Op8hh5+FYaR6lvvQ1Txw3Mhn86DyQXLcI0fi1EkFlTK7F+46OCk/j0AJMzZQm6g5Xg==} + '@oxc-parser/binding-win32-arm64-msvc@0.142.0': + resolution: {integrity: sha512-Had/VeVY28Oyb0K+Q4FV8KCzoBycIh93oDK6pCbya9lkzdq+ikMHMgBubsdqqlybjJmQRawCQRrnBRHyQwYvcQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@oxc-parser/binding-win32-ia32-msvc@0.140.0': - resolution: {integrity: sha512-sDS2Bai+g3ZWYwfZqmosiSuFDBcVnZ3Ta6pszzsiJoLMqsJEWKcxXXbGa7b7yXr++W2lQNPb3ZRJ8czseqL7RA==} + '@oxc-parser/binding-win32-ia32-msvc@0.142.0': + resolution: {integrity: sha512-GGi3+YphVHavvgs6gum2UXoNCqzHAmPt/nXkn8ZQZstV2Q1qZD1Mn8fz/nWrDkefHQtrG/+1/XrbMxsBTo6Svw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] - '@oxc-parser/binding-win32-x64-msvc@0.140.0': - resolution: {integrity: sha512-kHbE1zWyb5OQgJA6/5P4WjiuB01sYdQwtZnSSyE58FQEXDAMnyeeq4vj7KgN75i5SlBzOs8A5MrtlD3gOlDKqQ==} + '@oxc-parser/binding-win32-x64-msvc@0.142.0': + resolution: {integrity: sha512-Ny/Wv4Us1LGC/ljwNTp+Hx3r/pH15EFfeDF0p+n898gt+TtRd6C9SccHcuUhDiNTb8s5tt7jdeAMDRQZ4Vq6hg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -2916,6 +2962,9 @@ packages: '@oxc-project/types@0.140.0': resolution: {integrity: sha512-h5LUOzGArYemnW1NMz/DuuQhBi96J6JL2Bk8zE4kvqxB5Sg3jxmCiH4uyOWHDkiKSt5vWlG4FIwCR/DbstcNRQ==} + '@oxc-project/types@0.142.0': + resolution: {integrity: sha512-7W+2q5AKQVU36fkaryontrHn3YDt1RyUYXatw9i5H8ocYe2sPKSFB6eS8WNPeRKiN1qAWWZUPm7gwFzJGrccqQ==} + '@parcel/watcher-android-arm64@2.6.0': resolution: {integrity: sha512-trgpLSCKRC/huFjXX/Smh+0sWe4+YtKfktIToiMl59ghz7z+qkH6kMvNnUbLyRs9N11t8l4svSCs1+5B3rOAhA==} engines: {node: '>= 10.0.0'} @@ -2998,35 +3047,45 @@ packages: resolution: {integrity: sha512-7FNeNl8NCE7aINx7WXiKQrPYZWC/hvrTsmk6zmxbI7LTXE7hVek/n8AfVgpe2y82zl3w0HvCHN0bVKMBoJcC0w==} engines: {node: '>= 10.0.0'} - '@peculiar/asn1-cms@2.8.0': - resolution: {integrity: sha512-NgekZOrSJFSBFLFoLfwePguAWAx7z1+f2TEsWFUMyiqqfntZ4+S/S5hzqME3q4pCA0iOsFKdwiQ35dwY24eVqA==} + '@peculiar/asn1-cms@2.9.4': + resolution: {integrity: sha512-cben7oxmQsUGZqotus7yt0srYdncOT6RNWcTQ77T2RFOXejYVYkXadrfePdRcrVpO9K95IRLKKglG2k38jKXuw==} + engines: {node: '>=14'} - '@peculiar/asn1-csr@2.8.0': - resolution: {integrity: sha512-akbF8+uvleHs8sejNPQxwmVFuInAg6FMNHOwMILXfP518YfFJwdR3jr6oNUPOaEJfuEhn/vkNOCIT6ASUd4mbg==} + '@peculiar/asn1-csr@2.9.4': + resolution: {integrity: sha512-xd4YN4vpRjkDAQWVfZZkeu12IEND7DOpkqaHSIHxZl1uggUNa9Ju0QxY2jHvDAS9pP0zhRBytg8ifsnGo3V0jw==} + engines: {node: '>=14'} - '@peculiar/asn1-ecc@2.8.0': - resolution: {integrity: sha512-ohwlk+u9Rv2NOAY1c6MfHj45ATVF8R1DUN/WCgABiRtLi2ZftlZWZX7KvpAbU8v9xPcmoILfELeEABj/rn18AQ==} + '@peculiar/asn1-ecc@2.9.4': + resolution: {integrity: sha512-JJXefFshRAuVAjWQo/39bkg1ywc1VaiO44S8RRC+Ykvf/u2KDmYffoDb0ZBPCR5uJy4AGKQhl8mX+Q8ShcWaXQ==} + engines: {node: '>=14'} - '@peculiar/asn1-pfx@2.8.0': - resolution: {integrity: sha512-5yof1ytoB++RQtaFbqSUJ8pxDJtZT6vbVqZ8XoJ61ph7UjNVvfFwAilnCodqkNsAodpy13gDhoxZXw00pghnyg==} + '@peculiar/asn1-pfx@2.9.4': + resolution: {integrity: sha512-khuGzHTzNzk4GDlIBEILyIs6Lce0yn0ZBdoI9v93kmNncfZRhD+AQ5ODFqdhvoE8cMJF/JMTQ8yA+t1D14kqCw==} + engines: {node: '>=14'} - '@peculiar/asn1-pkcs8@2.8.0': - resolution: {integrity: sha512-qAKXtLpBEw9LqhKpjw3ajZSXlBur+ipW+y2ivVBQAG6F6qRx94yO+1ZR4mvw+YaCfKSaOzLeYEzsPaBp4SJELA==} + '@peculiar/asn1-pkcs8@2.9.4': + resolution: {integrity: sha512-duRdotlUx9eDZe6QrQpQKl61RbWykCHBCkKayP8V8XdEFwlKHZ8qGGDMyS6Pye7OX7nLFttTTpRkJeet78ckwQ==} + engines: {node: '>=14'} - '@peculiar/asn1-pkcs9@2.8.0': - resolution: {integrity: sha512-b5nDWCnkV60+cQ141D6sVVwK9nz64R5n3zSVnklGd+ECdkW2Ol3U1a6yYFlalpSOaD557yuJB64A+q42jG7lUQ==} + '@peculiar/asn1-pkcs9@2.9.4': + resolution: {integrity: sha512-kaL4cNxBpdQE2dKlyZBqz4ygCrwffO+8wfoxTEqM1Z8RadvCeELBRzcv0dzM8aY9azHMwODO5nxU65zXmhToOQ==} + engines: {node: '>=14'} - '@peculiar/asn1-rsa@2.8.0': - resolution: {integrity: sha512-zHEUlCqB2mk7x2lxDwHHJy7hWZOPdGHVlsmITWKB5/PbQo61atbu9PJ/0r9dQNMwFzbKPXZ8uK8/91eUhRznSg==} + '@peculiar/asn1-rsa@2.9.4': + resolution: {integrity: sha512-pZ96eD1PptovcWQ/GSmuNFXd/7EQJNlKfDaNCyE2rx3W0v6QFelkzquVqRSRyyDXXCYD69ZXJDzZ8GhIiQzKoA==} + engines: {node: '>=14'} - '@peculiar/asn1-schema@2.8.0': - resolution: {integrity: sha512-7YT0U/ze0tF2QOBbE15gKZwy5tvgGyLRiRHLzhlbOpf7BT032oBSd0haZqXn5W6l26WLlu3dyxzjM+2638/z2Q==} + '@peculiar/asn1-schema@2.9.4': + resolution: {integrity: sha512-GjzePcT9Iw8NzeOPf73iNS9xM+TBhd/FilAfP+RQGkTMQJTVWtytN3JHJACCjf/ABNau5S7mS3g+DcuxmRgYEg==} + engines: {node: '>=14'} - '@peculiar/asn1-x509-attr@2.8.0': - resolution: {integrity: sha512-tHjkfS/qhMnmrlB2J9NhflQlQ7In3khO3CfmVrriOlpTeErY9ZIKOso1hQ5JQiyrJ7ShvqVPk7E5fQmbclkSKA==} + '@peculiar/asn1-x509-attr@2.9.4': + resolution: {integrity: sha512-ehQXbpQaQYycgu8OrvigwSPTFfVRcu0ECNYCWw+yzBp02Lw5paRqzzhUpfOgO2K38+WfFZuEz/0RPtam5g0OMg==} + engines: {node: '>=14'} - '@peculiar/asn1-x509@2.8.0': - resolution: {integrity: sha512-N0CMuhWUzsWEVq6F1q9X6+VKUnWzSW+cSVg+aPaGGwDdbFoFWTYgin5MHwXgpWd6y9COMBxnfy/Qc+Xc7F0Zwg==} + '@peculiar/asn1-x509@2.9.4': + resolution: {integrity: sha512-CxhBo/RdEbMMob7T31ZdQjGuoyRFLVwrDzTn25bihzBasRg9kRm/0IxIPvhgQtcK/9dNcO1XQL2fuPugwELL0Q==} + engines: {node: '>=14'} '@peculiar/utils@2.0.3': resolution: {integrity: sha512-+oL3HPFRIZ1St2K50lWCXiioIgSoxzz7R1J3uF6neO2yl1sgmpgY6XXJH4BdpoDkMWznQTeYF6oWNDZLCdQ4eQ==} @@ -3582,8 +3641,8 @@ packages: '@types/express-serve-static-core@4.19.9': resolution: {integrity: sha512-QP2ESEe/ImWY0HDwNAnK9PvEffUyhLTnWkk7KXzHfyeWAnlrDe1fN77bXl6ia8KT3wPlmA7t9/VPRpnf4Ex9sg==} - '@types/express-serve-static-core@5.1.2': - resolution: {integrity: sha512-d3KvEXBSo/lOAMc2u6fkyDHBvetBHeqD7wm/AcXfLpSOQwlmG9D/aQ0SFswVjv05p7ullQS7Mjohj6/VdbZuTg==} + '@types/express-serve-static-core@5.1.3': + resolution: {integrity: sha512-dPfW8NFiOF4wOHc7+N/QSxlY9cfSsenewGbAz8C8U/MULPd/YZ27LvJUIlzaXie7e6Ove9YunJGgC9tbHD2cKw==} '@types/express@4.17.25': resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==} @@ -3630,8 +3689,8 @@ packages: '@types/loader-utils@3.0.0': resolution: {integrity: sha512-oOi4OGpiLUbb+Q/cN9FIkkDFgOpOGZ2cUAzb5i03wrGstnG6Syx1WDMhSiB5rcP10XX7cw7Uev8mv++/aplnNg==} - '@types/lodash@4.17.24': - resolution: {integrity: sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==} + '@types/lodash@4.17.25': + resolution: {integrity: sha512-+K1NIO8I+F9/wNulfVvu23QYd0Pe9/OCqRrim4NoYIf1VoEDL90Ve4ClzpyqBLc7NpGGWRvYNCKZ1BE/Jpf8dQ==} '@types/micromatch@2.3.35': resolution: {integrity: sha512-J749bHo/Zu56w0G0NI/IGHLQPiSsjx//0zJhfEVAN95K/xM5C8ZDmhkXtU3qns0sBOao7HuQzr8XV1/2o5LbXA==} @@ -3681,8 +3740,8 @@ packages: '@types/retry@0.12.2': resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==} - '@types/semver@7.7.1': - resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} + '@types/semver@7.8.0': + resolution: {integrity: sha512-1mAINjtQCXXeLkJ9ehXkwOcBpqtLxiVtKhpUf83DdRNdQKV0iXZpaHYqRr7nj+wvxuJzoAmAwXI+sCNMv1CzLQ==} '@types/send@0.17.6': resolution: {integrity: sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==} @@ -3771,8 +3830,8 @@ packages: resolution: {integrity: sha512-qjhfuTfLXjA4IOzXvz0rTjT01BqEiIgPoUeMwiEjnaHKJMTNo8rH5pYW1a2L/0Dnux2fPC85AeyJoWaGa8WxTA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/types@8.65.0': - resolution: {integrity: sha512-JSSwWNy+H0E/01jJEM+hrX6N0OFDzFzeIhHFSAS01tlVaevpG8cFyYRPhS5yjGOvBUx3sqQHVMjCL1CAZZMxBg==} + '@typescript-eslint/types@8.67.0': + resolution: {integrity: sha512-sBtgslww8nsMYUjhdPBiSyUqSzT8uR6g93A2QXnQC8+cGdjz0CyaOdqHDRJb1AtORbZCNUJBBeFA/tNR2uQmww==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@typescript-eslint/typescript-estree@8.64.0': @@ -3804,6 +3863,10 @@ packages: resolution: {integrity: sha512-VtpBz9R61GTFUxPiQmBhCOffQZRJZMA2EXO/FzbaoNczm/Xt2KkDJq0PPwV5qmRGeouDRxEKUQ+caJGVN0W7Ww==} engines: {node: '>=18'} + '@verdaccio/core@8.2.2': + resolution: {integrity: sha512-BSCCR5cFkepjL3HnosKUi6aRezwgHu1FihFtes63yxIiDXkMclVi5IekTH6SCeW/7MO1Uyp58kh1updbB6VW4w==} + engines: {node: '>=22'} + '@verdaccio/file-locking@13.0.1': resolution: {integrity: sha512-SZ9uxnQKppiM+/67xTaaBP4AZ/Q+weUB22ci1gF861icYWhWFu3njA3ofYig/4yNqkYRVEKVAIwnH97BaBEYbg==} engines: {node: '>=18'} @@ -3956,8 +4019,8 @@ packages: '@webassemblyjs/wast-printer@1.14.1': resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==} - '@xmldom/xmldom@0.8.13': - resolution: {integrity: sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw==} + '@xmldom/xmldom@0.8.15': + resolution: {integrity: sha512-/5NV/vDALVFDXgLmfsy9TRCBlKwO2LNBFzpzvb9iIj+jR+eSc6DLYYvVOdivT/jm7MtU6TebYuRmzEOI7w40UA==} engines: {node: '>=10.0.0'} '@xtuc/ieee754@1.2.0': @@ -3985,19 +4048,13 @@ packages: resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} engines: {node: '>= 0.6'} - acorn-import-phases@1.0.4: - resolution: {integrity: sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==} - engines: {node: '>=10.13.0'} - peerDependencies: - acorn: ^8.14.0 - acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.17.0: - resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==} + acorn@8.18.0: + resolution: {integrity: sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==} engines: {node: '>=0.4.0'} hasBin: true @@ -4059,8 +4116,8 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.2.2: - resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + ansi-regex@6.3.0: + resolution: {integrity: sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==} engines: {node: '>=12'} ansi-styles@4.3.0: @@ -4227,9 +4284,9 @@ packages: bare-abort-controller: optional: true - bare-fs@4.7.4: - resolution: {integrity: sha512-y1kC+ffIx/tPLdTE693uNjHfzTfr+ravR5tvWlMXe25nELbkqV400S71qHDwbkAQ1FVEZobB1NFRzFbCCcyBCQ==} - engines: {bare: '>=1.16.0'} + bare-fs@4.8.0: + resolution: {integrity: sha512-fM+MhCvdQhZ7NV6S95a07gPSqjIYKn6mFaXfx266wN3ajZGl/+1AzH+ubkXQ0fFZvOe2nk9VHkzdYkQE5zMV3Q==} + engines: {bare: '>=1.28.0'} peerDependencies: bare-buffer: '*' peerDependenciesMeta: @@ -4253,8 +4310,8 @@ packages: bare-events: optional: true - bare-url@2.4.6: - resolution: {integrity: sha512-iQxPClE07hETVpbRoX7JXX3v/ZQViCxe/SYCxylRLzdEx1xJAufPptfiOqR8tqiCtmbtMDANKWszzjLu1PMAZQ==} + bare-url@2.5.2: + resolution: {integrity: sha512-L13PCJzKG8RGvx8V1/DdMi12ERhC3tprr7/8a94BxpmnRsFqxh5XZNdhtMxu5HPkRshYOOWRGY8lDP7ZhpG9Cg==} base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -4263,8 +4320,8 @@ packages: resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} engines: {node: ^4.5.0 || >= 5.9} - baseline-browser-mapping@2.11.0: - resolution: {integrity: sha512-oCu2wfipvX3AePSgmOuKkIywOu+8n9psz7hXYmk56ghpu3+7KzNIBopaOs4c9BrtdnTtW30unG9GTfHo7EwERQ==} + baseline-browser-mapping@2.11.18: + resolution: {integrity: sha512-1iEmLEYSiE1SeBoAfPo/Mnx3PzfzHUkDK61ASkCpuk3YXugYLH5DYK1SzqV55F8FMI6s0F+/tCP7Polz1QRjxw==} engines: {node: '>=6.0.0'} hasBin: true @@ -4308,21 +4365,21 @@ packages: resolution: {integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==} engines: {node: '>=18'} - bonjour-service@1.4.3: - resolution: {integrity: sha512-2Kd5UYlFUVgAKMTyuBLl6w49wqfOnbxHqmuH0oCl/n7TfAikR0zoowNOP5BU4dfXmm+Vr9JyEN370auSMx+CNg==} + bonjour-service@1.4.4: + resolution: {integrity: sha512-jCZcVv7eoc4QesRscwEZtSROBen+6LpKAmBIsQYQrsAeVHLyMXWX/t6eIV5KiRZYNUBl8eVqImEEMQ8L5+c/Kw==} boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - brace-expansion@1.1.16: - resolution: {integrity: sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==} + brace-expansion@1.1.18: + resolution: {integrity: sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==} - brace-expansion@2.1.2: - resolution: {integrity: sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==} + brace-expansion@2.1.4: + resolution: {integrity: sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==} - brace-expansion@5.0.7: - resolution: {integrity: sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==} - engines: {node: 18 || 20 || >=22} + brace-expansion@5.0.9: + resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==} + engines: {node: 20 || >=22} braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} @@ -4346,8 +4403,8 @@ packages: browserify-zlib@0.1.4: resolution: {integrity: sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==} - browserslist@4.28.7: - resolution: {integrity: sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==} + browserslist@4.28.8: + resolution: {integrity: sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -4403,8 +4460,8 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - caniuse-lite@1.0.30001806: - resolution: {integrity: sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==} + caniuse-lite@1.0.30001809: + resolution: {integrity: sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==} caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} @@ -4457,9 +4514,9 @@ packages: resolution: {integrity: sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw==} engines: {node: '>=18.20'} - cli-truncate@5.2.0: - resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==} - engines: {node: '>=20'} + cli-truncate@6.1.1: + resolution: {integrity: sha512-06p9vyLahLa4zkGcgsGxU6iEkSOiuI4fhCH6Emhe2lPAcoUv73n72DnODsnHA+5wwXGnV0n9M9/qOQJSjYhFhw==} + engines: {node: '>=22'} cli-width@4.1.0: resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} @@ -4563,16 +4620,20 @@ packages: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} - content-type@2.0.0: - resolution: {integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==} + content-type@2.1.0: + resolution: {integrity: sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==} engines: {node: '>=18'} + content-type@3.0.0: + resolution: {integrity: sha512-AIi5H6p0xk5uknXcN3/rmhP8jgp69OfSe/JuKiQAFprJ7UGw7mwj7m4XcmDzlrnJDG+cGpphAINGdU3g3g7kDw==} + engines: {node: '>=22'} + conventional-commits-filter@6.0.1: resolution: {integrity: sha512-cs+LadpH7Kpw0M3k8wurk+sOVVDAENA0iK4OBOrkL94j5lEVYRJ4j3zd2bhY9qgzyrPqthdcYT3axzRN7AliMg==} engines: {node: '>=22'} - conventional-commits-parser@7.1.0: - resolution: {integrity: sha512-DPp6hkUjvwIivxbkrTiLXeRswNv1A/4GFA2X6scXma0AMa9632V3TwxmrlkUIEtUktiM3Ln+RrSH2xlP3/jUTw==} + conventional-commits-parser@7.1.2: + resolution: {integrity: sha512-O+x4N2yH+ijvqWlIyTHsXTAP+algNWgGbjY2duCe8w2vUMvUB95cLRslCPfTMQyLAKlet3bhZTdu6ozn4M+QJQ==} engines: {node: '>=22'} hasBin: true @@ -4603,8 +4664,9 @@ packages: peerDependencies: webpack: ^5.1.0 - core-js-compat@3.49.0: - resolution: {integrity: sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==} + core-js-compat@3.50.0: + resolution: {integrity: sha512-XGpFGbMLHwSt74YLTKho7Ib242qi6O8MSX+sRokV4oz7iKXvQWGYZthjIhjRGMxjzVkAubBO512dKGYcefmX3Q==} + engines: {node: '>=6.4.0'} core-util-is@1.0.2: resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} @@ -4743,8 +4805,8 @@ packages: resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} engines: {node: '>=18'} - default-browser@5.5.0: - resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==} + default-browser@5.5.1: + resolution: {integrity: sha512-m1pAzaJgZ/gssEqlOhJkPJp8Xly7QyW6xcrkUa2KKcDeDSEMP7X8xipU3snUcfisTQx0w1AGae+9UtJSfVnXGw==} engines: {node: '>=18'} defer-to-connect@2.0.1: @@ -4867,8 +4929,8 @@ packages: engines: {node: '>=0.12.18'} hasBin: true - electron-to-chromium@1.5.395: - resolution: {integrity: sha512-7zt9Aw+SrmxLWLN0zhaTWZQiCdryLVrYTq5R7iZakLvi2UQPYMMsROYV/2qVCzMeCiSXHwKOU+sZ4zOVVlrtKA==} + electron-to-chromium@1.5.412: + resolution: {integrity: sha512-z4rMe3esBzlzovKHj4gxJnsCGZRK5l4baUvm+gCGJBPE+gsyUMKsuU9tnEUtI1dOebXz1ytAPGjvXhmQ7rIPwA==} emoji-regex@10.6.0: resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} @@ -4912,8 +4974,8 @@ packages: resolution: {integrity: sha512-clKkw4C7nJ22mGgoVcCg6V/W/TxdNyIOTr89k2ONZu81qqkddPFDF0LXcbAwhzPD8DjkiRCjzuiO6Y+fkpD4vg==} engines: {node: '>=10.2.0'} - enhanced-resolve@5.24.3: - resolution: {integrity: sha512-PwKooW9JUzh5chmYfHM3IQl5OkK2u2Nm011MgeZrss3JmFraUx/fqrf78kk8GUMYoibx/14MdwTl/1WKkG7TpQ==} + enhanced-resolve@5.24.5: + resolution: {integrity: sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==} engines: {node: '>=10.13.0'} ent@2.2.2: @@ -4968,8 +5030,8 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - es-module-lexer@2.3.1: - resolution: {integrity: sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==} + es-module-lexer@2.3.2: + resolution: {integrity: sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==} es-object-atoms@1.1.2: resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} @@ -4987,13 +5049,13 @@ packages: resolution: {integrity: sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==} engines: {node: '>= 0.4'} - esbuild-wasm@0.28.1: - resolution: {integrity: sha512-p/GD4E8oYRjg3kjdKrnMb0s4PzXgJF42e0MF4H0+ACyK/kIlFRp3e0fzOleIG+wBBm6MM3XQrbpe7soEA+vJIA==} + esbuild-wasm@0.28.2: + resolution: {integrity: sha512-GccVwhv3mmOUVQHCQm2Ox/rby8n/EqUwvZxE6Pjfikrq/lWw9g9WX/u9EykWnpot3Ko6j426DgQdea2xWKIAQA==} engines: {node: '>=18'} hasBin: true - esbuild@0.28.1: - resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} + esbuild@0.28.2: + resolution: {integrity: sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==} engines: {node: '>=18'} hasBin: true @@ -5123,9 +5185,6 @@ packages: eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} - eventemitter3@5.0.4: - resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} - events-intercept@2.0.0: resolution: {integrity: sha512-blk1va0zol9QOrdZt0rFXo5KMkNPVSp92Eju/Qz8THwKWKRKeE0T8Br/1aW6+Edkyq9xHYgYxn2QtOnUKPUp+Q==} @@ -5136,8 +5195,8 @@ packages: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} - eventsource-parser@3.1.0: - resolution: {integrity: sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==} + eventsource-parser@3.1.1: + resolution: {integrity: sha512-EKN1vKAMcZ8MlYMpaNuxN6R9yakzH6uajHcHVTqWJzvu5pWw9DyhbP35HH8MVBQ+dZjAfDxk+A8NiR9KWaXiyQ==} engines: {node: '>=18.0.0'} eventsource@3.0.7: @@ -5151,8 +5210,8 @@ packages: express-rate-limit@5.5.1: resolution: {integrity: sha512-MTjE2eIbHv5DyfuFz4zLYWxpqVhEhkTiwFGuB74Q9CSou2WHO52nlE5y3Zlg6SIsiYUIPj6ifFxnkPz6O3sIUg==} - express-rate-limit@8.6.0: - resolution: {integrity: sha512-XKJXDsASUOo0LLtFwW5hCcQGH0N4WQc/Rn8/Pvoia+TJFOkkFPvrtW9lZOeeNcxQJspvOIERMwiRLsVFlhHEkA==} + express-rate-limit@8.6.2: + resolution: {integrity: sha512-YH4ru+eOJxQABscKFfRCy9R7x9QFGdezclVMwwgFFndzS2Xnm0uo6B0ABZsLhcpeptGv2qvuJVWlQr9gQZoC3A==} engines: {node: '>= 16'} peerDependencies: express: '>= 4.11' @@ -5198,8 +5257,8 @@ packages: fast-string-width@3.0.2: resolution: {integrity: sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==} - fast-uri@3.1.4: - resolution: {integrity: sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==} + fast-uri@3.1.6: + resolution: {integrity: sha512-7Ical1vFEMr0onbVzEDIreM22I4khW+fzyQPwvAFWBp1iwdshSZRsL4jjRvPG9JP1uiqMHRto+YU6R2/CzDz5Q==} fast-wrap-ansi@0.2.2: resolution: {integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==} @@ -5260,8 +5319,8 @@ packages: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} - firebase@12.16.0: - resolution: {integrity: sha512-CNw6hFBdONkzF8UGLDx/RDRY9gVa5VmJNHd7qi4gdmA3ZuLkuOrhmWefB2l+FN+OxFpN77Itq7aO6zlTi780ag==} + firebase@12.17.1: + resolution: {integrity: sha512-dhp41ye9jMQvhx5FwjMkf/hjDHJApl7gXmvzOZGvP0M7c/GZGUnQ4qvsvlOBkF0Pa7wAwHMdcpL0ON2pXCQ4Sw==} flat-cache@4.0.1: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} @@ -5271,8 +5330,8 @@ packages: resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} hasBin: true - flatted@3.4.2: - resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} + flatted@3.4.4: + resolution: {integrity: sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==} folder-hash@4.1.3: resolution: {integrity: sha512-94fj+fXj1XHT8zGumUy/VlyFARc/yrslKJ2+vjrP/U6ftTdL7u68+gQhvSBjz9wrwTuty6BpZ7JsbEK5OU9RNw==} @@ -5358,16 +5417,16 @@ packages: resolution: {integrity: sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==} engines: {node: '>=18'} - gaxios@7.2.0: - resolution: {integrity: sha512-CUVb4wcYe+771XevyH6HtGmXFAGGKkIC3kswAP8Z1JCe0j80JMaTPZH930DWFrvo0atjh18Arc0pEyUCWa5bfg==} + gaxios@7.3.1: + resolution: {integrity: sha512-kB3rzJV7d9juLZh8/56QTXCwQfxyhdOMdyYk1HdQKFtF8TJTDTZQJtixWIwXdE9Jji91mC41DUNpjleo4L4eAQ==} engines: {node: '>=18'} gcp-metadata@8.1.2: resolution: {integrity: sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==} engines: {node: '>=18'} - gcp-metadata@8.1.3: - resolution: {integrity: sha512-ziTrzUhhpL9Zk5k0HHzgP/KIpWDJT0VMBC/ynt/QIBvTW+UUcSivQRl6VlwTf/EilDxtSWklHoRsKy1c4k+59w==} + gcp-metadata@8.1.4: + resolution: {integrity: sha512-iJ9KMsiu+xKtNRX0PmGLSaIU3bUBAyzWTyqKemKPzNPsmmsBCQYmlNg+brEbES7IHSXtdVwzBPzx1vz3FAaipw==} engines: {node: '>=18'} generator-function@2.0.1: @@ -5460,12 +5519,12 @@ packages: resolution: {integrity: sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w==} engines: {node: '>=18'} - google-auth-library@10.9.0: - resolution: {integrity: sha512-xtvUqvINPhTaBm7nXqlYPcrMHJPm1lCNdSovxnKKhTm+4JsvQ+KGVYJViLoH9Yxu8w+T0Qv5HubzYT9BLrppJg==} + google-auth-library@10.9.1: + resolution: {integrity: sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw==} engines: {node: '>=18'} - google-gax@5.0.7: - resolution: {integrity: sha512-EhiqaWWJ+9h7sCcKJTsoo6tMcjokVHhWsbSuWCnZJT4vIBP3y4mAoFLnt9SzgkVZeq24ZsFaArr06nnYYku2yA==} + google-gax@5.0.8: + resolution: {integrity: sha512-M4vpZcXQIC1gqIVGQ7eaU3jXQA6zecStyTXu514TYfThlgSurYJOxHZo9fzU6hAgwPWvuEynAVHWyaIk80VeEA==} engines: {node: '>=18'} google-logging-utils@1.1.3: @@ -5540,8 +5599,8 @@ packages: resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} engines: {node: '>= 0.4'} - hono@4.12.31: - resolution: {integrity: sha512-zJIHFrl6bq3RDd2YusFNCDlM8qUprxKswyi/OPzPyzKDdyBXDqWx8bZlZ7R+saTdSTatUmb3O7K4SspGPaEOQg==} + hono@4.13.3: + resolution: {integrity: sha512-r8AO2mYHoLxSHkgafNeC/BXyb2vWRxD3jem4Ts+ptav8oTG5FIRifAjuJEmZI4bSvvc2ns0GxmIYiZnHqN3mMw==} engines: {node: '>=16.9.0'} hosted-git-info@10.1.1: @@ -5669,13 +5728,8 @@ packages: resolution: {integrity: sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==} engines: {node: '>= 4'} - image-size@0.5.5: - resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} - engines: {node: '>=0.10.0'} - hasBin: true - - immutable@3.8.3: - resolution: {integrity: sha512-AUY/VyX0E5XlibOmWt10uabJzam1zlYjwiEgQSDc5+UIkFNaF9WM0JxXKaNMGf+F/ffUF+7kRKXM9A7C0xXqMg==} + immutable@3.8.4: + resolution: {integrity: sha512-ZQv17KolYrYmsDoDB8N67zhIKsNi9mGYlk96y/yuxyAqJB2hLzSGSM7k/sB0/ZvO4kx27U9+fBeD/XlLGh/uXQ==} engines: {node: '>=0.10.0'} immutable@5.1.9: @@ -5706,16 +5760,16 @@ packages: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} - ip-address@10.2.0: - resolution: {integrity: sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==} + ip-address@10.5.0: + resolution: {integrity: sha512-R5SnVLJmgYYvf2F2ZgwSBnelz5G4q5AxIC277GDfUaNbrZKNANcBC7RHqYYePlszf4kBolVkJauG0ZjHHFh55g==} engines: {node: '>= 12'} ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} - ipaddr.js@2.4.0: - resolution: {integrity: sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==} + ipaddr.js@2.5.0: + resolution: {integrity: sha512-aq+t5NAc+cS6rZQQVWC2x98CPqGtKKTMDd4Gaodv0wShnItdKg/51djkGJ1hqH+Oy0ivDftCbSLCQob8zso01w==} engines: {node: '>= 10'} is-array-buffer@3.0.5: @@ -6003,8 +6057,8 @@ packages: resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} hasBin: true - jose@6.2.4: - resolution: {integrity: sha512-N8acGzVsQy6M/fjFcxtysNc4Q379TcM5dM/qKkNtsHFji88yANnXTr7BLeP75iPnFwBfQzM/jg2BZ9+HZrHCZA==} + jose@6.2.10: + resolution: {integrity: sha512-iiW7J9qRFlGxvCOIBDBDxFePQSn7ZMAnrYGhrrOo6siO/MIqwfyilLR27pkfDgUk+raLuzADS8A3S/KLBisc0g==} js-tokens@10.0.0: resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} @@ -6016,8 +6070,8 @@ packages: resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true - js-yaml@4.3.0: - resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==} + js-yaml@4.3.1: + resolution: {integrity: sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==} hasBin: true jsbn@0.1.1: @@ -6064,8 +6118,8 @@ packages: json-stringify-safe@5.0.1: resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} - json-with-bigint@3.5.10: - resolution: {integrity: sha512-Vcx+JVNEBts/xfcoCS69sKrOhOk/3TVlvlT+XzUOefVKnnrbYSCKpDCm10pohsJFtsJVYnwa/cXRZ4eElzaM6w==} + json-with-bigint@3.5.12: + resolution: {integrity: sha512-uwbF/wSSuOgC7qqlq27Xp5B6a2MHVug3t0idZdTqu0JnlFvgJuH7ju+KAk/J06C7GfhoYy2gnb9wz2INqcne7w==} json5@1.0.2: resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} @@ -6154,8 +6208,8 @@ packages: webpack: optional: true - less@4.6.7: - resolution: {integrity: sha512-o3UxHBPPVY1HtCXx15/z1NlknQiWyafRNbtLEv+6xFaDRI2g2xPKIH43do9dSwt8bGLTsjNSaifa48N3d6odsQ==} + less@4.9.0: + resolution: {integrity: sha512-umRhrCH7fCi8Uj2RcwKjJdvUORTjeWqkdKx0LbcZvjIwsAVsnIAGcxHaqowPeBFBjQuWOeC/bve0AlpFzF/+SQ==} engines: {node: '>=18'} hasBin: true @@ -6255,18 +6309,14 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - listr2@10.2.2: - resolution: {integrity: sha512-JtNtbZj8q5BnDMR7trpwvwk3RIrANtIVzEUm8w7amp6xelLgyuq+4WZoTH913XaQAoH/cNdYhaNzBPA2U3xbDw==} + listr2@11.0.0: + resolution: {integrity: sha512-8K88S0aSrcSXdJfiZtEy5BQMnR+TyjrCGLcgAvQs6ta0NEnIm0RJ72/Pv67Jvg07cfBhDbuN74V81lSSVYEFEw==} engines: {node: '>=22.13.0'} lmdb@3.5.6: resolution: {integrity: sha512-j3uE8ReKNyUWDjhfEFSJqE/1DLtfTR5Z8yFzVHvBjAk37wNg7HdScjcv8ttPHRvrdgPQMPWxFFI0SsdBzI5lBw==} hasBin: true - loader-runner@4.3.2: - resolution: {integrity: sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==} - engines: {node: '>=6.11.5'} - loader-utils@2.0.4: resolution: {integrity: sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==} engines: {node: '>=8.9.0'} @@ -6309,6 +6359,9 @@ packages: lodash.isstring@4.0.1: resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + lodash.once@4.1.1: resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} @@ -6322,9 +6375,9 @@ packages: resolution: {integrity: sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==} engines: {node: '>=18'} - log-update@6.1.0: - resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} - engines: {node: '>=18'} + log-update@8.0.0: + resolution: {integrity: sha512-lddSgOt3bPASrylL54ZSpy8nBHns+vBVSoILlVOx+dei300pnLRN958rj/EdlVLKuWlSESU3qdnDZdAI7FXYGg==} + engines: {node: '>=22'} log4js@6.9.1: resolution: {integrity: sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==} @@ -6361,8 +6414,8 @@ packages: magic-string@1.0.0: resolution: {integrity: sha512-CGvjzMN08iv6w1mm4/x3Gh1hLb4VnyRUA15FFpl6CsCIGGoe36k7kY5KNz9QDbSBN5I/fWHM6ZlIkUTa5xdUEA==} - magicast@0.5.3: - resolution: {integrity: sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==} + magicast@0.5.4: + resolution: {integrity: sha512-llBEhWm1SacoRwgHUoQJYtwp4PBLF4faQi5TCpIGyGs9n4y5+juI0tDgyKIfpqxckRHaHzouUEph3THklWh03w==} make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} @@ -6383,14 +6436,12 @@ packages: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} - media-typer@1.1.0: - resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} + media-typer@1.1.1: + resolution: {integrity: sha512-yz3xRaG20c6/BOzvYoDaGtPmGscs7YivItZEEqe6GbwNfHuxu9YNmvnEkMzKldAGY4/80pRcQRZSEnhquk9XuQ==} engines: {node: '>= 0.8'} - memfs@4.64.0: - resolution: {integrity: sha512-Kw72fgY7Wn+sD8KmtNWSafl1dz0UvAsE/PHs3YVfLiaZuA3HxNm9sRLqAu0ATiBGJvME1PxZXbBZPv5GycDeAw==} - peerDependencies: - tslib: '2' + memfs@4.68.1: + resolution: {integrity: sha512-OD+IDRUvIxu3QHL+nFm9gdyugInD27FDJ+sl4B5QgomPHXMlbw+GP918P8VNKu2FkNlVeqBkpzkwROpamVifRw==} merge-descriptors@1.0.3: resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} @@ -6466,8 +6517,8 @@ packages: minimalistic-assert@1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} - minimatch@10.2.5: - resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + minimatch@10.2.6: + resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} engines: {node: 18 || 20 || >=22} minimatch@3.1.5: @@ -6579,14 +6630,19 @@ packages: resolution: {integrity: sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==} engines: {node: ^20.17.0 || >=22.9.0} - nanoid@3.3.16: - resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} + nanoid@3.3.18: + resolution: {integrity: sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + needle@2.9.1: + resolution: {integrity: sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==} + engines: {node: '>= 4.4.x'} + hasBin: true + needle@3.5.0: resolution: {integrity: sha512-jaQyPKKk2YokHrEg+vFDYxXIHTCBgiZwSHOoVx/8V3GIBS8/VN6NdVRmg8q1ERtPkMvmOvebsgga4sAj5hls/w==} engines: {node: '>= 4.4.x'} @@ -6600,19 +6656,19 @@ packages: resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} engines: {node: '>= 0.6'} - negotiator@1.0.0: - resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} - engines: {node: '>= 0.6'} + negotiator@1.1.0: + resolution: {integrity: sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==} + engines: {node: '>=18'} neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - ng-packagr@22.1.0-next.3: - resolution: {integrity: sha512-wl36HBl2TCU2O4JOl4iGeKALBtkX1yaiW/GEnzYiTLuQQqlNSuhUWFFl9Y/nzrcnjKlcJkg2CoKdF+PSu8amfg==} + ng-packagr@22.1.1: + resolution: {integrity: sha512-jZzpQckw2SFvuYI3aWfYMefSVKKG/04E+vrX2KD6coMx7ciLBotVWuLc0331Fjb6XNmAVcsmgQ5NY/Lf+9Himw==} engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0} hasBin: true peerDependencies: - '@angular/compiler-cli': ^22.1.0-next + '@angular/compiler-cli': ^22.0.0 || ^22.1.0-next || ^22.2.0-next tailwindcss: ^2.0.0 || ^3.0.0 || ^4.0.0 tslib: ^2.3.0 typescript: '>=6.0 <6.1' @@ -6620,8 +6676,8 @@ packages: tailwindcss: optional: true - nock@14.0.16: - resolution: {integrity: sha512-8r4KEc6nT1D/fdLD/R1BO1CPaVEL8o40u/guFRJlXabN7vr3RmMqyjsY5Krt0nMwhsOAwXQ/mtN5vy5Jh3aErg==} + nock@14.0.17: + resolution: {integrity: sha512-EjRr1weMa4ALQX35AgZTEnP+weJJjlW1KGDiNM2IQC2069YDHas4f4B4UUYR+TTLyKWxJvOz2wObDKQs/LNreA==} engines: {node: '>=18.20.0 <20 || >=20.12.1'} node-addon-api@6.1.0: @@ -6663,8 +6719,8 @@ packages: resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} hasBin: true - node-releases@2.0.51: - resolution: {integrity: sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==} + node-releases@2.0.53: + resolution: {integrity: sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==} engines: {node: '>=18'} normalize-path@3.0.0: @@ -6778,8 +6834,8 @@ packages: resolution: {integrity: sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg==} engines: {node: '>= 0.4'} - oxc-parser@0.140.0: - resolution: {integrity: sha512-h6QFWd6lBMfjESqgQ27GjzrSDb0qbznp7VDQqp2zvgsrWut4vcchyMIzOVXvGQ2GMZgKw9RWrFNWv9WqGL0p7Q==} + oxc-parser@0.142.0: + resolution: {integrity: sha512-kKR+jPiRJYJDexVoziIg/FVGvr1fT1FZSSJOk6tVoMKKSlsf1Cso+cgGCJkOEDWOP174vRntCPFKg+AS7InWvw==} engines: {node: ^20.19.0 || >=22.12.0} p-cancelable@2.1.1: @@ -6992,15 +7048,15 @@ packages: peerDependencies: postcss: ^8.4.31 - postcss-selector-parser@7.1.4: - resolution: {integrity: sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg==} + postcss-selector-parser@7.1.5: + resolution: {integrity: sha512-KvvtD7SrlBP7dlgkBghEE3r84CABm5SmV2aNcG4oCA+qDnJ/tvKonFVvwWAyyWUEwxuNawdfEAZKP9zM3oZ2Uw==} engines: {node: '>=4'} postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.5.19: - resolution: {integrity: sha512-Mz8SaolMd8nB+G13WkORcxQKHZ/NE4xXevtkJHVuG+guo9/wYKlIMTKAqGdEmYOXR2ijPjTYNHssizdaVSUNdQ==} + postcss@8.5.25: + resolution: {integrity: sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==} engines: {node: ^10 || ^12 || >=14} powershell-utils@0.1.0: @@ -7016,6 +7072,9 @@ packages: engines: {node: '>=14'} hasBin: true + probe-image-size@7.4.0: + resolution: {integrity: sha512-cdEprVtZxV+awMde9X+4jILBFYh4CARxVrQaMl4wY4YcPWbul9jntXrIW95NInBDyJwcVUP3U0T6yukN8rMBaQ==} + proc-log@7.0.0: resolution: {integrity: sha512-FYgfaA69XZ93zaXLoMNQ+ViDXGGBgR8aLh03txzcFhV+9xOXx7+8DLCULrKKpR9+GsH9ZfHm82aSUPpozX0Ztg==} engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} @@ -7026,8 +7085,8 @@ packages: process-warning@1.0.0: resolution: {integrity: sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==} - process-warning@5.0.0: - resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} + process-warning@5.1.0: + resolution: {integrity: sha512-jQSaVHsPgtyw60e1rQ/A+/ArPEj/S8pS/vFnyGa/gYFXrKk/6RuDkoqVDQ5NI5MmS01698ltlAk0NoDBNLujRw==} process@0.11.10: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} @@ -7089,8 +7148,8 @@ packages: pvtsutils@1.3.6: resolution: {integrity: sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==} - pvutils@1.1.5: - resolution: {integrity: sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==} + pvutils@1.2.0: + resolution: {integrity: sha512-BbubeCEyTuQjVMakvJQ/Sxbc93F2pwmbsxONT/ZRrwU7Ua38d8unYTwXpTVLAKJ4BDuH9IGztCjQcd/N/39Dvg==} engines: {node: '>=16.0.0'} qjobs@1.2.0: @@ -7135,8 +7194,9 @@ packages: resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} engines: {node: '>= 0.10'} - re2js@0.4.3: - resolution: {integrity: sha512-EuNmh7jurhHEE8Ge/lBo9JuMLb3qf866Xjjfyovw3wPc7+hlqDkZq4LwhrCQMEI+ARWfrKrHozEndzlpNT0WDg==} + re2js@2.8.6: + resolution: {integrity: sha512-xLgQil4kIUCrAzVk9fRSkxkFNwmygLFjVxXrLc65aE1F0+Zsb8rxumFBy4XKyvgMCTL6kilDq3EZ0piE2dP/Dg==} + engines: {node: '>=18.0.0'} readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} @@ -7157,8 +7217,8 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} - readdirp@5.0.0: - resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} + readdirp@5.1.1: + resolution: {integrity: sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==} engines: {node: '>= 20.19.0'} real-require@0.2.0: @@ -7240,8 +7300,8 @@ packages: resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} engines: {node: '>=18'} - retry-request@8.0.3: - resolution: {integrity: sha512-qqoc4kkGgP9cmQDWELlOpAmfgJOg0Yi7MT82ZjiPWu451ayju4itwomjM4/dBEliify8C1b3tSaeCOldugtwPQ==} + retry-request@8.0.4: + resolution: {integrity: sha512-pI6/7eabUYkZxamkOq0g0uMxKLLGnjzhefY+vL8bVXag5rto4OU2YBTPytWLuHH7aEKD6fn7kJycQfid0Mwnkw==} engines: {node: '>=18'} retry@0.13.1: @@ -7368,8 +7428,8 @@ packages: engines: {node: '>=20.19.0'} hasBin: true - sax@1.6.0: - resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} + sax@1.6.1: + resolution: {integrity: sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==} engines: {node: '>=11.0.0'} saxes@6.0.0: @@ -7409,8 +7469,8 @@ packages: resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} engines: {node: '>= 18'} - serialize-javascript@7.0.7: - resolution: {integrity: sha512-YAy8Od6KV+uuwUuU50np8fGB/Aues6Y0nAhA9y/hId74PlKUcme4pXcBD46NWKr1Q4osN/iseZ17YqO1XfmI8g==} + serialize-javascript@7.1.0: + resolution: {integrity: sha512-RNEqWOyhhUQYN9V1GfHwu9AR/g+NTciH6Z5u3/no6X3/w+04J2lVDL+svFQVXgXrEGBMG2puMVN3gq2SNGuTGw==} engines: {node: '>=20.0.0'} serve-index@1.9.2: @@ -7489,13 +7549,9 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} - slice-ansi@7.1.2: - resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} - engines: {node: '>=18'} - - slice-ansi@8.0.0: - resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==} - engines: {node: '>=20'} + slice-ansi@9.0.0: + resolution: {integrity: sha512-SO/3iYL5S3W57LLEniscOGPZgOqZUPCx6d3dB+52B80yJ0XstzsC/eV8gnA4tM3MHDrKz+OCFSLNjswdSC+/bA==} + engines: {node: '>=22'} socket.io-adapter@2.5.8: resolution: {integrity: sha512-6Oy52pbg+kvdCVvjcN+FnY7BvxZ7cIHNScbvztT/It5d0vbwoJoVZmF2gjJmnV0/4WlXRfG15zc45ySk9Ah8bw==} @@ -7615,6 +7671,9 @@ packages: stream-events@1.0.5: resolution: {integrity: sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==} + stream-parser@0.3.1: + resolution: {integrity: sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ==} + stream-shift@1.0.3: resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==} @@ -7686,9 +7745,9 @@ packages: stubs@3.0.0: resolution: {integrity: sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==} - supports-color@10.2.2: - resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==} - engines: {node: '>=18'} + supports-color@11.0.0: + resolution: {integrity: sha512-/zyImLdxhdygBIaVX0xTlQhKaCDLCrm665aqHk8xqK/Pa6k61fL6gwQGQq1k31yNyz6x55PppQgF2DMyPQa5xw==} + engines: {node: '>=22'} supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} @@ -7715,8 +7774,8 @@ packages: tar-stream@3.2.0: resolution: {integrity: sha512-ojzvCvVaNp6aOTFmG7jaRD0meowIAuPc3cMMhSgKiVWws1GyHbGd/xvnyuRKcKlMpt3qvxx6r0hreCNITP9hIg==} - teeny-request@10.1.3: - resolution: {integrity: sha512-5yDliI1uWkYPo7W+Zvrxg6YmoWuj5iC5EydewqrRTvc68nyMTZhlPPlLg6cptUGfbQAb+N9XDPDPzF6N081lug==} + teeny-request@10.1.4: + resolution: {integrity: sha512-R1Cg4Vu0UULeDfHL/kjABLaTW++9yD/B6n2g48y5dJ04hsEaxcfmAqbNDzNsbqAYJyIpZafjklLG9YxRu9uzOg==} engines: {node: '>=18'} teex@1.0.1: @@ -7730,8 +7789,8 @@ packages: text-decoder@1.2.7: resolution: {integrity: sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==} - thingies@2.6.0: - resolution: {integrity: sha512-rMHRjmlFLM1R96UYPvpmnc3LYtdFrT33JIB7L9hetGue1qAPfn1N2LJeEjxUSidu1Iku+haLZXDuEXUHNGO/lg==} + thingies@2.6.1: + resolution: {integrity: sha512-cV/CMGTK3M4MlnJ/0At6ismOw/A0EEniDNScajjz/Br3c1sqE72YD01rGpPTKwd27wAxI5Pr+6+0w8yofzFRYw==} engines: {node: '>=10.18'} peerDependencies: tslib: ^2 @@ -7757,30 +7816,30 @@ packages: tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - tinyexec@1.2.4: - resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} + tinyexec@1.3.0: + resolution: {integrity: sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==} engines: {node: '>=18'} tinyglobby@0.2.17: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} - tinyrainbow@3.1.0: - resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} + tinyrainbow@3.1.1: + resolution: {integrity: sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==} engines: {node: '>=14.0.0'} tldts-core@6.1.86: resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} - tldts-core@7.4.9: - resolution: {integrity: sha512-DxKfPBI52p2msTEu7MPhdpdDTBhhVQg1a/8PjQckeyAvO13eMYElX545grIp6nnTGIMZlRvFZPvFhvI/WIz2Vg==} + tldts-core@7.4.10: + resolution: {integrity: sha512-KnQjp53ZekKgm/r3l+u8kJGGzYgrWdP8+Mql7a4vijh2WE0IrZWspQj/TpTxDho/YxO+AnOZnIjQcCD+q6iJsw==} tldts@6.1.86: resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} hasBin: true - tldts@7.4.9: - resolution: {integrity: sha512-3kZ8wQQ/k5DrChD4X4FVvr2D7E5uoRgAqkPyLpSCGUvqOvqu+JEdr3mwMUaVWb+vMHZaKhF5fp2PBigKsui7hA==} + tldts@7.4.10: + resolution: {integrity: sha512-GgouD1B+sWwvkaEq8vXC15DjQitxbvs12oIXELpconwm+Tg3zfcEv4jgzq3vtKverDXsg3VI8aRgNL2Nra0Iog==} hasBin: true tmp@0.2.7: @@ -7838,8 +7897,8 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tsx@4.23.1: - resolution: {integrity: sha512-GQHnkIfxyx1wYCOS/wonik5MVRZU9hi1TEZmzGZSCJB1y9YgoZ8H6itNE/u4suE+yLmOzuE4E5S4TZ/ZX2wcWQ==} + tsx@4.23.12: + resolution: {integrity: sha512-FDf4L4sYzKtzWYhU/Xm0AQFdTjdIxNo9ElTf2mxXM6k8YMHXzYUe4yODVaXP4V9uMFbVg8c0qyBccK2OOxb45Q==} engines: {node: '>=18.0.0'} hasBin: true @@ -7925,12 +7984,12 @@ packages: undici-types@7.18.2: resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} - undici@6.27.0: - resolution: {integrity: sha512-YmfV3YnEDzXRC5lZ2jWtWWHKGUm1zIt8AhesR1tens+HTNv+YZlN/dp6G727LOvMJ8xjP9Be7Y2Sdr96LDm+pg==} + undici@6.28.0: + resolution: {integrity: sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==} engines: {node: '>=18.17'} - undici@7.28.0: - resolution: {integrity: sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==} + undici@7.29.0: + resolution: {integrity: sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==} engines: {node: '>=20.18.1'} undici@8.7.0: @@ -7979,8 +8038,8 @@ packages: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} - update-browserslist-db@1.2.3: - resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + update-browserslist-db@1.3.1: + resolution: {integrity: sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -8026,9 +8085,9 @@ packages: resolution: {integrity: sha512-n5VYOooGpXr3ZE2DjNx6lJPkCFd2sORDVMmbs0o7Mqx6g0kOHTkfkY5DygZAwOvGtFy0CecufRrl49RzAD9Jkg==} engines: {node: '>=18'} - verdaccio-auth-memory@13.0.3: - resolution: {integrity: sha512-EXzDLxTfpm7/B0TEAUKHgi/ygWqjNAyQ+O2rGAF9WONMZY99LVPmf7IpGoKMWCarf2L+nuKVxJ9hbyQeFbyysQ==} - engines: {node: '>=18'} + verdaccio-auth-memory@13.1.2: + resolution: {integrity: sha512-Z5CH/iUa37QmaNt+nbgvyjojyQ6WZA0r06ymsGjor8xCqFBzGtIlLsM8Es0Njh/fU06r928RcsfEjha7zFqv1w==} + engines: {node: '>=22'} verdaccio-htpasswd@13.0.3: resolution: {integrity: sha512-xh0VO4zRfcbIR2bpH2SwW4kLHzCEKFYg9lykpuEENJ9OIcoc12mGXH5DTuOuJ9po8Y0mGTzFh3JUZIwXJlmOSw==} @@ -8210,8 +8269,8 @@ packages: html-webpack-plugin: optional: true - webpack@5.108.4: - resolution: {integrity: sha512-yur8LyJoeiWh47dErD+Ok7vlbmDsJ3UbbRPAoxbGJ54WpE2y5yVo5G/inUzujnYgw3tPmBRdn+G7PoxXaYC33w==} + webpack@5.109.2: + resolution: {integrity: sha512-U9/cvLzxObKNEZ9+TtdqrHM5/9z3lgl2c+c4BzbqGxFQvQvBAq87yql5A8pQ+rrMbS496MZJeF5enVBndIy2hw==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -8284,8 +8343,8 @@ packages: wordwrap@1.0.0: resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - wrap-ansi@10.0.0: - resolution: {integrity: sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ==} + wrap-ansi@10.0.1: + resolution: {integrity: sha512-M0N4xzyzosiIok3svYlEo1sdLZts/8FPgYH/GPC3wvlmPoRvnoManGMrE54waYj3tISA8w6lsdesfVv67qSr8Q==} engines: {node: '>=20'} wrap-ansi@7.0.0: @@ -8303,8 +8362,8 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - ws@8.21.1: - resolution: {integrity: sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==} + ws@8.21.3: + resolution: {integrity: sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -8374,16 +8433,16 @@ packages: resolution: {integrity: sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==} engines: {node: '>=12'} - yargs@18.0.0: - resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} + yargs@18.1.0: + resolution: {integrity: sha512-2rAgRKu54VsHkqI0/tYkmluGXHD4KW7yZoycuqDQ15QOTnc2VVfy0nN/1eMhnQLO00A+dwtK20xuCnc1YGeUyg==} engines: {node: ^20.19.0 || ^22.12.0 || >=23} yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - yoctocolors@2.1.2: - resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} + yoctocolors@2.2.0: + resolution: {integrity: sha512-xYqdZFUK/VYazNl/oCDYN+3WloWQwMfZxBoiNt6qNyk+xfOdi598muWE42rNZFp1kNOiqW936q5RhUdnpqElSg==} engines: {node: '>=18'} zod-to-json-schema@3.25.2: @@ -8414,7 +8473,7 @@ snapshots: '@actions/http-client@4.0.1': dependencies: tunnel: 0.0.6 - undici: 6.27.0 + undici: 6.28.0 '@actions/io@3.0.2': {} @@ -8423,29 +8482,29 @@ snapshots: '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 - '@angular/animations@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))': + '@angular/animations@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))': dependencies: - '@angular/core': 22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/core': 22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2) tslib: 2.8.1 - '@angular/cdk@22.1.0-next.4(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.0-rc.0(@angular/animations@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2)': + '@angular/cdk@22.1.4(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.4(@angular/animations@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2)': dependencies: - '@angular/common': 22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) - '@angular/core': 22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2) - '@angular/platform-browser': 22.1.0-rc.0(@angular/animations@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)) + '@angular/common': 22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/core': 22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/platform-browser': 22.1.4(@angular/animations@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)) parse5: 8.0.1 rxjs: 7.8.2 tslib: 2.8.1 - '@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2)': + '@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2)': dependencies: - '@angular/core': 22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/core': 22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2) rxjs: 7.8.2 tslib: 2.8.1 - '@angular/compiler-cli@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(typescript@6.0.3)': + '@angular/compiler-cli@22.1.4(@angular/compiler@22.1.4)(typescript@6.0.3)': dependencies: - '@angular/compiler': 22.1.0-rc.0 + '@angular/compiler': 22.1.4 '@babel/core': 8.0.1 '@jridgewell/sourcemap-codec': 1.5.5 chokidar: 5.0.0 @@ -8453,68 +8512,68 @@ snapshots: reflect-metadata: 0.2.2 semver: 7.8.5 tslib: 2.8.1 - yargs: 18.0.0 + yargs: 18.1.0 optionalDependencies: typescript: 6.0.3 - '@angular/compiler@22.1.0-rc.0': + '@angular/compiler@22.1.4': dependencies: tslib: 2.8.1 - '@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)': + '@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)': dependencies: rxjs: 7.8.2 tslib: 2.8.1 optionalDependencies: - '@angular/compiler': 22.1.0-rc.0 + '@angular/compiler': 22.1.4 zone.js: 0.16.2 - '@angular/forms@22.1.0-rc.0(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.0-rc.0(@angular/animations@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2)': + '@angular/forms@22.1.4(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.4(@angular/animations@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2)': dependencies: - '@angular/common': 22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) - '@angular/core': 22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2) - '@angular/platform-browser': 22.1.0-rc.0(@angular/animations@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)) + '@angular/common': 22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/core': 22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/platform-browser': 22.1.4(@angular/animations@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)) '@standard-schema/spec': 1.1.0 rxjs: 7.8.2 tslib: 2.8.1 zod: 4.4.3 - '@angular/localize@22.1.0-rc.0(@angular/compiler-cli@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(typescript@6.0.3))(@angular/compiler@22.1.0-rc.0)': + '@angular/localize@22.1.4(@angular/compiler-cli@22.1.4(@angular/compiler@22.1.4)(typescript@6.0.3))(@angular/compiler@22.1.4)': dependencies: - '@angular/compiler': 22.1.0-rc.0 - '@angular/compiler-cli': 22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(typescript@6.0.3) + '@angular/compiler': 22.1.4 + '@angular/compiler-cli': 22.1.4(@angular/compiler@22.1.4)(typescript@6.0.3) '@babel/core': 8.0.1 tinyglobby: 0.2.17 - yargs: 18.0.0 + yargs: 18.1.0 - '@angular/material@22.1.0-next.4(4ff7080c77e2fe320ac430b9737f79ee)': + '@angular/material@22.1.4(37c77e13676b90a7dcd0d6f9cc058167)': dependencies: - '@angular/cdk': 22.1.0-next.4(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.0-rc.0(@angular/animations@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) - '@angular/common': 22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) - '@angular/core': 22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2) - '@angular/forms': 22.1.0-rc.0(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.0-rc.0(@angular/animations@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) - '@angular/platform-browser': 22.1.0-rc.0(@angular/animations@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)) + '@angular/cdk': 22.1.4(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.4(@angular/animations@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) + '@angular/common': 22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/core': 22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/forms': 22.1.4(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.4(@angular/animations@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) + '@angular/platform-browser': 22.1.4(@angular/animations@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)) rxjs: 7.8.2 tslib: 2.8.1 - '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/7a67d5221a9efec2b69b102759d04223a3fc8552(@modelcontextprotocol/sdk@1.29.0(supports-color@10.2.2)(zod@4.4.3))': + '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/beec8fe17573a33c9934487ce99ce9cce3e3f6bf(@modelcontextprotocol/sdk@1.30.0(supports-color@11.0.0)(zod@4.4.3))': dependencies: '@actions/core': 3.0.1 - '@conventional-changelog/git-client': 3.1.0(conventional-commits-filter@6.0.1)(conventional-commits-parser@7.1.0) - '@google-cloud/spanner': 8.0.0(supports-color@10.2.2) - '@google/genai': 2.12.0(@modelcontextprotocol/sdk@1.29.0(supports-color@10.2.2)(zod@4.4.3))(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) + '@conventional-changelog/git-client': 3.1.2(conventional-commits-filter@6.0.1)(conventional-commits-parser@7.1.2) + '@google-cloud/spanner': 8.0.0(supports-color@11.0.0) + '@google/genai': 2.17.1(@modelcontextprotocol/sdk@1.30.0(supports-color@11.0.0)(zod@4.4.3))(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6) '@inquirer/prompts': 8.5.2(@types/node@24.13.3) '@inquirer/type': 4.0.7(@types/node@24.13.3) - '@octokit/auth-app': 8.2.0 - '@octokit/core': 7.0.6 - '@octokit/graphql': 9.0.3 + '@octokit/auth-app': 8.3.0 + '@octokit/core': 7.0.7 + '@octokit/graphql': 9.0.4 '@octokit/graphql-schema': 15.26.1 - '@octokit/openapi-types': 27.0.0 - '@octokit/plugin-paginate-rest': 14.0.0(@octokit/core@7.0.6) - '@octokit/plugin-rest-endpoint-methods': 17.0.0(@octokit/core@7.0.6) - '@octokit/request-error': 7.1.0 + '@octokit/openapi-types': 28.0.0 + '@octokit/plugin-paginate-rest': 15.0.0(@octokit/core@7.0.7) + '@octokit/plugin-rest-endpoint-methods': 18.0.0(@octokit/core@7.0.7) + '@octokit/request-error': 7.1.1 '@octokit/rest': 22.0.1 - '@octokit/types': 16.0.0 + '@octokit/types': 17.0.0 '@pnpm/dependency-path': 1001.1.10 '@types/cli-progress': 3.11.6 '@types/ejs': 3.1.5 @@ -8522,7 +8581,7 @@ snapshots: '@types/folder-hash': 4.0.4 '@types/jasmine': 6.0.0 '@types/node': 24.13.3 - '@types/semver': 7.7.1 + '@types/semver': 7.8.0 '@types/which': 3.0.4 '@types/yargs': 17.0.35 '@types/yarnpkg__lockfile': 1.1.9 @@ -8530,70 +8589,70 @@ snapshots: bufferutil: 4.1.0 cli-progress: 3.12.0 conventional-commits-filter: 6.0.1 - conventional-commits-parser: 7.1.0 + conventional-commits-parser: 7.1.2 ejs: 6.0.1 encoding: 0.1.13 fast-glob: 3.3.3 - firebase: 12.16.0 - folder-hash: 4.1.3(supports-color@10.2.2) + firebase: 12.17.1 + folder-hash: 4.1.3(supports-color@11.0.0) jasmine: 6.3.0 jasmine-core: 6.3.0 jasmine-reporters: 2.5.2 jsonc-parser: 3.3.1 - minimatch: 10.2.5 + minimatch: 10.2.6 multimatch: 8.0.0 - nock: 14.0.16 + nock: 14.0.17 semver: 7.8.5 - supports-color: 10.2.2 - tsx: 4.23.1 + supports-color: 11.0.0 + tsx: 4.23.12 typed-graphqlify: 3.1.6 typescript: 6.0.3 utf-8-validate: 6.0.6 which: 7.0.0 yaml: 2.9.0 - yargs: 18.0.0 + yargs: 18.1.0 zod: 4.4.3 transitivePeerDependencies: - '@modelcontextprotocol/sdk' - '@react-native-async-storage/async-storage' - '@angular/platform-browser@22.1.0-rc.0(@angular/animations@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))': + '@angular/platform-browser@22.1.4(@angular/animations@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))': dependencies: - '@angular/common': 22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) - '@angular/core': 22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/common': 22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/core': 22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2) tslib: 2.8.1 optionalDependencies: - '@angular/animations': 22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)) + '@angular/animations': 22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)) - '@angular/platform-server@22.1.0-rc.0(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/compiler@22.1.0-rc.0)(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.0-rc.0(@angular/animations@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2)': + '@angular/platform-server@22.1.4(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/compiler@22.1.4)(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.4(@angular/animations@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2)': dependencies: - '@angular/common': 22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) - '@angular/compiler': 22.1.0-rc.0 - '@angular/core': 22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2) - '@angular/platform-browser': 22.1.0-rc.0(@angular/animations@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)) + '@angular/common': 22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/compiler': 22.1.4 + '@angular/core': 22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/platform-browser': 22.1.4(@angular/animations@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)) rxjs: 7.8.2 tslib: 2.8.1 xhr2: 0.2.1 - '@angular/router@22.1.0-rc.0(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.0-rc.0(@angular/animations@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2)': + '@angular/router@22.1.4(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.1.4(@angular/animations@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2)': dependencies: - '@angular/common': 22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) - '@angular/core': 22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2) - '@angular/platform-browser': 22.1.0-rc.0(@angular/animations@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2)) + '@angular/common': 22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/core': 22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/platform-browser': 22.1.4(@angular/animations@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2)) rxjs: 7.8.2 tslib: 2.8.1 - '@angular/service-worker@22.1.0-rc.0(@angular/core@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2)': + '@angular/service-worker@22.1.4(@angular/core@22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2)': dependencies: - '@angular/core': 22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/core': 22.1.4(@angular/compiler@22.1.4)(rxjs@7.8.2)(zone.js@0.16.2) rxjs: 7.8.2 tslib: 2.8.1 '@asamuzakjp/css-color@5.1.11': dependencies: '@asamuzakjp/generational-cache': 1.0.1 - '@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - '@csstools/css-color-parser': 4.1.9(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-calc': 3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-color-parser': 4.2.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) '@csstools/css-tokenizer': 4.0.0 @@ -8624,20 +8683,20 @@ snapshots: '@babel/compat-data@8.0.0': {} - '@babel/core@7.29.7(supports-color@10.2.2)': + '@babel/core@7.29.7(supports-color@11.0.0)': dependencies: '@babel/code-frame': 7.29.7 - '@babel/generator': 7.29.7 + '@babel/generator': 7.29.8 '@babel/helper-compilation-targets': 7.29.7 - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@11.0.0))(supports-color@11.0.0) '@babel/helpers': 7.29.7 - '@babel/parser': 7.29.7 + '@babel/parser': 7.29.8 '@babel/template': 7.29.7 - '@babel/traverse': 7.29.7(supports-color@10.2.2) - '@babel/types': 7.29.7 + '@babel/traverse': 7.29.8(supports-color@11.0.0) + '@babel/types': 7.29.8 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -8663,10 +8722,10 @@ snapshots: obug: 2.1.4 semver: 7.8.5 - '@babel/generator@7.29.7': + '@babel/generator@7.29.8': dependencies: - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 @@ -8688,7 +8747,7 @@ snapshots: dependencies: '@babel/compat-data': 7.29.7 '@babel/helper-validator-option': 7.29.7 - browserslist: 4.28.7 + browserslist: 4.28.8 lru-cache: 5.1.1 semver: 6.3.1 @@ -8696,7 +8755,7 @@ snapshots: dependencies: '@babel/compat-data': 8.0.0 '@babel/helper-validator-option': 8.0.0 - browserslist: 4.28.7 + browserslist: 4.28.8 lru-cache: 11.5.2 semver: 7.8.5 @@ -8734,10 +8793,10 @@ snapshots: '@babel/traverse': 8.0.4 '@babel/types': 8.0.4 - '@babel/helper-module-imports@7.29.7(supports-color@10.2.2)': + '@babel/helper-module-imports@7.29.7(supports-color@11.0.0)': dependencies: - '@babel/traverse': 7.29.7(supports-color@10.2.2) - '@babel/types': 7.29.7 + '@babel/traverse': 7.29.8(supports-color@11.0.0) + '@babel/types': 7.29.8 transitivePeerDependencies: - supports-color @@ -8746,12 +8805,12 @@ snapshots: '@babel/traverse': 8.0.4 '@babel/types': 8.0.4 - '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)': + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7(supports-color@11.0.0))(supports-color@11.0.0)': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/helper-module-imports': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@11.0.0) + '@babel/helper-module-imports': 7.29.7(supports-color@11.0.0) '@babel/helper-validator-identifier': 7.29.7 - '@babel/traverse': 7.29.7(supports-color@10.2.2) + '@babel/traverse': 7.29.8(supports-color@11.0.0) transitivePeerDependencies: - supports-color @@ -8791,7 +8850,7 @@ snapshots: '@babel/helper-split-export-declaration@7.24.7': dependencies: - '@babel/types': 7.29.7 + '@babel/types': 7.29.8 '@babel/helper-string-parser@7.29.7': {} @@ -8814,16 +8873,16 @@ snapshots: '@babel/helpers@7.29.7': dependencies: '@babel/template': 7.29.7 - '@babel/types': 7.29.7 + '@babel/types': 7.29.8 '@babel/helpers@8.0.0': dependencies: '@babel/template': 8.0.0 '@babel/types': 8.0.4 - '@babel/parser@7.29.7': + '@babel/parser@7.29.8': dependencies: - '@babel/types': 7.29.7 + '@babel/types': 7.29.8 '@babel/parser@8.0.4': dependencies: @@ -9224,7 +9283,7 @@ snapshots: '@babel/plugin-transform-unicode-sets-regex': 8.0.1(@babel/core@8.0.1) '@babel/preset-modules': 0.2.0(@babel/core@8.0.1) babel-plugin-polyfill-corejs3: 1.0.0(@babel/core@8.0.1) - core-js-compat: 3.49.0 + core-js-compat: 3.50.0 semver: 7.8.5 '@babel/preset-modules@0.2.0(@babel/core@8.0.1)': @@ -9241,8 +9300,8 @@ snapshots: '@babel/template@7.29.7': dependencies: '@babel/code-frame': 7.29.7 - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 '@babel/template@8.0.0': dependencies: @@ -9250,15 +9309,15 @@ snapshots: '@babel/parser': 8.0.4 '@babel/types': 8.0.4 - '@babel/traverse@7.29.7(supports-color@10.2.2)': + '@babel/traverse@7.29.8(supports-color@11.0.0)': dependencies: '@babel/code-frame': 7.29.7 - '@babel/generator': 7.29.7 + '@babel/generator': 7.29.8 '@babel/helper-globals': 7.29.7 - '@babel/parser': 7.29.7 + '@babel/parser': 7.29.8 '@babel/template': 7.29.7 - '@babel/types': 7.29.7 - debug: 4.4.3(supports-color@10.2.2) + '@babel/types': 7.29.8 + debug: 4.4.3(supports-color@11.0.0) transitivePeerDependencies: - supports-color @@ -9272,7 +9331,7 @@ snapshots: '@babel/types': 8.0.4 obug: 2.1.4 - '@babel/types@7.29.7': + '@babel/types@7.29.8': dependencies: '@babel/helper-string-parser': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 @@ -9296,26 +9355,26 @@ snapshots: '@colors/colors@1.5.0': {} - '@conventional-changelog/git-client@3.1.0(conventional-commits-filter@6.0.1)(conventional-commits-parser@7.1.0)': + '@conventional-changelog/git-client@3.1.2(conventional-commits-filter@6.0.1)(conventional-commits-parser@7.1.2)': dependencies: '@simple-libs/child-process-utils': 2.0.0 '@simple-libs/stream-utils': 2.0.0 semver: 7.8.5 optionalDependencies: conventional-commits-filter: 6.0.1 - conventional-commits-parser: 7.1.0 + conventional-commits-parser: 7.1.2 - '@csstools/color-helpers@6.1.0': {} + '@csstools/color-helpers@6.1.1': {} - '@csstools/css-calc@3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + '@csstools/css-calc@3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': dependencies: '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) '@csstools/css-tokenizer': 4.0.0 - '@csstools/css-color-parser@4.1.9(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + '@csstools/css-color-parser@4.2.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': dependencies: - '@csstools/color-helpers': 6.1.0 - '@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/color-helpers': 6.1.1 + '@csstools/css-calc': 3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) '@csstools/css-tokenizer': 4.0.0 @@ -9323,7 +9382,7 @@ snapshots: dependencies: '@csstools/css-tokenizer': 4.0.0 - '@csstools/css-syntax-patches-for-csstree@1.1.6(css-tree@3.2.1)': + '@csstools/css-syntax-patches-for-csstree@1.1.8(css-tree@3.2.1)': optionalDependencies: css-tree: 3.2.1 @@ -9379,102 +9438,102 @@ snapshots: tslib: 2.8.1 optional: true - '@esbuild/aix-ppc64@0.28.1': + '@esbuild/aix-ppc64@0.28.2': optional: true - '@esbuild/android-arm64@0.28.1': + '@esbuild/android-arm64@0.28.2': optional: true - '@esbuild/android-arm@0.28.1': + '@esbuild/android-arm@0.28.2': optional: true - '@esbuild/android-x64@0.28.1': + '@esbuild/android-x64@0.28.2': optional: true - '@esbuild/darwin-arm64@0.28.1': + '@esbuild/darwin-arm64@0.28.2': optional: true - '@esbuild/darwin-x64@0.28.1': + '@esbuild/darwin-x64@0.28.2': optional: true - '@esbuild/freebsd-arm64@0.28.1': + '@esbuild/freebsd-arm64@0.28.2': optional: true - '@esbuild/freebsd-x64@0.28.1': + '@esbuild/freebsd-x64@0.28.2': optional: true - '@esbuild/linux-arm64@0.28.1': + '@esbuild/linux-arm64@0.28.2': optional: true - '@esbuild/linux-arm@0.28.1': + '@esbuild/linux-arm@0.28.2': optional: true - '@esbuild/linux-ia32@0.28.1': + '@esbuild/linux-ia32@0.28.2': optional: true - '@esbuild/linux-loong64@0.28.1': + '@esbuild/linux-loong64@0.28.2': optional: true - '@esbuild/linux-mips64el@0.28.1': + '@esbuild/linux-mips64el@0.28.2': optional: true - '@esbuild/linux-ppc64@0.28.1': + '@esbuild/linux-ppc64@0.28.2': optional: true - '@esbuild/linux-riscv64@0.28.1': + '@esbuild/linux-riscv64@0.28.2': optional: true - '@esbuild/linux-s390x@0.28.1': + '@esbuild/linux-s390x@0.28.2': optional: true - '@esbuild/linux-x64@0.28.1': + '@esbuild/linux-x64@0.28.2': optional: true - '@esbuild/netbsd-arm64@0.28.1': + '@esbuild/netbsd-arm64@0.28.2': optional: true - '@esbuild/netbsd-x64@0.28.1': + '@esbuild/netbsd-x64@0.28.2': optional: true - '@esbuild/openbsd-arm64@0.28.1': + '@esbuild/openbsd-arm64@0.28.2': optional: true - '@esbuild/openbsd-x64@0.28.1': + '@esbuild/openbsd-x64@0.28.2': optional: true - '@esbuild/openharmony-arm64@0.28.1': + '@esbuild/openharmony-arm64@0.28.2': optional: true - '@esbuild/sunos-x64@0.28.1': + '@esbuild/sunos-x64@0.28.2': optional: true - '@esbuild/win32-arm64@0.28.1': + '@esbuild/win32-arm64@0.28.2': optional: true - '@esbuild/win32-ia32@0.28.1': + '@esbuild/win32-ia32@0.28.2': optional: true - '@esbuild/win32-x64@0.28.1': + '@esbuild/win32-x64@0.28.2': optional: true - '@eslint-community/eslint-utils@4.10.1(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))': + '@eslint-community/eslint-utils@4.10.1(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))': dependencies: - eslint: 10.7.0(jiti@2.7.0)(supports-color@10.2.2) + eslint: 10.7.0(jiti@2.7.0)(supports-color@11.0.0) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} - '@eslint/compat@2.1.0(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))': + '@eslint/compat@2.1.0(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))': dependencies: '@eslint/core': 1.2.1 optionalDependencies: - eslint: 10.7.0(jiti@2.7.0)(supports-color@10.2.2) + eslint: 10.7.0(jiti@2.7.0)(supports-color@11.0.0) - '@eslint/config-array@0.23.5(supports-color@10.2.2)': + '@eslint/config-array@0.23.5(supports-color@11.0.0)': dependencies: '@eslint/object-schema': 3.0.5 - debug: 4.4.3(supports-color@10.2.2) - minimatch: 10.2.5 + debug: 4.4.3(supports-color@11.0.0) + minimatch: 10.2.6 transitivePeerDependencies: - supports-color @@ -9486,23 +9545,23 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 - '@eslint/eslintrc@3.3.6(supports-color@10.2.2)': + '@eslint/eslintrc@3.3.6(supports-color@11.0.0)': dependencies: ajv: 6.15.0 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) espree: 10.4.0 globals: 14.0.0 ignore: 5.3.2 import-fresh: 3.3.1 - js-yaml: 4.3.0 + js-yaml: 4.3.1 minimatch: 3.1.5 strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color - '@eslint/js@10.0.1(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))': + '@eslint/js@10.0.1(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))': optionalDependencies: - eslint: 10.7.0(jiti@2.7.0)(supports-color@10.2.2) + eslint: 10.7.0(jiti@2.7.0)(supports-color@11.0.0) '@eslint/object-schema@3.0.5': {} @@ -9513,221 +9572,221 @@ snapshots: '@exodus/bytes@1.15.1': {} - '@firebase/ai@2.13.1(@firebase/app-types@0.9.5)(@firebase/app@0.15.1)': + '@firebase/ai@2.14.0(@firebase/app-types@0.9.5)(@firebase/app@0.16.0)': dependencies: - '@firebase/app': 0.15.1 + '@firebase/app': 0.16.0 '@firebase/app-check-interop-types': 0.3.4 '@firebase/app-types': 0.9.5 - '@firebase/component': 0.7.3 + '@firebase/component': 0.7.4 '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 tslib: 2.8.1 - '@firebase/analytics-compat@0.2.28(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1)': + '@firebase/analytics-compat@0.2.29(@firebase/app-compat@0.5.16)(@firebase/app@0.16.0)': dependencies: - '@firebase/analytics': 0.10.22(@firebase/app@0.15.1) + '@firebase/analytics': 0.10.23(@firebase/app@0.16.0) '@firebase/analytics-types': 0.8.4 - '@firebase/app-compat': 0.5.15 - '@firebase/component': 0.7.3 - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.0 + '@firebase/app-compat': 0.5.16 + '@firebase/component': 0.7.4 + '@firebase/util': 1.15.2 tslib: 2.8.1 - transitivePeerDependencies: - - '@firebase/app' '@firebase/analytics-types@0.8.4': {} - '@firebase/analytics@0.10.22(@firebase/app@0.15.1)': + '@firebase/analytics@0.10.23(@firebase/app@0.16.0)': dependencies: - '@firebase/app': 0.15.1 - '@firebase/component': 0.7.3 - '@firebase/installations': 0.6.22(@firebase/app@0.15.1) + '@firebase/app': 0.16.0 + '@firebase/component': 0.7.4 + '@firebase/installations': 0.6.23(@firebase/app@0.16.0) '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 tslib: 2.8.1 - '@firebase/app-check-compat@0.4.5(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1)': + '@firebase/app-check-compat@0.4.6(@firebase/app-compat@0.5.16)(@firebase/app@0.16.0)': dependencies: - '@firebase/app-check': 0.12.0(@firebase/app@0.15.1) + '@firebase/app': 0.16.0 + '@firebase/app-check': 0.13.0(@firebase/app@0.16.0) '@firebase/app-check-types': 0.5.4 - '@firebase/app-compat': 0.5.15 - '@firebase/component': 0.7.3 + '@firebase/app-compat': 0.5.16 + '@firebase/component': 0.7.4 '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 tslib: 2.8.1 - transitivePeerDependencies: - - '@firebase/app' '@firebase/app-check-interop-types@0.3.4': {} '@firebase/app-check-types@0.5.4': {} - '@firebase/app-check@0.12.0(@firebase/app@0.15.1)': + '@firebase/app-check@0.13.0(@firebase/app@0.16.0)': dependencies: - '@firebase/app': 0.15.1 - '@firebase/component': 0.7.3 + '@firebase/app': 0.16.0 + '@firebase/component': 0.7.4 '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 tslib: 2.8.1 - '@firebase/app-compat@0.5.15': + '@firebase/app-compat@0.5.16': dependencies: - '@firebase/app': 0.15.1 - '@firebase/component': 0.7.3 + '@firebase/app': 0.16.0 + '@firebase/component': 0.7.4 '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 tslib: 2.8.1 '@firebase/app-types@0.9.5': dependencies: '@firebase/logger': 0.5.1 - '@firebase/app@0.15.1': + '@firebase/app@0.16.0': dependencies: - '@firebase/component': 0.7.3 + '@firebase/component': 0.7.4 '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 idb: 7.1.1 tslib: 2.8.1 - '@firebase/auth-compat@0.6.8(@firebase/app-compat@0.5.15)(@firebase/app-types@0.9.5)(@firebase/app@0.15.1)': + '@firebase/auth-compat@0.6.9(@firebase/app-compat@0.5.16)(@firebase/app-types@0.9.5)(@firebase/app@0.16.0)': dependencies: - '@firebase/app-compat': 0.5.15 - '@firebase/auth': 1.13.3(@firebase/app@0.15.1) - '@firebase/auth-types': 0.13.1(@firebase/app-types@0.9.5)(@firebase/util@1.15.1) - '@firebase/component': 0.7.3 - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.0 + '@firebase/app-compat': 0.5.16 + '@firebase/auth': 1.13.4(@firebase/app@0.16.0) + '@firebase/auth-types': 0.13.1(@firebase/app-types@0.9.5)(@firebase/util@1.15.2) + '@firebase/component': 0.7.4 + '@firebase/util': 1.15.2 tslib: 2.8.1 transitivePeerDependencies: - - '@firebase/app' - '@firebase/app-types' - '@react-native-async-storage/async-storage' '@firebase/auth-interop-types@0.2.5': {} - '@firebase/auth-types@0.13.1(@firebase/app-types@0.9.5)(@firebase/util@1.15.1)': + '@firebase/auth-types@0.13.1(@firebase/app-types@0.9.5)(@firebase/util@1.15.2)': dependencies: '@firebase/app-types': 0.9.5 - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 - '@firebase/auth@1.13.3(@firebase/app@0.15.1)': + '@firebase/auth@1.13.4(@firebase/app@0.16.0)': dependencies: - '@firebase/app': 0.15.1 - '@firebase/component': 0.7.3 + '@firebase/app': 0.16.0 + '@firebase/component': 0.7.4 '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 tslib: 2.8.1 - '@firebase/component@0.7.3': + '@firebase/component@0.7.4': dependencies: - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 tslib: 2.8.1 - '@firebase/data-connect@0.7.1(@firebase/app@0.15.1)': + '@firebase/data-connect@0.7.3(@firebase/app@0.16.0)': dependencies: - '@firebase/app': 0.15.1 + '@firebase/app': 0.16.0 '@firebase/auth-interop-types': 0.2.5 - '@firebase/component': 0.7.3 + '@firebase/component': 0.7.4 '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 tslib: 2.8.1 - '@firebase/database-compat@2.1.4': + '@firebase/database-compat@2.1.6(@firebase/app-compat@0.5.16)(@firebase/app@0.16.0)': dependencies: - '@firebase/component': 0.7.3 - '@firebase/database': 1.1.3 - '@firebase/database-types': 1.0.20 + '@firebase/component': 0.7.4 + '@firebase/database': 1.1.4 + '@firebase/database-types': 1.0.21 '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 tslib: 2.8.1 + optionalDependencies: + '@firebase/app': 0.16.0 + '@firebase/app-compat': 0.5.16 - '@firebase/database-types@1.0.20': + '@firebase/database-types@1.0.21': dependencies: '@firebase/app-types': 0.9.5 - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 - '@firebase/database@1.1.3': + '@firebase/database@1.1.4': dependencies: '@firebase/app-check-interop-types': 0.3.4 '@firebase/auth-interop-types': 0.2.5 - '@firebase/component': 0.7.3 + '@firebase/component': 0.7.4 '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 faye-websocket: 0.11.4 tslib: 2.8.1 - '@firebase/firestore-compat@0.4.11(@firebase/app-compat@0.5.15)(@firebase/app-types@0.9.5)(@firebase/app@0.15.1)': + '@firebase/firestore-compat@0.4.12(@firebase/app-compat@0.5.16)(@firebase/app-types@0.9.5)(@firebase/app@0.16.0)': dependencies: - '@firebase/app-compat': 0.5.15 - '@firebase/component': 0.7.3 - '@firebase/firestore': 4.16.0(@firebase/app@0.15.1) - '@firebase/firestore-types': 3.0.4(@firebase/app-types@0.9.5)(@firebase/util@1.15.1) - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.0 + '@firebase/app-compat': 0.5.16 + '@firebase/component': 0.7.4 + '@firebase/firestore': 4.17.0(@firebase/app@0.16.0) + '@firebase/firestore-types': 3.0.4(@firebase/app-types@0.9.5)(@firebase/util@1.15.2) + '@firebase/util': 1.15.2 tslib: 2.8.1 transitivePeerDependencies: - - '@firebase/app' - '@firebase/app-types' - '@firebase/firestore-types@3.0.4(@firebase/app-types@0.9.5)(@firebase/util@1.15.1)': + '@firebase/firestore-types@3.0.4(@firebase/app-types@0.9.5)(@firebase/util@1.15.2)': dependencies: '@firebase/app-types': 0.9.5 - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 - '@firebase/firestore@4.16.0(@firebase/app@0.15.1)': + '@firebase/firestore@4.17.0(@firebase/app@0.16.0)': dependencies: - '@firebase/app': 0.15.1 - '@firebase/component': 0.7.3 + '@firebase/app': 0.16.0 + '@firebase/component': 0.7.4 '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 '@firebase/webchannel-wrapper': 1.0.6 '@grpc/grpc-js': 1.9.16 '@grpc/proto-loader': 0.7.15 - re2js: 0.4.3 + re2js: 2.8.6 tslib: 2.8.1 - '@firebase/functions-compat@0.4.5(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1)': + '@firebase/functions-compat@0.4.6(@firebase/app-compat@0.5.16)(@firebase/app@0.16.0)': dependencies: - '@firebase/app-compat': 0.5.15 - '@firebase/component': 0.7.3 - '@firebase/functions': 0.13.5(@firebase/app@0.15.1) + '@firebase/app': 0.16.0 + '@firebase/app-compat': 0.5.16 + '@firebase/component': 0.7.4 + '@firebase/functions': 0.13.6(@firebase/app@0.16.0) '@firebase/functions-types': 0.6.4 - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 tslib: 2.8.1 - transitivePeerDependencies: - - '@firebase/app' '@firebase/functions-types@0.6.4': {} - '@firebase/functions@0.13.5(@firebase/app@0.15.1)': + '@firebase/functions@0.13.6(@firebase/app@0.16.0)': dependencies: - '@firebase/app': 0.15.1 + '@firebase/app': 0.16.0 '@firebase/app-check-interop-types': 0.3.4 '@firebase/auth-interop-types': 0.2.5 - '@firebase/component': 0.7.3 + '@firebase/component': 0.7.4 '@firebase/messaging-interop-types': 0.2.5 - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 tslib: 2.8.1 - '@firebase/installations-compat@0.2.22(@firebase/app-compat@0.5.15)(@firebase/app-types@0.9.5)(@firebase/app@0.15.1)': + '@firebase/installations-compat@0.2.23(@firebase/app-compat@0.5.16)(@firebase/app-types@0.9.5)(@firebase/app@0.16.0)': dependencies: - '@firebase/app-compat': 0.5.15 - '@firebase/component': 0.7.3 - '@firebase/installations': 0.6.22(@firebase/app@0.15.1) + '@firebase/app': 0.16.0 + '@firebase/app-compat': 0.5.16 + '@firebase/component': 0.7.4 + '@firebase/installations': 0.6.23(@firebase/app@0.16.0) '@firebase/installations-types': 0.5.4(@firebase/app-types@0.9.5) - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 tslib: 2.8.1 transitivePeerDependencies: - - '@firebase/app' - '@firebase/app-types' '@firebase/installations-types@0.5.4(@firebase/app-types@0.9.5)': dependencies: '@firebase/app-types': 0.9.5 - '@firebase/installations@0.6.22(@firebase/app@0.15.1)': + '@firebase/installations@0.6.23(@firebase/app@0.16.0)': dependencies: - '@firebase/app': 0.15.1 - '@firebase/component': 0.7.3 - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.0 + '@firebase/component': 0.7.4 + '@firebase/util': 1.15.2 idb: 7.1.1 tslib: 2.8.1 @@ -9735,100 +9794,97 @@ snapshots: dependencies: tslib: 2.8.1 - '@firebase/messaging-compat@0.2.27(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1)': + '@firebase/messaging-compat@0.2.28(@firebase/app-compat@0.5.16)(@firebase/app@0.16.0)': dependencies: - '@firebase/app-compat': 0.5.15 - '@firebase/component': 0.7.3 - '@firebase/messaging': 0.13.0(@firebase/app@0.15.1) - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.0 + '@firebase/app-compat': 0.5.16 + '@firebase/component': 0.7.4 + '@firebase/messaging': 0.13.1(@firebase/app@0.16.0) + '@firebase/util': 1.15.2 tslib: 2.8.1 - transitivePeerDependencies: - - '@firebase/app' '@firebase/messaging-interop-types@0.2.5': {} - '@firebase/messaging@0.13.0(@firebase/app@0.15.1)': + '@firebase/messaging@0.13.1(@firebase/app@0.16.0)': dependencies: - '@firebase/app': 0.15.1 - '@firebase/component': 0.7.3 - '@firebase/installations': 0.6.22(@firebase/app@0.15.1) + '@firebase/app': 0.16.0 + '@firebase/component': 0.7.4 + '@firebase/installations': 0.6.23(@firebase/app@0.16.0) '@firebase/messaging-interop-types': 0.2.5 - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 idb: 7.1.1 tslib: 2.8.1 - '@firebase/performance-compat@0.2.25(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1)': + '@firebase/performance-compat@0.2.26(@firebase/app-compat@0.5.16)(@firebase/app@0.16.0)': dependencies: - '@firebase/app-compat': 0.5.15 - '@firebase/component': 0.7.3 + '@firebase/app': 0.16.0 + '@firebase/app-compat': 0.5.16 + '@firebase/component': 0.7.4 '@firebase/logger': 0.5.1 - '@firebase/performance': 0.7.12(@firebase/app@0.15.1) + '@firebase/performance': 0.7.13(@firebase/app@0.16.0) '@firebase/performance-types': 0.2.4 - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 tslib: 2.8.1 - transitivePeerDependencies: - - '@firebase/app' '@firebase/performance-types@0.2.4': {} - '@firebase/performance@0.7.12(@firebase/app@0.15.1)': + '@firebase/performance@0.7.13(@firebase/app@0.16.0)': dependencies: - '@firebase/app': 0.15.1 - '@firebase/component': 0.7.3 - '@firebase/installations': 0.6.22(@firebase/app@0.15.1) + '@firebase/app': 0.16.0 + '@firebase/component': 0.7.4 + '@firebase/installations': 0.6.23(@firebase/app@0.16.0) '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 tslib: 2.8.1 web-vitals: 4.2.4 - '@firebase/remote-config-compat@0.2.27(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1)': + '@firebase/remote-config-compat@0.2.28(@firebase/app-compat@0.5.16)(@firebase/app@0.16.0)': dependencies: - '@firebase/app-compat': 0.5.15 - '@firebase/component': 0.7.3 + '@firebase/app': 0.16.0 + '@firebase/app-compat': 0.5.16 + '@firebase/component': 0.7.4 '@firebase/logger': 0.5.1 - '@firebase/remote-config': 0.9.0(@firebase/app@0.15.1) + '@firebase/remote-config': 0.9.1(@firebase/app@0.16.0) '@firebase/remote-config-types': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 tslib: 2.8.1 - transitivePeerDependencies: - - '@firebase/app' '@firebase/remote-config-types@0.5.1': {} - '@firebase/remote-config@0.9.0(@firebase/app@0.15.1)': + '@firebase/remote-config@0.9.1(@firebase/app@0.16.0)': dependencies: - '@firebase/app': 0.15.1 - '@firebase/component': 0.7.3 - '@firebase/installations': 0.6.22(@firebase/app@0.15.1) + '@firebase/app': 0.16.0 + '@firebase/component': 0.7.4 + '@firebase/installations': 0.6.23(@firebase/app@0.16.0) '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 tslib: 2.8.1 - '@firebase/storage-compat@0.4.3(@firebase/app-compat@0.5.15)(@firebase/app-types@0.9.5)(@firebase/app@0.15.1)': + '@firebase/storage-compat@0.4.4(@firebase/app-compat@0.5.16)(@firebase/app-types@0.9.5)(@firebase/app@0.16.0)': dependencies: - '@firebase/app-compat': 0.5.15 - '@firebase/component': 0.7.3 - '@firebase/storage': 0.14.3(@firebase/app@0.15.1) - '@firebase/storage-types': 0.8.4(@firebase/app-types@0.9.5)(@firebase/util@1.15.1) - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.0 + '@firebase/app-compat': 0.5.16 + '@firebase/component': 0.7.4 + '@firebase/storage': 0.14.4(@firebase/app@0.16.0) + '@firebase/storage-types': 0.8.4(@firebase/app-types@0.9.5)(@firebase/util@1.15.2) + '@firebase/util': 1.15.2 tslib: 2.8.1 transitivePeerDependencies: - - '@firebase/app' - '@firebase/app-types' - '@firebase/storage-types@0.8.4(@firebase/app-types@0.9.5)(@firebase/util@1.15.1)': + '@firebase/storage-types@0.8.4(@firebase/app-types@0.9.5)(@firebase/util@1.15.2)': dependencies: '@firebase/app-types': 0.9.5 - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.2 - '@firebase/storage@0.14.3(@firebase/app@0.15.1)': + '@firebase/storage@0.14.4(@firebase/app@0.16.0)': dependencies: - '@firebase/app': 0.15.1 - '@firebase/component': 0.7.3 - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.0 + '@firebase/component': 0.7.4 + '@firebase/util': 1.15.2 tslib: 2.8.1 - '@firebase/util@1.15.1': + '@firebase/util@1.15.2': dependencies: tslib: 2.8.1 @@ -9836,35 +9892,35 @@ snapshots: '@glideapps/ts-necessities@2.2.3': {} - '@google-cloud/common@6.0.1(supports-color@10.2.2)': + '@google-cloud/common@6.1.0(supports-color@11.0.0)': dependencies: '@google-cloud/projectify': 4.0.0 '@google-cloud/promisify': 4.1.0 arrify: 2.0.1 duplexify: 4.1.3 extend: 3.0.2 - google-auth-library: 10.9.0(supports-color@10.2.2) + google-auth-library: 10.9.1(supports-color@11.0.0) html-entities: 2.6.0 - retry-request: 8.0.3(supports-color@10.2.2) - teeny-request: 10.1.3(supports-color@10.2.2) + retry-request: 8.0.4(supports-color@11.0.0) + teeny-request: 10.1.4(supports-color@11.0.0) transitivePeerDependencies: - supports-color - '@google-cloud/precise-date@5.1.0': {} + '@google-cloud/precise-date@5.2.0': {} '@google-cloud/projectify@4.0.0': {} - '@google-cloud/projectify@5.1.0': {} + '@google-cloud/projectify@5.2.0': {} '@google-cloud/promisify@4.1.0': {} '@google-cloud/promisify@5.1.0': {} - '@google-cloud/spanner@8.0.0(supports-color@10.2.2)': + '@google-cloud/spanner@8.0.0(supports-color@11.0.0)': dependencies: - '@google-cloud/common': 6.0.1(supports-color@10.2.2) - '@google-cloud/precise-date': 5.1.0 - '@google-cloud/projectify': 5.1.0 + '@google-cloud/common': 6.1.0(supports-color@11.0.0) + '@google-cloud/precise-date': 5.2.0 + '@google-cloud/projectify': 5.2.0 '@google-cloud/promisify': 5.1.0 '@grpc/proto-loader': 0.7.15 '@opentelemetry/api': 1.9.1 @@ -9878,31 +9934,31 @@ snapshots: duplexify: 4.1.3 events-intercept: 2.0.0 extend: 3.0.2 - google-auth-library: 10.9.0(supports-color@10.2.2) - google-gax: 5.0.7(supports-color@10.2.2) + google-auth-library: 10.9.1(supports-color@11.0.0) + google-gax: 5.0.8(supports-color@11.0.0) grpc-gcp: 1.1.1 is: 3.3.2 lodash.snakecase: 4.1.1 merge-stream: 2.0.0 p-queue: 6.6.2 protobufjs: 7.6.5 - retry-request: 8.0.3(supports-color@10.2.2) + retry-request: 8.0.4(supports-color@11.0.0) split-array-stream: 2.0.0 stack-trace: 0.0.10 stream-events: 1.0.5 - teeny-request: 10.1.3(supports-color@10.2.2) + teeny-request: 10.1.4(supports-color@11.0.0) through2: 4.0.2 transitivePeerDependencies: - supports-color - '@google/genai@2.12.0(@modelcontextprotocol/sdk@1.29.0(supports-color@10.2.2)(zod@4.4.3))(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6)': + '@google/genai@2.17.1(@modelcontextprotocol/sdk@1.30.0(supports-color@11.0.0)(zod@4.4.3))(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6)': dependencies: - google-auth-library: 10.9.0(supports-color@10.2.2) + google-auth-library: 10.9.1(supports-color@11.0.0) p-retry: 4.6.2 protobufjs: 7.6.5 - ws: 8.21.1(bufferutil@4.1.0)(utf-8-validate@6.0.6) + ws: 8.21.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) optionalDependencies: - '@modelcontextprotocol/sdk': 1.29.0(supports-color@10.2.2)(zod@4.4.3) + '@modelcontextprotocol/sdk': 1.30.0(supports-color@11.0.0)(zod@4.4.3) transitivePeerDependencies: - bufferutil - supports-color @@ -9935,9 +9991,9 @@ snapshots: '@harperfast/extended-iterable@1.0.3': optional: true - '@hono/node-server@1.19.14(hono@4.12.31)': + '@hono/node-server@2.1.1(hono@4.13.3)': dependencies: - hono: 4.12.31 + hono: 4.13.3 '@humanfs/core@0.19.2': dependencies: @@ -9957,15 +10013,31 @@ snapshots: '@inquirer/ansi@2.0.7': {} - '@inquirer/checkbox@5.2.1(@types/node@24.13.3)': + '@inquirer/checkbox@5.2.2(@types/node@22.20.1)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/core': 11.2.1(@types/node@24.13.3) - '@inquirer/figures': 2.0.7 + '@inquirer/core': 12.0.0(@types/node@22.20.1) + '@inquirer/figures': 2.0.8 + '@inquirer/type': 4.0.7(@types/node@22.20.1) + optionalDependencies: + '@types/node': 22.20.1 + + '@inquirer/checkbox@5.2.2(@types/node@24.13.3)': + dependencies: + '@inquirer/ansi': 2.0.7 + '@inquirer/core': 12.0.0(@types/node@24.13.3) + '@inquirer/figures': 2.0.8 '@inquirer/type': 4.0.7(@types/node@24.13.3) optionalDependencies: '@types/node': 24.13.3 + '@inquirer/confirm@6.1.1(@types/node@22.20.1)': + dependencies: + '@inquirer/core': 11.2.1(@types/node@22.20.1) + '@inquirer/type': 4.0.7(@types/node@22.20.1) + optionalDependencies: + '@types/node': 22.20.1 + '@inquirer/confirm@6.1.1(@types/node@24.13.3)': dependencies: '@inquirer/core': 11.2.1(@types/node@24.13.3) @@ -9973,10 +10045,22 @@ snapshots: optionalDependencies: '@types/node': 24.13.3 + '@inquirer/core@11.2.1(@types/node@22.20.1)': + dependencies: + '@inquirer/ansi': 2.0.7 + '@inquirer/figures': 2.0.8 + '@inquirer/type': 4.0.7(@types/node@22.20.1) + cli-width: 4.1.0 + fast-wrap-ansi: 0.2.2 + mute-stream: 3.0.0 + signal-exit: 4.1.0 + optionalDependencies: + '@types/node': 22.20.1 + '@inquirer/core@11.2.1(@types/node@24.13.3)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/figures': 2.0.7 + '@inquirer/figures': 2.0.8 '@inquirer/type': 4.0.7(@types/node@24.13.3) cli-width: 4.1.0 fast-wrap-ansi: 0.2.2 @@ -9985,91 +10069,202 @@ snapshots: optionalDependencies: '@types/node': 24.13.3 - '@inquirer/editor@5.2.2(@types/node@24.13.3)': + '@inquirer/core@12.0.0(@types/node@22.20.1)': dependencies: - '@inquirer/core': 11.2.1(@types/node@24.13.3) - '@inquirer/external-editor': 3.0.3(@types/node@24.13.3) + '@inquirer/ansi': 2.0.7 + '@inquirer/figures': 2.0.8 + '@inquirer/type': 4.0.7(@types/node@22.20.1) + cli-width: 4.1.0 + fast-wrap-ansi: 0.2.2 + mute-stream: 3.0.0 + signal-exit: 4.1.0 + optionalDependencies: + '@types/node': 22.20.1 + + '@inquirer/core@12.0.0(@types/node@24.13.3)': + dependencies: + '@inquirer/ansi': 2.0.7 + '@inquirer/figures': 2.0.8 '@inquirer/type': 4.0.7(@types/node@24.13.3) + cli-width: 4.1.0 + fast-wrap-ansi: 0.2.2 + mute-stream: 3.0.0 + signal-exit: 4.1.0 optionalDependencies: '@types/node': 24.13.3 - '@inquirer/expand@5.1.1(@types/node@24.13.3)': + '@inquirer/editor@5.3.0(@types/node@22.20.1)': dependencies: - '@inquirer/core': 11.2.1(@types/node@24.13.3) + '@inquirer/core': 12.0.0(@types/node@22.20.1) + '@inquirer/external-editor': 3.0.4(@types/node@22.20.1) + '@inquirer/type': 4.0.7(@types/node@22.20.1) + optionalDependencies: + '@types/node': 22.20.1 + + '@inquirer/editor@5.3.0(@types/node@24.13.3)': + dependencies: + '@inquirer/core': 12.0.0(@types/node@24.13.3) + '@inquirer/external-editor': 3.0.4(@types/node@24.13.3) '@inquirer/type': 4.0.7(@types/node@24.13.3) optionalDependencies: '@types/node': 24.13.3 - '@inquirer/external-editor@3.0.3(@types/node@24.13.3)': + '@inquirer/expand@5.1.2(@types/node@22.20.1)': + dependencies: + '@inquirer/core': 12.0.0(@types/node@22.20.1) + '@inquirer/type': 4.0.7(@types/node@22.20.1) + optionalDependencies: + '@types/node': 22.20.1 + + '@inquirer/expand@5.1.2(@types/node@24.13.3)': + dependencies: + '@inquirer/core': 12.0.0(@types/node@24.13.3) + '@inquirer/type': 4.0.7(@types/node@24.13.3) + optionalDependencies: + '@types/node': 24.13.3 + + '@inquirer/external-editor@3.0.4(@types/node@22.20.1)': + dependencies: + chardet: 2.2.0 + iconv-lite: 0.7.3 + optionalDependencies: + '@types/node': 22.20.1 + + '@inquirer/external-editor@3.0.4(@types/node@24.13.3)': dependencies: chardet: 2.2.0 iconv-lite: 0.7.3 optionalDependencies: '@types/node': 24.13.3 - '@inquirer/figures@2.0.7': {} + '@inquirer/figures@2.0.8': {} - '@inquirer/input@5.1.2(@types/node@24.13.3)': + '@inquirer/input@5.1.3(@types/node@22.20.1)': dependencies: - '@inquirer/core': 11.2.1(@types/node@24.13.3) + '@inquirer/core': 12.0.0(@types/node@22.20.1) + '@inquirer/type': 4.0.7(@types/node@22.20.1) + optionalDependencies: + '@types/node': 22.20.1 + + '@inquirer/input@5.1.3(@types/node@24.13.3)': + dependencies: + '@inquirer/core': 12.0.0(@types/node@24.13.3) '@inquirer/type': 4.0.7(@types/node@24.13.3) optionalDependencies: '@types/node': 24.13.3 - '@inquirer/number@4.1.1(@types/node@24.13.3)': + '@inquirer/number@4.2.0(@types/node@22.20.1)': dependencies: - '@inquirer/core': 11.2.1(@types/node@24.13.3) + '@inquirer/core': 12.0.0(@types/node@22.20.1) + '@inquirer/type': 4.0.7(@types/node@22.20.1) + optionalDependencies: + '@types/node': 22.20.1 + + '@inquirer/number@4.2.0(@types/node@24.13.3)': + dependencies: + '@inquirer/core': 12.0.0(@types/node@24.13.3) '@inquirer/type': 4.0.7(@types/node@24.13.3) optionalDependencies: '@types/node': 24.13.3 - '@inquirer/password@5.1.1(@types/node@24.13.3)': + '@inquirer/password@5.1.2(@types/node@22.20.1)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/core': 11.2.1(@types/node@24.13.3) + '@inquirer/core': 12.0.0(@types/node@22.20.1) + '@inquirer/type': 4.0.7(@types/node@22.20.1) + optionalDependencies: + '@types/node': 22.20.1 + + '@inquirer/password@5.1.2(@types/node@24.13.3)': + dependencies: + '@inquirer/ansi': 2.0.7 + '@inquirer/core': 12.0.0(@types/node@24.13.3) '@inquirer/type': 4.0.7(@types/node@24.13.3) optionalDependencies: '@types/node': 24.13.3 + '@inquirer/prompts@8.5.2(@types/node@22.20.1)': + dependencies: + '@inquirer/checkbox': 5.2.2(@types/node@22.20.1) + '@inquirer/confirm': 6.1.1(@types/node@22.20.1) + '@inquirer/editor': 5.3.0(@types/node@22.20.1) + '@inquirer/expand': 5.1.2(@types/node@22.20.1) + '@inquirer/input': 5.1.3(@types/node@22.20.1) + '@inquirer/number': 4.2.0(@types/node@22.20.1) + '@inquirer/password': 5.1.2(@types/node@22.20.1) + '@inquirer/rawlist': 5.3.2(@types/node@22.20.1) + '@inquirer/search': 4.3.0(@types/node@22.20.1) + '@inquirer/select': 5.2.2(@types/node@22.20.1) + optionalDependencies: + '@types/node': 22.20.1 + '@inquirer/prompts@8.5.2(@types/node@24.13.3)': dependencies: - '@inquirer/checkbox': 5.2.1(@types/node@24.13.3) + '@inquirer/checkbox': 5.2.2(@types/node@24.13.3) '@inquirer/confirm': 6.1.1(@types/node@24.13.3) - '@inquirer/editor': 5.2.2(@types/node@24.13.3) - '@inquirer/expand': 5.1.1(@types/node@24.13.3) - '@inquirer/input': 5.1.2(@types/node@24.13.3) - '@inquirer/number': 4.1.1(@types/node@24.13.3) - '@inquirer/password': 5.1.1(@types/node@24.13.3) - '@inquirer/rawlist': 5.3.1(@types/node@24.13.3) - '@inquirer/search': 4.2.1(@types/node@24.13.3) - '@inquirer/select': 5.2.1(@types/node@24.13.3) + '@inquirer/editor': 5.3.0(@types/node@24.13.3) + '@inquirer/expand': 5.1.2(@types/node@24.13.3) + '@inquirer/input': 5.1.3(@types/node@24.13.3) + '@inquirer/number': 4.2.0(@types/node@24.13.3) + '@inquirer/password': 5.1.2(@types/node@24.13.3) + '@inquirer/rawlist': 5.3.2(@types/node@24.13.3) + '@inquirer/search': 4.3.0(@types/node@24.13.3) + '@inquirer/select': 5.2.2(@types/node@24.13.3) optionalDependencies: '@types/node': 24.13.3 - '@inquirer/rawlist@5.3.1(@types/node@24.13.3)': + '@inquirer/rawlist@5.3.2(@types/node@22.20.1)': dependencies: - '@inquirer/core': 11.2.1(@types/node@24.13.3) + '@inquirer/core': 12.0.0(@types/node@22.20.1) + '@inquirer/type': 4.0.7(@types/node@22.20.1) + optionalDependencies: + '@types/node': 22.20.1 + + '@inquirer/rawlist@5.3.2(@types/node@24.13.3)': + dependencies: + '@inquirer/core': 12.0.0(@types/node@24.13.3) '@inquirer/type': 4.0.7(@types/node@24.13.3) optionalDependencies: '@types/node': 24.13.3 - '@inquirer/search@4.2.1(@types/node@24.13.3)': + '@inquirer/search@4.3.0(@types/node@22.20.1)': dependencies: - '@inquirer/core': 11.2.1(@types/node@24.13.3) - '@inquirer/figures': 2.0.7 + '@inquirer/core': 12.0.0(@types/node@22.20.1) + '@inquirer/figures': 2.0.8 + '@inquirer/type': 4.0.7(@types/node@22.20.1) + optionalDependencies: + '@types/node': 22.20.1 + + '@inquirer/search@4.3.0(@types/node@24.13.3)': + dependencies: + '@inquirer/core': 12.0.0(@types/node@24.13.3) + '@inquirer/figures': 2.0.8 '@inquirer/type': 4.0.7(@types/node@24.13.3) optionalDependencies: '@types/node': 24.13.3 - '@inquirer/select@5.2.1(@types/node@24.13.3)': + '@inquirer/select@5.2.2(@types/node@22.20.1)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/core': 11.2.1(@types/node@24.13.3) - '@inquirer/figures': 2.0.7 + '@inquirer/core': 12.0.0(@types/node@22.20.1) + '@inquirer/figures': 2.0.8 + '@inquirer/type': 4.0.7(@types/node@22.20.1) + optionalDependencies: + '@types/node': 22.20.1 + + '@inquirer/select@5.2.2(@types/node@24.13.3)': + dependencies: + '@inquirer/ansi': 2.0.7 + '@inquirer/core': 12.0.0(@types/node@24.13.3) + '@inquirer/figures': 2.0.8 '@inquirer/type': 4.0.7(@types/node@24.13.3) optionalDependencies: '@types/node': 24.13.3 + '@inquirer/type@4.0.7(@types/node@22.20.1)': + optionalDependencies: + '@types/node': 22.20.1 + '@inquirer/type@4.0.7(@types/node@24.13.3)': optionalDependencies: '@types/node': 24.13.3 @@ -10085,7 +10280,7 @@ snapshots: '@istanbuljs/schema@0.1.6': {} - '@jasminejs/reporters@1.0.0': {} + '@jasminejs/reporters@1.1.0': {} '@jridgewell/gen-mapping@0.3.13': dependencies: @@ -10137,59 +10332,59 @@ snapshots: dependencies: tslib: 2.8.1 - '@jsonjoy.com/fs-core@4.64.0(tslib@2.8.1)': + '@jsonjoy.com/fs-core@4.68.1(tslib@2.8.1)': dependencies: - '@jsonjoy.com/fs-node-builtins': 4.64.0(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.64.0(tslib@2.8.1) - thingies: 2.6.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.68.1(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.68.1(tslib@2.8.1) + thingies: 2.6.1(tslib@2.8.1) tslib: 2.8.1 - '@jsonjoy.com/fs-fsa@4.64.0(tslib@2.8.1)': + '@jsonjoy.com/fs-fsa@4.68.1(tslib@2.8.1)': dependencies: - '@jsonjoy.com/fs-core': 4.64.0(tslib@2.8.1) - '@jsonjoy.com/fs-node-builtins': 4.64.0(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.64.0(tslib@2.8.1) - thingies: 2.6.0(tslib@2.8.1) + '@jsonjoy.com/fs-core': 4.68.1(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.68.1(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.68.1(tslib@2.8.1) + thingies: 2.6.1(tslib@2.8.1) tslib: 2.8.1 - '@jsonjoy.com/fs-node-builtins@4.64.0(tslib@2.8.1)': + '@jsonjoy.com/fs-node-builtins@4.68.1(tslib@2.8.1)': dependencies: tslib: 2.8.1 - '@jsonjoy.com/fs-node-to-fsa@4.64.0(tslib@2.8.1)': + '@jsonjoy.com/fs-node-to-fsa@4.68.1(tslib@2.8.1)': dependencies: - '@jsonjoy.com/fs-fsa': 4.64.0(tslib@2.8.1) - '@jsonjoy.com/fs-node-builtins': 4.64.0(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-fsa': 4.68.1(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.68.1(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.68.1(tslib@2.8.1) tslib: 2.8.1 - '@jsonjoy.com/fs-node-utils@4.64.0(tslib@2.8.1)': + '@jsonjoy.com/fs-node-utils@4.68.1(tslib@2.8.1)': dependencies: - '@jsonjoy.com/fs-node-builtins': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.68.1(tslib@2.8.1) glob-to-regex.js: 1.2.0(tslib@2.8.1) tslib: 2.8.1 - '@jsonjoy.com/fs-node@4.64.0(tslib@2.8.1)': + '@jsonjoy.com/fs-node@4.68.1(tslib@2.8.1)': dependencies: - '@jsonjoy.com/fs-core': 4.64.0(tslib@2.8.1) - '@jsonjoy.com/fs-node-builtins': 4.64.0(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.64.0(tslib@2.8.1) - '@jsonjoy.com/fs-print': 4.64.0(tslib@2.8.1) - '@jsonjoy.com/fs-snapshot': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-core': 4.68.1(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.68.1(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.68.1(tslib@2.8.1) + '@jsonjoy.com/fs-print': 4.68.1(tslib@2.8.1) + '@jsonjoy.com/fs-snapshot': 4.68.1(tslib@2.8.1) glob-to-regex.js: 1.2.0(tslib@2.8.1) - thingies: 2.6.0(tslib@2.8.1) + thingies: 2.6.1(tslib@2.8.1) tslib: 2.8.1 - '@jsonjoy.com/fs-print@4.64.0(tslib@2.8.1)': + '@jsonjoy.com/fs-print@4.68.1(tslib@2.8.1)': dependencies: - '@jsonjoy.com/fs-node-utils': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.68.1(tslib@2.8.1) tree-dump: 1.1.0(tslib@2.8.1) tslib: 2.8.1 - '@jsonjoy.com/fs-snapshot@4.64.0(tslib@2.8.1)': + '@jsonjoy.com/fs-snapshot@4.68.1(tslib@2.8.1)': dependencies: '@jsonjoy.com/buffers': 17.67.0(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.68.1(tslib@2.8.1) '@jsonjoy.com/json-pack': 17.67.0(tslib@2.8.1) '@jsonjoy.com/util': 17.67.0(tslib@2.8.1) tslib: 2.8.1 @@ -10202,7 +10397,7 @@ snapshots: '@jsonjoy.com/json-pointer': 1.0.2(tslib@2.8.1) '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) hyperdyperid: 1.2.0 - thingies: 2.6.0(tslib@2.8.1) + thingies: 2.6.1(tslib@2.8.1) tree-dump: 1.1.0(tslib@2.8.1) tslib: 2.8.1 @@ -10214,7 +10409,7 @@ snapshots: '@jsonjoy.com/json-pointer': 17.67.0(tslib@2.8.1) '@jsonjoy.com/util': 17.67.0(tslib@2.8.1) hyperdyperid: 1.2.0 - thingies: 2.6.0(tslib@2.8.1) + thingies: 2.6.1(tslib@2.8.1) tree-dump: 1.1.0(tslib@2.8.1) tslib: 2.8.1 @@ -10243,11 +10438,11 @@ snapshots: '@leichtgewicht/ip-codec@2.0.5': {} - '@listr2/prompt-adapter-inquirer@4.2.4(@inquirer/prompts@8.5.2(@types/node@24.13.3))(@types/node@24.13.3)(listr2@10.2.2)': + '@listr2/prompt-adapter-inquirer@4.2.5(@inquirer/prompts@8.5.2(@types/node@22.20.1))(@types/node@22.20.1)(listr2@11.0.0)': dependencies: - '@inquirer/prompts': 8.5.2(@types/node@24.13.3) - '@inquirer/type': 4.0.7(@types/node@24.13.3) - listr2: 10.2.2 + '@inquirer/prompts': 8.5.2(@types/node@22.20.1) + '@inquirer/type': 4.0.7(@types/node@22.20.1) + listr2: 11.0.0 transitivePeerDependencies: - '@types/node' @@ -10272,20 +10467,20 @@ snapshots: '@lmdb/lmdb-win32-x64@3.5.6': optional: true - '@modelcontextprotocol/sdk@1.29.0(supports-color@10.2.2)(zod@4.4.3)': + '@modelcontextprotocol/sdk@1.30.0(supports-color@11.0.0)(zod@4.4.3)': dependencies: - '@hono/node-server': 1.19.14(hono@4.12.31) + '@hono/node-server': 2.1.1(hono@4.13.3) ajv: 8.20.0 ajv-formats: 3.0.1(ajv@8.20.0) content-type: 1.0.5 cors: 2.8.6 cross-spawn: 7.0.6 eventsource: 3.0.7 - eventsource-parser: 3.1.0 - express: 5.2.1(supports-color@10.2.2) - express-rate-limit: 8.6.0(express@5.2.1(supports-color@10.2.2))(supports-color@10.2.2) - hono: 4.12.31 - jose: 6.2.4 + eventsource-parser: 3.1.1 + express: 5.2.1(supports-color@11.0.0) + express-rate-limit: 8.6.2(express@5.2.1(supports-color@11.0.0))(supports-color@11.0.0) + hono: 4.13.3 + jose: 6.2.10 json-schema-typed: 8.0.2 pkce-challenge: 5.0.1 raw-body: 3.0.2 @@ -10393,14 +10588,14 @@ snapshots: '@napi-rs/nice-win32-x64-msvc': 1.1.1 optional: true - '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + '@napi-rs/wasm-runtime@1.2.3(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': dependencies: '@emnapi/core': 1.11.1 '@emnapi/runtime': 1.11.1 '@tybys/wasm-util': 0.10.3 optional: true - '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': + '@napi-rs/wasm-runtime@1.2.3(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': dependencies: '@emnapi/core': 1.11.2 '@emnapi/runtime': 1.11.2 @@ -10421,55 +10616,55 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - '@octokit/auth-app@8.2.0': + '@octokit/auth-app@8.3.0': dependencies: - '@octokit/auth-oauth-app': 9.0.3 - '@octokit/auth-oauth-user': 6.0.2 - '@octokit/request': 10.0.11 - '@octokit/request-error': 7.1.0 - '@octokit/types': 16.0.0 + '@octokit/auth-oauth-app': 9.0.4 + '@octokit/auth-oauth-user': 6.0.3 + '@octokit/request': 10.0.15 + '@octokit/request-error': 7.1.1 + '@octokit/types': 17.0.0 toad-cache: 3.7.4 universal-github-app-jwt: 2.2.2 universal-user-agent: 7.0.3 - '@octokit/auth-oauth-app@9.0.3': + '@octokit/auth-oauth-app@9.0.4': dependencies: - '@octokit/auth-oauth-device': 8.0.3 - '@octokit/auth-oauth-user': 6.0.2 - '@octokit/request': 10.0.11 - '@octokit/types': 16.0.0 + '@octokit/auth-oauth-device': 8.0.4 + '@octokit/auth-oauth-user': 6.0.3 + '@octokit/request': 10.0.15 + '@octokit/types': 17.0.0 universal-user-agent: 7.0.3 - '@octokit/auth-oauth-device@8.0.3': + '@octokit/auth-oauth-device@8.0.4': dependencies: - '@octokit/oauth-methods': 6.0.2 - '@octokit/request': 10.0.11 - '@octokit/types': 16.0.0 + '@octokit/oauth-methods': 6.0.4 + '@octokit/request': 10.0.15 + '@octokit/types': 17.0.0 universal-user-agent: 7.0.3 - '@octokit/auth-oauth-user@6.0.2': + '@octokit/auth-oauth-user@6.0.3': dependencies: - '@octokit/auth-oauth-device': 8.0.3 - '@octokit/oauth-methods': 6.0.2 - '@octokit/request': 10.0.11 - '@octokit/types': 16.0.0 + '@octokit/auth-oauth-device': 8.0.4 + '@octokit/oauth-methods': 6.0.4 + '@octokit/request': 10.0.15 + '@octokit/types': 17.0.0 universal-user-agent: 7.0.3 '@octokit/auth-token@6.0.0': {} - '@octokit/core@7.0.6': + '@octokit/core@7.0.7': dependencies: '@octokit/auth-token': 6.0.0 - '@octokit/graphql': 9.0.3 - '@octokit/request': 10.0.11 - '@octokit/request-error': 7.1.0 - '@octokit/types': 16.0.0 + '@octokit/graphql': 9.0.4 + '@octokit/request': 10.0.15 + '@octokit/request-error': 7.1.1 + '@octokit/types': 17.0.0 before-after-hook: 4.0.0 universal-user-agent: 7.0.3 - '@octokit/endpoint@11.0.3': + '@octokit/endpoint@11.0.4': dependencies: - '@octokit/types': 16.0.0 + '@octokit/types': 17.0.0 universal-user-agent: 7.0.3 '@octokit/graphql-schema@15.26.1': @@ -10477,61 +10672,77 @@ snapshots: graphql: 16.14.2 graphql-tag: 2.12.7(graphql@16.14.2) - '@octokit/graphql@9.0.3': + '@octokit/graphql@9.0.4': dependencies: - '@octokit/request': 10.0.11 - '@octokit/types': 16.0.0 + '@octokit/request': 10.0.15 + '@octokit/types': 17.0.0 universal-user-agent: 7.0.3 '@octokit/oauth-authorization-url@8.0.0': {} - '@octokit/oauth-methods@6.0.2': + '@octokit/oauth-methods@6.0.4': dependencies: '@octokit/oauth-authorization-url': 8.0.0 - '@octokit/request': 10.0.11 - '@octokit/request-error': 7.1.0 - '@octokit/types': 16.0.0 + '@octokit/request': 10.0.15 + '@octokit/request-error': 7.1.1 + '@octokit/types': 17.0.0 '@octokit/openapi-types@27.0.0': {} - '@octokit/plugin-paginate-rest@14.0.0(@octokit/core@7.0.6)': + '@octokit/openapi-types@28.0.0': {} + + '@octokit/plugin-paginate-rest@14.0.0(@octokit/core@7.0.7)': dependencies: - '@octokit/core': 7.0.6 + '@octokit/core': 7.0.7 '@octokit/types': 16.0.0 - '@octokit/plugin-request-log@6.0.0(@octokit/core@7.0.6)': + '@octokit/plugin-paginate-rest@15.0.0(@octokit/core@7.0.7)': dependencies: - '@octokit/core': 7.0.6 + '@octokit/core': 7.0.7 + '@octokit/types': 17.0.0 - '@octokit/plugin-rest-endpoint-methods@17.0.0(@octokit/core@7.0.6)': + '@octokit/plugin-request-log@6.0.0(@octokit/core@7.0.7)': dependencies: - '@octokit/core': 7.0.6 - '@octokit/types': 16.0.0 + '@octokit/core': 7.0.7 - '@octokit/request-error@7.1.0': + '@octokit/plugin-rest-endpoint-methods@17.0.0(@octokit/core@7.0.7)': dependencies: + '@octokit/core': 7.0.7 '@octokit/types': 16.0.0 - '@octokit/request@10.0.11': + '@octokit/plugin-rest-endpoint-methods@18.0.0(@octokit/core@7.0.7)': dependencies: - '@octokit/endpoint': 11.0.3 - '@octokit/request-error': 7.1.0 - '@octokit/types': 16.0.0 - content-type: 2.0.0 - json-with-bigint: 3.5.10 + '@octokit/core': 7.0.7 + '@octokit/types': 17.0.0 + + '@octokit/request-error@7.1.1': + dependencies: + '@octokit/types': 17.0.0 + + '@octokit/request@10.0.15': + dependencies: + '@octokit/endpoint': 11.0.4 + '@octokit/request-error': 7.1.1 + '@octokit/types': 17.0.0 + content-type: 3.0.0 + json-with-bigint: 3.5.12 universal-user-agent: 7.0.3 '@octokit/rest@22.0.1': dependencies: - '@octokit/core': 7.0.6 - '@octokit/plugin-paginate-rest': 14.0.0(@octokit/core@7.0.6) - '@octokit/plugin-request-log': 6.0.0(@octokit/core@7.0.6) - '@octokit/plugin-rest-endpoint-methods': 17.0.0(@octokit/core@7.0.6) + '@octokit/core': 7.0.7 + '@octokit/plugin-paginate-rest': 14.0.0(@octokit/core@7.0.7) + '@octokit/plugin-request-log': 6.0.0(@octokit/core@7.0.7) + '@octokit/plugin-rest-endpoint-methods': 17.0.0(@octokit/core@7.0.7) '@octokit/types@16.0.0': dependencies: '@octokit/openapi-types': 27.0.0 + '@octokit/types@17.0.0': + dependencies: + '@octokit/openapi-types': 28.0.0 + '@open-draft/deferred-promise@2.2.0': {} '@open-draft/logger@0.3.0': @@ -10554,74 +10765,76 @@ snapshots: '@opentelemetry/semantic-conventions@1.43.0': {} - '@oxc-parser/binding-android-arm-eabi@0.140.0': + '@oxc-parser/binding-android-arm-eabi@0.142.0': optional: true - '@oxc-parser/binding-android-arm64@0.140.0': + '@oxc-parser/binding-android-arm64@0.142.0': optional: true - '@oxc-parser/binding-darwin-arm64@0.140.0': + '@oxc-parser/binding-darwin-arm64@0.142.0': optional: true - '@oxc-parser/binding-darwin-x64@0.140.0': + '@oxc-parser/binding-darwin-x64@0.142.0': optional: true - '@oxc-parser/binding-freebsd-x64@0.140.0': + '@oxc-parser/binding-freebsd-x64@0.142.0': optional: true - '@oxc-parser/binding-linux-arm-gnueabihf@0.140.0': + '@oxc-parser/binding-linux-arm-gnueabihf@0.142.0': optional: true - '@oxc-parser/binding-linux-arm-musleabihf@0.140.0': + '@oxc-parser/binding-linux-arm-musleabihf@0.142.0': optional: true - '@oxc-parser/binding-linux-arm64-gnu@0.140.0': + '@oxc-parser/binding-linux-arm64-gnu@0.142.0': optional: true - '@oxc-parser/binding-linux-arm64-musl@0.140.0': + '@oxc-parser/binding-linux-arm64-musl@0.142.0': optional: true - '@oxc-parser/binding-linux-ppc64-gnu@0.140.0': + '@oxc-parser/binding-linux-ppc64-gnu@0.142.0': optional: true - '@oxc-parser/binding-linux-riscv64-gnu@0.140.0': + '@oxc-parser/binding-linux-riscv64-gnu@0.142.0': optional: true - '@oxc-parser/binding-linux-riscv64-musl@0.140.0': + '@oxc-parser/binding-linux-riscv64-musl@0.142.0': optional: true - '@oxc-parser/binding-linux-s390x-gnu@0.140.0': + '@oxc-parser/binding-linux-s390x-gnu@0.142.0': optional: true - '@oxc-parser/binding-linux-x64-gnu@0.140.0': + '@oxc-parser/binding-linux-x64-gnu@0.142.0': optional: true - '@oxc-parser/binding-linux-x64-musl@0.140.0': + '@oxc-parser/binding-linux-x64-musl@0.142.0': optional: true - '@oxc-parser/binding-openharmony-arm64@0.140.0': + '@oxc-parser/binding-openharmony-arm64@0.142.0': optional: true - '@oxc-parser/binding-wasm32-wasi@0.140.0': + '@oxc-parser/binding-wasm32-wasi@0.142.0': dependencies: '@emnapi/core': 1.11.2 '@emnapi/runtime': 1.11.2 - '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + '@napi-rs/wasm-runtime': 1.2.3(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) optional: true - '@oxc-parser/binding-win32-arm64-msvc@0.140.0': + '@oxc-parser/binding-win32-arm64-msvc@0.142.0': optional: true - '@oxc-parser/binding-win32-ia32-msvc@0.140.0': + '@oxc-parser/binding-win32-ia32-msvc@0.142.0': optional: true - '@oxc-parser/binding-win32-x64-msvc@0.140.0': + '@oxc-parser/binding-win32-x64-msvc@0.142.0': optional: true '@oxc-project/types@0.139.0': {} '@oxc-project/types@0.140.0': {} + '@oxc-project/types@0.142.0': {} + '@parcel/watcher-android-arm64@2.6.0': optional: true @@ -10679,78 +10892,78 @@ snapshots: '@parcel/watcher-win32-x64': 2.6.0 optional: true - '@peculiar/asn1-cms@2.8.0': + '@peculiar/asn1-cms@2.9.4': dependencies: - '@peculiar/asn1-schema': 2.8.0 - '@peculiar/asn1-x509': 2.8.0 - '@peculiar/asn1-x509-attr': 2.8.0 + '@peculiar/asn1-schema': 2.9.4 + '@peculiar/asn1-x509': 2.9.4 + '@peculiar/asn1-x509-attr': 2.9.4 asn1js: 3.0.10 tslib: 2.8.1 - '@peculiar/asn1-csr@2.8.0': + '@peculiar/asn1-csr@2.9.4': dependencies: - '@peculiar/asn1-schema': 2.8.0 - '@peculiar/asn1-x509': 2.8.0 + '@peculiar/asn1-schema': 2.9.4 + '@peculiar/asn1-x509': 2.9.4 asn1js: 3.0.10 tslib: 2.8.1 - '@peculiar/asn1-ecc@2.8.0': + '@peculiar/asn1-ecc@2.9.4': dependencies: - '@peculiar/asn1-schema': 2.8.0 - '@peculiar/asn1-x509': 2.8.0 + '@peculiar/asn1-schema': 2.9.4 + '@peculiar/asn1-x509': 2.9.4 asn1js: 3.0.10 tslib: 2.8.1 - '@peculiar/asn1-pfx@2.8.0': + '@peculiar/asn1-pfx@2.9.4': dependencies: - '@peculiar/asn1-cms': 2.8.0 - '@peculiar/asn1-pkcs8': 2.8.0 - '@peculiar/asn1-rsa': 2.8.0 - '@peculiar/asn1-schema': 2.8.0 + '@peculiar/asn1-cms': 2.9.4 + '@peculiar/asn1-pkcs8': 2.9.4 + '@peculiar/asn1-rsa': 2.9.4 + '@peculiar/asn1-schema': 2.9.4 asn1js: 3.0.10 tslib: 2.8.1 - '@peculiar/asn1-pkcs8@2.8.0': + '@peculiar/asn1-pkcs8@2.9.4': dependencies: - '@peculiar/asn1-schema': 2.8.0 - '@peculiar/asn1-x509': 2.8.0 + '@peculiar/asn1-schema': 2.9.4 + '@peculiar/asn1-x509': 2.9.4 asn1js: 3.0.10 tslib: 2.8.1 - '@peculiar/asn1-pkcs9@2.8.0': + '@peculiar/asn1-pkcs9@2.9.4': dependencies: - '@peculiar/asn1-cms': 2.8.0 - '@peculiar/asn1-pfx': 2.8.0 - '@peculiar/asn1-pkcs8': 2.8.0 - '@peculiar/asn1-schema': 2.8.0 - '@peculiar/asn1-x509': 2.8.0 - '@peculiar/asn1-x509-attr': 2.8.0 + '@peculiar/asn1-cms': 2.9.4 + '@peculiar/asn1-pfx': 2.9.4 + '@peculiar/asn1-pkcs8': 2.9.4 + '@peculiar/asn1-schema': 2.9.4 + '@peculiar/asn1-x509': 2.9.4 + '@peculiar/asn1-x509-attr': 2.9.4 asn1js: 3.0.10 tslib: 2.8.1 - '@peculiar/asn1-rsa@2.8.0': + '@peculiar/asn1-rsa@2.9.4': dependencies: - '@peculiar/asn1-schema': 2.8.0 - '@peculiar/asn1-x509': 2.8.0 + '@peculiar/asn1-schema': 2.9.4 + '@peculiar/asn1-x509': 2.9.4 asn1js: 3.0.10 tslib: 2.8.1 - '@peculiar/asn1-schema@2.8.0': + '@peculiar/asn1-schema@2.9.4': dependencies: '@peculiar/utils': 2.0.3 asn1js: 3.0.10 tslib: 2.8.1 - '@peculiar/asn1-x509-attr@2.8.0': + '@peculiar/asn1-x509-attr@2.9.4': dependencies: - '@peculiar/asn1-schema': 2.8.0 - '@peculiar/asn1-x509': 2.8.0 + '@peculiar/asn1-schema': 2.9.4 + '@peculiar/asn1-x509': 2.9.4 asn1js: 3.0.10 tslib: 2.8.1 - '@peculiar/asn1-x509@2.8.0': + '@peculiar/asn1-x509@2.9.4': dependencies: - '@peculiar/asn1-schema': 2.8.0 + '@peculiar/asn1-schema': 2.9.4 '@peculiar/utils': 2.0.3 asn1js: 3.0.10 tslib: 2.8.1 @@ -10761,13 +10974,13 @@ snapshots: '@peculiar/x509@1.14.3': dependencies: - '@peculiar/asn1-cms': 2.8.0 - '@peculiar/asn1-csr': 2.8.0 - '@peculiar/asn1-ecc': 2.8.0 - '@peculiar/asn1-pkcs9': 2.8.0 - '@peculiar/asn1-rsa': 2.8.0 - '@peculiar/asn1-schema': 2.8.0 - '@peculiar/asn1-x509': 2.8.0 + '@peculiar/asn1-cms': 2.9.4 + '@peculiar/asn1-csr': 2.9.4 + '@peculiar/asn1-ecc': 2.9.4 + '@peculiar/asn1-pkcs9': 2.9.4 + '@peculiar/asn1-rsa': 2.9.4 + '@peculiar/asn1-schema': 2.9.4 + '@peculiar/asn1-x509': 2.9.4 pvtsutils: 1.3.6 reflect-metadata: 0.2.2 tslib: 2.8.1 @@ -10821,7 +11034,7 @@ snapshots: '@puppeteer/browsers@3.0.6': dependencies: modern-tar: 0.7.7 - yargs: 18.0.0 + yargs: 18.1.0 '@rolldown/binding-android-arm64@1.1.5': optional: true @@ -10899,14 +11112,14 @@ snapshots: dependencies: '@emnapi/core': 1.11.1 '@emnapi/runtime': 1.11.1 - '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + '@napi-rs/wasm-runtime': 1.2.3(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) optional: true '@rolldown/binding-wasm32-wasi@1.2.0': dependencies: '@emnapi/core': 1.11.2 '@emnapi/runtime': 1.11.2 - '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + '@napi-rs/wasm-runtime': 1.2.3(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) optional: true '@rolldown/binding-win32-arm64-msvc@1.1.5': @@ -11058,11 +11271,11 @@ snapshots: '@standard-schema/spec@1.1.0': {} - '@stylistic/eslint-plugin@5.10.0(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))': + '@stylistic/eslint-plugin@5.10.0(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))': dependencies: - '@eslint-community/eslint-utils': 4.10.1(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2)) - '@typescript-eslint/types': 8.65.0 - eslint: 10.7.0(jiti@2.7.0)(supports-color@10.2.2) + '@eslint-community/eslint-utils': 4.10.1(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0)) + '@typescript-eslint/types': 8.67.0 + eslint: 10.7.0(jiti@2.7.0)(supports-color@11.0.0) eslint-visitor-keys: 4.2.1 espree: 10.4.0 estraverse: 5.3.0 @@ -11072,9 +11285,9 @@ snapshots: dependencies: defer-to-connect: 2.0.1 - '@tony.ganchev/eslint-plugin-header@3.4.4(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))': + '@tony.ganchev/eslint-plugin-header@3.4.4(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))': dependencies: - eslint: 10.7.0(jiti@2.7.0)(supports-color@10.2.2) + eslint: 10.7.0(jiti@2.7.0)(supports-color@11.0.0) '@tybys/wasm-util@0.10.3': dependencies: @@ -11083,24 +11296,24 @@ snapshots: '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 '@types/babel__generator': 7.27.0 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.28.0 '@types/babel__generator@7.27.0': dependencies: - '@babel/types': 7.29.7 + '@babel/types': 7.29.8 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 '@types/babel__traverse@7.28.0': dependencies: - '@babel/types': 7.29.7 + '@babel/types': 7.29.8 '@types/big.js@6.2.2': {} @@ -11163,7 +11376,7 @@ snapshots: '@types/range-parser': 1.2.7 '@types/send': 1.2.1 - '@types/express-serve-static-core@5.1.2': + '@types/express-serve-static-core@5.1.3': dependencies: '@types/node': 22.20.1 '@types/qs': 6.15.1 @@ -11180,7 +11393,7 @@ snapshots: '@types/express@5.0.6': dependencies: '@types/body-parser': 1.19.6 - '@types/express-serve-static-core': 5.1.2 + '@types/express-serve-static-core': 5.1.3 '@types/serve-static': 2.2.0 '@types/folder-hash@4.0.4': {} @@ -11209,19 +11422,19 @@ snapshots: '@types/json5@0.0.29': {} - '@types/karma@6.3.9(supports-color@10.2.2)': + '@types/karma@6.3.9(supports-color@11.0.0)': dependencies: '@types/node': 22.20.1 - log4js: 6.9.1(supports-color@10.2.2) + log4js: 6.9.1(supports-color@11.0.0) transitivePeerDependencies: - supports-color '@types/less@3.0.8': {} - '@types/loader-utils@3.0.0(esbuild@0.28.1)': + '@types/loader-utils@3.0.0(esbuild@0.28.2)': dependencies: '@types/node': 22.20.1 - webpack: 5.108.4(esbuild@0.28.1) + webpack: 5.109.2(esbuild@0.28.2) transitivePeerDependencies: - '@minify-html/node' - '@swc/core' @@ -11237,7 +11450,7 @@ snapshots: - uglify-js - webpack-cli - '@types/lodash@4.17.24': {} + '@types/lodash@4.17.25': {} '@types/micromatch@2.3.35': dependencies: @@ -11287,7 +11500,7 @@ snapshots: '@types/retry@0.12.2': {} - '@types/semver@7.7.1': {} + '@types/semver@7.8.0': {} '@types/send@0.17.6': dependencies: @@ -11344,15 +11557,15 @@ snapshots: '@types/yarnpkg__lockfile@1.1.9': {} - '@typescript-eslint/eslint-plugin@8.64.0(@typescript-eslint/parser@8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': + '@typescript-eslint/eslint-plugin@8.64.0(@typescript-eslint/parser@8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3))(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/parser': 8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3) '@typescript-eslint/scope-manager': 8.64.0 - '@typescript-eslint/type-utils': 8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) - '@typescript-eslint/utils': 8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/type-utils': 8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3) + '@typescript-eslint/utils': 8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3) '@typescript-eslint/visitor-keys': 8.64.0 - eslint: 10.7.0(jiti@2.7.0)(supports-color@10.2.2) + eslint: 10.7.0(jiti@2.7.0)(supports-color@11.0.0) ignore: 7.0.6 natural-compare: 1.4.0 ts-api-utils: 2.5.0(typescript@6.0.3) @@ -11360,23 +11573,23 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': + '@typescript-eslint/parser@8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3)': dependencies: '@typescript-eslint/scope-manager': 8.64.0 '@typescript-eslint/types': 8.64.0 - '@typescript-eslint/typescript-estree': 8.64.0(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/typescript-estree': 8.64.0(supports-color@11.0.0)(typescript@6.0.3) '@typescript-eslint/visitor-keys': 8.64.0 - debug: 4.4.3(supports-color@10.2.2) - eslint: 10.7.0(jiti@2.7.0)(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) + eslint: 10.7.0(jiti@2.7.0)(supports-color@11.0.0) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.64.0(supports-color@10.2.2)(typescript@6.0.3)': + '@typescript-eslint/project-service@8.64.0(supports-color@11.0.0)(typescript@6.0.3)': dependencies: '@typescript-eslint/tsconfig-utils': 8.64.0(typescript@6.0.3) '@typescript-eslint/types': 8.64.0 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) typescript: 6.0.3 transitivePeerDependencies: - supports-color @@ -11390,13 +11603,13 @@ snapshots: dependencies: typescript: 6.0.3 - '@typescript-eslint/type-utils@8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': + '@typescript-eslint/type-utils@8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3)': dependencies: '@typescript-eslint/types': 8.64.0 - '@typescript-eslint/typescript-estree': 8.64.0(supports-color@10.2.2)(typescript@6.0.3) - '@typescript-eslint/utils': 8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) - debug: 4.4.3(supports-color@10.2.2) - eslint: 10.7.0(jiti@2.7.0)(supports-color@10.2.2) + '@typescript-eslint/typescript-estree': 8.64.0(supports-color@11.0.0)(typescript@6.0.3) + '@typescript-eslint/utils': 8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3) + debug: 4.4.3(supports-color@11.0.0) + eslint: 10.7.0(jiti@2.7.0)(supports-color@11.0.0) ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 transitivePeerDependencies: @@ -11404,16 +11617,16 @@ snapshots: '@typescript-eslint/types@8.64.0': {} - '@typescript-eslint/types@8.65.0': {} + '@typescript-eslint/types@8.67.0': {} - '@typescript-eslint/typescript-estree@8.64.0(supports-color@10.2.2)(typescript@6.0.3)': + '@typescript-eslint/typescript-estree@8.64.0(supports-color@11.0.0)(typescript@6.0.3)': dependencies: - '@typescript-eslint/project-service': 8.64.0(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/project-service': 8.64.0(supports-color@11.0.0)(typescript@6.0.3) '@typescript-eslint/tsconfig-utils': 8.64.0(typescript@6.0.3) '@typescript-eslint/types': 8.64.0 '@typescript-eslint/visitor-keys': 8.64.0 - debug: 4.4.3(supports-color@10.2.2) - minimatch: 10.2.5 + debug: 4.4.3(supports-color@11.0.0) + minimatch: 10.2.6 semver: 7.8.5 tinyglobby: 0.2.17 ts-api-utils: 2.5.0(typescript@6.0.3) @@ -11421,13 +11634,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': + '@typescript-eslint/utils@8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3)': dependencies: - '@eslint-community/eslint-utils': 4.10.1(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2)) + '@eslint-community/eslint-utils': 4.10.1(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0)) '@typescript-eslint/scope-manager': 8.64.0 '@typescript-eslint/types': 8.64.0 - '@typescript-eslint/typescript-estree': 8.64.0(supports-color@10.2.2)(typescript@6.0.3) - eslint: 10.7.0(jiti@2.7.0)(supports-color@10.2.2) + '@typescript-eslint/typescript-estree': 8.64.0(supports-color@11.0.0)(typescript@6.0.3) + eslint: 10.7.0(jiti@2.7.0)(supports-color@11.0.0) typescript: 6.0.3 transitivePeerDependencies: - supports-color @@ -11437,22 +11650,22 @@ snapshots: '@typescript-eslint/types': 8.64.0 eslint-visitor-keys: 5.0.1 - '@verdaccio/auth@8.0.4(supports-color@10.2.2)': + '@verdaccio/auth@8.0.4(supports-color@11.0.0)': dependencies: - '@verdaccio/config': 8.1.2(supports-color@10.2.2) + '@verdaccio/config': 8.1.2(supports-color@11.0.0) '@verdaccio/core': 8.1.2 - '@verdaccio/loaders': 8.0.3(supports-color@10.2.2) - '@verdaccio/signature': 8.0.3(supports-color@10.2.2) - debug: 4.4.3(supports-color@10.2.2) + '@verdaccio/loaders': 8.0.3(supports-color@11.0.0) + '@verdaccio/signature': 8.0.3(supports-color@11.0.0) + debug: 4.4.3(supports-color@11.0.0) lodash: 4.18.1 - verdaccio-htpasswd: 13.0.3(supports-color@10.2.2) + verdaccio-htpasswd: 13.0.3(supports-color@11.0.0) transitivePeerDependencies: - supports-color - '@verdaccio/config@8.1.2(supports-color@10.2.2)': + '@verdaccio/config@8.1.2(supports-color@11.0.0)': dependencies: '@verdaccio/core': 8.1.2 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) js-yaml: 4.1.1 lodash: 4.18.1 transitivePeerDependencies: @@ -11467,34 +11680,43 @@ snapshots: process-warning: 1.0.0 semver: 7.7.4 + '@verdaccio/core@8.2.2': + dependencies: + ajv: 8.20.0 + http-errors: 2.0.1 + http-status-codes: 2.3.0 + minimatch: 10.2.6 + process-warning: 1.0.0 + semver: 7.8.5 + '@verdaccio/file-locking@13.0.1': dependencies: lockfile: 1.0.4 - '@verdaccio/hooks@8.0.4(supports-color@10.2.2)': + '@verdaccio/hooks@8.0.4(supports-color@11.0.0)': dependencies: '@verdaccio/core': 8.1.2 - '@verdaccio/logger': 8.0.3(supports-color@10.2.2) - debug: 4.4.3(supports-color@10.2.2) + '@verdaccio/logger': 8.0.3(supports-color@11.0.0) + debug: 4.4.3(supports-color@11.0.0) got-cjs: 12.5.4 handlebars: 4.7.9 transitivePeerDependencies: - supports-color - '@verdaccio/loaders@8.0.3(supports-color@10.2.2)': + '@verdaccio/loaders@8.0.3(supports-color@11.0.0)': dependencies: '@verdaccio/core': 8.1.2 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) lodash: 4.18.1 transitivePeerDependencies: - supports-color - '@verdaccio/local-storage-legacy@11.3.4(supports-color@10.2.2)': + '@verdaccio/local-storage-legacy@11.3.4(supports-color@11.0.0)': dependencies: '@verdaccio/core': 8.1.2 '@verdaccio/file-locking': 13.0.1 '@verdaccio/streams': 10.2.5 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) globby: 11.1.0 lodash: 4.18.1 lowdb: 1.0.0 @@ -11503,12 +11725,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@verdaccio/logger-commons@8.0.3(supports-color@10.2.2)': + '@verdaccio/logger-commons@8.0.3(supports-color@11.0.0)': dependencies: '@verdaccio/core': 8.1.2 '@verdaccio/logger-prettify': 8.0.1 colorette: 2.0.20 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) transitivePeerDependencies: - supports-color @@ -11521,57 +11743,57 @@ snapshots: pino-abstract-transport: 1.2.0 sonic-boom: 3.8.1 - '@verdaccio/logger@8.0.3(supports-color@10.2.2)': + '@verdaccio/logger@8.0.3(supports-color@11.0.0)': dependencies: - '@verdaccio/logger-commons': 8.0.3(supports-color@10.2.2) + '@verdaccio/logger-commons': 8.0.3(supports-color@11.0.0) pino: 9.14.0 transitivePeerDependencies: - supports-color - '@verdaccio/middleware@8.0.5(supports-color@10.2.2)': + '@verdaccio/middleware@8.0.5(supports-color@11.0.0)': dependencies: - '@verdaccio/config': 8.1.2(supports-color@10.2.2) + '@verdaccio/config': 8.1.2(supports-color@11.0.0) '@verdaccio/core': 8.1.2 - '@verdaccio/url': 13.0.3(supports-color@10.2.2) - debug: 4.4.3(supports-color@10.2.2) - express: 4.22.1(supports-color@10.2.2) + '@verdaccio/url': 13.0.3(supports-color@11.0.0) + debug: 4.4.3(supports-color@11.0.0) + express: 4.22.1(supports-color@11.0.0) express-rate-limit: 5.5.1 lodash: 4.18.1 lru-cache: 7.18.3 transitivePeerDependencies: - supports-color - '@verdaccio/package-filter@13.0.3(supports-color@10.2.2)': + '@verdaccio/package-filter@13.0.3(supports-color@11.0.0)': dependencies: '@verdaccio/core': 8.1.2 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) semver: 7.7.4 transitivePeerDependencies: - supports-color - '@verdaccio/search-indexer@8.0.2(supports-color@10.2.2)': + '@verdaccio/search-indexer@8.0.2(supports-color@11.0.0)': dependencies: - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) fuse.js: 7.3.0 transitivePeerDependencies: - supports-color - '@verdaccio/signature@8.0.3(supports-color@10.2.2)': + '@verdaccio/signature@8.0.3(supports-color@11.0.0)': dependencies: - '@verdaccio/config': 8.1.2(supports-color@10.2.2) + '@verdaccio/config': 8.1.2(supports-color@11.0.0) '@verdaccio/core': 8.1.2 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) jsonwebtoken: 9.0.3 transitivePeerDependencies: - supports-color '@verdaccio/streams@10.2.5': {} - '@verdaccio/tarball@13.0.3(supports-color@10.2.2)': + '@verdaccio/tarball@13.0.3(supports-color@11.0.0)': dependencies: '@verdaccio/core': 8.1.2 - '@verdaccio/url': 13.0.3(supports-color@10.2.2) - debug: 4.4.3(supports-color@10.2.2) + '@verdaccio/url': 13.0.3(supports-color@11.0.0) + debug: 4.4.3(supports-color@11.0.0) gunzip-maybe: 1.4.2 tar-stream: 3.1.7 transitivePeerDependencies: @@ -11579,16 +11801,16 @@ snapshots: - react-native-b4a - supports-color - '@verdaccio/ui-theme@9.0.0-next-9.21(supports-color@10.2.2)': + '@verdaccio/ui-theme@9.0.0-next-9.21(supports-color@11.0.0)': dependencies: - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) transitivePeerDependencies: - supports-color - '@verdaccio/url@13.0.3(supports-color@10.2.2)': + '@verdaccio/url@13.0.3(supports-color@11.0.0)': dependencies: '@verdaccio/core': 8.1.2 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) validator: 13.15.26 transitivePeerDependencies: - supports-color @@ -11599,9 +11821,9 @@ snapshots: lodash: 4.18.1 minimatch: 7.4.9 - '@vitejs/plugin-basic-ssl@2.3.0(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.7)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0))': + '@vitejs/plugin-basic-ssl@2.3.0(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.0(supports-color@11.0.0))(sass@1.101.0)(terser@5.49.0)(tsx@4.23.12)(yaml@2.9.0))': dependencies: - vite: 8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.7)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0) + vite: 8.1.5(@types/node@22.20.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.0(supports-color@11.0.0))(sass@1.101.0)(terser@5.49.0)(tsx@4.23.12)(yaml@2.9.0) '@vitest/coverage-v8@4.1.10(vitest@4.1.10)': dependencies: @@ -11611,11 +11833,11 @@ snapshots: istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-reports: 3.2.0 - magicast: 0.5.3 + magicast: 0.5.4 obug: 2.1.4 std-env: 4.2.0 - tinyrainbow: 3.1.0 - vitest: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/coverage-v8@4.1.10)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(less@4.6.7)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0) + tinyrainbow: 3.1.1 + vitest: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(@vitest/coverage-v8@4.1.10)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@29.1.1)(less@4.9.0(supports-color@11.0.0))(sass@1.101.0)(terser@5.49.0)(tsx@4.23.12)(yaml@2.9.0) '@vitest/expect@4.1.10': dependencies: @@ -11624,19 +11846,19 @@ snapshots: '@vitest/spy': 4.1.10 '@vitest/utils': 4.1.10 chai: 6.2.2 - tinyrainbow: 3.1.0 + tinyrainbow: 3.1.1 - '@vitest/mocker@4.1.10(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.7)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0))': + '@vitest/mocker@4.1.10(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.0(supports-color@11.0.0))(sass@1.101.0)(terser@5.49.0)(tsx@4.23.12)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.10 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.7)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0) + vite: 8.1.5(@types/node@22.20.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.0(supports-color@11.0.0))(sass@1.101.0)(terser@5.49.0)(tsx@4.23.12)(yaml@2.9.0) '@vitest/pretty-format@4.1.10': dependencies: - tinyrainbow: 3.1.0 + tinyrainbow: 3.1.1 '@vitest/runner@4.1.10': dependencies: @@ -11656,7 +11878,7 @@ snapshots: dependencies: '@vitest/pretty-format': 4.1.10 convert-source-map: 2.0.0 - tinyrainbow: 3.1.0 + tinyrainbow: 3.1.1 '@webassemblyjs/ast@1.14.1': dependencies: @@ -11734,7 +11956,7 @@ snapshots: '@webassemblyjs/ast': 1.14.1 '@xtuc/long': 4.2.2 - '@xmldom/xmldom@0.8.13': {} + '@xmldom/xmldom@0.8.15': {} '@xtuc/ieee754@1.2.0': {} @@ -11759,26 +11981,22 @@ snapshots: accepts@2.0.0: dependencies: mime-types: 3.0.2 - negotiator: 1.0.0 - - acorn-import-phases@1.0.4(acorn@8.17.0): - dependencies: - acorn: 8.17.0 + negotiator: 1.1.0 - acorn-jsx@5.3.2(acorn@8.17.0): + acorn-jsx@5.3.2(acorn@8.18.0): dependencies: - acorn: 8.17.0 + acorn: 8.18.0 - acorn@8.17.0: {} + acorn@8.18.0: {} adjust-sourcemap-loader@4.0.0: dependencies: loader-utils: 2.0.4 regex-parser: 2.3.1 - agent-base@6.0.2(supports-color@10.2.2): + agent-base@6.0.2(supports-color@11.0.0): dependencies: - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) transitivePeerDependencies: - supports-color @@ -11809,14 +12027,14 @@ snapshots: ajv@8.18.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.4 + fast-uri: 3.1.6 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 ajv@8.20.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.4 + fast-uri: 3.1.6 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 @@ -11830,7 +12048,7 @@ snapshots: ansi-regex@5.0.1: {} - ansi-regex@6.2.2: {} + ansi-regex@6.3.0: {} ansi-styles@4.3.0: dependencies: @@ -11916,7 +12134,7 @@ snapshots: asn1js@3.0.10: dependencies: pvtsutils: 1.3.6 - pvutils: 1.1.5 + pvutils: 1.2.0 tslib: 2.8.1 assert-plus@1.0.0: {} @@ -11943,13 +12161,13 @@ snapshots: atomic-sleep@1.0.0: {} - autoprefixer@10.5.4(postcss@8.5.19): + autoprefixer@10.5.4(postcss@8.5.25): dependencies: - browserslist: 4.28.7 - caniuse-lite: 1.0.30001806 + browserslist: 4.28.8 + caniuse-lite: 1.0.30001809 fraction.js: 5.3.4 picocolors: 1.1.1 - postcss: 8.5.19 + postcss: 8.5.25 postcss-value-parser: 4.2.0 available-typed-arrays@1.0.7: @@ -11962,18 +12180,18 @@ snapshots: b4a@1.8.1: {} - babel-loader@10.1.1(@babel/core@8.0.1)(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)): + babel-loader@10.1.1(@babel/core@8.0.1)(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)): dependencies: '@babel/core': 8.0.1 find-up: 5.0.0 optionalDependencies: - webpack: 5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3) + webpack: 5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3) babel-plugin-polyfill-corejs3@1.0.0(@babel/core@8.0.1): dependencies: '@babel/core': 8.0.1 '@babel/helper-define-polyfill-provider': 1.0.0(@babel/core@8.0.1) - core-js-compat: 3.49.0 + core-js-compat: 3.50.0 balanced-match@1.0.2: {} @@ -11981,12 +12199,12 @@ snapshots: bare-events@2.9.1: {} - bare-fs@4.7.4: + bare-fs@4.8.0: dependencies: bare-events: 2.9.1 bare-path: 3.1.1 bare-stream: 2.13.3(bare-events@2.9.1) - bare-url: 2.4.6 + bare-url: 2.5.2 fast-fifo: 1.3.2 transitivePeerDependencies: - bare-abort-controller @@ -12004,7 +12222,7 @@ snapshots: transitivePeerDependencies: - react-native-b4a - bare-url@2.4.6: + bare-url@2.5.2: dependencies: bare-path: 3.1.1 @@ -12012,7 +12230,7 @@ snapshots: base64id@2.0.0: {} - baseline-browser-mapping@2.11.0: {} + baseline-browser-mapping@2.11.18: {} batch@0.6.1: {} @@ -12030,9 +12248,9 @@ snapshots: domhandler: 5.0.3 htmlparser2: 10.1.0 picocolors: 1.1.1 - postcss: 8.5.19 + postcss: 8.5.25 postcss-media-query-parser: 0.2.3 - postcss-safe-parser: 7.0.1(postcss@8.5.19) + postcss-safe-parser: 7.0.1(postcss@8.5.25) before-after-hook@4.0.0: {} @@ -12048,11 +12266,11 @@ snapshots: binary-extensions@2.3.0: {} - body-parser@1.20.6(supports-color@10.2.2): + body-parser@1.20.6(supports-color@11.0.0): dependencies: bytes: 3.1.2 content-type: 1.0.5 - debug: 2.6.9(supports-color@10.2.2) + debug: 2.6.9(supports-color@11.0.0) depd: 2.0.0 destroy: 1.2.0 http-errors: 2.0.1 @@ -12065,11 +12283,11 @@ snapshots: transitivePeerDependencies: - supports-color - body-parser@2.3.0(supports-color@10.2.2): + body-parser@2.3.0(supports-color@11.0.0): dependencies: bytes: 3.1.2 - content-type: 2.0.0 - debug: 4.4.3(supports-color@10.2.2) + content-type: 2.1.0 + debug: 4.4.3(supports-color@11.0.0) http-errors: 2.0.1 iconv-lite: 0.7.3 on-finished: 2.4.1 @@ -12079,23 +12297,23 @@ snapshots: transitivePeerDependencies: - supports-color - bonjour-service@1.4.3: + bonjour-service@1.4.4: dependencies: fast-deep-equal: 3.1.3 multicast-dns: 7.2.5 boolbase@1.0.0: {} - brace-expansion@1.1.16: + brace-expansion@1.1.18: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - brace-expansion@2.1.2: + brace-expansion@2.1.4: dependencies: balanced-match: 1.0.2 - brace-expansion@5.0.7: + brace-expansion@5.0.9: dependencies: balanced-match: 4.0.4 @@ -12111,28 +12329,28 @@ snapshots: fresh: 0.5.2 mitt: 1.2.0 - browser-sync-ui@3.0.4(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6): + browser-sync-ui@3.0.4(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6): dependencies: async-each-series: 0.1.1 chalk: 4.1.2 connect-history-api-fallback: 1.6.0 - immutable: 3.8.3 + immutable: 3.8.4 server-destroy: 1.0.1 - socket.io-client: 4.8.3(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) + socket.io-client: 4.8.3(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6) stream-throttle: 0.1.3 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - browser-sync@3.0.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6): + browser-sync@3.0.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6): dependencies: browser-sync-client: 3.0.4 - browser-sync-ui: 3.0.4(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) + browser-sync-ui: 3.0.4(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6) bs-recipes: 1.3.4 chalk: 4.1.2 chokidar: 3.6.0 - connect: 3.6.6(supports-color@10.2.2) + connect: 3.6.6(supports-color@11.0.0) connect-history-api-fallback: 1.6.0 dev-ip: 1.0.1 easy-extender: 2.3.4 @@ -12140,19 +12358,19 @@ snapshots: etag: 1.8.1 fresh: 0.5.2 fs-extra: 3.0.1 - http-proxy: 1.18.1(debug@4.4.3(supports-color@10.2.2)) - immutable: 3.8.3 + http-proxy: 1.18.1(debug@4.4.3(supports-color@11.0.0)) + immutable: 3.8.4 micromatch: 4.0.8 opn: 5.3.0 portscanner: 2.2.0 raw-body: 2.5.3 - resp-modifier: 6.0.2(supports-color@10.2.2) + resp-modifier: 6.0.2(supports-color@11.0.0) rx: 4.1.0 - send: 0.19.2(supports-color@10.2.2) - serve-index: 1.9.2(supports-color@10.2.2) - serve-static: 1.16.3(supports-color@10.2.2) + send: 0.19.2(supports-color@11.0.0) + serve-index: 1.9.2(supports-color@11.0.0) + serve-static: 1.16.3(supports-color@11.0.0) server-destroy: 1.0.1 - socket.io: 4.8.3(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) + socket.io: 4.8.3(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6) ua-parser-js: 1.0.41 yargs: 17.7.3 transitivePeerDependencies: @@ -12165,13 +12383,13 @@ snapshots: dependencies: pako: 0.2.9 - browserslist@4.28.7: + browserslist@4.28.8: dependencies: - baseline-browser-mapping: 2.11.0 - caniuse-lite: 1.0.30001806 - electron-to-chromium: 1.5.395 - node-releases: 2.0.51 - update-browserslist-db: 1.2.3(browserslist@4.28.7) + baseline-browser-mapping: 2.11.18 + caniuse-lite: 1.0.30001809 + electron-to-chromium: 1.5.412 + node-releases: 2.0.53 + update-browserslist-db: 1.3.1(browserslist@4.28.8) bs-recipes@1.3.4: {} @@ -12227,7 +12445,7 @@ snapshots: callsites@3.1.0: {} - caniuse-lite@1.0.30001806: {} + caniuse-lite@1.0.30001809: {} caseless@0.12.0: {} @@ -12264,7 +12482,7 @@ snapshots: chokidar@5.0.0: dependencies: - readdirp: 5.0.0 + readdirp: 5.1.1 chrome-trace-event@1.0.4: {} @@ -12284,9 +12502,9 @@ snapshots: cli-spinners@3.4.0: {} - cli-truncate@5.2.0: + cli-truncate@6.1.1: dependencies: - slice-ansi: 8.0.0 + slice-ansi: 9.0.0 string-width: 8.2.2 cli-width@4.1.0: {} @@ -12351,11 +12569,11 @@ snapshots: dependencies: mime-db: 1.54.0 - compression@1.8.1(supports-color@10.2.2): + compression@1.8.1(supports-color@11.0.0): dependencies: bytes: 3.1.2 compressible: 2.0.18 - debug: 2.6.9(supports-color@10.2.2) + debug: 2.6.9(supports-color@11.0.0) negotiator: 0.6.4 on-headers: 1.1.0 safe-buffer: 5.2.1 @@ -12369,19 +12587,19 @@ snapshots: connect-history-api-fallback@2.0.0: {} - connect@3.6.6(supports-color@10.2.2): + connect@3.6.6(supports-color@11.0.0): dependencies: - debug: 2.6.9(supports-color@10.2.2) - finalhandler: 1.1.0(supports-color@10.2.2) + debug: 2.6.9(supports-color@11.0.0) + finalhandler: 1.1.0(supports-color@11.0.0) parseurl: 1.3.3 utils-merge: 1.0.1 transitivePeerDependencies: - supports-color - connect@3.7.0(supports-color@10.2.2): + connect@3.7.0(supports-color@11.0.0): dependencies: - debug: 2.6.9(supports-color@10.2.2) - finalhandler: 1.1.2(supports-color@10.2.2) + debug: 2.6.9(supports-color@11.0.0) + finalhandler: 1.1.2(supports-color@11.0.0) parseurl: 1.3.3 utils-merge: 1.0.1 transitivePeerDependencies: @@ -12397,11 +12615,13 @@ snapshots: content-type@1.0.5: {} - content-type@2.0.0: {} + content-type@2.1.0: {} + + content-type@3.0.0: {} conventional-commits-filter@6.0.1: {} - conventional-commits-parser@7.1.0: + conventional-commits-parser@7.1.2: dependencies: '@simple-libs/stream-utils': 2.0.0 argue-cli: 3.1.0 @@ -12420,18 +12640,18 @@ snapshots: dependencies: is-what: 4.1.16 - copy-webpack-plugin@14.0.0(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)): + copy-webpack-plugin@14.0.0(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)): dependencies: glob-parent: 6.0.2 normalize-path: 3.0.0 schema-utils: 4.3.3 - serialize-javascript: 7.0.7 + serialize-javascript: 7.1.0 tinyglobby: 0.2.17 - webpack: 5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3) + webpack: 5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3) - core-js-compat@3.49.0: + core-js-compat@3.50.0: dependencies: - browserslist: 4.28.7 + browserslist: 4.28.8 core-util-is@1.0.2: {} @@ -12446,7 +12666,7 @@ snapshots: dependencies: env-paths: 2.2.1 import-fresh: 3.3.1 - js-yaml: 4.3.0 + js-yaml: 4.3.1 parse-json: 5.2.0 optionalDependencies: typescript: 6.0.3 @@ -12457,18 +12677,18 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - css-loader@7.1.4(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)): + css-loader@7.1.4(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)): dependencies: - icss-utils: 5.1.0(postcss@8.5.19) - postcss: 8.5.19 - postcss-modules-extract-imports: 3.1.0(postcss@8.5.19) - postcss-modules-local-by-default: 4.2.0(postcss@8.5.19) - postcss-modules-scope: 3.2.1(postcss@8.5.19) - postcss-modules-values: 4.0.0(postcss@8.5.19) + icss-utils: 5.1.0(postcss@8.5.25) + postcss: 8.5.25 + postcss-modules-extract-imports: 3.1.0(postcss@8.5.25) + postcss-modules-local-by-default: 4.2.0(postcss@8.5.25) + postcss-modules-scope: 3.2.1(postcss@8.5.25) + postcss-modules-values: 4.0.0(postcss@8.5.25) postcss-value-parser: 4.2.0 semver: 7.8.5 optionalDependencies: - webpack: 5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3) + webpack: 5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3) css-select@6.0.0: dependencies: @@ -12524,29 +12744,29 @@ snapshots: dayjs@1.11.18: {} - debug@2.6.9(supports-color@10.2.2): + debug@2.6.9(supports-color@11.0.0): dependencies: ms: 2.0.0 optionalDependencies: - supports-color: 10.2.2 + supports-color: 11.0.0 - debug@3.2.7(supports-color@10.2.2): + debug@3.2.7(supports-color@11.0.0): dependencies: ms: 2.1.3 optionalDependencies: - supports-color: 10.2.2 + supports-color: 11.0.0 - debug@4.4.0(supports-color@10.2.2): + debug@4.4.0(supports-color@11.0.0): dependencies: ms: 2.1.3 optionalDependencies: - supports-color: 10.2.2 + supports-color: 11.0.0 - debug@4.4.3(supports-color@10.2.2): + debug@4.4.3(supports-color@11.0.0): dependencies: ms: 2.1.3 optionalDependencies: - supports-color: 10.2.2 + supports-color: 11.0.0 decimal.js@10.6.0: {} @@ -12560,7 +12780,7 @@ snapshots: default-browser-id@5.0.1: {} - default-browser@5.5.0: + default-browser@5.5.1: dependencies: bundle-name: 4.1.0 default-browser-id: 5.0.1 @@ -12683,7 +12903,7 @@ snapshots: ejs@6.0.1: {} - electron-to-chromium@1.5.395: {} + electron-to-chromium@1.5.412: {} emoji-regex@10.6.0: {} @@ -12707,12 +12927,12 @@ snapshots: dependencies: once: 1.4.0 - engine.io-client@6.6.6(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6): + engine.io-client@6.6.6(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6): dependencies: '@socket.io/component-emitter': 3.1.2 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) engine.io-parser: 5.2.3 - ws: 8.21.1(bufferutil@4.1.0)(utf-8-validate@6.0.6) + ws: 8.21.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) xmlhttprequest-ssl: 2.1.2 transitivePeerDependencies: - bufferutil @@ -12721,7 +12941,7 @@ snapshots: engine.io-parser@5.2.3: {} - engine.io@6.6.9(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6): + engine.io@6.6.9(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6): dependencies: '@types/cors': 2.8.19 '@types/node': 22.20.1 @@ -12730,15 +12950,15 @@ snapshots: base64id: 2.0.0 cookie: 0.7.2 cors: 2.8.6 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) engine.io-parser: 5.2.3 - ws: 8.21.1(bufferutil@4.1.0)(utf-8-validate@6.0.6) + ws: 8.21.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - enhanced-resolve@5.24.3: + enhanced-resolve@5.24.5: dependencies: graceful-fs: 4.2.11 tapable: 2.3.3 @@ -12839,7 +13059,7 @@ snapshots: es-errors@1.3.0: {} - es-module-lexer@2.3.1: {} + es-module-lexer@2.3.2: {} es-object-atoms@1.1.2: dependencies: @@ -12865,36 +13085,36 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 - esbuild-wasm@0.28.1: {} + esbuild-wasm@0.28.2: {} - esbuild@0.28.1: + esbuild@0.28.2: optionalDependencies: - '@esbuild/aix-ppc64': 0.28.1 - '@esbuild/android-arm': 0.28.1 - '@esbuild/android-arm64': 0.28.1 - '@esbuild/android-x64': 0.28.1 - '@esbuild/darwin-arm64': 0.28.1 - '@esbuild/darwin-x64': 0.28.1 - '@esbuild/freebsd-arm64': 0.28.1 - '@esbuild/freebsd-x64': 0.28.1 - '@esbuild/linux-arm': 0.28.1 - '@esbuild/linux-arm64': 0.28.1 - '@esbuild/linux-ia32': 0.28.1 - '@esbuild/linux-loong64': 0.28.1 - '@esbuild/linux-mips64el': 0.28.1 - '@esbuild/linux-ppc64': 0.28.1 - '@esbuild/linux-riscv64': 0.28.1 - '@esbuild/linux-s390x': 0.28.1 - '@esbuild/linux-x64': 0.28.1 - '@esbuild/netbsd-arm64': 0.28.1 - '@esbuild/netbsd-x64': 0.28.1 - '@esbuild/openbsd-arm64': 0.28.1 - '@esbuild/openbsd-x64': 0.28.1 - '@esbuild/openharmony-arm64': 0.28.1 - '@esbuild/sunos-x64': 0.28.1 - '@esbuild/win32-arm64': 0.28.1 - '@esbuild/win32-ia32': 0.28.1 - '@esbuild/win32-x64': 0.28.1 + '@esbuild/aix-ppc64': 0.28.2 + '@esbuild/android-arm': 0.28.2 + '@esbuild/android-arm64': 0.28.2 + '@esbuild/android-x64': 0.28.2 + '@esbuild/darwin-arm64': 0.28.2 + '@esbuild/darwin-x64': 0.28.2 + '@esbuild/freebsd-arm64': 0.28.2 + '@esbuild/freebsd-x64': 0.28.2 + '@esbuild/linux-arm': 0.28.2 + '@esbuild/linux-arm64': 0.28.2 + '@esbuild/linux-ia32': 0.28.2 + '@esbuild/linux-loong64': 0.28.2 + '@esbuild/linux-mips64el': 0.28.2 + '@esbuild/linux-ppc64': 0.28.2 + '@esbuild/linux-riscv64': 0.28.2 + '@esbuild/linux-s390x': 0.28.2 + '@esbuild/linux-x64': 0.28.2 + '@esbuild/netbsd-arm64': 0.28.2 + '@esbuild/netbsd-x64': 0.28.2 + '@esbuild/openbsd-arm64': 0.28.2 + '@esbuild/openbsd-x64': 0.28.2 + '@esbuild/openharmony-arm64': 0.28.2 + '@esbuild/sunos-x64': 0.28.2 + '@esbuild/win32-arm64': 0.28.2 + '@esbuild/win32-ia32': 0.28.2 + '@esbuild/win32-x64': 0.28.2 escalade@3.2.0: {} @@ -12902,40 +13122,40 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-prettier@10.1.8(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2)): + eslint-config-prettier@10.1.8(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0)): dependencies: - eslint: 10.7.0(jiti@2.7.0)(supports-color@10.2.2) + eslint: 10.7.0(jiti@2.7.0)(supports-color@11.0.0) - eslint-import-resolver-node@0.3.10(supports-color@10.2.2): + eslint-import-resolver-node@0.3.10(supports-color@11.0.0): dependencies: - debug: 3.2.7(supports-color@10.2.2) + debug: 3.2.7(supports-color@11.0.0) is-core-module: 2.16.2 resolve: 2.0.0-next.7 transitivePeerDependencies: - supports-color - eslint-module-utils@2.14.0(@typescript-eslint/parser@8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint-import-resolver-node@0.3.10(supports-color@10.2.2))(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2): + eslint-module-utils@2.14.0(@typescript-eslint/parser@8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3))(eslint-import-resolver-node@0.3.10(supports-color@11.0.0))(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0): dependencies: - debug: 3.2.7(supports-color@10.2.2) + debug: 3.2.7(supports-color@11.0.0) optionalDependencies: - '@typescript-eslint/parser': 8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) - eslint: 10.7.0(jiti@2.7.0)(supports-color@10.2.2) - eslint-import-resolver-node: 0.3.10(supports-color@10.2.2) + '@typescript-eslint/parser': 8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3) + eslint: 10.7.0(jiti@2.7.0)(supports-color@11.0.0) + eslint-import-resolver-node: 0.3.10(supports-color@11.0.0) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3))(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 array.prototype.findlastindex: 1.2.6 array.prototype.flat: 1.3.3 array.prototype.flatmap: 1.3.3 - debug: 3.2.7(supports-color@10.2.2) + debug: 3.2.7(supports-color@11.0.0) doctrine: 2.1.0 - eslint: 10.7.0(jiti@2.7.0)(supports-color@10.2.2) - eslint-import-resolver-node: 0.3.10(supports-color@10.2.2) - eslint-module-utils: 2.14.0(@typescript-eslint/parser@8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint-import-resolver-node@0.3.10(supports-color@10.2.2))(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2) + eslint: 10.7.0(jiti@2.7.0)(supports-color@11.0.0) + eslint-import-resolver-node: 0.3.10(supports-color@11.0.0) + eslint-module-utils: 2.14.0(@typescript-eslint/parser@8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3))(eslint-import-resolver-node@0.3.10(supports-color@11.0.0))(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0) hasown: 2.0.4 is-core-module: 2.16.2 is-glob: 4.0.3 @@ -12947,7 +13167,7 @@ snapshots: string.prototype.trimend: 1.0.10 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/parser': 8.64.0(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -12971,11 +13191,11 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2): + eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0): dependencies: - '@eslint-community/eslint-utils': 4.10.1(eslint@10.7.0(jiti@2.7.0)(supports-color@10.2.2)) + '@eslint-community/eslint-utils': 4.10.1(eslint@10.7.0(jiti@2.7.0)(supports-color@11.0.0)) '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.23.5(supports-color@10.2.2) + '@eslint/config-array': 0.23.5(supports-color@11.0.0) '@eslint/config-helpers': 0.6.0 '@eslint/core': 1.2.1 '@eslint/plugin-kit': 0.7.2 @@ -12985,7 +13205,7 @@ snapshots: '@types/estree': 1.0.9 ajv: 6.15.0 cross-spawn: 7.0.6 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) escape-string-regexp: 4.0.0 eslint-scope: 9.1.2 eslint-visitor-keys: 5.0.1 @@ -13000,7 +13220,7 @@ snapshots: imurmurhash: 0.1.4 is-glob: 4.0.3 json-stable-stringify-without-jsonify: 1.0.1 - minimatch: 10.2.5 + minimatch: 10.2.6 natural-compare: 1.4.0 optionator: 0.9.4 optionalDependencies: @@ -13010,14 +13230,14 @@ snapshots: espree@10.4.0: dependencies: - acorn: 8.17.0 - acorn-jsx: 5.3.2(acorn@8.17.0) + acorn: 8.18.0 + acorn-jsx: 5.3.2(acorn@8.18.0) eslint-visitor-keys: 4.2.1 espree@11.2.0: dependencies: - acorn: 8.17.0 - acorn-jsx: 5.3.2(acorn@8.17.0) + acorn: 8.18.0 + acorn-jsx: 5.3.2(acorn@8.18.0) eslint-visitor-keys: 5.0.1 esquery@1.7.0: @@ -13046,8 +13266,6 @@ snapshots: eventemitter3@4.0.7: {} - eventemitter3@5.0.4: {} - events-intercept@2.0.0: {} events-universal@1.0.1: @@ -13058,39 +13276,39 @@ snapshots: events@3.3.0: {} - eventsource-parser@3.1.0: {} + eventsource-parser@3.1.1: {} eventsource@3.0.7: dependencies: - eventsource-parser: 3.1.0 + eventsource-parser: 3.1.1 expect-type@1.4.0: {} express-rate-limit@5.5.1: {} - express-rate-limit@8.6.0(express@5.2.1(supports-color@10.2.2))(supports-color@10.2.2): + express-rate-limit@8.6.2(express@5.2.1(supports-color@11.0.0))(supports-color@11.0.0): dependencies: - debug: 4.4.3(supports-color@10.2.2) - express: 5.2.1(supports-color@10.2.2) - ip-address: 10.2.0 + debug: 4.4.3(supports-color@11.0.0) + express: 5.2.1(supports-color@11.0.0) + ip-address: 10.5.0 transitivePeerDependencies: - supports-color - express@4.22.1(supports-color@10.2.2): + express@4.22.1(supports-color@11.0.0): dependencies: accepts: 1.3.8 array-flatten: 1.1.1 - body-parser: 1.20.6(supports-color@10.2.2) + body-parser: 1.20.6(supports-color@11.0.0) content-disposition: 0.5.4 content-type: 1.0.5 cookie: 0.7.2 cookie-signature: 1.0.7 - debug: 2.6.9(supports-color@10.2.2) + debug: 2.6.9(supports-color@11.0.0) depd: 2.0.0 encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 - finalhandler: 1.3.2(supports-color@10.2.2) + finalhandler: 1.3.2(supports-color@11.0.0) fresh: 0.5.2 http-errors: 2.0.1 merge-descriptors: 1.0.3 @@ -13102,8 +13320,8 @@ snapshots: qs: 6.14.2 range-parser: 1.2.1 safe-buffer: 5.2.1 - send: 0.19.2(supports-color@10.2.2) - serve-static: 1.16.3(supports-color@10.2.2) + send: 0.19.2(supports-color@11.0.0) + serve-static: 1.16.3(supports-color@11.0.0) setprototypeof: 1.2.0 statuses: 2.0.2 type-is: 1.6.18 @@ -13112,21 +13330,21 @@ snapshots: transitivePeerDependencies: - supports-color - express@4.22.2(supports-color@10.2.2): + express@4.22.2(supports-color@11.0.0): dependencies: accepts: 1.3.8 array-flatten: 1.1.1 - body-parser: 1.20.6(supports-color@10.2.2) + body-parser: 1.20.6(supports-color@11.0.0) content-disposition: 0.5.4 content-type: 1.0.5 cookie: 0.7.2 cookie-signature: 1.0.7 - debug: 2.6.9(supports-color@10.2.2) + debug: 2.6.9(supports-color@11.0.0) depd: 2.0.0 encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 - finalhandler: 1.3.2(supports-color@10.2.2) + finalhandler: 1.3.2(supports-color@11.0.0) fresh: 0.5.2 http-errors: 2.0.1 merge-descriptors: 1.0.3 @@ -13138,8 +13356,8 @@ snapshots: qs: 6.15.3 range-parser: 1.2.1 safe-buffer: 5.2.1 - send: 0.19.2(supports-color@10.2.2) - serve-static: 1.16.3(supports-color@10.2.2) + send: 0.19.2(supports-color@11.0.0) + serve-static: 1.16.3(supports-color@11.0.0) setprototypeof: 1.2.0 statuses: 2.0.2 type-is: 1.6.18 @@ -13148,20 +13366,20 @@ snapshots: transitivePeerDependencies: - supports-color - express@5.2.1(supports-color@10.2.2): + express@5.2.1(supports-color@11.0.0): dependencies: accepts: 2.0.0 - body-parser: 2.3.0(supports-color@10.2.2) + body-parser: 2.3.0(supports-color@11.0.0) content-disposition: 1.1.0 content-type: 1.0.5 cookie: 0.7.2 cookie-signature: 1.2.2 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) depd: 2.0.0 encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 - finalhandler: 2.1.1(supports-color@10.2.2) + finalhandler: 2.1.1(supports-color@11.0.0) fresh: 2.0.0 http-errors: 2.0.1 merge-descriptors: 2.0.0 @@ -13172,9 +13390,9 @@ snapshots: proxy-addr: 2.0.7 qs: 6.15.3 range-parser: 1.3.0 - router: 2.2.0(supports-color@10.2.2) - send: 1.2.1(supports-color@10.2.2) - serve-static: 2.2.1(supports-color@10.2.2) + router: 2.2.0(supports-color@11.0.0) + send: 1.2.1(supports-color@11.0.0) + serve-static: 2.2.1(supports-color@11.0.0) statuses: 2.0.2 type-is: 2.1.0 vary: 1.1.2 @@ -13207,7 +13425,7 @@ snapshots: dependencies: fast-string-truncated-width: 3.0.3 - fast-uri@3.1.4: {} + fast-uri@3.1.6: {} fast-wrap-ansi@0.2.2: dependencies: @@ -13238,9 +13456,9 @@ snapshots: dependencies: to-regex-range: 5.0.1 - finalhandler@1.1.0(supports-color@10.2.2): + finalhandler@1.1.0(supports-color@11.0.0): dependencies: - debug: 2.6.9(supports-color@10.2.2) + debug: 2.6.9(supports-color@11.0.0) encodeurl: 1.0.2 escape-html: 1.0.3 on-finished: 2.3.0 @@ -13250,9 +13468,9 @@ snapshots: transitivePeerDependencies: - supports-color - finalhandler@1.1.2(supports-color@10.2.2): + finalhandler@1.1.2(supports-color@11.0.0): dependencies: - debug: 2.6.9(supports-color@10.2.2) + debug: 2.6.9(supports-color@11.0.0) encodeurl: 1.0.2 escape-html: 1.0.3 on-finished: 2.3.0 @@ -13262,9 +13480,9 @@ snapshots: transitivePeerDependencies: - supports-color - finalhandler@1.3.2(supports-color@10.2.2): + finalhandler@1.3.2(supports-color@11.0.0): dependencies: - debug: 2.6.9(supports-color@10.2.2) + debug: 2.6.9(supports-color@11.0.0) encodeurl: 2.0.0 escape-html: 1.0.3 on-finished: 2.4.1 @@ -13274,9 +13492,9 @@ snapshots: transitivePeerDependencies: - supports-color - finalhandler@2.1.1(supports-color@10.2.2): + finalhandler@2.1.1(supports-color@11.0.0): dependencies: - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) encodeurl: 2.0.0 escape-html: 1.0.3 on-finished: 2.4.1 @@ -13297,58 +13515,58 @@ snapshots: locate-path: 6.0.0 path-exists: 4.0.0 - firebase@12.16.0: + firebase@12.17.1: dependencies: - '@firebase/ai': 2.13.1(@firebase/app-types@0.9.5)(@firebase/app@0.15.1) - '@firebase/analytics': 0.10.22(@firebase/app@0.15.1) - '@firebase/analytics-compat': 0.2.28(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1) - '@firebase/app': 0.15.1 - '@firebase/app-check': 0.12.0(@firebase/app@0.15.1) - '@firebase/app-check-compat': 0.4.5(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1) - '@firebase/app-compat': 0.5.15 + '@firebase/ai': 2.14.0(@firebase/app-types@0.9.5)(@firebase/app@0.16.0) + '@firebase/analytics': 0.10.23(@firebase/app@0.16.0) + '@firebase/analytics-compat': 0.2.29(@firebase/app-compat@0.5.16)(@firebase/app@0.16.0) + '@firebase/app': 0.16.0 + '@firebase/app-check': 0.13.0(@firebase/app@0.16.0) + '@firebase/app-check-compat': 0.4.6(@firebase/app-compat@0.5.16)(@firebase/app@0.16.0) + '@firebase/app-compat': 0.5.16 '@firebase/app-types': 0.9.5 - '@firebase/auth': 1.13.3(@firebase/app@0.15.1) - '@firebase/auth-compat': 0.6.8(@firebase/app-compat@0.5.15)(@firebase/app-types@0.9.5)(@firebase/app@0.15.1) - '@firebase/data-connect': 0.7.1(@firebase/app@0.15.1) - '@firebase/database': 1.1.3 - '@firebase/database-compat': 2.1.4 - '@firebase/firestore': 4.16.0(@firebase/app@0.15.1) - '@firebase/firestore-compat': 0.4.11(@firebase/app-compat@0.5.15)(@firebase/app-types@0.9.5)(@firebase/app@0.15.1) - '@firebase/functions': 0.13.5(@firebase/app@0.15.1) - '@firebase/functions-compat': 0.4.5(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1) - '@firebase/installations': 0.6.22(@firebase/app@0.15.1) - '@firebase/installations-compat': 0.2.22(@firebase/app-compat@0.5.15)(@firebase/app-types@0.9.5)(@firebase/app@0.15.1) - '@firebase/messaging': 0.13.0(@firebase/app@0.15.1) - '@firebase/messaging-compat': 0.2.27(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1) - '@firebase/performance': 0.7.12(@firebase/app@0.15.1) - '@firebase/performance-compat': 0.2.25(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1) - '@firebase/remote-config': 0.9.0(@firebase/app@0.15.1) - '@firebase/remote-config-compat': 0.2.27(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1) - '@firebase/storage': 0.14.3(@firebase/app@0.15.1) - '@firebase/storage-compat': 0.4.3(@firebase/app-compat@0.5.15)(@firebase/app-types@0.9.5)(@firebase/app@0.15.1) - '@firebase/util': 1.15.1 + '@firebase/auth': 1.13.4(@firebase/app@0.16.0) + '@firebase/auth-compat': 0.6.9(@firebase/app-compat@0.5.16)(@firebase/app-types@0.9.5)(@firebase/app@0.16.0) + '@firebase/data-connect': 0.7.3(@firebase/app@0.16.0) + '@firebase/database': 1.1.4 + '@firebase/database-compat': 2.1.6(@firebase/app-compat@0.5.16)(@firebase/app@0.16.0) + '@firebase/firestore': 4.17.0(@firebase/app@0.16.0) + '@firebase/firestore-compat': 0.4.12(@firebase/app-compat@0.5.16)(@firebase/app-types@0.9.5)(@firebase/app@0.16.0) + '@firebase/functions': 0.13.6(@firebase/app@0.16.0) + '@firebase/functions-compat': 0.4.6(@firebase/app-compat@0.5.16)(@firebase/app@0.16.0) + '@firebase/installations': 0.6.23(@firebase/app@0.16.0) + '@firebase/installations-compat': 0.2.23(@firebase/app-compat@0.5.16)(@firebase/app-types@0.9.5)(@firebase/app@0.16.0) + '@firebase/messaging': 0.13.1(@firebase/app@0.16.0) + '@firebase/messaging-compat': 0.2.28(@firebase/app-compat@0.5.16)(@firebase/app@0.16.0) + '@firebase/performance': 0.7.13(@firebase/app@0.16.0) + '@firebase/performance-compat': 0.2.26(@firebase/app-compat@0.5.16)(@firebase/app@0.16.0) + '@firebase/remote-config': 0.9.1(@firebase/app@0.16.0) + '@firebase/remote-config-compat': 0.2.28(@firebase/app-compat@0.5.16)(@firebase/app@0.16.0) + '@firebase/storage': 0.14.4(@firebase/app@0.16.0) + '@firebase/storage-compat': 0.4.4(@firebase/app-compat@0.5.16)(@firebase/app-types@0.9.5)(@firebase/app@0.16.0) + '@firebase/util': 1.15.2 transitivePeerDependencies: - '@react-native-async-storage/async-storage' flat-cache@4.0.1: dependencies: - flatted: 3.4.2 + flatted: 3.4.4 keyv: 4.5.4 flat@5.0.2: {} - flatted@3.4.2: {} + flatted@3.4.4: {} - folder-hash@4.1.3(supports-color@10.2.2): + folder-hash@4.1.3(supports-color@11.0.0): dependencies: - debug: 4.4.0(supports-color@10.2.2) + debug: 4.4.0(supports-color@11.0.0) minimatch: 7.4.9 transitivePeerDependencies: - supports-color - follow-redirects@1.16.0(debug@4.4.3(supports-color@10.2.2)): + follow-redirects@1.16.0(debug@4.4.3(supports-color@11.0.0)): optionalDependencies: - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) for-each@0.3.5: dependencies: @@ -13418,34 +13636,34 @@ snapshots: fuse.js@7.3.0: {} - gaxios@7.1.3(supports-color@10.2.2): + gaxios@7.1.3(supports-color@11.0.0): dependencies: extend: 3.0.2 - https-proxy-agent: 7.0.6(supports-color@10.2.2) + https-proxy-agent: 7.0.6(supports-color@11.0.0) node-fetch: 3.3.2 rimraf: 5.0.10 transitivePeerDependencies: - supports-color - gaxios@7.2.0(supports-color@10.2.2): + gaxios@7.3.1(supports-color@11.0.0): dependencies: extend: 3.0.2 - https-proxy-agent: 7.0.6(supports-color@10.2.2) + https-proxy-agent: 7.0.6(supports-color@11.0.0) node-fetch: 3.3.2 transitivePeerDependencies: - supports-color - gcp-metadata@8.1.2(supports-color@10.2.2): + gcp-metadata@8.1.2(supports-color@11.0.0): dependencies: - gaxios: 7.2.0(supports-color@10.2.2) + gaxios: 7.3.1(supports-color@11.0.0) google-logging-utils: 1.1.3 json-bigint: 1.0.0 transitivePeerDependencies: - supports-color - gcp-metadata@8.1.3(supports-color@10.2.2): + gcp-metadata@8.1.4(supports-color@11.0.0): dependencies: - gaxios: 7.1.3(supports-color@10.2.2) + gaxios: 7.1.3(supports-color@11.0.0) google-logging-utils: 1.1.3 json-bigint: 1.0.0 transitivePeerDependencies: @@ -13518,7 +13736,7 @@ snapshots: glob@13.0.6: dependencies: - minimatch: 10.2.5 + minimatch: 10.2.6 minipass: 7.1.3 path-scurry: 2.0.2 @@ -13549,41 +13767,41 @@ snapshots: merge2: 1.4.1 slash: 3.0.0 - google-auth-library@10.5.0(supports-color@10.2.2): + google-auth-library@10.5.0(supports-color@11.0.0): dependencies: base64-js: 1.5.1 ecdsa-sig-formatter: 1.0.11 - gaxios: 7.2.0(supports-color@10.2.2) - gcp-metadata: 8.1.3(supports-color@10.2.2) + gaxios: 7.3.1(supports-color@11.0.0) + gcp-metadata: 8.1.4(supports-color@11.0.0) google-logging-utils: 1.1.3 - gtoken: 8.0.0(supports-color@10.2.2) + gtoken: 8.0.0(supports-color@11.0.0) jws: 4.0.1 transitivePeerDependencies: - supports-color - google-auth-library@10.9.0(supports-color@10.2.2): + google-auth-library@10.9.1(supports-color@11.0.0): dependencies: base64-js: 1.5.1 ecdsa-sig-formatter: 1.0.11 - gaxios: 7.2.0(supports-color@10.2.2) - gcp-metadata: 8.1.2(supports-color@10.2.2) + gaxios: 7.3.1(supports-color@11.0.0) + gcp-metadata: 8.1.2(supports-color@11.0.0) google-logging-utils: 1.1.3 jws: 4.0.1 transitivePeerDependencies: - supports-color - google-gax@5.0.7(supports-color@10.2.2): + google-gax@5.0.8(supports-color@11.0.0): dependencies: '@grpc/grpc-js': 1.14.4 '@grpc/proto-loader': 0.8.1 duplexify: 4.1.3 - google-auth-library: 10.5.0(supports-color@10.2.2) + google-auth-library: 10.5.0(supports-color@11.0.0) google-logging-utils: 1.1.3 node-fetch: 3.3.2 object-hash: 3.0.0 proto3-json-serializer: 3.0.4 protobufjs: 7.6.5 - retry-request: 8.0.3(supports-color@10.2.2) + retry-request: 8.0.4(supports-color@11.0.0) rimraf: 5.0.10 transitivePeerDependencies: - supports-color @@ -13621,9 +13839,9 @@ snapshots: '@grpc/grpc-js': 1.14.4 protobufjs: 7.6.5 - gtoken@8.0.0(supports-color@10.2.2): + gtoken@8.0.0(supports-color@11.0.0): dependencies: - gaxios: 7.2.0(supports-color@10.2.2) + gaxios: 7.3.1(supports-color@11.0.0) jws: 4.0.1 transitivePeerDependencies: - supports-color @@ -13670,7 +13888,7 @@ snapshots: dependencies: function-bind: 1.1.2 - hono@4.12.31: {} + hono@4.13.3: {} hosted-git-info@10.1.1: dependencies: @@ -13722,17 +13940,17 @@ snapshots: http-parser-js@0.5.10: {} - http-proxy-agent@7.0.2(supports-color@10.2.2): + http-proxy-agent@7.0.2(supports-color@11.0.0): dependencies: agent-base: 7.1.4 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) transitivePeerDependencies: - supports-color - http-proxy-middleware@2.0.10(@types/express@4.17.25)(debug@4.4.3(supports-color@10.2.2)): + http-proxy-middleware@2.0.10(@types/express@4.17.25)(debug@4.4.3(supports-color@11.0.0)): dependencies: '@types/http-proxy': 1.17.17 - http-proxy: 1.18.1(debug@4.4.3(supports-color@10.2.2)) + http-proxy: 1.18.1(debug@4.4.3(supports-color@11.0.0)) is-glob: 4.0.3 is-plain-obj: 3.0.0 micromatch: 4.0.8 @@ -13741,9 +13959,9 @@ snapshots: transitivePeerDependencies: - debug - http-proxy-middleware@4.2.0(supports-color@10.2.2): + http-proxy-middleware@4.2.0(supports-color@11.0.0): dependencies: - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) httpxy: 0.5.5 is-glob: 4.0.3 is-plain-obj: 4.1.0 @@ -13751,10 +13969,10 @@ snapshots: transitivePeerDependencies: - supports-color - http-proxy@1.18.1(debug@4.4.3(supports-color@10.2.2)): + http-proxy@1.18.1(debug@4.4.3(supports-color@11.0.0)): dependencies: eventemitter3: 4.0.7 - follow-redirects: 1.16.0(debug@4.4.3(supports-color@10.2.2)) + follow-redirects: 1.16.0(debug@4.4.3(supports-color@11.0.0)) requires-port: 1.0.0 transitivePeerDependencies: - debug @@ -13772,24 +13990,24 @@ snapshots: quick-lru: 5.1.1 resolve-alpn: 1.2.1 - https-proxy-agent@5.0.1(supports-color@10.2.2): + https-proxy-agent@5.0.1(supports-color@11.0.0): dependencies: - agent-base: 6.0.2(supports-color@10.2.2) - debug: 4.4.3(supports-color@10.2.2) + agent-base: 6.0.2(supports-color@11.0.0) + debug: 4.4.3(supports-color@11.0.0) transitivePeerDependencies: - supports-color - https-proxy-agent@7.0.6(supports-color@10.2.2): + https-proxy-agent@7.0.6(supports-color@11.0.0): dependencies: agent-base: 7.1.4 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) transitivePeerDependencies: - supports-color - https-proxy-agent@9.1.0(supports-color@10.2.2): + https-proxy-agent@9.1.0(supports-color@11.0.0): dependencies: agent-base: 9.0.0 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) proxy-agent-negotiate: 1.1.0 transitivePeerDependencies: - kerberos @@ -13813,9 +14031,9 @@ snapshots: dependencies: safer-buffer: 2.1.2 - icss-utils@5.1.0(postcss@8.5.19): + icss-utils@5.1.0(postcss@8.5.25): dependencies: - postcss: 8.5.19 + postcss: 8.5.25 idb@7.1.1: {} @@ -13825,10 +14043,7 @@ snapshots: ignore@7.0.6: {} - image-size@0.5.5: - optional: true - - immutable@3.8.3: {} + immutable@3.8.4: {} immutable@5.1.9: {} @@ -13858,11 +14073,11 @@ snapshots: hasown: 2.0.4 side-channel: 1.1.1 - ip-address@10.2.0: {} + ip-address@10.5.0: {} ipaddr.js@1.9.1: {} - ipaddr.js@2.4.0: {} + ipaddr.js@2.5.0: {} is-array-buffer@3.0.5: dependencies: @@ -14064,20 +14279,20 @@ snapshots: istanbul-lib-coverage@3.2.2: {} - istanbul-lib-instrument@5.2.1(supports-color@10.2.2): + istanbul-lib-instrument@5.2.1(supports-color@11.0.0): dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/parser': 7.29.7 + '@babel/core': 7.29.7(supports-color@11.0.0) + '@babel/parser': 7.29.8 '@istanbuljs/schema': 0.1.6 istanbul-lib-coverage: 3.2.2 semver: 6.3.1 transitivePeerDependencies: - supports-color - istanbul-lib-instrument@6.0.3(supports-color@10.2.2): + istanbul-lib-instrument@6.0.3(supports-color@11.0.0): dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/parser': 7.29.7 + '@babel/core': 7.29.7(supports-color@11.0.0) + '@babel/parser': 7.29.8 '@istanbuljs/schema': 0.1.6 istanbul-lib-coverage: 3.2.2 semver: 7.8.5 @@ -14090,9 +14305,9 @@ snapshots: make-dir: 4.0.0 supports-color: 7.2.0 - istanbul-lib-source-maps@4.0.1(supports-color@10.2.2): + istanbul-lib-source-maps@4.0.1(supports-color@11.0.0): dependencies: - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) istanbul-lib-coverage: 3.2.2 source-map: 0.6.1 transitivePeerDependencies: @@ -14115,7 +14330,7 @@ snapshots: jasmine-reporters@2.5.2: dependencies: - '@xmldom/xmldom': 0.8.13 + '@xmldom/xmldom': 0.8.15 mkdirp: 1.0.4 jasmine-spec-reporter@7.0.0: @@ -14124,7 +14339,7 @@ snapshots: jasmine@6.3.0: dependencies: - '@jasminejs/reporters': 1.0.0 + '@jasminejs/reporters': 1.1.0 glob: 13.0.6 jasmine-core: 6.3.0 @@ -14136,7 +14351,7 @@ snapshots: jiti@2.7.0: {} - jose@6.2.4: {} + jose@6.2.10: {} js-tokens@10.0.0: {} @@ -14146,7 +14361,7 @@ snapshots: dependencies: argparse: 2.0.1 - js-yaml@4.3.0: + js-yaml@4.3.1: dependencies: argparse: 2.0.1 @@ -14157,7 +14372,7 @@ snapshots: '@asamuzakjp/css-color': 5.1.11 '@asamuzakjp/dom-selector': 7.1.1 '@bramus/specificity': 2.4.2 - '@csstools/css-syntax-patches-for-csstree': 1.1.6(css-tree@3.2.1) + '@csstools/css-syntax-patches-for-csstree': 1.1.8(css-tree@3.2.1) '@exodus/bytes': 1.15.1 css-tree: 3.2.1 data-urls: 7.0.0 @@ -14169,7 +14384,7 @@ snapshots: saxes: 6.0.0 symbol-tree: 3.2.4 tough-cookie: 6.0.2 - undici: 7.28.0 + undici: 7.29.0 w3c-xmlserializer: 5.0.0 webidl-conversions: 8.0.1 whatwg-mimetype: 5.0.0 @@ -14200,7 +14415,7 @@ snapshots: json-stringify-safe@5.0.1: {} - json-with-bigint@3.5.10: {} + json-with-bigint@3.5.12: {} json5@1.0.2: dependencies: @@ -14255,54 +14470,54 @@ snapshots: dependencies: which: 1.3.1 - karma-coverage@2.2.1(supports-color@10.2.2): + karma-coverage@2.2.1(supports-color@11.0.0): dependencies: istanbul-lib-coverage: 3.2.2 - istanbul-lib-instrument: 5.2.1(supports-color@10.2.2) + istanbul-lib-instrument: 5.2.1(supports-color@11.0.0) istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 4.0.1(supports-color@10.2.2) + istanbul-lib-source-maps: 4.0.1(supports-color@11.0.0) istanbul-reports: 3.2.0 minimatch: 3.1.5 transitivePeerDependencies: - supports-color - karma-jasmine-html-reporter@2.2.0(jasmine-core@6.3.0)(karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6)))(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6)): + karma-jasmine-html-reporter@2.2.0(jasmine-core@6.3.0)(karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6)))(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6)): dependencies: jasmine-core: 6.3.0 - karma: 6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6) - karma-jasmine: 5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6)) + karma: 6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6) + karma-jasmine: 5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6)) - karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6)): + karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6)): dependencies: jasmine-core: 4.6.1 - karma: 6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6) + karma: 6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6) karma-source-map-support@1.4.0: dependencies: source-map-support: 0.5.21 - karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6): + karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6): dependencies: '@colors/colors': 1.5.0 - body-parser: 1.20.6(supports-color@10.2.2) + body-parser: 1.20.6(supports-color@11.0.0) braces: 3.0.3 chokidar: 3.6.0 - connect: 3.7.0(supports-color@10.2.2) + connect: 3.7.0(supports-color@11.0.0) di: 0.0.1 dom-serialize: 2.2.1 glob: 7.2.3 graceful-fs: 4.2.11 - http-proxy: 1.18.1(debug@4.4.3(supports-color@10.2.2)) + http-proxy: 1.18.1(debug@4.4.3(supports-color@11.0.0)) isbinaryfile: 4.0.10 lodash: 4.18.1 - log4js: 6.9.1(supports-color@10.2.2) + log4js: 6.9.1(supports-color@11.0.0) mime: 2.6.0 minimatch: 3.1.5 mkdirp: 0.5.6 qjobs: 1.2.0 range-parser: 1.3.0 rimraf: 3.0.2 - socket.io: 4.8.3(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) + socket.io: 4.8.3(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6) source-map: 0.6.1 tmp: 0.2.7 ua-parser-js: 0.7.41 @@ -14324,36 +14539,38 @@ snapshots: picocolors: 1.1.1 shell-quote: 1.10.0 - less-loader@13.0.0(less@4.6.7)(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)): + less-loader@13.0.0(less@4.9.0(supports-color@11.0.0))(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)): dependencies: '@types/less': 3.0.8 - less: 4.6.7 + less: 4.9.0(supports-color@11.0.0) optionalDependencies: - webpack: 5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3) + webpack: 5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3) - less@4.6.7: + less@4.9.0(supports-color@11.0.0): dependencies: copy-anything: 3.0.5 parse-node-version: 1.0.1 optionalDependencies: errno: 0.1.8 graceful-fs: 4.2.11 - image-size: 0.5.5 make-dir: 5.1.0 mime: 1.6.0 needle: 3.5.0 + probe-image-size: 7.4.0(supports-color@11.0.0) source-map: 0.6.1 + transitivePeerDependencies: + - supports-color levn@0.4.1: dependencies: prelude-ls: 1.2.1 type-check: 0.4.0 - license-webpack-plugin@4.0.2(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)): + license-webpack-plugin@4.0.2(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)): dependencies: webpack-sources: 3.5.1 optionalDependencies: - webpack: 5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3) + webpack: 5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3) lightningcss-android-arm64@1.33.0: optional: true @@ -14410,13 +14627,11 @@ snapshots: lines-and-columns@1.2.4: {} - listr2@10.2.2: + listr2@11.0.0: dependencies: - cli-truncate: 5.2.0 - eventemitter3: 5.0.4 - log-update: 6.1.0 - rfdc: 1.4.1 - wrap-ansi: 10.0.0 + cli-truncate: 6.1.1 + log-update: 8.0.0 + wrap-ansi: 10.0.1 lmdb@3.5.6: dependencies: @@ -14436,8 +14651,6 @@ snapshots: '@lmdb/lmdb-win32-x64': 3.5.6 optional: true - loader-runner@4.3.2: {} - loader-utils@2.0.4: dependencies: big.js: 5.2.2 @@ -14472,6 +14685,9 @@ snapshots: lodash.isstring@4.0.1: {} + lodash.merge@4.6.2: + optional: true + lodash.once@4.1.1: {} lodash.snakecase@4.1.1: {} @@ -14481,23 +14697,24 @@ snapshots: log-symbols@7.0.1: dependencies: is-unicode-supported: 2.1.0 - yoctocolors: 2.1.2 + yoctocolors: 2.2.0 - log-update@6.1.0: + log-update@8.0.0: dependencies: ansi-escapes: 7.3.0 cli-cursor: 5.0.0 - slice-ansi: 7.1.2 + slice-ansi: 9.0.0 + string-width: 8.2.2 strip-ansi: 7.2.0 - wrap-ansi: 9.0.2 + wrap-ansi: 10.0.1 - log4js@6.9.1(supports-color@10.2.2): + log4js@6.9.1(supports-color@11.0.0): dependencies: date-format: 4.0.14 - debug: 4.4.3(supports-color@10.2.2) - flatted: 3.4.2 + debug: 4.4.3(supports-color@11.0.0) + flatted: 3.4.4 rfdc: 1.4.1 - streamroller: 3.1.5(supports-color@10.2.2) + streamroller: 3.1.5(supports-color@11.0.0) transitivePeerDependencies: - supports-color @@ -14531,10 +14748,10 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - magicast@0.5.3: + magicast@0.5.4: dependencies: - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 source-map-js: 1.2.1 make-dir@4.0.0: @@ -14550,22 +14767,22 @@ snapshots: media-typer@0.3.0: {} - media-typer@1.1.0: {} + media-typer@1.1.1: {} - memfs@4.64.0(tslib@2.8.1): + memfs@4.68.1: dependencies: - '@jsonjoy.com/fs-core': 4.64.0(tslib@2.8.1) - '@jsonjoy.com/fs-fsa': 4.64.0(tslib@2.8.1) - '@jsonjoy.com/fs-node': 4.64.0(tslib@2.8.1) - '@jsonjoy.com/fs-node-builtins': 4.64.0(tslib@2.8.1) - '@jsonjoy.com/fs-node-to-fsa': 4.64.0(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.64.0(tslib@2.8.1) - '@jsonjoy.com/fs-print': 4.64.0(tslib@2.8.1) - '@jsonjoy.com/fs-snapshot': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-core': 4.68.1(tslib@2.8.1) + '@jsonjoy.com/fs-fsa': 4.68.1(tslib@2.8.1) + '@jsonjoy.com/fs-node': 4.68.1(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.68.1(tslib@2.8.1) + '@jsonjoy.com/fs-node-to-fsa': 4.68.1(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.68.1(tslib@2.8.1) + '@jsonjoy.com/fs-print': 4.68.1(tslib@2.8.1) + '@jsonjoy.com/fs-snapshot': 4.68.1(tslib@2.8.1) '@jsonjoy.com/json-pack': 1.21.0(tslib@2.8.1) '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) glob-to-regex.js: 1.2.0(tslib@2.8.1) - thingies: 2.6.0(tslib@2.8.1) + thingies: 2.6.1(tslib@2.8.1) tree-dump: 1.1.0(tslib@2.8.1) tslib: 2.8.1 @@ -14608,54 +14825,54 @@ snapshots: mimic-response@3.1.0: {} - mini-css-extract-plugin@2.10.2(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)): + mini-css-extract-plugin@2.10.2(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)): dependencies: schema-utils: 4.3.3 tapable: 2.3.3 - webpack: 5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3) + webpack: 5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3) minimalistic-assert@1.0.1: {} - minimatch@10.2.5: + minimatch@10.2.6: dependencies: - brace-expansion: 5.0.7 + brace-expansion: 5.0.9 minimatch@3.1.5: dependencies: - brace-expansion: 1.1.16 + brace-expansion: 1.1.18 minimatch@7.4.9: dependencies: - brace-expansion: 2.1.2 + brace-expansion: 2.1.4 minimatch@9.0.9: dependencies: - brace-expansion: 2.1.2 + brace-expansion: 2.1.4 minimist@1.2.8: {} - minimizer-webpack-plugin@5.6.1(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)): + minimizer-webpack-plugin@5.6.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)): dependencies: '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 schema-utils: 4.3.3 terser: 5.49.0 - webpack: 5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3) + webpack: 5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3) optionalDependencies: - esbuild: 0.28.1 + esbuild: 0.28.2 lightningcss: 1.33.0 - postcss: 8.5.19 + postcss: 8.5.25 uglify-js: 3.19.3 - minimizer-webpack-plugin@5.6.1(esbuild@0.28.1)(webpack@5.108.4(esbuild@0.28.1)): + minimizer-webpack-plugin@5.6.1(esbuild@0.28.2)(webpack@5.109.2(esbuild@0.28.2)): dependencies: '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 schema-utils: 4.3.3 terser: 5.49.0 - webpack: 5.108.4(esbuild@0.28.1) + webpack: 5.109.2(esbuild@0.28.2) optionalDependencies: - esbuild: 0.28.1 + esbuild: 0.28.2 minipass@7.1.3: {} @@ -14703,47 +14920,58 @@ snapshots: dependencies: array-differ: 4.0.0 array-union: 3.0.1 - minimatch: 10.2.5 + minimatch: 10.2.6 mute-stream@3.0.0: {} - nanoid@3.3.16: {} + nanoid@3.3.18: {} natural-compare@1.4.0: {} + needle@2.9.1(supports-color@11.0.0): + dependencies: + debug: 3.2.7(supports-color@11.0.0) + iconv-lite: 0.4.24 + sax: 1.6.1 + transitivePeerDependencies: + - supports-color + optional: true + needle@3.5.0: dependencies: iconv-lite: 0.6.3 - sax: 1.6.0 + sax: 1.6.1 optional: true negotiator@0.6.3: {} negotiator@0.6.4: {} - negotiator@1.0.0: {} + negotiator@1.1.0: + dependencies: + content-type: 2.1.0 neo-async@2.6.2: {} - ng-packagr@22.1.0-next.3(@angular/compiler-cli@22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(typescript@6.0.3))(tslib@2.8.1)(typescript@6.0.3): + ng-packagr@22.1.1(@angular/compiler-cli@22.1.4(@angular/compiler@22.1.4)(typescript@6.0.3))(supports-color@11.0.0)(tslib@2.8.1)(typescript@6.0.3): dependencies: '@ampproject/remapping': 2.3.0 - '@angular/compiler-cli': 22.1.0-rc.0(@angular/compiler@22.1.0-rc.0)(typescript@6.0.3) + '@angular/compiler-cli': 22.1.4(@angular/compiler@22.1.4)(typescript@6.0.3) '@rollup/plugin-json': 6.1.0(rollup@4.62.2) '@rollup/wasm-node': 4.62.2 ajv: 8.20.0 - browserslist: 4.28.7 + browserslist: 4.28.8 chokidar: 5.0.0 commander: 15.0.0 dependency-graph: 1.0.0 - esbuild: 0.28.1 + esbuild: 0.28.2 find-cache-directory: 6.0.0 injection-js: 2.6.1 jsonc-parser: 3.3.1 - less: 4.6.7 + less: 4.9.0(supports-color@11.0.0) ora: 9.4.1 piscina: 5.2.0 - postcss: 8.5.19 + postcss: 8.5.25 rollup-plugin-dts: 6.4.1(rollup@4.62.2)(typescript@6.0.3) rxjs: 7.8.2 sass: 1.101.0 @@ -14752,8 +14980,10 @@ snapshots: typescript: 6.0.3 optionalDependencies: rollup: 4.62.2 + transitivePeerDependencies: + - supports-color - nock@14.0.16: + nock@14.0.17: dependencies: '@mswjs/interceptors': 0.41.9 json-stringify-safe: 5.0.1 @@ -14795,7 +15025,7 @@ snapshots: node-gyp-build@4.8.4: {} - node-releases@2.0.51: {} + node-releases@2.0.53: {} normalize-path@3.0.0: {} @@ -14882,14 +15112,14 @@ snapshots: open@10.2.0: dependencies: - default-browser: 5.5.0 + default-browser: 5.5.1 define-lazy-prop: 3.0.0 is-inside-container: 1.0.0 wsl-utils: 0.1.0 open@11.0.0: dependencies: - default-browser: 5.5.0 + default-browser: 5.5.1 define-lazy-prop: 3.0.0 is-in-ssh: 1.0.0 is-inside-container: 1.0.0 @@ -14932,30 +15162,30 @@ snapshots: object-keys: 1.1.1 safe-push-apply: 1.0.0 - oxc-parser@0.140.0: + oxc-parser@0.142.0: dependencies: - '@oxc-project/types': 0.140.0 + '@oxc-project/types': 0.142.0 optionalDependencies: - '@oxc-parser/binding-android-arm-eabi': 0.140.0 - '@oxc-parser/binding-android-arm64': 0.140.0 - '@oxc-parser/binding-darwin-arm64': 0.140.0 - '@oxc-parser/binding-darwin-x64': 0.140.0 - '@oxc-parser/binding-freebsd-x64': 0.140.0 - '@oxc-parser/binding-linux-arm-gnueabihf': 0.140.0 - '@oxc-parser/binding-linux-arm-musleabihf': 0.140.0 - '@oxc-parser/binding-linux-arm64-gnu': 0.140.0 - '@oxc-parser/binding-linux-arm64-musl': 0.140.0 - '@oxc-parser/binding-linux-ppc64-gnu': 0.140.0 - '@oxc-parser/binding-linux-riscv64-gnu': 0.140.0 - '@oxc-parser/binding-linux-riscv64-musl': 0.140.0 - '@oxc-parser/binding-linux-s390x-gnu': 0.140.0 - '@oxc-parser/binding-linux-x64-gnu': 0.140.0 - '@oxc-parser/binding-linux-x64-musl': 0.140.0 - '@oxc-parser/binding-openharmony-arm64': 0.140.0 - '@oxc-parser/binding-wasm32-wasi': 0.140.0 - '@oxc-parser/binding-win32-arm64-msvc': 0.140.0 - '@oxc-parser/binding-win32-ia32-msvc': 0.140.0 - '@oxc-parser/binding-win32-x64-msvc': 0.140.0 + '@oxc-parser/binding-android-arm-eabi': 0.142.0 + '@oxc-parser/binding-android-arm64': 0.142.0 + '@oxc-parser/binding-darwin-arm64': 0.142.0 + '@oxc-parser/binding-darwin-x64': 0.142.0 + '@oxc-parser/binding-freebsd-x64': 0.142.0 + '@oxc-parser/binding-linux-arm-gnueabihf': 0.142.0 + '@oxc-parser/binding-linux-arm-musleabihf': 0.142.0 + '@oxc-parser/binding-linux-arm64-gnu': 0.142.0 + '@oxc-parser/binding-linux-arm64-musl': 0.142.0 + '@oxc-parser/binding-linux-ppc64-gnu': 0.142.0 + '@oxc-parser/binding-linux-riscv64-gnu': 0.142.0 + '@oxc-parser/binding-linux-riscv64-musl': 0.142.0 + '@oxc-parser/binding-linux-s390x-gnu': 0.142.0 + '@oxc-parser/binding-linux-x64-gnu': 0.142.0 + '@oxc-parser/binding-linux-x64-musl': 0.142.0 + '@oxc-parser/binding-openharmony-arm64': 0.142.0 + '@oxc-parser/binding-wasm32-wasi': 0.142.0 + '@oxc-parser/binding-win32-arm64-msvc': 0.142.0 + '@oxc-parser/binding-win32-ia32-msvc': 0.142.0 + '@oxc-parser/binding-win32-x64-msvc': 0.142.0 p-cancelable@2.1.1: {} @@ -15084,7 +15314,7 @@ snapshots: on-exit-leak-free: 2.1.2 pino-abstract-transport: 2.0.0 pino-std-serializers: 7.1.0 - process-warning: 5.0.0 + process-warning: 5.1.0 quick-format-unescaped: 4.0.4 real-require: 0.2.0 safe-stable-stringify: 2.5.0 @@ -15107,7 +15337,7 @@ snapshots: asn1js: 3.0.10 bytestreamjs: 2.0.1 pvtsutils: 1.3.6 - pvutils: 1.1.5 + pvutils: 1.2.0 tslib: 2.8.1 pluralize@8.0.0: {} @@ -15119,54 +15349,54 @@ snapshots: possible-typed-array-names@1.1.0: {} - postcss-loader@8.2.1(postcss@8.5.19)(typescript@6.0.3)(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)): + postcss-loader@8.2.1(postcss@8.5.25)(typescript@6.0.3)(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)): dependencies: cosmiconfig: 9.0.2(typescript@6.0.3) jiti: 2.7.0 - postcss: 8.5.19 + postcss: 8.5.25 semver: 7.8.5 optionalDependencies: - webpack: 5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3) + webpack: 5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3) transitivePeerDependencies: - typescript postcss-media-query-parser@0.2.3: {} - postcss-modules-extract-imports@3.1.0(postcss@8.5.19): + postcss-modules-extract-imports@3.1.0(postcss@8.5.25): dependencies: - postcss: 8.5.19 + postcss: 8.5.25 - postcss-modules-local-by-default@4.2.0(postcss@8.5.19): + postcss-modules-local-by-default@4.2.0(postcss@8.5.25): dependencies: - icss-utils: 5.1.0(postcss@8.5.19) - postcss: 8.5.19 - postcss-selector-parser: 7.1.4 + icss-utils: 5.1.0(postcss@8.5.25) + postcss: 8.5.25 + postcss-selector-parser: 7.1.5 postcss-value-parser: 4.2.0 - postcss-modules-scope@3.2.1(postcss@8.5.19): + postcss-modules-scope@3.2.1(postcss@8.5.25): dependencies: - postcss: 8.5.19 - postcss-selector-parser: 7.1.4 + postcss: 8.5.25 + postcss-selector-parser: 7.1.5 - postcss-modules-values@4.0.0(postcss@8.5.19): + postcss-modules-values@4.0.0(postcss@8.5.25): dependencies: - icss-utils: 5.1.0(postcss@8.5.19) - postcss: 8.5.19 + icss-utils: 5.1.0(postcss@8.5.25) + postcss: 8.5.25 - postcss-safe-parser@7.0.1(postcss@8.5.19): + postcss-safe-parser@7.0.1(postcss@8.5.25): dependencies: - postcss: 8.5.19 + postcss: 8.5.25 - postcss-selector-parser@7.1.4: + postcss-selector-parser@7.1.5: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 postcss-value-parser@4.2.0: {} - postcss@8.5.19: + postcss@8.5.25: dependencies: - nanoid: 3.3.16 + nanoid: 3.3.18 picocolors: 1.1.1 source-map-js: 1.2.1 @@ -15176,13 +15406,22 @@ snapshots: prettier@3.9.6: {} + probe-image-size@7.4.0(supports-color@11.0.0): + dependencies: + lodash.merge: 4.6.2 + needle: 2.9.1(supports-color@11.0.0) + stream-parser: 0.3.1(supports-color@11.0.0) + transitivePeerDependencies: + - supports-color + optional: true + proc-log@7.0.0: {} process-nextick-args@2.0.1: {} process-warning@1.0.0: {} - process-warning@5.0.0: {} + process-warning@5.1.0: {} process@0.11.10: {} @@ -15243,7 +15482,7 @@ snapshots: devtools-protocol: 0.0.1638949 typed-query-selector: 2.12.2 webdriver-bidi-protocol: 0.4.2 - ws: 8.21.1(bufferutil@4.1.0)(utf-8-validate@6.0.6) + ws: 8.21.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) transitivePeerDependencies: - bufferutil - proxy-agent @@ -15268,7 +15507,7 @@ snapshots: dependencies: tslib: 2.8.1 - pvutils@1.1.5: {} + pvutils@1.2.0: {} qjobs@1.2.0: {} @@ -15321,7 +15560,7 @@ snapshots: iconv-lite: 0.7.3 unpipe: 1.0.0 - re2js@0.4.3: {} + re2js@2.8.6: {} readable-stream@2.3.8: dependencies: @@ -15359,7 +15598,7 @@ snapshots: dependencies: picomatch: 2.3.2 - readdirp@5.0.0: {} + readdirp@5.1.1: {} real-require@0.2.0: {} @@ -15423,7 +15662,7 @@ snapshots: adjust-sourcemap-loader: 4.0.0 convert-source-map: 1.9.0 loader-utils: 2.0.4 - postcss: 8.5.19 + postcss: 8.5.25 source-map: 0.6.1 resolve@1.22.12: @@ -15442,9 +15681,9 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - resp-modifier@6.0.2(supports-color@10.2.2): + resp-modifier@6.0.2(supports-color@11.0.0): dependencies: - debug: 2.6.9(supports-color@10.2.2) + debug: 2.6.9(supports-color@11.0.0) minimatch: 3.1.5 transitivePeerDependencies: - supports-color @@ -15458,10 +15697,10 @@ snapshots: onetime: 7.0.0 signal-exit: 4.1.0 - retry-request@8.0.3(supports-color@10.2.2): + retry-request@8.0.4(supports-color@11.0.0): dependencies: extend: 3.0.2 - teeny-request: 10.1.3(supports-color@10.2.2) + teeny-request: 10.1.4(supports-color@11.0.0) transitivePeerDependencies: - supports-color @@ -15577,9 +15816,9 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.62.2 fsevents: 2.3.3 - router@2.2.0(supports-color@10.2.2): + router@2.2.0(supports-color@11.0.0): dependencies: - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) depd: 2.0.0 is-promise: 4.0.0 parseurl: 1.3.3 @@ -15630,10 +15869,10 @@ snapshots: dependencies: truncate-utf8-bytes: 1.0.2 - sass-loader@17.0.0(sass@1.101.0)(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)): + sass-loader@17.0.0(sass@1.101.0)(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)): optionalDependencies: sass: 1.101.0 - webpack: 5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3) + webpack: 5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3) sass@1.101.0: dependencies: @@ -15643,7 +15882,7 @@ snapshots: optionalDependencies: '@parcel/watcher': 2.6.0 - sax@1.6.0: + sax@1.6.1: optional: true saxes@6.0.0: @@ -15670,9 +15909,9 @@ snapshots: semver@7.8.5: {} - send@0.19.2(supports-color@10.2.2): + send@0.19.2(supports-color@11.0.0): dependencies: - debug: 2.6.9(supports-color@10.2.2) + debug: 2.6.9(supports-color@11.0.0) depd: 2.0.0 destroy: 1.2.0 encodeurl: 2.0.0 @@ -15688,9 +15927,9 @@ snapshots: transitivePeerDependencies: - supports-color - send@1.2.1(supports-color@10.2.2): + send@1.2.1(supports-color@11.0.0): dependencies: - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 @@ -15704,13 +15943,13 @@ snapshots: transitivePeerDependencies: - supports-color - serialize-javascript@7.0.7: {} + serialize-javascript@7.1.0: {} - serve-index@1.9.2(supports-color@10.2.2): + serve-index@1.9.2(supports-color@11.0.0): dependencies: accepts: 1.3.8 batch: 0.6.1 - debug: 2.6.9(supports-color@10.2.2) + debug: 2.6.9(supports-color@11.0.0) escape-html: 1.0.3 http-errors: 1.8.1 mime-types: 2.1.35 @@ -15718,21 +15957,21 @@ snapshots: transitivePeerDependencies: - supports-color - serve-static@1.16.3(supports-color@10.2.2): + serve-static@1.16.3(supports-color@11.0.0): dependencies: encodeurl: 2.0.0 escape-html: 1.0.3 parseurl: 1.3.3 - send: 0.19.2(supports-color@10.2.2) + send: 0.19.2(supports-color@11.0.0) transitivePeerDependencies: - supports-color - serve-static@2.2.1(supports-color@10.2.2): + serve-static@2.2.1(supports-color@11.0.0): dependencies: encodeurl: 2.0.0 escape-html: 1.0.3 parseurl: 1.3.3 - send: 1.2.1(supports-color@10.2.2) + send: 1.2.1(supports-color@11.0.0) transitivePeerDependencies: - supports-color @@ -15810,52 +16049,47 @@ snapshots: slash@3.0.0: {} - slice-ansi@7.1.2: + slice-ansi@9.0.0: dependencies: ansi-styles: 6.2.3 is-fullwidth-code-point: 5.1.0 - slice-ansi@8.0.0: + socket.io-adapter@2.5.8(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6): dependencies: - ansi-styles: 6.2.3 - is-fullwidth-code-point: 5.1.0 - - socket.io-adapter@2.5.8(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6): - dependencies: - debug: 4.4.3(supports-color@10.2.2) - ws: 8.21.1(bufferutil@4.1.0)(utf-8-validate@6.0.6) + debug: 4.4.3(supports-color@11.0.0) + ws: 8.21.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - socket.io-client@4.8.3(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6): + socket.io-client@4.8.3(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6): dependencies: '@socket.io/component-emitter': 3.1.2 - debug: 4.4.3(supports-color@10.2.2) - engine.io-client: 6.6.6(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) - socket.io-parser: 4.2.7(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) + engine.io-client: 6.6.6(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6) + socket.io-parser: 4.2.7(supports-color@11.0.0) transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - socket.io-parser@4.2.7(supports-color@10.2.2): + socket.io-parser@4.2.7(supports-color@11.0.0): dependencies: '@socket.io/component-emitter': 3.1.2 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) transitivePeerDependencies: - supports-color - socket.io@4.8.3(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6): + socket.io@4.8.3(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6): dependencies: accepts: 1.3.8 base64id: 2.0.0 cors: 2.8.6 - debug: 4.4.3(supports-color@10.2.2) - engine.io: 6.6.9(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) - socket.io-adapter: 2.5.8(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) - socket.io-parser: 4.2.7(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) + engine.io: 6.6.9(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6) + socket.io-adapter: 2.5.8(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6) + socket.io-parser: 4.2.7(supports-color@11.0.0) transitivePeerDependencies: - bufferutil - supports-color @@ -15877,11 +16111,11 @@ snapshots: source-map-js@1.2.1: {} - source-map-loader@5.0.0(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)): + source-map-loader@5.0.0(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)): dependencies: iconv-lite: 0.6.3 source-map-js: 1.2.1 - webpack: 5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3) + webpack: 5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3) source-map-support@0.5.21: dependencies: @@ -15905,9 +16139,9 @@ snapshots: spdx-license-ids@3.0.23: {} - spdy-transport@3.0.0(supports-color@10.2.2): + spdy-transport@3.0.0(supports-color@11.0.0): dependencies: - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) detect-node: 2.1.0 hpack.js: 2.1.6 obuf: 1.1.2 @@ -15916,13 +16150,13 @@ snapshots: transitivePeerDependencies: - supports-color - spdy@4.0.2(supports-color@10.2.2): + spdy@4.0.2(supports-color@11.0.0): dependencies: - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) handle-thing: 2.0.1 http-deceiver: 1.2.7 select-hose: 2.0.0 - spdy-transport: 3.0.0(supports-color@10.2.2) + spdy-transport: 3.0.0(supports-color@11.0.0) transitivePeerDependencies: - supports-color @@ -15980,6 +16214,13 @@ snapshots: dependencies: stubs: 3.0.0 + stream-parser@0.3.1(supports-color@11.0.0): + dependencies: + debug: 2.6.9(supports-color@11.0.0) + transitivePeerDependencies: + - supports-color + optional: true + stream-shift@1.0.3: {} stream-throttle@0.1.3: @@ -15987,10 +16228,10 @@ snapshots: commander: 2.20.3 limiter: 1.1.5 - streamroller@3.1.5(supports-color@10.2.2): + streamroller@3.1.5(supports-color@11.0.0): dependencies: date-format: 4.0.14 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) fs-extra: 8.1.0 transitivePeerDependencies: - supports-color @@ -16067,7 +16308,7 @@ snapshots: strip-ansi@7.2.0: dependencies: - ansi-regex: 6.2.2 + ansi-regex: 6.3.0 strip-bom@3.0.0: {} @@ -16075,7 +16316,7 @@ snapshots: stubs@3.0.0: {} - supports-color@10.2.2: {} + supports-color@11.0.0: {} supports-color@7.2.0: dependencies: @@ -16103,7 +16344,7 @@ snapshots: tar-stream@3.2.0: dependencies: b4a: 1.8.1 - bare-fs: 4.7.4 + bare-fs: 4.8.0 fast-fifo: 1.3.2 streamx: 2.28.0 transitivePeerDependencies: @@ -16111,10 +16352,10 @@ snapshots: - bare-buffer - react-native-b4a - teeny-request@10.1.3(supports-color@10.2.2): + teeny-request@10.1.4(supports-color@11.0.0): dependencies: - http-proxy-agent: 7.0.2(supports-color@10.2.2) - https-proxy-agent: 7.0.6(supports-color@10.2.2) + http-proxy-agent: 7.0.2(supports-color@11.0.0) + https-proxy-agent: 7.0.6(supports-color@11.0.0) node-fetch: 3.3.2 stream-events: 1.0.5 transitivePeerDependencies: @@ -16130,7 +16371,7 @@ snapshots: terser@5.49.0: dependencies: '@jridgewell/source-map': 0.3.11 - acorn: 8.17.0 + acorn: 8.18.0 commander: 2.20.3 source-map-support: 0.5.21 @@ -16140,7 +16381,7 @@ snapshots: transitivePeerDependencies: - react-native-b4a - thingies@2.6.0(tslib@2.8.1): + thingies@2.6.1(tslib@2.8.1): dependencies: tslib: 2.8.1 @@ -16165,26 +16406,26 @@ snapshots: tinybench@2.9.0: {} - tinyexec@1.2.4: {} + tinyexec@1.3.0: {} tinyglobby@0.2.17: dependencies: fdir: 6.5.0(picomatch@4.0.5) picomatch: 4.0.5 - tinyrainbow@3.1.0: {} + tinyrainbow@3.1.1: {} tldts-core@6.1.86: {} - tldts-core@7.4.9: {} + tldts-core@7.4.10: {} tldts@6.1.86: dependencies: tldts-core: 6.1.86 - tldts@7.4.9: + tldts@7.4.10: dependencies: - tldts-core: 7.4.9 + tldts-core: 7.4.10 tmp@0.2.7: {} @@ -16202,7 +16443,7 @@ snapshots: tough-cookie@6.0.2: dependencies: - tldts: 7.4.9 + tldts: 7.4.10 tr46@0.0.3: {} @@ -16233,9 +16474,9 @@ snapshots: tslib@2.8.1: {} - tsx@4.23.1: + tsx@4.23.12: dependencies: - esbuild: 0.28.1 + esbuild: 0.28.2 optionalDependencies: fsevents: 2.3.3 @@ -16264,8 +16505,8 @@ snapshots: type-is@2.1.0: dependencies: - content-type: 2.0.0 - media-typer: 1.1.0 + content-type: 2.1.0 + media-typer: 1.1.1 mime-types: 3.0.2 typed-array-buffer@1.0.3: @@ -16327,9 +16568,9 @@ snapshots: undici-types@7.18.2: {} - undici@6.27.0: {} + undici@6.28.0: {} - undici@7.28.0: {} + undici@7.29.0: {} undici@8.7.0: {} @@ -16372,9 +16613,9 @@ snapshots: unpipe@1.0.0: {} - update-browserslist-db@1.2.3(browserslist@4.28.7): + update-browserslist-db@1.3.1(browserslist@4.28.8): dependencies: - browserslist: 4.28.7 + browserslist: 4.28.8 escalade: 3.2.0 picocolors: 1.1.1 @@ -16402,69 +16643,69 @@ snapshots: vary@1.1.2: {} - verdaccio-audit@13.0.3(encoding@0.1.13)(supports-color@10.2.2): + verdaccio-audit@13.0.3(encoding@0.1.13)(supports-color@11.0.0): dependencies: - '@verdaccio/config': 8.1.2(supports-color@10.2.2) + '@verdaccio/config': 8.1.2(supports-color@11.0.0) '@verdaccio/core': 8.1.2 - express: 4.22.1(supports-color@10.2.2) - https-proxy-agent: 5.0.1(supports-color@10.2.2) + express: 4.22.1(supports-color@11.0.0) + https-proxy-agent: 5.0.1(supports-color@11.0.0) node-fetch: 2.6.7(encoding@0.1.13) transitivePeerDependencies: - encoding - supports-color - verdaccio-auth-memory@13.0.3(supports-color@10.2.2): + verdaccio-auth-memory@13.1.2(supports-color@11.0.0): dependencies: - '@verdaccio/core': 8.1.2 - debug: 4.4.3(supports-color@10.2.2) + '@verdaccio/core': 8.2.2 + debug: 4.4.3(supports-color@11.0.0) transitivePeerDependencies: - supports-color - verdaccio-htpasswd@13.0.3(supports-color@10.2.2): + verdaccio-htpasswd@13.0.3(supports-color@11.0.0): dependencies: '@verdaccio/core': 8.1.2 '@verdaccio/file-locking': 13.0.1 apache-md5: 1.1.8 bcryptjs: 2.4.3 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) http-errors: 2.0.1 unix-crypt-td-js: 1.1.4 transitivePeerDependencies: - supports-color - verdaccio@6.8.0(encoding@0.1.13)(supports-color@10.2.2): + verdaccio@6.8.0(encoding@0.1.13)(supports-color@11.0.0): dependencies: '@cypress/request': 3.0.10 - '@verdaccio/auth': 8.0.4(supports-color@10.2.2) - '@verdaccio/config': 8.1.2(supports-color@10.2.2) + '@verdaccio/auth': 8.0.4(supports-color@11.0.0) + '@verdaccio/config': 8.1.2(supports-color@11.0.0) '@verdaccio/core': 8.1.2 - '@verdaccio/hooks': 8.0.4(supports-color@10.2.2) - '@verdaccio/loaders': 8.0.3(supports-color@10.2.2) - '@verdaccio/local-storage-legacy': 11.3.4(supports-color@10.2.2) - '@verdaccio/logger': 8.0.3(supports-color@10.2.2) - '@verdaccio/middleware': 8.0.5(supports-color@10.2.2) - '@verdaccio/package-filter': 13.0.3(supports-color@10.2.2) - '@verdaccio/search-indexer': 8.0.2(supports-color@10.2.2) - '@verdaccio/signature': 8.0.3(supports-color@10.2.2) + '@verdaccio/hooks': 8.0.4(supports-color@11.0.0) + '@verdaccio/loaders': 8.0.3(supports-color@11.0.0) + '@verdaccio/local-storage-legacy': 11.3.4(supports-color@11.0.0) + '@verdaccio/logger': 8.0.3(supports-color@11.0.0) + '@verdaccio/middleware': 8.0.5(supports-color@11.0.0) + '@verdaccio/package-filter': 13.0.3(supports-color@11.0.0) + '@verdaccio/search-indexer': 8.0.2(supports-color@11.0.0) + '@verdaccio/signature': 8.0.3(supports-color@11.0.0) '@verdaccio/streams': 10.2.5 - '@verdaccio/tarball': 13.0.3(supports-color@10.2.2) - '@verdaccio/ui-theme': 9.0.0-next-9.21(supports-color@10.2.2) - '@verdaccio/url': 13.0.3(supports-color@10.2.2) + '@verdaccio/tarball': 13.0.3(supports-color@11.0.0) + '@verdaccio/ui-theme': 9.0.0-next-9.21(supports-color@11.0.0) + '@verdaccio/url': 13.0.3(supports-color@11.0.0) '@verdaccio/utils': 8.1.3 JSONStream: 1.3.5 async: 3.2.6 clipanion: 4.0.0-rc.4 - compression: 1.8.1(supports-color@10.2.2) + compression: 1.8.1(supports-color@11.0.0) cors: 2.8.6 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) envinfo: 7.21.0 - express: 4.22.2(supports-color@10.2.2) + express: 4.22.2(supports-color@11.0.0) lodash: 4.18.1 lru-cache: 7.18.3 mime: 3.0.0 semver: 7.8.5 - verdaccio-audit: 13.0.3(encoding@0.1.13)(supports-color@10.2.2) - verdaccio-htpasswd: 13.0.3(supports-color@10.2.2) + verdaccio-audit: 13.0.3(encoding@0.1.13)(supports-color@11.0.0) + verdaccio-htpasswd: 13.0.3(supports-color@11.0.0) transitivePeerDependencies: - bare-abort-controller - encoding @@ -16477,34 +16718,34 @@ snapshots: core-util-is: 1.0.2 extsprintf: 1.3.0 - vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.7)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0): + vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.0(supports-color@11.0.0))(sass@1.101.0)(terser@5.49.0)(tsx@4.23.12)(yaml@2.9.0): dependencies: lightningcss: 1.33.0 picomatch: 4.0.5 - postcss: 8.5.19 + postcss: 8.5.25 rolldown: 1.1.5 tinyglobby: 0.2.17 optionalDependencies: - '@types/node': 24.13.3 - esbuild: 0.28.1 + '@types/node': 22.20.1 + esbuild: 0.28.2 fsevents: 2.3.3 jiti: 2.7.0 - less: 4.6.7 + less: 4.9.0(supports-color@11.0.0) sass: 1.101.0 terser: 5.49.0 - tsx: 4.23.1 + tsx: 4.23.12 yaml: 2.9.0 - vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/coverage-v8@4.1.10)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(less@4.6.7)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0): + vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(@vitest/coverage-v8@4.1.10)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@29.1.1)(less@4.9.0(supports-color@11.0.0))(sass@1.101.0)(terser@5.49.0)(tsx@4.23.12)(yaml@2.9.0): dependencies: '@vitest/expect': 4.1.10 - '@vitest/mocker': 4.1.10(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.7)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0)) + '@vitest/mocker': 4.1.10(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.0(supports-color@11.0.0))(sass@1.101.0)(terser@5.49.0)(tsx@4.23.12)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.10 '@vitest/runner': 4.1.10 '@vitest/snapshot': 4.1.10 '@vitest/spy': 4.1.10 '@vitest/utils': 4.1.10 - es-module-lexer: 2.3.1 + es-module-lexer: 2.3.2 expect-type: 1.4.0 magic-string: 0.30.21 obug: 2.1.4 @@ -16512,14 +16753,14 @@ snapshots: picomatch: 4.0.5 std-env: 4.2.0 tinybench: 2.9.0 - tinyexec: 1.2.4 + tinyexec: 1.3.0 tinyglobby: 0.2.17 - tinyrainbow: 3.1.0 - vite: 8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.7)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0) + tinyrainbow: 3.1.1 + vite: 8.1.5(@types/node@22.20.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.0(supports-color@11.0.0))(sass@1.101.0)(terser@5.49.0)(tsx@4.23.12)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: '@opentelemetry/api': 1.9.1 - '@types/node': 24.13.3 + '@types/node': 22.20.1 '@vitest/coverage-v8': 4.1.10(vitest@4.1.10) jsdom: 29.1.1 transitivePeerDependencies: @@ -16563,32 +16804,28 @@ snapshots: webidl-conversions@8.0.1: {} - webpack-dev-middleware@7.4.5(tslib@2.8.1)(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)): + webpack-dev-middleware@7.4.5(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)): dependencies: colorette: 2.0.20 - memfs: 4.64.0(tslib@2.8.1) + memfs: 4.68.1 mime-types: 3.0.2 on-finished: 2.4.1 range-parser: 1.3.0 schema-utils: 4.3.3 optionalDependencies: - webpack: 5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3) - transitivePeerDependencies: - - tslib + webpack: 5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3) - webpack-dev-middleware@8.0.3(tslib@2.8.1)(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)): + webpack-dev-middleware@8.0.3(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)): dependencies: - memfs: 4.64.0(tslib@2.8.1) + memfs: 4.68.1 mime-types: 3.0.2 on-finished: 2.4.1 range-parser: 1.3.0 schema-utils: 4.3.3 optionalDependencies: - webpack: 5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3) - transitivePeerDependencies: - - tslib + webpack: 5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3) - webpack-dev-server@5.2.6(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(tslib@2.8.1)(utf-8-validate@6.0.6)(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)): + webpack-dev-server@5.2.6(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6)(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)): dependencies: '@types/bonjour': 3.5.13 '@types/connect-history-api-fallback': 1.5.4 @@ -16599,32 +16836,31 @@ snapshots: '@types/sockjs': 0.3.36 '@types/ws': 8.18.1 ansi-html-community: 0.0.8 - bonjour-service: 1.4.3 + bonjour-service: 1.4.4 chokidar: 3.6.0 colorette: 2.0.20 - compression: 1.8.1(supports-color@10.2.2) + compression: 1.8.1(supports-color@11.0.0) connect-history-api-fallback: 2.0.0 - express: 4.22.2(supports-color@10.2.2) + express: 4.22.2(supports-color@11.0.0) graceful-fs: 4.2.11 - http-proxy-middleware: 2.0.10(@types/express@4.17.25)(debug@4.4.3(supports-color@10.2.2)) - ipaddr.js: 2.4.0 + http-proxy-middleware: 2.0.10(@types/express@4.17.25)(debug@4.4.3(supports-color@11.0.0)) + ipaddr.js: 2.5.0 launch-editor: 2.14.1 open: 10.2.0 p-retry: 6.2.1 schema-utils: 4.3.3 selfsigned: 5.5.0 - serve-index: 1.9.2(supports-color@10.2.2) + serve-index: 1.9.2(supports-color@11.0.0) sockjs: 0.3.24 - spdy: 4.0.2(supports-color@10.2.2) - webpack-dev-middleware: 7.4.5(tslib@2.8.1)(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)) - ws: 8.21.1(bufferutil@4.1.0)(utf-8-validate@6.0.6) + spdy: 4.0.2(supports-color@11.0.0) + webpack-dev-middleware: 7.4.5(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)) + ws: 8.21.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) optionalDependencies: - webpack: 5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3) + webpack: 5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3) transitivePeerDependencies: - bufferutil - debug - supports-color - - tslib - utf-8-validate webpack-merge@6.0.1: @@ -16635,30 +16871,28 @@ snapshots: webpack-sources@3.5.1: {} - webpack-subresource-integrity@5.1.0(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)): + webpack-subresource-integrity@5.1.0(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)): dependencies: typed-assert: 1.0.9 - webpack: 5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3) + webpack: 5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3) - webpack@5.108.4(esbuild@0.28.1): + webpack@5.109.2(esbuild@0.28.2): dependencies: '@types/estree': 1.0.9 '@types/json-schema': 7.0.15 '@webassemblyjs/ast': 1.14.1 '@webassemblyjs/wasm-edit': 1.14.1 '@webassemblyjs/wasm-parser': 1.14.1 - acorn: 8.17.0 - acorn-import-phases: 1.0.4(acorn@8.17.0) - browserslist: 4.28.7 + acorn: 8.18.0 + browserslist: 4.28.8 chrome-trace-event: 1.0.4 - enhanced-resolve: 5.24.3 - es-module-lexer: 2.3.1 + enhanced-resolve: 5.24.5 + es-module-lexer: 2.3.2 eslint-scope: 5.1.1 events: 3.3.0 graceful-fs: 4.2.11 - loader-runner: 4.3.2 mime-db: 1.54.0 - minimizer-webpack-plugin: 5.6.1(esbuild@0.28.1)(webpack@5.108.4(esbuild@0.28.1)) + minimizer-webpack-plugin: 5.6.1(esbuild@0.28.2)(webpack@5.109.2(esbuild@0.28.2)) neo-async: 2.6.2 schema-utils: 4.3.3 tapable: 2.3.3 @@ -16678,25 +16912,23 @@ snapshots: - postcss - uglify-js - webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3): + webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3): dependencies: '@types/estree': 1.0.9 '@types/json-schema': 7.0.15 '@webassemblyjs/ast': 1.14.1 '@webassemblyjs/wasm-edit': 1.14.1 '@webassemblyjs/wasm-parser': 1.14.1 - acorn: 8.17.0 - acorn-import-phases: 1.0.4(acorn@8.17.0) - browserslist: 4.28.7 + acorn: 8.18.0 + browserslist: 4.28.8 chrome-trace-event: 1.0.4 - enhanced-resolve: 5.24.3 - es-module-lexer: 2.3.1 + enhanced-resolve: 5.24.5 + es-module-lexer: 2.3.2 eslint-scope: 5.1.1 events: 3.3.0 graceful-fs: 4.2.11 - loader-runner: 4.3.2 mime-db: 1.54.0 - minimizer-webpack-plugin: 5.6.1(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)(webpack@5.108.4(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)(uglify-js@3.19.3)) + minimizer-webpack-plugin: 5.6.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)(webpack@5.109.2(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.25)(uglify-js@3.19.3)) neo-async: 2.6.2 schema-utils: 4.3.3 tapable: 2.3.3 @@ -16803,11 +17035,10 @@ snapshots: wordwrap@1.0.0: {} - wrap-ansi@10.0.0: + wrap-ansi@10.0.1: dependencies: ansi-styles: 6.2.3 string-width: 8.2.2 - strip-ansi: 7.2.0 wrap-ansi@7.0.0: dependencies: @@ -16829,7 +17060,7 @@ snapshots: wrappy@1.0.2: {} - ws@8.21.1(bufferutil@4.1.0)(utf-8-validate@6.0.6): + ws@8.21.3(bufferutil@4.1.0)(utf-8-validate@6.0.6): optionalDependencies: bufferutil: 4.1.0 utf-8-validate: 6.0.6 @@ -16885,18 +17116,18 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 - yargs@18.0.0: + yargs@18.1.0: dependencies: cliui: 9.0.1 escalade: 3.2.0 get-caller-file: 2.0.5 - string-width: 7.2.0 + string-width: 8.2.2 y18n: 5.0.8 yargs-parser: 22.0.0 yocto-queue@0.1.0: {} - yoctocolors@2.1.2: {} + yoctocolors@2.2.0: {} zod-to-json-schema@3.25.2(zod@4.4.3): dependencies: diff --git a/renovate.json b/renovate.json index 0299498febd8..0b21b680f015 100644 --- a/renovate.json +++ b/renovate.json @@ -4,6 +4,10 @@ "extends": ["github>angular/dev-infra//renovate-presets/default.json5"], "ignorePaths": ["tests/e2e/assets/**", "tests/schematics/update/packages/**"], "packageRules": [ + { + "matchFileNames": ["tests/e2e/ng-snapshot/package.json"], + "schedule": ["before 8am"] + }, { "enabled": false, "matchFileNames": ["tests/e2e/ng-snapshot/package.json"], @@ -16,6 +20,7 @@ "packages/schematics/angular/utility/latest-versions/package.json" ], "matchPackageNames": ["*"], + "matchUpdateTypes": ["minor", "patch"], "groupName": "schematics dependencies", "lockFileMaintenance": { "enabled": false diff --git a/scripts/saucelabs/start-tunnel.sh b/scripts/saucelabs/start-tunnel.sh deleted file mode 100755 index badf130e6eea..000000000000 --- a/scripts/saucelabs/start-tunnel.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bash - -set -x -u -e -o pipefail - -readonly currentDir=$(cd $(dirname $0); pwd) -readonly connectVersion="sc-4.9.2-linux" -readonly connectHash="2f8a3f87e1da4dc9a41bc45ec7c3a2ecdba4c72d72b7d0193f04ad66c5809104" - -echo "Downloading Sauce Connect" - -curl https://saucelabs.com/downloads/${connectVersion}.tar.gz -o ${currentDir}/${connectVersion}.tar.gz -echo "${connectHash} ${currentDir}/${connectVersion}.tar.gz" | shasum -a 256 -c -tar -xzf ${currentDir}/${connectVersion}.tar.gz -C ${currentDir} - -# Command arguments that will be passed to sauce-connect. By default we disable SSL bumping for -# all requests. This is because SSL bumping is not needed for our test setup and in order -# to perform the SSL bumping, Saucelabs intercepts all HTTP requests in the tunnel VM and modifies -# them. This can cause flakiness as it makes all requests dependent on the SSL bumping middleware. -# See: https://wiki.saucelabs.com/display/DOCS/Troubleshooting+Sauce+Connect#TroubleshootingSauceConnect-DisablingSSLBumping -sauceArgs="--no-ssl-bump-domains all" - -if [[ ! -z "${SAUCE_LOG_FILE:-}" ]]; then - mkdir -p $(dirname ${SAUCE_LOG_FILE}) - sauceArgs="${sauceArgs} --logfile ${SAUCE_LOG_FILE}" -fi - -if [[ ! -z "${SAUCE_READY_FILE:-}" ]]; then - mkdir -p $(dirname ${SAUCE_READY_FILE}) - sauceArgs="${sauceArgs} --readyfile ${SAUCE_READY_FILE}" -fi - -if [[ ! -z "${SAUCE_PID_FILE:-}" ]]; then - mkdir -p $(dirname ${SAUCE_PID_FILE}) - sauceArgs="${sauceArgs} --pidfile ${SAUCE_PID_FILE}" -fi - - -echo "Starting Sauce Connect. Passed arguments: ${sauceArgs}" - -${currentDir}/${connectVersion}/bin/sc -u ${SAUCE_USERNAME} -k ${SAUCE_ACCESS_KEY} ${sauceArgs} diff --git a/scripts/saucelabs/stop-tunnel.sh b/scripts/saucelabs/stop-tunnel.sh deleted file mode 100755 index 4ea8d13c7e12..000000000000 --- a/scripts/saucelabs/stop-tunnel.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash - -# Disable printing of any executed command because this would cause a lot -# of spam due to the loop. -set +x -u -e -o pipefail - -if [[ ! -f ${SAUCE_PID_FILE} ]]; then - echo "Could not find Saucelabs tunnel PID file. Cannot stop tunnel.." - exit 1 -fi - -echo "Shutting down Sauce Connect tunnel" - -# The process id for the sauce-connect instance is stored inside of the pidfile. -tunnelProcessId=$(cat ${SAUCE_PID_FILE}) - -# Kill the process by using the PID that has been read from the pidfile. Note that -# we cannot use killall because CI base container images don't have it installed. -kill ${tunnelProcessId} - -while (ps -p ${tunnelProcessId} &> /dev/null); do - printf "." - sleep .5 -done - -echo "" -echo "Sauce Connect tunnel has been shut down" diff --git a/scripts/saucelabs/wait-for-tunnel.sh b/scripts/saucelabs/wait-for-tunnel.sh deleted file mode 100755 index feda9a85b694..000000000000 --- a/scripts/saucelabs/wait-for-tunnel.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env bash - -# Disable printing of any executed command because this would cause a lot -# of spam due to the loop. -set +x -u -e -o pipefail - -# Waits for Saucelabs Connect to be ready before executing any tests. -counter=0 - -while [[ ! -f ${SAUCE_READY_FILE} ]]; do - counter=$((counter + 1)) - - # Counter needs to be multiplied by two because the while loop only sleeps a half second. - # This has been made in favor of better progress logging (printing dots every half second) - if [ $counter -gt $[${SAUCE_READY_FILE_TIMEOUT} * 2] ]; then - echo "Timed out after ${SAUCE_READY_FILE_TIMEOUT} seconds waiting for tunnel ready file." - echo "Printing logfile output:" - echo "" - cat ${SAUCE_LOG_FILE} - exit 5 - fi - - printf "." - sleep 0.5 -done - -echo "" -echo "Connected to Saucelabs" diff --git a/tests/e2e/assets/protractor-saucelabs.conf.js b/tests/e2e/assets/protractor-saucelabs.conf.js index fb9ab42798a8..cb21d8a3be15 100644 --- a/tests/e2e/assets/protractor-saucelabs.conf.js +++ b/tests/e2e/assets/protractor-saucelabs.conf.js @@ -5,7 +5,50 @@ const { SpecReporter, StacktraceOption } = require('jasmine-spec-reporter'); -const tunnelIdentifier = process.env['SAUCE_TUNNEL_IDENTIFIER']; +const tunnelName = process.env['SAUCE_TUNNEL_IDENTIFIER']; + +const capabilities = [ + { + browserName: 'chrome', + version: '132', + platform: 'Windows 11', + }, + { + browserName: 'chrome', + version: '131', + platform: 'Windows 11', + }, + { + browserName: 'firefox', + version: '134', + platform: 'Windows 11', + }, + { + browserName: 'firefox', + version: '128', // Latest Firefox ESR version as of Jan 2025 + platform: 'Windows 11', + }, + { + browserName: 'safari', + platform: 'macOS 13', + version: '17', + }, + { + browserName: 'safari', + platform: 'macOS 12', + version: '16', + }, + { + browserName: 'MicrosoftEdge', + platform: 'Windows 11', + version: '132', + }, + { + browserName: 'MicrosoftEdge', + platform: 'Windows 11', + version: '131', + }, +]; /** * @type { import("protractor").Config } @@ -13,61 +56,16 @@ const tunnelIdentifier = process.env['SAUCE_TUNNEL_IDENTIFIER']; exports.config = { sauceUser: process.env['SAUCE_USERNAME'], sauceKey: process.env['SAUCE_ACCESS_KEY'], + sauceRegion: 'us', allScriptsTimeout: 11000, specs: ['./src/**/*.e2e-spec.ts'], // NOTE: https://saucelabs.com/products/platform-configurator can be used to determine configuration values - multiCapabilities: [ - { - browserName: 'chrome', - version: '132', - platform: 'Windows 11', - tunnelIdentifier, - }, - { - browserName: 'chrome', - version: '131', - platform: 'Windows 11', - tunnelIdentifier, - }, - { - browserName: 'firefox', - version: '134', - platform: 'Windows 11', - tunnelIdentifier, - }, - { - browserName: 'firefox', - version: '128', // Latest Firefox ESR version as of Jan 2025 - platform: 'Windows 11', - tunnelIdentifier, - }, - { - browserName: 'safari', - platform: 'macOS 13', - version: '17', - tunnelIdentifier, - }, - { - browserName: 'safari', - platform: 'macOS 12', - version: '16', - tunnelIdentifier, - }, - { - browserName: 'MicrosoftEdge', - platform: 'Windows 11', - version: '132', - tunnelIdentifier, - }, - { - browserName: 'MicrosoftEdge', - platform: 'Windows 11', - version: '131', - tunnelIdentifier, - }, - ], + multiCapabilities: capabilities.map((caps) => ({ + ...caps, + tunnelName, + })), // Only allow one session at a time to prevent over saturation of Saucelabs sessions. maxSessions: 1, diff --git a/tests/e2e/tests/build/incremental-watch.ts b/tests/e2e/tests/build/incremental-watch.ts index b2d1662469bb..344d2fb9e916 100644 --- a/tests/e2e/tests/build/incremental-watch.ts +++ b/tests/e2e/tests/build/incremental-watch.ts @@ -7,6 +7,32 @@ import { execAndWaitForOutputToMatch, waitForAnyProcessOutputToMatch } from '../ const buildReadyRegEx = /Application bundle generation complete\./; +async function getOutputFiles( + dir: string, + predicate: (files: string[]) => boolean, + timeout = 10_000, +): Promise { + const start = Date.now(); + while (Date.now() - start < timeout) { + try { + const files = await readdir(dir); + if (predicate(files)) { + return files; + } + } catch (err: any) { + if (err?.code !== 'ENOENT') { + throw err; + } + } + await setTimeout(50); + } + + const files = await readdir(dir); + assert(predicate(files), `Condition not met for files in ${dir}: ${JSON.stringify(files)}`); + + return files; +} + export default async function () { const usingApplicationBuilder = getGlobalVariable('argv')['esbuild']; assert( @@ -20,15 +46,17 @@ export default async function () { ['build', '--watch', '--configuration=development'], buildReadyRegEx, ); - await setTimeout(500); - const initialOutputFiles = await readdir('dist/test-project/browser'); + const initialOutputFiles = await getOutputFiles( + 'dist/test-project/browser', + (files) => files.length > 0, + ); const originalMain = await readFile('src/main.ts'); // Add a dynamic import to create an additional output chunk await Promise.all([ waitForAnyProcessOutputToMatch(buildReadyRegEx), - await writeFile( + writeFile( 'src/a.ts', ` export function sayHi() { @@ -38,8 +66,10 @@ export default async function () { ), appendToFile('src/main.ts', `\nimport('./a').then((m) => m.sayHi());`), ]); - await setTimeout(500); - const intermediateOutputFiles = await readdir('dist/test-project/browser'); + const intermediateOutputFiles = await getOutputFiles( + 'dist/test-project/browser', + (files) => files.length > initialOutputFiles.length, + ); assert( initialOutputFiles.length < intermediateOutputFiles.length, 'Additional chunks should be present', @@ -50,8 +80,10 @@ export default async function () { waitForAnyProcessOutputToMatch(buildReadyRegEx), writeFile('src/main.ts', originalMain), ]); - await setTimeout(500); - const finalOutputFiles = await readdir('dist/test-project/browser'); + const finalOutputFiles = await getOutputFiles( + 'dist/test-project/browser', + (files) => files.length === initialOutputFiles.length, + ); assert.equal( initialOutputFiles.length, finalOutputFiles.length, diff --git a/tests/e2e/tests/commands/add/add-tailwindcss.ts b/tests/e2e/tests/commands/add/add-tailwindcss.ts index 54fd617a4e1e..fa42815d2fdf 100644 --- a/tests/e2e/tests/commands/add/add-tailwindcss.ts +++ b/tests/e2e/tests/commands/add/add-tailwindcss.ts @@ -1,4 +1,5 @@ -import { expectFileToExist, expectFileToMatch, rimraf } from '../../../utils/fs'; +import assert from 'node:assert'; +import { expectFileToExist, expectFileToMatch, readFile, rimraf } from '../../../utils/fs'; import { getActivePackageManager, uninstallPackage } from '../../../utils/packages'; import { ng } from '../../../utils/process'; @@ -14,9 +15,19 @@ export default async function () { await ng('add', 'tailwindcss', '--skip-confirmation'); await expectFileToExist('.postcssrc.json'); await expectFileToMatch('src/styles.css', /@import 'tailwindcss';/); - await expectFileToMatch('package.json', /"tailwindcss":/); - await expectFileToMatch('package.json', /"@tailwindcss\/postcss":/); - await expectFileToMatch('package.json', /"postcss":/); + + const { dependencies, devDependencies } = JSON.parse(await readFile('package.json')); + assert.strictEqual( + dependencies?.tailwindcss, + undefined, + 'tailwindcss should not be added to dependencies.', + ); + assert.ok(devDependencies?.tailwindcss, 'tailwindcss should be added to devDependencies.'); + assert.ok( + devDependencies?.['@tailwindcss/postcss'], + '@tailwindcss/postcss should be added to devDependencies.', + ); + assert.ok(devDependencies?.postcss, 'postcss should be added to devDependencies.'); // Ensure the project builds await ng('build', '--configuration=development'); diff --git a/tests/e2e/tests/commands/add/add-vitest-browser.ts b/tests/e2e/tests/commands/add/add-vitest-browser.ts index 4e7aaf1a4044..7a2b780c0d8f 100644 --- a/tests/e2e/tests/commands/add/add-vitest-browser.ts +++ b/tests/e2e/tests/commands/add/add-vitest-browser.ts @@ -1,4 +1,5 @@ -import { expectFileToMatch } from '../../../utils/fs'; +import assert from 'node:assert'; +import { expectFileToMatch, readFile } from '../../../utils/fs'; import { uninstallPackage } from '../../../utils/packages'; import { ng } from '../../../utils/process'; import { applyVitestBuilder } from '../../../utils/vitest'; @@ -9,8 +10,18 @@ export default async function () { try { await ng('add', '@vitest/browser-playwright', '--skip-confirmation'); - await expectFileToMatch('package.json', /"@vitest\/browser-playwright":/); - await expectFileToMatch('package.json', /"playwright":/); + const { dependencies, devDependencies } = JSON.parse(await readFile('package.json')); + assert.strictEqual( + dependencies?.['@vitest/browser-playwright'], + undefined, + '@vitest/browser-playwright should not be added to dependencies.', + ); + assert.ok( + devDependencies?.['@vitest/browser-playwright'], + '@vitest/browser-playwright should be added to devDependencies.', + ); + assert.ok(devDependencies?.playwright, 'playwright should be added to devDependencies.'); + await expectFileToMatch('tsconfig.spec.json', /"vitest\/globals"/); await expectFileToMatch('tsconfig.spec.json', /"@vitest\/browser-playwright"/); } finally { diff --git a/tests/e2e/tests/test/test-scripts.ts b/tests/e2e/tests/test/test-scripts.ts index 1537cdddf349..953ed52cfbd7 100644 --- a/tests/e2e/tests/test/test-scripts.ts +++ b/tests/e2e/tests/test/test-scripts.ts @@ -5,10 +5,6 @@ import { updateJsonFile } from '../../utils/project'; import { expectToFail } from '../../utils/utils'; export default async function () { - // TODO(architect): Delete this test. It is now in devkit/build-angular. - - await ng('test', '--watch=false'); - // prepare global scripts test files await writeMultipleFiles({ 'src/string-script.js': `globalThis.stringScriptGlobal = 'string-scripts.js';`, diff --git a/tests/e2e/tests/vite/reuse-dep-optimization-cache.ts b/tests/e2e/tests/vite/reuse-dep-optimization-cache.ts index 56ecdfee8cd0..07be3f2a911b 100644 --- a/tests/e2e/tests/vite/reuse-dep-optimization-cache.ts +++ b/tests/e2e/tests/vite/reuse-dep-optimization-cache.ts @@ -1,29 +1,20 @@ import assert from 'node:assert'; import { findFreePort } from '../../utils/network'; -import { - execAndWaitForOutputToMatch, - killAllProcesses, - ng, - waitForAnyProcessOutputToMatch, -} from '../../utils/process'; +import { execAndWaitForOutputToMatch, killAllProcesses, ng } from '../../utils/process'; export default async function () { await ng('cache', 'clean'); await ng('cache', 'on'); const port = await findFreePort(); - const serveReady = execAndWaitForOutputToMatch( + await execAndWaitForOutputToMatch( 'ng', ['serve', '--port', `${port}`], - /Application bundle generation complete/, + /dependencies optimized/, // Use CI:0 to force caching { ...process.env, DEBUG: 'vite:deps', CI: '0', NO_COLOR: 'true' }, ); - // Note: Don't await `serveReady` before, as otherwise we might not see - // the dependencies optimized output. There is some debouncing for `ng serve` - // going on that could cause this. - await Promise.all([serveReady, waitForAnyProcessOutputToMatch(/dependencies optimized/, 10_000)]); const response = await fetch(`http://localhost:${port}/main.js`); assert(response.ok, `Expected 'response.ok' to be 'true'.`); diff --git a/tests/e2e/tests/vitest/larger-project.ts b/tests/e2e/tests/vitest/larger-project.ts index 90bb283f2d8a..7b8db953c30c 100644 --- a/tests/e2e/tests/vitest/larger-project.ts +++ b/tests/e2e/tests/vitest/larger-project.ts @@ -1,7 +1,9 @@ -import { ng } from '../../utils/process'; -import { applyVitestBuilder } from '../../utils/vitest'; import assert from 'node:assert'; +import { mkdir, writeFile } from 'node:fs/promises'; +import { dirname } from 'node:path'; import { installPackage } from '../../utils/packages'; +import { ng } from '../../utils/process'; +import { applyVitestBuilder } from '../../utils/vitest'; export default async function () { await applyVitestBuilder(); @@ -39,31 +41,110 @@ export default async function () { } async function generateArtifactsInBatches(artifactCount: number): Promise { - const BATCH_SIZE = 5; - let commands: Promise[] = []; + const files: { [path: string]: string } = {}; for (let i = 0; i < artifactCount; i++) { const type = i % 3; const name = `test-artifact-${i}`; - let generateType: string; switch (type) { case 0: - generateType = 'component'; + files[`src/app/${name}/${name}.ts`] = ` +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-${name}', + template: '', +}) +export class TestArtifact${i}Component {} +`; + files[`src/app/${name}/${name}.spec.ts`] = ` +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { TestArtifact${i}Component } from './${name}'; + +describe('TestArtifact${i}Component', () => { + let component: TestArtifact${i}Component; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [TestArtifact${i}Component], + }).compileComponents(); + + fixture = TestBed.createComponent(TestArtifact${i}Component); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); +`; break; case 1: - generateType = 'service'; + files[`src/app/${name}.ts`] = ` +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root', +}) +export class TestArtifact${i}Service {} +`; + files[`src/app/${name}.spec.ts`] = ` +import { TestBed } from '@angular/core/testing'; +import { TestArtifact${i}Service } from './${name}'; + +describe('TestArtifact${i}Service', () => { + let service: TestArtifact${i}Service; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(TestArtifact${i}Service); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); +`; break; default: - generateType = 'pipe'; - break; - } + files[`src/app/${name}-pipe.ts`] = ` +import { Pipe, PipeTransform } from '@angular/core'; - commands.push(ng('generate', generateType, name, '--skip-tests=false')); +@Pipe({ + name: 'testArtifact${i}', +}) +export class TestArtifact${i}Pipe implements PipeTransform { + transform(value: unknown): unknown { + return null; + } +} +`; + files[`src/app/${name}-pipe.spec.ts`] = ` +import { TestArtifact${i}Pipe } from './${name}-pipe'; - if (commands.length === BATCH_SIZE || i === artifactCount - 1) { - await Promise.all(commands); - commands = []; +describe('TestArtifact${i}Pipe', () => { + it('create an instance', () => { + const pipe = new TestArtifact${i}Pipe(); + expect(pipe).toBeTruthy(); + }); +}); +`; + break; } } + + const entries = Object.entries(files); + const CONCURRENCY_LIMIT = 100; + for (let i = 0; i < entries.length; i += CONCURRENCY_LIMIT) { + const chunk = entries.slice(i, i + CONCURRENCY_LIMIT); + await Promise.all( + chunk.map(async ([filePath, content]) => { + await mkdir(dirname(filePath), { recursive: true }); + await writeFile(filePath, content.trim()); + }), + ); + } } diff --git a/tests/e2e/utils/puppeteer.ts b/tests/e2e/utils/puppeteer.ts index d33411938639..ae8aae45761a 100644 --- a/tests/e2e/utils/puppeteer.ts +++ b/tests/e2e/utils/puppeteer.ts @@ -40,7 +40,7 @@ export async function executeBrowserTest(options: BrowserTestOptions = {}) { const browser = await launch({ executablePath: process.env['CHROME_BIN'], headless: true, - args: ['--no-sandbox'], + args: ['--no-sandbox', '--disable-dev-shm-usage', '--disable-gpu'], }); try { const page = await browser.newPage();