diff --git a/.github/workflows/assistant-to-the-branch-manager.yml b/.github/workflows/assistant-to-the-branch-manager.yml
index 5431306096a7..f50263aad6ab 100644
--- a/.github/workflows/assistant-to-the-branch-manager.yml
+++ b/.github/workflows/assistant-to-the-branch-manager.yml
@@ -18,6 +18,6 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- - uses: angular/dev-infra/github-actions/branch-manager@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ - uses: angular/dev-infra/github-actions/branch-manager@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ad97a6cf125e..6397ee443590 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@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Setup Bazel
- uses: angular/dev-infra/github-actions/bazel/setup@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/setup@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # 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@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Setup Bazel
- uses: angular/dev-infra/github-actions/bazel/setup@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/setup@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Setup Bazel RBE
- uses: angular/dev-infra/github-actions/bazel/configure-remote@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/configure-remote@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # 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@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Setup Bazel
- uses: angular/dev-infra/github-actions/bazel/setup@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/setup@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Setup Bazel RBE
- uses: angular/dev-infra/github-actions/bazel/configure-remote@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/configure-remote@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # 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@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Setup Bazel
- uses: angular/dev-infra/github-actions/bazel/setup@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/setup@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Setup Bazel RBE
- uses: angular/dev-infra/github-actions/bazel/configure-remote@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/configure-remote@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # 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@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Setup Bazel
- uses: angular/dev-infra/github-actions/bazel/setup@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/setup@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Setup Bazel RBE
- uses: angular/dev-infra/github-actions/bazel/configure-remote@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/configure-remote@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # 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@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # 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@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Setup Bazel
- uses: angular/dev-infra/github-actions/bazel/setup@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/setup@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Setup Bazel RBE
- uses: angular/dev-infra/github-actions/bazel/configure-remote@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/configure-remote@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # 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@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Setup Bazel
- uses: angular/dev-infra/github-actions/bazel/setup@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/setup@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Setup Bazel RBE
- uses: angular/dev-infra/github-actions/bazel/configure-remote@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/configure-remote@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
with:
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
- name: Run CLI E2E tests
@@ -208,13 +208,13 @@ jobs:
SAUCE_TUNNEL_IDENTIFIER: angular-cli-${{ github.workflow }}-${{ github.run_number }}
steps:
- name: Initialize environment
- uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Setup Bazel
- uses: angular/dev-infra/github-actions/bazel/setup@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/setup@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Setup Bazel RBE
- uses: angular/dev-infra/github-actions/bazel/configure-remote@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/configure-remote@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
with:
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
- name: Start Sauce Connect
@@ -245,11 +245,11 @@ jobs:
CIRCLE_BRANCH: ${{ github.ref_name }}
steps:
- name: Initialize environment
- uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Setup Bazel
- uses: angular/dev-infra/github-actions/bazel/setup@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/setup@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- run: pnpm admin snapshots --verbose
env:
SNAPSHOT_BUILDS_GITHUB_TOKEN: ${{ secrets.SNAPSHOT_BUILDS_GITHUB_TOKEN }}
diff --git a/.github/workflows/dev-infra.yml b/.github/workflows/dev-infra.yml
index 98d8d726c99b..b85b240f82dc 100644
--- a/.github/workflows/dev-infra.yml
+++ b/.github/workflows/dev-infra.yml
@@ -16,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@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ - uses: angular/dev-infra/github-actions/labeling/pull-request@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # 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@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ - uses: angular/dev-infra/github-actions/post-approval-changes@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # 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@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ - uses: angular/dev-infra/github-actions/labeling/issue@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # 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 e61e4d1bb083..21a061c26de5 100644
--- a/.github/workflows/perf.yml
+++ b/.github/workflows/perf.yml
@@ -22,7 +22,7 @@ jobs:
workflows: ${{ steps.workflows.outputs.workflows }}
steps:
- name: Initialize environment
- uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Install node modules
run: pnpm install --frozen-lockfile
- id: workflows
@@ -40,9 +40,9 @@ jobs:
workflow: ${{ fromJSON(needs.list.outputs.workflows) }}
steps:
- name: Initialize environment
- uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Setup Bazel
- uses: angular/dev-infra/github-actions/bazel/setup@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/setup@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # 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
diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
index 7cf337949011..f0eb6e091f47 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -34,9 +34,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
- uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Setup Bazel
- uses: angular/dev-infra/github-actions/bazel/setup@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/setup@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # 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@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/linting/licenses@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
build:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
- uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Setup Bazel
- uses: angular/dev-infra/github-actions/bazel/setup@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/setup@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Setup Bazel RBE
- uses: angular/dev-infra/github-actions/bazel/configure-remote@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/configure-remote@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # 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@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Setup Bazel
- uses: angular/dev-infra/github-actions/bazel/setup@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/setup@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Setup Bazel RBE
- uses: angular/dev-infra/github-actions/bazel/configure-remote@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/configure-remote@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # 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@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Setup Bazel
- uses: angular/dev-infra/github-actions/bazel/setup@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/setup@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Setup Bazel RBE
- uses: angular/dev-infra/github-actions/bazel/configure-remote@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/configure-remote@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # 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@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Setup Bazel
- uses: angular/dev-infra/github-actions/bazel/setup@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/setup@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Setup Bazel RBE
- uses: angular/dev-infra/github-actions/bazel/configure-remote@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/configure-remote@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # 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@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # 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@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Setup Bazel
- uses: angular/dev-infra/github-actions/bazel/setup@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/setup@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Setup Bazel RBE
- uses: angular/dev-infra/github-actions/bazel/configure-remote@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/configure-remote@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # 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@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Setup Bazel
- uses: angular/dev-infra/github-actions/bazel/setup@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/setup@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # main
- name: Setup Bazel RBE
- uses: angular/dev-infra/github-actions/bazel/configure-remote@b137f89f74478e0d2b3902372c538d5656795e9a # main
+ uses: angular/dev-infra/github-actions/bazel/configure-remote@c09a8058c7eee99ed9cec6213ff967bad6d6b73c # 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/.nvmrc b/.nvmrc
index df6ae3370f9f..a43a5b943d99 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-24.21.0
+24.22.0
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1922874a08d9..a3c4fa9dd66e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,135 @@
+
+
+# 22.3.0-next.2 (2026-10-15)
+
+### @angular/cli
+
+| Commit | Type | Description |
+| --------------------------------------------------------------------------------------------------- | ---- | ----------------------------------------------------------------- |
+| [5c656152e](https://github.com/angular/angular-cli/commit/5c656152ef91e2731155f6027a845d8014b53e4f) | fix | accept multi-digit array indices in ng config |
+| [2e0f48e3f](https://github.com/angular/angular-cli/commit/2e0f48e3ff40289725d3590fa8e1fc059fbaeb88) | fix | keep ng version working when the package manager is not installed |
+| [a1cf33bc4](https://github.com/angular/angular-cli/commit/a1cf33bc45882fb74578cc7d1faeba8cecec7b73) | fix | resolve package name in npm workspace members |
+
+### @schematics/angular
+
+| Commit | Type | Description |
+| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------------------- |
+| [639d31f11](https://github.com/angular/angular-cli/commit/639d31f11b102a12776ae8dce6369d6edd1b6ff3) | feat | add use-library-builder migration to migrate from ng-packagr |
+| [445cc767e](https://github.com/angular/angular-cli/commit/445cc767e62b72631dd53c0c5324b458fee76608) | fix | keep the workspace build version in the use-application-builder migration |
+
+### @angular-devkit/schematics
+
+| Commit | Type | Description |
+| --------------------------------------------------------------------------------------------------- | ---- | --------------------------------------------- |
+| [b39a5fcda](https://github.com/angular/angular-cli/commit/b39a5fcdac288e317f3b00468c09173a1d306f98) | fix | avoid stack overflow when chaining many rules |
+
+### @angular/build
+
+| Commit | Type | Description |
+| --------------------------------------------------------------------------------------------------- | ---- | --------------------------------------------------------------------------------- |
+| [b975da4b0](https://github.com/angular/angular-cli/commit/b975da4b016eaa107acc259eb8205135d9396f95) | fix | add CSP nonce to stylesheet and modulepreload link elements |
+| [13923047f](https://github.com/angular/angular-cli/commit/13923047f64b6e1063f7f07029c70295b5c99d69) | fix | always use AOT when extracting i18n messages |
+| [d2233e225](https://github.com/angular/angular-cli/commit/d2233e225aa5fd507e3ce7bfd35ae2268c036aa4) | fix | coalesce external watcher directories to avoid macOS FSEvents limit |
+| [23d42fc80](https://github.com/angular/angular-cli/commit/23d42fc806f174c7da961c35e07a42aa1e00d1e7) | fix | conditionally declare tslib in built library package |
+| [f0a74e8f0](https://github.com/angular/angular-cli/commit/f0a74e8f0ea04fd3f839be0120346067440b1350) | fix | disable Vitest fsModuleCache in unit-test builder |
+| [2c518a6db](https://github.com/angular/angular-cli/commit/2c518a6dbe8734d247dfe4eb2c1c4af5e169fa94) | fix | enhance build logs and output location for library builder |
+| [47c328d3e](https://github.com/angular/angular-cli/commit/47c328d3ef7b409af02f270a48f5e99a520fbe14) | fix | ensure Sass importers return global Promise instances |
+| [432aea016](https://github.com/angular/angular-cli/commit/432aea0161840bc135704c040108e46092e61c27) | fix | filter Rolldown warnings and disable .d.ts annotation comments in library builder |
+| [39d230e18](https://github.com/angular/angular-cli/commit/39d230e1862f2f626d3fba03bbf51873f3578153) | fix | keep Vite server file watcher disabled in Vitest watch mode |
+| [93f238c97](https://github.com/angular/angular-cli/commit/93f238c9781897997b1c64d607f3bb3c91ba1fd1) | fix | rebuild library when transitive stylesheet dependencies change in watch mode |
+| [7714a8537](https://github.com/angular/angular-cli/commit/7714a8537589afc6180443cc36acd5149a459c57) | fix | resolve unimported NgModule scopes when filtering unit-test files |
+| [ad4845583](https://github.com/angular/angular-cli/commit/ad4845583b8d1b8de26ccc0e45b4e6e58d95b362) | fix | respect tsconfig declarationMap and compilationMode in library builder |
+| [01afbf418](https://github.com/angular/angular-cli/commit/01afbf418cf6a7688f3f131988eeba3cdac2bde4) | fix | sort discovered unit-test files for deterministic builds |
+| [b640b32e1](https://github.com/angular/angular-cli/commit/b640b32e148ab68f820b390b1d9f03ae9a809266) | fix | use module.registerHooks() for in-memory ESM loader |
+| [0a077eeed](https://github.com/angular/angular-cli/commit/0a077eeed92b43fa195bf10f479d39a7aca2d3f7) | perf | avoid invalidating Angular diagnostic cache on stylesheet change |
+| [2b5a9a620](https://github.com/angular/angular-cli/commit/2b5a9a620495b4c85bf5cfa3db39b632d88e6ca5) | perf | enable TypeScript incremental build cache in library builder |
+| [07845f019](https://github.com/angular/angular-cli/commit/07845f019cf7d70c17f037d711b430a776f96031) | perf | optimize incremental watch rebuilds in AOT compilation |
+| [fb7efc862](https://github.com/angular/angular-cli/commit/fb7efc86228164330f68ed86801f9d5bbe9ad5b0) | perf | resolve asset patterns concurrently with bounded concurrency |
+| [dcf906a62](https://github.com/angular/angular-cli/commit/dcf906a6261a00f95cfbdb18cf9065e1c966e182) | perf | reuse extendedConfigCache in TypeScript compilation |
+
+### @angular/ssr
+
+| Commit | Type | Description |
+| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------ |
+| [0b9a52cc9](https://github.com/angular/angular-cli/commit/0b9a52cc9516d28afa0d9ef0d07ec745967faf56) | fix | preserve preload metadata for nested empty-path routes |
+| [f2cd8c8cf](https://github.com/angular/angular-cli/commit/f2cd8c8cf7c5aa7e7076c87e9c0c55b3bf880f4b) | fix | preserve query parameters on relative route redirects |
+| [b3bbada1e](https://github.com/angular/angular-cli/commit/b3bbada1efd0d3a414cce8843b7284e9560f66fc) | fix | resolve relative redirects against the parent route |
+
+
+
+
+
+# 22.2.3 (2026-10-15)
+
+### @angular/cli
+
+| Commit | Type | Description |
+| --------------------------------------------------------------------------------------------------- | ---- | ----------------------------------------------------------------- |
+| [3158e865f](https://github.com/angular/angular-cli/commit/3158e865ffdd828711d645dff16cc17fd26bb58e) | fix | accept multi-digit array indices in ng config |
+| [bcff0e76a](https://github.com/angular/angular-cli/commit/bcff0e76adf73cfa32b02c5256490189675cb132) | fix | keep ng version working when the package manager is not installed |
+| [5570c91d2](https://github.com/angular/angular-cli/commit/5570c91d2f38764cd841fcce146f1d13fef49b0c) | fix | resolve package name in npm workspace members |
+
+### @schematics/angular
+
+| Commit | Type | Description |
+| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------------------- |
+| [881865f36](https://github.com/angular/angular-cli/commit/881865f364b33b36630aa6ab7a129f7ed665cfa7) | fix | keep the workspace build version in the use-application-builder migration |
+
+### @angular-devkit/schematics
+
+| Commit | Type | Description |
+| --------------------------------------------------------------------------------------------------- | ---- | --------------------------------------------- |
+| [cf1f3b9d4](https://github.com/angular/angular-cli/commit/cf1f3b9d43177e15cf9a00973e6da3baeaf4b2dd) | fix | avoid stack overflow when chaining many rules |
+
+### @angular/build
+
+| Commit | Type | Description |
+| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------------- |
+| [1d477d6bc](https://github.com/angular/angular-cli/commit/1d477d6bc27159cb0c78288e047fcadfe6fc31d4) | fix | add CSP nonce to stylesheet and modulepreload link elements |
+| [fbe208f83](https://github.com/angular/angular-cli/commit/fbe208f8392ec0ce82d597e8b690f146370bdc81) | fix | always use AOT when extracting i18n messages |
+| [c1c4216a6](https://github.com/angular/angular-cli/commit/c1c4216a680891b80670660a621d6736c4aecaf0) | fix | coalesce external watcher directories to avoid macOS FSEvents limit |
+| [792990bc2](https://github.com/angular/angular-cli/commit/792990bc2eacdcc8ed4de6ef46e58ceeb5fe8741) | fix | disable Vitest fsModuleCache in unit-test builder |
+| [82439399c](https://github.com/angular/angular-cli/commit/82439399cbfb4c1d21d1c80d976021efa9e4a39a) | fix | ensure Sass importers return global Promise instances |
+| [a818de415](https://github.com/angular/angular-cli/commit/a818de415e933819e7a2e3e679cd0b2d2be734de) | fix | keep Vite server file watcher disabled in Vitest watch mode |
+| [91bad469e](https://github.com/angular/angular-cli/commit/91bad469ec5ce7b2dfd07e394b482d2cef411407) | fix | sort discovered unit-test files for deterministic builds |
+| [e84db4af7](https://github.com/angular/angular-cli/commit/e84db4af70ca9be490b462e6d8112524dc8eb6d4) | fix | use module.registerHooks() for in-memory ESM loader |
+| [a428021b7](https://github.com/angular/angular-cli/commit/a428021b77dbccf404f39712f1c88bed9b8e4272) | perf | avoid invalidating Angular diagnostic cache on stylesheet change |
+| [b0ac394a0](https://github.com/angular/angular-cli/commit/b0ac394a063f084d885df67660224b6a25e2c614) | perf | resolve asset patterns concurrently with bounded concurrency |
+
+### @angular/ssr
+
+| Commit | Type | Description |
+| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------ |
+| [bd09b98fc](https://github.com/angular/angular-cli/commit/bd09b98fcaff4b76c7fd65999b51bfaa942d1858) | fix | preserve preload metadata for nested empty-path routes |
+| [a92546892](https://github.com/angular/angular-cli/commit/a925468929c74c30a3e64b361a6dc5d6fdc1006a) | fix | preserve query parameters on relative route redirects |
+| [a2b86cc94](https://github.com/angular/angular-cli/commit/a2b86cc94d408ba4c3d422224b58e26b7a68f692) | fix | resolve relative redirects against the parent route |
+
+
+
+
+
+# 21.2.27 (2026-10-14)
+
+### @angular/cli
+
+| Commit | Type | Description |
+| --------------------------------------------------------------------------------------------------- | ---- | ------------------- |
+| [2e1742adf](https://github.com/angular/angular-cli/commit/2e1742adf28645635bb6cff3cc08ad9c94c7d085) | fix | update zod to 4.6.6 |
+
+
+
+
+
+# 20.3.40 (2026-10-14)
+
+### @angular/cli
+
+| Commit | Type | Description |
+| --------------------------------------------------------------------------------------------------- | ---- | ------------------- |
+| [bfe1908f4](https://github.com/angular/angular-cli/commit/bfe1908f46f5799e839dcf0f162955df59a94cb0) | fix | update zod to 4.6.6 |
+
+
+
# 22.3.0-next.1 (2026-10-07)
diff --git a/MODULE.bazel b/MODULE.bazel
index 1a6f890d5188..69ddf30cdb73 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -19,36 +19,36 @@ bazel_dep(name = "aspect_rules_jasmine", version = "2.0.4")
bazel_dep(name = "rules_angular")
git_override(
module_name = "rules_angular",
- commit = "2d9142c529ac31dddf1bb4e7e5a61c696f97a8f4",
+ commit = "bfe6e98434982bad38c393f1bd472ec33f16cd32",
remote = "https://github.com/angular/rules_angular.git",
)
bazel_dep(name = "devinfra")
git_override(
module_name = "devinfra",
- commit = "b137f89f74478e0d2b3902372c538d5656795e9a",
+ commit = "c09a8058c7eee99ed9cec6213ff967bad6d6b73c",
remote = "https://github.com/angular/dev-infra.git",
)
bazel_dep(name = "rules_browsers")
git_override(
module_name = "rules_browsers",
- commit = "dba44a25ad8789113c37c2aace5574d794faa7ef",
+ commit = "48a956da3908e5c923f21e6ffd1c72c5605d61fe",
remote = "https://github.com/angular/rules_browsers.git",
)
node = use_extension("@rules_nodejs//nodejs:extensions.bzl", "node")
node.toolchain(
node_repositories = {
- "24.21.0-darwin_arm64": ("node-v24.21.0-darwin-arm64.tar.gz", "node-v24.21.0-darwin-arm64", "bed7eea5325e1108f32ce5228ddd6a5f0f08a499ee42aa7442aea583702f6057"),
- "24.21.0-darwin_amd64": ("node-v24.21.0-darwin-x64.tar.gz", "node-v24.21.0-darwin-x64", "1462cb3b3046b815cf8ea436d3da450ec1a9f11dac7e5a46b0ada5305d7e8097"),
- "24.21.0-linux_arm64": ("node-v24.21.0-linux-arm64.tar.xz", "node-v24.21.0-linux-arm64", "6ad1325edbdb5649c379b75a237147a666c95d4f9ae8d340fef2d1575d289ad2"),
- "24.21.0-linux_ppc64le": ("node-v24.21.0-linux-ppc64le.tar.xz", "node-v24.21.0-linux-ppc64le", "1936fd64623a2f98d1fb31b456686d10c30e92639899cfefdefa8835d22adccd"),
- "24.21.0-linux_s390x": ("node-v24.21.0-linux-s390x.tar.xz", "node-v24.21.0-linux-s390x", "2ef7e2ecbf7a6c2f3d08d106f6b2f279419c6dac89fe91b8cad193af7890082c"),
- "24.21.0-linux_amd64": ("node-v24.21.0-linux-x64.tar.xz", "node-v24.21.0-linux-x64", "fd8e59d5a511510f6a298afb548f18c7d2b1be404d8b4a27d94fbe49f56cb2d6"),
- "24.21.0-windows_amd64": ("node-v24.21.0-win-x64.zip", "node-v24.21.0-win-x64", "158f7685b44de51f6c0df1d153526cbcd3e1bc739a8dfc607721cef75de9e541"),
+ "24.22.0-darwin_arm64": ("node-v24.22.0-darwin-arm64.tar.gz", "node-v24.22.0-darwin-arm64", "6a9724d9b50a5f22b4816cded441b5a8d9ddae546191a5e5b7efa5a5e2ee26d5"),
+ "24.22.0-darwin_amd64": ("node-v24.22.0-darwin-x64.tar.gz", "node-v24.22.0-darwin-x64", "495e3f273c645f3c4677d438304cdfc701729ea5dec5728f5c8e76a2dece4b91"),
+ "24.22.0-linux_arm64": ("node-v24.22.0-linux-arm64.tar.xz", "node-v24.22.0-linux-arm64", "fef00bb4d36e1c50104a9775a10359beee98f162b4104dd12472c75065c6a143"),
+ "24.22.0-linux_ppc64le": ("node-v24.22.0-linux-ppc64le.tar.xz", "node-v24.22.0-linux-ppc64le", "edfc950d84a74b4fb4fedc8d2a569976682f6bbbf182961a4e916b7aad856013"),
+ "24.22.0-linux_s390x": ("node-v24.22.0-linux-s390x.tar.xz", "node-v24.22.0-linux-s390x", "ee3a16f7700188d62cd87b50fde39f8cbd8ab82f25611114e5ed6ef00d914431"),
+ "24.22.0-linux_amd64": ("node-v24.22.0-linux-x64.tar.xz", "node-v24.22.0-linux-x64", "cc2f601cee82d9a5a233302fe307abc600727035fd7d2c3a3571755989e95008"),
+ "24.22.0-windows_amd64": ("node-v24.22.0-win-x64.zip", "node-v24.22.0-win-x64", "f9683a19877e12a9b167305c8db71040d812876359de21f0d2e97c3f321f80c3"),
},
- node_version = "24.21.0",
+ node_version = "24.22.0",
)
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 = "12.3.4",
- pnpm_version_integrity = "sha512-lhqkH7B32joEpEHZ+OFevAyW2o73ELLrZ7+e58sGEOq9SPH9hfUc/+c4RnhfoPh8VqOocqHYk/hEZ0G1zORUVw==",
+ pnpm_version = "12.11.2",
+ pnpm_version_integrity = "sha512-JaUWUqGWeFr18ovabf6NxYLr76SsHRgCIc4TkCMcX7dmN4IupLbkYzznSs3LCnf3Ja8RutOBd/3t2u6BipVcuQ==",
)
use_repo(pnpm, "pnpm")
diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock
index c29e353e22a7..ec705b4eb497 100644
--- a/MODULE.bazel.lock
+++ b/MODULE.bazel.lock
@@ -93,7 +93,6 @@
"https://bcr.bazel.build/modules/hermetic_launcher/0.0.15/source.json": "aceb903a3bda5131b0a3132ccf77f36f32b96dcb70864049ec8cfdf9c0b0f068",
"https://bcr.bazel.build/modules/jq.bzl/0.1.0/MODULE.bazel": "2ce69b1af49952cd4121a9c3055faa679e748ce774c7f1fda9657f936cae902f",
"https://bcr.bazel.build/modules/jq.bzl/0.4.0/MODULE.bazel": "a7b39b37589f2b0dad53fd6c1ccaabbdb290330caa920d7ef3e6aad068cd4ab2",
- "https://bcr.bazel.build/modules/jq.bzl/0.7.0/MODULE.bazel": "9d382531c42e7a7f6f2ea486aa8f27c605c54f6109e565f04056015e5764deca",
"https://bcr.bazel.build/modules/jq.bzl/0.7.1/MODULE.bazel": "2dc4fd806df09b30aa7e0339f141a661f72df6af237f6db1fc4ca5c5045f1772",
"https://bcr.bazel.build/modules/jq.bzl/0.7.1/source.json": "0dbd7febb9361e34247c952e749f21f258b5123126248624c0d921c4592eac96",
"https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075",
@@ -181,7 +180,6 @@
"https://bcr.bazel.build/modules/rules_nodejs/6.2.0/MODULE.bazel": "ec27907f55eb34705adb4e8257952162a2d4c3ed0f0b3b4c3c1aad1fac7be35e",
"https://bcr.bazel.build/modules/rules_nodejs/6.5.0/MODULE.bazel": "546d0cf79f36f9f6e080816045f97234b071c205f4542e3351bd4424282a8810",
"https://bcr.bazel.build/modules/rules_nodejs/6.7.3/MODULE.bazel": "c22a48b2a0dbf05a9dc5f83837bbc24c226c1f6e618de3c3a610044c9f336056",
- "https://bcr.bazel.build/modules/rules_nodejs/6.7.5/MODULE.bazel": "97e6794043821d23c013baa4a50fd1c599f2e6ae92b06e2c5f1cd7074fd83e7c",
"https://bcr.bazel.build/modules/rules_nodejs/6.7.6/MODULE.bazel": "45f203b9c0d721bcb1a5932815f218091fa2169cede2af3d88a8a17a4fb7676a",
"https://bcr.bazel.build/modules/rules_nodejs/6.7.6/source.json": "ad9987b7979be1ce93d10ffee9b6af4f84f8835cbc7def27937d632da2e4750e",
"https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc",
@@ -386,7 +384,7 @@
"aspect_rules_jasmine": "2.0.4",
"aspect_tools_telemetry": "0.5.2"
},
- "last_notice": 3
+ "last_notice": 0
}
}
},
@@ -447,16 +445,16 @@
},
"@@rules_browsers+//browsers:extensions.bzl%browsers": {
"general": {
- "bzlTransitiveDigest": "v0vEY6SvVg9HBAENk4KWY5NR6epcg4ucdSnkhcCNv8E=",
+ "bzlTransitiveDigest": "OZ8V6/fUTaz9GXcrxaCB7fqf29DyphGiugzTRl7yPR8=",
"usagesDigest": "FmXYJVoVJlnfUU8x8gObSvu4qWcco/9Faw61aC/wBF0=",
"recordedInputs": [],
"generatedRepoSpecs": {
"rules_browsers_chrome_linux": {
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
"attributes": {
- "sha256": "272b05d40a44082c82d09beb35c7cb7116564a6a85ff2f7a48bc161129fc5772",
+ "sha256": "e3f19706550899e76efdadb1ad172c3af2bb89c137a1350fe7f72333d2a4d0a4",
"urls": [
- "https://storage.googleapis.com/chrome-for-testing-public/157.0.8089.0/linux64/chrome-headless-shell-linux64.zip"
+ "https://storage.googleapis.com/chrome-for-testing-public/158.0.8106.0/linux64/chrome-headless-shell-linux64.zip"
],
"named_files": {
"CHROME-HEADLESS-SHELL": "chrome-headless-shell-linux64/chrome-headless-shell"
@@ -472,9 +470,9 @@
"rules_browsers_chrome_mac": {
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
"attributes": {
- "sha256": "9c28150b8c24fa99ac1e9e39fa07247b61d7f6f15f1c25ca9273c1b4273e2afd",
+ "sha256": "1f98187b068d2c631d4465a437ce7c4d83f7bde9b6a0e19faae1c9de04eb4a4d",
"urls": [
- "https://storage.googleapis.com/chrome-for-testing-public/157.0.8089.0/mac-x64/chrome-headless-shell-mac-x64.zip"
+ "https://storage.googleapis.com/chrome-for-testing-public/158.0.8106.0/mac-x64/chrome-headless-shell-mac-x64.zip"
],
"named_files": {
"CHROME-HEADLESS-SHELL": "chrome-headless-shell-mac-x64/chrome-headless-shell"
@@ -490,9 +488,9 @@
"rules_browsers_chrome_mac_arm": {
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
"attributes": {
- "sha256": "a6471f52b4eeb52af88d2f45e16125a9327517fd8b43512fc5561a3318487640",
+ "sha256": "a564d6b8c498a1c8624e9e14f83ece2d9903db1ec2b491e9fa8fdc7805187dce",
"urls": [
- "https://storage.googleapis.com/chrome-for-testing-public/157.0.8089.0/mac-arm64/chrome-headless-shell-mac-arm64.zip"
+ "https://storage.googleapis.com/chrome-for-testing-public/158.0.8106.0/mac-arm64/chrome-headless-shell-mac-arm64.zip"
],
"named_files": {
"CHROME-HEADLESS-SHELL": "chrome-headless-shell-mac-arm64/chrome-headless-shell"
@@ -508,9 +506,9 @@
"rules_browsers_chrome_win64": {
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
"attributes": {
- "sha256": "64332865f3d250a66f704e90d37a3d57f9800d6ea774138ede35ea37d1af7f2c",
+ "sha256": "3a874f0d0d36a84a89c4fedf7e0dfdcad7e4818bbaf22842ac06762305256b87",
"urls": [
- "https://storage.googleapis.com/chrome-for-testing-public/157.0.8089.0/win64/chrome-headless-shell-win64.zip"
+ "https://storage.googleapis.com/chrome-for-testing-public/158.0.8106.0/win64/chrome-headless-shell-win64.zip"
],
"named_files": {
"CHROME-HEADLESS-SHELL": "chrome-headless-shell-win64/chrome-headless-shell.exe"
@@ -526,9 +524,9 @@
"rules_browsers_chromedriver_linux": {
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
"attributes": {
- "sha256": "0901026cbac4cce608a95bcbdcc87166e7736c9cc0431f5d3466058c9e570aec",
+ "sha256": "51b3afc67a5765403601420074ad7091e083133ca8f82e878a49b783614256df",
"urls": [
- "https://storage.googleapis.com/chrome-for-testing-public/157.0.8089.0/linux64/chromedriver-linux64.zip"
+ "https://storage.googleapis.com/chrome-for-testing-public/158.0.8106.0/linux64/chromedriver-linux64.zip"
],
"named_files": {
"CHROMEDRIVER": "chromedriver-linux64/chromedriver"
@@ -542,9 +540,9 @@
"rules_browsers_chromedriver_mac": {
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
"attributes": {
- "sha256": "69b0982bfe954c969cbc9357a39efb2f1861447f4168017831ffafec62448d90",
+ "sha256": "944924ff8ba2ca15407e788f1d36918e4979f9f5329d0bdf8689c9a96c1818fc",
"urls": [
- "https://storage.googleapis.com/chrome-for-testing-public/157.0.8089.0/mac-x64/chromedriver-mac-x64.zip"
+ "https://storage.googleapis.com/chrome-for-testing-public/158.0.8106.0/mac-x64/chromedriver-mac-x64.zip"
],
"named_files": {
"CHROMEDRIVER": "chromedriver-mac-x64/chromedriver"
@@ -558,9 +556,9 @@
"rules_browsers_chromedriver_mac_arm": {
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
"attributes": {
- "sha256": "18d30af4843f5535d56ab615702749650f1fc9c6b67ec3fd419ed5a9d4fcbf58",
+ "sha256": "2b46fd5f3838e6a2ea73e29e67537c97f43a23eeddbf5522ac15cd27f05a4987",
"urls": [
- "https://storage.googleapis.com/chrome-for-testing-public/157.0.8089.0/mac-arm64/chromedriver-mac-arm64.zip"
+ "https://storage.googleapis.com/chrome-for-testing-public/158.0.8106.0/mac-arm64/chromedriver-mac-arm64.zip"
],
"named_files": {
"CHROMEDRIVER": "chromedriver-mac-arm64/chromedriver"
@@ -574,9 +572,9 @@
"rules_browsers_chromedriver_win64": {
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
"attributes": {
- "sha256": "9b79fc95eed9212d5888a1a7de456eba68df54d65b6fb490ce34d55efdc5cd48",
+ "sha256": "5c38e2e1d06b51e34885fb0474bf74a5bb36e4a6a517327df8d74f49d7cf9dd8",
"urls": [
- "https://storage.googleapis.com/chrome-for-testing-public/157.0.8089.0/win64/chromedriver-win64.zip"
+ "https://storage.googleapis.com/chrome-for-testing-public/158.0.8106.0/win64/chromedriver-win64.zip"
],
"named_files": {
"CHROMEDRIVER": "chromedriver-win64/chromedriver.exe"
@@ -590,9 +588,9 @@
"rules_browsers_firefox_linux": {
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
"attributes": {
- "sha256": "42f2c62a562316982ef5a796738c57602bf84a984f5c616e80bcff4627f78fff",
+ "sha256": "9549b054ec4cf85f50f6a19d8c6fb79580312e71ebc4ec2cb217ec9af09dc12a",
"urls": [
- "https://archive.mozilla.org/pub/firefox/releases/157.0/linux-x86_64/en-US/firefox-157.0.tar.xz"
+ "https://archive.mozilla.org/pub/firefox/releases/158.0/linux-x86_64/en-US/firefox-158.0.tar.xz"
],
"named_files": {
"FIREFOX": "firefox/firefox"
@@ -606,9 +604,9 @@
"rules_browsers_firefox_mac": {
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
"attributes": {
- "sha256": "df6d8c79b6126bcf24cb70ebab9371916a662028e2d706e462d432e78fdf396c",
+ "sha256": "dfe8508ee8880cec1578253eb02b9154b5971a55e832d97396f463cd07b5ef67",
"urls": [
- "https://archive.mozilla.org/pub/firefox/releases/157.0/mac/en-US/Firefox%20157.0.dmg"
+ "https://archive.mozilla.org/pub/firefox/releases/158.0/mac/en-US/Firefox%20158.0.dmg"
],
"named_files": {
"FIREFOX": "Firefox.app/Contents/MacOS/firefox"
@@ -622,9 +620,9 @@
"rules_browsers_firefox_mac_arm": {
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
"attributes": {
- "sha256": "df6d8c79b6126bcf24cb70ebab9371916a662028e2d706e462d432e78fdf396c",
+ "sha256": "dfe8508ee8880cec1578253eb02b9154b5971a55e832d97396f463cd07b5ef67",
"urls": [
- "https://archive.mozilla.org/pub/firefox/releases/157.0/mac/en-US/Firefox%20157.0.dmg"
+ "https://archive.mozilla.org/pub/firefox/releases/158.0/mac/en-US/Firefox%20158.0.dmg"
],
"named_files": {
"FIREFOX": "Firefox.app/Contents/MacOS/firefox"
@@ -638,9 +636,9 @@
"rules_browsers_firefox_win64": {
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
"attributes": {
- "sha256": "58c90afab6e4b9a6b34d2958fe06d1a143dd9226ea8834377e5cd45e815936d7",
+ "sha256": "450ab1c772e02f0c9ef02f489b153d86c45bd9311b202d10dc233f3c0206f8d1",
"urls": [
- "https://archive.mozilla.org/pub/firefox/releases/157.0/win64/en-US/Firefox%20Setup%20157.0.exe"
+ "https://archive.mozilla.org/pub/firefox/releases/158.0/win64/en-US/Firefox%20Setup%20158.0.exe"
],
"named_files": {
"FIREFOX": "core/firefox.exe"
@@ -1071,6 +1069,9 @@
}
},
"facts": {
+ "@@aspect_rules_js+//npm:extensions.bzl%pnpm": {
+ "exe:12.11.2": "{\"darwin-arm64\":\"sha512-n9M4On66y8FDxUAKgMO1FXt0qihyG4e+56p3/F0uo8Bx9KplW8BwKVnXigzCJ8aNM6sVVPkOE6M9XXbeVIxnZA==\",\"darwin-x64\":\"sha512-oSW7n3sBT0c0cyk4kj10T2Y6Mpm+OFEiCAWozgX039tdoI6yqJF1uaFD3sw7ugLdu6VV3+uY0pa1TUZIPdxDWA==\",\"linux-arm64\":\"sha512-6e8ZAQUwFXAWHHHv5FesWqf/kEK04wuitBv5f/gxzkC0DiBfaixr+f+6JQede8SF4Ji5LcMwVFJbzAtffpWxEg==\",\"linux-arm64-musl\":\"sha512-uMEYDwKRktGwANubQ+kYCwmhNwg3Ik6qK89ahsbQ5cP30R/5FVJb/T99vr9XRUBC/A7mZI6eeT92oyVas9ACyg==\",\"linux-x64\":\"sha512-FK7QKe24AYgppJwO3mpooYptduuvIGqKJPi5ac7MdnWkjUy46JBfYhCW0grnkWKC8YOf0x+vGviuQqJEj3SpQQ==\",\"linux-x64-musl\":\"sha512-7eIxQR05fvJxCujUSKp5KTtehJ7QqrgqP/HD1+BcB/SaV2Be4XI1PEHiOgA1zxsiMIeMvTF6E4G4dYHrFjeXRg==\",\"win32-arm64\":\"sha512-PCTjVDdJb6VvraZxrEeFv6EqEA0hhIsAySx28e95J2Tqpi88hLpgOXgNqV0vpxq9A+b8GLQfyk/D+1UlJPv/YQ==\",\"win32-x64\":\"sha512-8sgX86OvRjJ3yZs/TvGR2L31wH9ScPZ+f+geKI3ikuB0RRiK3i4LlTRO8OXN6pdRqj8epMde4312MCjj7JsJdA==\"}"
+ },
"@@aspect_tools_telemetry+//:extension.bzl%telemetry": {
"notice_version": "3"
}
diff --git a/modules/testing/builder/package.json b/modules/testing/builder/package.json
index 8823cbf0c68e..398a200cdf8a 100644
--- a/modules/testing/builder/package.json
+++ b/modules/testing/builder/package.json
@@ -4,12 +4,12 @@
"@angular-devkit/build-angular": "workspace:*",
"@angular-devkit/core": "workspace:*",
"@angular/ssr": "workspace:*",
- "@vitest/coverage-v8": "5.0.3",
+ "@vitest/coverage-v8": "5.0.4",
"browser-sync": "3.0.4",
"istanbul-lib-instrument": "6.0.3",
"jsdom": "30.1.2",
"ng-packagr": "22.3.0-next.2",
"rxjs": "7.8.2",
- "vitest": "5.0.3"
+ "vitest": "5.0.4"
}
}
diff --git a/modules/testing/builder/projects/hello-world-lib/projects/lib/tsconfig.lib.json b/modules/testing/builder/projects/hello-world-lib/projects/lib/tsconfig.lib.json
index fe12470400e2..23e851ac9c8b 100644
--- a/modules/testing/builder/projects/hello-world-lib/projects/lib/tsconfig.lib.json
+++ b/modules/testing/builder/projects/hello-world-lib/projects/lib/tsconfig.lib.json
@@ -2,7 +2,6 @@
"extends": "../../tsconfig.json",
"compilerOptions": {
"declaration": true,
- "declarationMap": true,
"inlineSources": true,
"types": []
},
diff --git a/package.json b/package.json
index 1037a8bfa7c6..911eea20e9f6 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@angular/devkit-repo",
- "version": "22.3.0-next.1",
+ "version": "22.3.0-next.2",
"private": true,
"description": "Software Development Kit for Angular",
"keywords": [
@@ -29,12 +29,12 @@
"type": "git",
"url": "git+https://github.com/angular/angular-cli.git"
},
- "packageManager": "pnpm@12.10.1",
+ "packageManager": "pnpm@12.11.2",
"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": "12.10.1"
+ "pnpm": "12.11.2"
},
"author": "Angular Authors",
"license": "MIT",
@@ -43,23 +43,23 @@
},
"homepage": "https://github.com/angular/angular-cli",
"dependencies": {
- "@angular/compiler-cli": "22.3.0-next.1",
+ "@angular/compiler-cli": "22.3.0-next.2",
"typescript": "6.0.3"
},
"devDependencies": {
- "@angular/animations": "22.3.0-next.1",
- "@angular/cdk": "22.3.0-next.1",
- "@angular/common": "22.3.0-next.1",
- "@angular/compiler": "22.3.0-next.1",
- "@angular/core": "22.3.0-next.1",
- "@angular/forms": "22.3.0-next.1",
- "@angular/localize": "22.3.0-next.1",
- "@angular/material": "22.3.0-next.1",
- "@angular/ng-dev": "https://github.com/angular/dev-infra-private-ng-dev-builds.git#89b8c002e5d47ba1cbc4483d3ec06b0ae0aaccb7",
- "@angular/platform-browser": "22.3.0-next.1",
- "@angular/platform-server": "22.3.0-next.1",
- "@angular/router": "22.3.0-next.1",
- "@angular/service-worker": "22.3.0-next.1",
+ "@angular/animations": "22.3.0-next.2",
+ "@angular/cdk": "22.3.0-next.2",
+ "@angular/common": "22.3.0-next.2",
+ "@angular/compiler": "22.3.0-next.2",
+ "@angular/core": "22.3.0-next.2",
+ "@angular/forms": "22.3.0-next.2",
+ "@angular/localize": "22.3.0-next.2",
+ "@angular/material": "22.3.0-next.2",
+ "@angular/ng-dev": "https://github.com/angular/dev-infra-private-ng-dev-builds.git#940c0beef0de4cb128e90962d47ff80e352a1cd8",
+ "@angular/platform-browser": "22.3.0-next.2",
+ "@angular/platform-server": "22.3.0-next.2",
+ "@angular/router": "22.3.0-next.2",
+ "@angular/service-worker": "22.3.0-next.2",
"@babel/core": "8.0.7",
"@bazel/bazelisk": "1.28.1",
"@bazel/buildifier": "8.2.1",
@@ -70,7 +70,7 @@
"@rollup/plugin-commonjs": "^29.0.0",
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-node-resolve": "16.0.3",
- "@rollup/wasm-node": "4.64.1",
+ "@rollup/wasm-node": "4.64.6",
"@stylistic/eslint-plugin": "^5.0.0",
"@tony.ganchev/eslint-plugin-header": "~3.4.0",
"@types/babel__core": "7.20.5",
@@ -91,8 +91,8 @@
"@types/semver": "^7.3.12",
"@types/yargs": "^17.0.20",
"@types/yargs-parser": "^21.0.0",
- "@typescript-eslint/eslint-plugin": "8.71.1",
- "@typescript-eslint/parser": "8.71.1",
+ "@typescript-eslint/eslint-plugin": "8.71.2",
+ "@typescript-eslint/parser": "8.71.2",
"ajv": "8.20.0",
"buffer": "6.0.3",
"esbuild": "0.28.2",
@@ -100,7 +100,7 @@
"eslint": "10.12.0",
"eslint-config-prettier": "10.1.8",
"eslint-plugin-import": "2.32.0",
- "express": "5.2.1",
+ "express": "5.3.0",
"fast-glob": "3.3.3",
"globals": "17.13.0",
"http-proxy": "^1.18.1",
@@ -119,15 +119,15 @@
"lodash": "^4.17.21",
"magic-string": "1.4.3",
"prettier": "^3.0.0",
- "puppeteer": "25.12.0",
+ "puppeteer": "25.14.0",
"quicktype-core": "26.0.0",
- "rollup": "4.64.1",
+ "rollup": "4.64.6",
"rollup-plugin-dts": "6.5.1",
"rollup-plugin-sourcemaps2": "0.5.9",
"semver": "7.8.5",
"source-map-support": "0.5.21",
"tslib": "2.8.1",
- "undici": "8.11.2",
+ "undici": "8.12.1",
"verdaccio": "6.10.5",
"verdaccio-auth-memory": "^13.0.0",
"zone.js": "^0.16.0"
diff --git a/packages/angular/build/BUILD.bazel b/packages/angular/build/BUILD.bazel
index bf6c034292df..d0ab55750e98 100644
--- a/packages/angular/build/BUILD.bazel
+++ b/packages/angular/build/BUILD.bazel
@@ -153,6 +153,7 @@ ts_project(
":build",
":node_modules/@angular-devkit/core",
":node_modules/@babel/core",
+ ":node_modules/@parcel/watcher",
":node_modules/oxc-parser",
"//:node_modules/@angular/compiler-cli",
"//:node_modules/@angular/router",
diff --git a/packages/angular/build/package.json b/packages/angular/build/package.json
index 2aa20f0c6b8f..711ab5893f75 100644
--- a/packages/angular/build/package.json
+++ b/packages/angular/build/package.json
@@ -24,27 +24,27 @@
"@inquirer/confirm": "6.3.3",
"@parcel/watcher": "2.6.0",
"@vitejs/plugin-basic-ssl": "2.3.0",
- "beasties": "0.5.4",
+ "beasties": "0.5.5",
"browserslist": "^4.26.0",
"chokidar": "5.0.0",
"esbuild": "0.28.2",
"https-proxy-agent": "9.1.0",
"jsonc-parser": "3.3.1",
- "listr2": "11.1.1",
+ "listr2": "11.2.0",
"magic-string": "1.4.3",
"mrmime": "2.0.1",
- "oxc-parser": "0.153.0",
+ "oxc-parser": "0.154.0",
"parse5-html-rewriting-stream": "8.0.1",
"picomatch": "4.0.7",
"piscina": "5.3.2",
- "rolldown": "1.2.12",
- "rolldown-plugin-dts": "0.28.6",
+ "rolldown": "1.2.14",
+ "rolldown-plugin-dts": "0.28.8",
"sass": "1.105.1",
"sass-embedded": "1.105.1",
"semver": "7.8.5",
"source-map-support": "0.5.21",
"tinyglobby": "0.2.17",
- "vite": "8.3.3",
+ "vite": "8.3.4",
"xxhash-wasm": "1.1.0"
},
"optionalDependencies": {
@@ -53,16 +53,16 @@
"devDependencies": {
"@angular-devkit/core": "workspace:*",
"@angular/ssr": "workspace:*",
- "@oxc-project/types": "0.153.0",
- "@vitest/coverage-v8": "5.0.3",
+ "@oxc-project/types": "0.154.0",
+ "@vitest/coverage-v8": "5.0.4",
"istanbul-lib-instrument": "6.0.3",
"jsdom": "30.1.2",
"less": "4.9.1",
"ng-packagr": "22.3.0-next.2",
- "postcss": "8.5.29",
- "rollup": "4.64.1",
+ "postcss": "8.5.30",
+ "rollup": "4.64.6",
"rxjs": "7.8.2",
- "vitest": "5.0.3"
+ "vitest": "5.0.4"
},
"peerDependencies": {
"@angular/compiler": "0.0.0-ANGULAR-FW-PEER-DEP",
diff --git a/packages/angular/build/src/builders/application/build-action.ts b/packages/angular/build/src/builders/application/build-action.ts
index b728ab9a8df5..eaae50848a48 100644
--- a/packages/angular/build/src/builders/application/build-action.ts
+++ b/packages/angular/build/src/builders/application/build-action.ts
@@ -333,7 +333,7 @@ function* emitOutputResults(
incrementalResult.files.push({
path: destination,
type: BuildOutputFileType.Browser,
- inputPath: source,
+ source,
origin: 'disk',
});
}
@@ -406,7 +406,7 @@ function createFullResult(
...assetFiles.map(({ source, destination }) => ({
path: destination,
type: BuildOutputFileType.Browser,
- inputPath: source,
+ source,
origin: 'disk' as const,
})),
...outputFiles.map((file) => ({
diff --git a/packages/angular/build/src/builders/application/index.ts b/packages/angular/build/src/builders/application/index.ts
index 59ded1cd8182..db2cee237896 100644
--- a/packages/angular/build/src/builders/application/index.ts
+++ b/packages/angular/build/src/builders/application/index.ts
@@ -8,12 +8,12 @@
import { Builder, BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/architect';
import assert from 'node:assert';
-import fs from 'node:fs/promises';
import path from 'node:path';
import { BuildOutputFileType } from '../../tools/esbuild/bundler-files';
-import { createJsonBuildManifest, emitFilesToDisk } from '../../tools/esbuild/utils';
+import { createJsonBuildManifest } from '../../tools/esbuild/utils';
import { colors as ansiColors } from '../../utils/color';
import { deleteOutputDir } from '../../utils/delete-output-dir';
+import { deleteFilesFromDisk, emitFilesToDisk } from '../../utils/disk-files';
import { bazelEsbuildPluginPath, useJSONBuildLogs } from '../../utils/environment-options';
import { isSubDirectory } from '../../utils/path';
import { purgeStaleBuildCache } from '../../utils/purge-cache';
@@ -197,37 +197,14 @@ export async function* buildApplication(
}
// Writes the output files to disk and ensures the containing directories are present
- const directoryExists = new Set();
try {
- await emitFilesToDisk(result.files, async (file) => {
- if (
- outputOptions.ignoreServer &&
- (file.type === BuildOutputFileType.ServerApplication ||
- file.type === BuildOutputFileType.ServerRoot)
- ) {
- return;
- }
-
- const fullFilePath = generateFullPath(file.path, file.type, outputOptions);
-
- // Ensure output subdirectories exist
- const fileBasePath = path.dirname(fullFilePath);
- if (fileBasePath && !directoryExists.has(fileBasePath)) {
- await fs.mkdir(fileBasePath, { recursive: true });
- directoryExists.add(fileBasePath);
- }
-
- if (file.origin === 'memory') {
- // Write file contents
- await fs.writeFile(fullFilePath, file.contents);
- } else {
- // Copy file contents
- await fs.cp(file.inputPath, fullFilePath, {
- mode: fs.constants.COPYFILE_FICLONE,
- preserveTimestamps: true,
- });
- }
- });
+ await emitFilesToDisk(result.files, (file) =>
+ outputOptions.ignoreServer &&
+ (file.type === BuildOutputFileType.ServerApplication ||
+ file.type === BuildOutputFileType.ServerRoot)
+ ? undefined
+ : generateFullPath(file.path, file.type, outputOptions),
+ );
} catch (error) {
context.logger.error(error instanceof Error ? error.message : String(error));
yield { success: false };
@@ -237,13 +214,10 @@ export async function* buildApplication(
// Delete any removed files if incremental
if (result.kind === ResultKind.Incremental && result.removed?.length) {
try {
- await Promise.all(
- result.removed.map((file) => {
- const fullFilePath = generateFullPath(file.path, file.type, outputOptions);
-
- return fs.rm(fullFilePath, { force: true, maxRetries: 3 });
- }),
+ const filesToDelete = result.removed.map((file) =>
+ generateFullPath(file.path, file.type, outputOptions),
);
+ await deleteFilesFromDisk(filesToDelete);
} catch (error) {
context.logger.error(error instanceof Error ? error.message : String(error));
yield { success: false };
diff --git a/packages/angular/build/src/builders/application/options.ts b/packages/angular/build/src/builders/application/options.ts
index 322c2dbef897..0e225be24045 100644
--- a/packages/angular/build/src/builders/application/options.ts
+++ b/packages/angular/build/src/builders/application/options.ts
@@ -287,7 +287,7 @@ export async function normalizeOptions(
// Skip tailwind configuration if postcss is customized
const tailwindConfiguration = postcssConfiguration
? undefined
- : await getTailwindConfig(searchDirectories, workspaceRoot, context.logger);
+ : getTailwindConfig(searchDirectories, workspaceRoot, context.logger);
let serverEntryPoint: string | undefined;
if (typeof options.server === 'string') {
diff --git a/packages/angular/build/src/builders/application/results.ts b/packages/angular/build/src/builders/application/results.ts
index 8e95176639f5..e9bd786a3fe6 100644
--- a/packages/angular/build/src/builders/application/results.ts
+++ b/packages/angular/build/src/builders/application/results.ts
@@ -53,7 +53,7 @@ export interface BaseResultFile {
export interface DiskFile extends BaseResultFile {
origin: 'disk';
- inputPath: string;
+ source: string;
}
export interface MemoryFile extends BaseResultFile {
diff --git a/packages/angular/build/src/builders/application/tests/behavior/rebuild-errors_spec.ts b/packages/angular/build/src/builders/application/tests/behavior/rebuild-errors_spec.ts
index de53c7223fff..5e7bdeb3fd9c 100644
--- a/packages/angular/build/src/builders/application/tests/behavior/rebuild-errors_spec.ts
+++ b/packages/angular/build/src/builders/application/tests/behavior/rebuild-errors_spec.ts
@@ -15,12 +15,6 @@ import {
expectNoLog,
} from '../setup';
-/**
- * Maximum time in milliseconds for single build/rebuild
- * This accounts for CI variability.
- */
-export const BUILD_TIMEOUT = 30_000;
-
describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => {
describe('Behavior: "Rebuild Error Detection"', () => {
it('detects template errors with no AOT codegen or TS emit differences', async () => {
@@ -128,6 +122,235 @@ describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => {
);
});
+ it('detects template errors across components on watch rebuild when isolatedModules is enabled', async () => {
+ harness.useTarget('build', {
+ ...BASE_OPTIONS,
+ watch: true,
+ });
+
+ await harness.modifyFile('tsconfig.json', (content) => {
+ const tsconfig = JSON.parse(content);
+ tsconfig.compilerOptions = {
+ ...tsconfig.compilerOptions,
+ isolatedModules: true,
+ };
+
+ return JSON.stringify(tsconfig);
+ });
+
+ const goodChildComponentContents = `
+ import { Component, Input } from '@angular/core';
+ @Component({
+ selector: 'child',
+ standalone: true,
+ template: '{{ value }}
',
+ })
+ export class ChildComponent {
+ @Input() value!: number;
+ }
+ `;
+
+ const typeErrorText = `Type 'number' is not assignable to type 'string'.`;
+
+ await harness.writeFiles({
+ 'src/app/child.component.ts': goodChildComponentContents,
+ 'src/app/app.module.ts': `
+ import { NgModule } from '@angular/core';
+ import { BrowserModule } from '@angular/platform-browser';
+ import { AppComponent } from './app.component';
+ @NgModule({
+ imports: [
+ BrowserModule,
+ AppComponent,
+ ],
+ providers: [],
+ bootstrap: [AppComponent]
+ })
+ export class AppModule { }
+ `,
+ 'src/app/app.component.ts': `
+ import { Component } from '@angular/core';
+ import { ChildComponent } from './child.component';
+ @Component({
+ selector: 'app-root',
+ standalone: true,
+ imports: [ChildComponent],
+ template: '',
+ })
+ export class AppComponent {}
+ `,
+ });
+
+ await harness.executeWithCases(
+ [
+ async ({ result }) => {
+ expect(result?.success).toBeTrue();
+
+ // Update child component to change input type from number to string
+ await harness.writeFile(
+ 'src/app/child.component.ts',
+ `
+ import { Component, Input } from '@angular/core';
+ @Component({
+ selector: 'child',
+ standalone: true,
+ template: '{{ value }}
',
+ })
+ export class ChildComponent {
+ @Input() value!: string;
+ }
+ `,
+ );
+ },
+ async ({ result, logs }) => {
+ expect(result?.success).toBeFalse();
+ expectLog(logs, typeErrorText);
+
+ // Make an unrelated change to verify error persists
+ await harness.modifyFile('src/main.ts', (content) => content + '\n');
+ },
+ async ({ result, logs }) => {
+ expect(result?.success).toBeFalse();
+ expectLog(logs, typeErrorText);
+
+ // Revert back to number
+ await harness.writeFile('src/app/child.component.ts', goodChildComponentContents);
+ },
+ async ({ result, logs }) => {
+ expect(result?.success).toBeTrue();
+ expectNoLog(logs, typeErrorText);
+
+ // Make an unrelated change to verify error cache cleared
+ await harness.modifyFile('src/main.ts', (content) => content + '\n');
+ },
+ ({ result, logs }) => {
+ expect(result?.success).toBeTrue();
+ expectNoLog(logs, typeErrorText);
+ },
+ ],
+ { outputLogsOnFailure: false },
+ );
+ });
+
+ it('detects template errors when an input becomes required or a selector is renamed on watch rebuild', async () => {
+ harness.useTarget('build', {
+ ...BASE_OPTIONS,
+ watch: true,
+ });
+
+ await harness.modifyFile('tsconfig.json', (content) => {
+ const tsconfig = JSON.parse(content);
+ tsconfig.compilerOptions = {
+ ...tsconfig.compilerOptions,
+ isolatedModules: true,
+ };
+
+ return JSON.stringify(tsconfig);
+ });
+
+ const goodChildComponentContents = `
+ import { Component, input } from '@angular/core';
+ @Component({
+ selector: 'app-child',
+ standalone: true,
+ template: '{{ label() }}
',
+ })
+ export class ChildComponent {
+ label = input('');
+ }
+ `;
+
+ const requiredInputErrorText = `Required input 'label' from component ChildComponent must be specified.`;
+ const unknownElementErrorText = `'app-child' is not a known element`;
+
+ await harness.writeFiles({
+ 'src/app/child.component.ts': goodChildComponentContents,
+ 'src/app/app.module.ts': `
+ import { NgModule } from '@angular/core';
+ import { BrowserModule } from '@angular/platform-browser';
+ import { AppComponent } from './app.component';
+ @NgModule({
+ imports: [
+ BrowserModule,
+ AppComponent,
+ ],
+ providers: [],
+ bootstrap: [AppComponent]
+ })
+ export class AppModule { }
+ `,
+ 'src/app/app.component.ts': `
+ import { Component } from '@angular/core';
+ import { ChildComponent } from './child.component';
+ @Component({
+ selector: 'app-root',
+ standalone: true,
+ imports: [ChildComponent],
+ template: '',
+ })
+ export class AppComponent {}
+ `,
+ });
+
+ await harness.executeWithCases(
+ [
+ async ({ result }) => {
+ expect(result?.success).toBeTrue();
+
+ // Make input required using signal input.required() (which has the same TS .d.ts type InputSignal)
+ await harness.writeFile(
+ 'src/app/child.component.ts',
+ `
+ import { Component, input } from '@angular/core';
+ @Component({
+ selector: 'app-child',
+ standalone: true,
+ template: '{{ label() }}
',
+ })
+ export class ChildComponent {
+ label = input.required();
+ }
+ `,
+ );
+ },
+ async ({ result, logs }) => {
+ expect(result?.success).toBeFalse();
+ expectLog(logs, requiredInputErrorText);
+
+ // Revert required input and rename selector instead
+ await harness.writeFile(
+ 'src/app/child.component.ts',
+ `
+ import { Component, input } from '@angular/core';
+ @Component({
+ selector: 'app-child-renamed',
+ standalone: true,
+ template: '{{ label() }}
',
+ })
+ export class ChildComponent {
+ label = input('');
+ }
+ `,
+ );
+ },
+ async ({ result, logs }) => {
+ expect(result?.success).toBeFalse();
+ expectNoLog(logs, requiredInputErrorText);
+ expectLog(logs, unknownElementErrorText);
+
+ // Revert back to valid child component
+ await harness.writeFile('src/app/child.component.ts', goodChildComponentContents);
+ },
+ ({ result, logs }) => {
+ expect(result?.success).toBeTrue();
+ expectNoLog(logs, requiredInputErrorText);
+ expectNoLog(logs, unknownElementErrorText);
+ },
+ ],
+ { outputLogsOnFailure: false },
+ );
+ });
+
it('detects cumulative block syntax errors', async () => {
harness.useTarget('build', {
...BASE_OPTIONS,
@@ -234,7 +457,7 @@ describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => {
await harness.appendToFile('src/app/app.component.html', 'Guten Tag
');
},
({ logs }) => {
- expectNoLog(logs, 'invalid-css-content');
+ expectNoLog(logs, 'Unexpected character "EOF"');
harness.expectFile('dist/browser/main.js').content.toContain('Hello, world!');
harness.expectFile('dist/browser/main.js').content.toContain('Guten Tag');
diff --git a/packages/angular/build/src/builders/dev-server/schema.json b/packages/angular/build/src/builders/dev-server/schema.json
index 023478ff7e52..3517d3098887 100644
--- a/packages/angular/build/src/builders/dev-server/schema.json
+++ b/packages/angular/build/src/builders/dev-server/schema.json
@@ -91,7 +91,7 @@
},
"hmr": {
"type": "boolean",
- "description": "Enable hot module replacement. Defaults to the value of 'liveReload'. Currently, only global and component stylesheets are supported."
+ "description": "Enable hot module replacement. Defaults to the value of 'liveReload'. Currently, global stylesheets, component stylesheets, and component templates are supported."
},
"watch": {
"type": "boolean",
diff --git a/packages/angular/build/src/builders/dev-server/vite/utils.ts b/packages/angular/build/src/builders/dev-server/vite/utils.ts
index bc2d4a513b5a..4a0b85b9324a 100644
--- a/packages/angular/build/src/builders/dev-server/vite/utils.ts
+++ b/packages/angular/build/src/builders/dev-server/vite/utils.ts
@@ -40,7 +40,7 @@ export function updateResultRecord(
): void {
if (file.origin === 'disk') {
assetFiles.set('/' + normalizePath(file.path), {
- source: normalizePath(file.inputPath),
+ source: normalizePath(file.source),
updated: !initial,
});
diff --git a/packages/angular/build/src/builders/extract-i18n/application-extraction.ts b/packages/angular/build/src/builders/extract-i18n/application-extraction.ts
index ff223ba0bd16..02233fade493 100644
--- a/packages/angular/build/src/builders/extract-i18n/application-extraction.ts
+++ b/packages/angular/build/src/builders/extract-i18n/application-extraction.ts
@@ -39,6 +39,7 @@ export async function extractMessages(
await context.getTargetOptions(options.buildTarget),
builderName,
)) as unknown as ApplicationBuilderInternalOptions;
+ buildOptions.aot = true;
buildOptions.optimization = false;
buildOptions.sourceMap = { scripts: true, vendor: true, styles: false };
buildOptions.localize = false;
@@ -106,7 +107,7 @@ function setupLocalizeExtractor(
if (file?.origin === 'memory') {
content = textDecoder.decode(file.contents);
} else if (file?.origin === 'disk') {
- content = readFileSync(file.inputPath, 'utf-8');
+ content = readFileSync(file.source, 'utf-8');
}
if (content === undefined) {
throw new Error('Unknown file requested: ' + requestedPath);
diff --git a/packages/angular/build/src/builders/karma/assets-middleware.ts b/packages/angular/build/src/builders/karma/assets-middleware.ts
index 45483cb4ec41..6f04faffae46 100644
--- a/packages/angular/build/src/builders/karma/assets-middleware.ts
+++ b/packages/angular/build/src/builders/karma/assets-middleware.ts
@@ -60,7 +60,7 @@ export class AngularAssetsMiddleware {
// https://github.com/karma-runner/karma/blob/84f85e7016efc2266fa6b3465f494a3fa151c85c/lib/middleware/common.js#L10
switch (file.origin) {
case 'disk':
- this.serveFile(file.inputPath, undefined, res, undefined, undefined, /* doNotCache */ true);
+ this.serveFile(file.source, undefined, res, undefined, undefined, /* doNotCache */ true);
break;
case 'memory':
// Include pathname to help with Content-Type headers.
diff --git a/packages/angular/build/src/builders/library/builder-state.ts b/packages/angular/build/src/builders/library/builder-state.ts
new file mode 100644
index 000000000000..81b4e21e778d
--- /dev/null
+++ b/packages/angular/build/src/builders/library/builder-state.ts
@@ -0,0 +1,333 @@
+/**
+ * @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 { toPosixPath } from '../../utils/path';
+import { ExecutionResult } from './execution-result';
+import type {
+ BundleResult,
+ LibraryCompilationOutput,
+ NormalizedLibraryOptions,
+ SingleProgramCache,
+} from './types';
+
+/**
+ * Encapsulates incremental compilation state, transitive resource reference tracking,
+ * watched compilation file tracking, and execution results across watch-mode rebuilds.
+ */
+export class BuilderState {
+ readonly #referencingFiles = new Map>();
+ readonly #referencedByFile = new Map>();
+ readonly #watchedCompilationFiles = new Set();
+ readonly #pendingCompilationFiles = new Set();
+
+ #executionResult = new ExecutionResult();
+ #singleProgramCache?: SingleProgramCache;
+ #compilationMode?: 'partial' | 'full';
+
+ /** Map of entry point names to their previous bundle results. */
+ readonly previousBundleResults = new Map();
+
+ /** Set of changed POSIX ESM file paths pending bundling. */
+ readonly pendingChangedEsmFiles = new Set();
+
+ /** Set of changed POSIX TypeScript declaration file paths pending bundling. */
+ readonly pendingChangedDtsFiles = new Set();
+
+ /** Whether the previous build iteration encountered a compilation or diagnostic error. */
+ hasCompilationError = false;
+
+ /** Whether package.json and secondary entry point manifests have been emitted. */
+ hasEmittedManifests = false;
+
+ /** Whether the last emitted root package.json included a tslib dependency. */
+ hasEmittedTslib = false;
+
+ /** Whether static assets have been emitted in a prior iteration. */
+ hasEmittedAssets = false;
+
+ /** Whether entry points in package.json changed since the last compilation. */
+ hasEntryPointsChanges = false;
+
+ constructor(
+ options?: Partial<
+ Pick
+ >,
+ ) {
+ if (options?.tsConfigPath) {
+ this.#watchedCompilationFiles.add(options.tsConfigPath);
+ }
+ if (options?.packageJsonPath) {
+ this.#watchedCompilationFiles.add(options.packageJsonPath);
+ }
+ if (options?.entryPoints) {
+ for (const entryPoint of options.entryPoints.values()) {
+ this.#watchedCompilationFiles.add(entryPoint.entryFilePath);
+ }
+ }
+ }
+
+ /** Cached unified TypeScript and Angular compilation state. */
+ get singleProgramCache(): SingleProgramCache | undefined {
+ return this.#singleProgramCache;
+ }
+
+ /** Effective compilation mode resolved from builder options and tsconfig. */
+ get compilationMode(): 'partial' | 'full' | undefined {
+ return this.#compilationMode;
+ }
+
+ /** Whether any active entry point bundle imports `tslib`. */
+ get hasTslibImport(): boolean {
+ for (const result of this.previousBundleResults.values()) {
+ if (result.hasTslibImport) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Set of POSIX file paths tracked for compilation and configuration
+ * (including `tsconfig.json`, `package.json`, entry points, and referenced source,
+ * template, and stylesheet files).
+ */
+ get watchedCompilationFiles(): Set {
+ return this.#watchedCompilationFiles;
+ }
+
+ /**
+ * Execution result holding errors, warnings, and logs for the current build iteration.
+ */
+ get executionResult(): ExecutionResult {
+ return this.#executionResult;
+ }
+
+ /**
+ * Resets the execution result for a new build iteration.
+ *
+ * @returns The fresh `ExecutionResult` instance for the current build iteration.
+ */
+ resetExecutionResult(): ExecutionResult {
+ this.#executionResult = new ExecutionResult();
+
+ return this.#executionResult;
+ }
+
+ /**
+ * Records transitive resource dependencies (such as Sass partials) for a containing
+ * component or stylesheet file and registers them in `watchedCompilationFiles`.
+ * Multiple calls for the same containing file accumulate references additively.
+ *
+ * @param containingFile Path of the referencing component or stylesheet file.
+ * @param referencedFiles Paths of the referenced files.
+ */
+ addFileReferences(containingFile: string, referencedFiles: Iterable): void {
+ const posixContainingFile = toPosixPath(containingFile);
+ let forwardReferences = this.#referencedByFile.get(posixContainingFile);
+
+ for (const file of referencedFiles) {
+ const posixFile = toPosixPath(file);
+ this.#watchedCompilationFiles.add(posixFile);
+ if (posixFile === posixContainingFile) {
+ continue;
+ }
+
+ if (!forwardReferences) {
+ forwardReferences = new Set();
+ this.#referencedByFile.set(posixContainingFile, forwardReferences);
+ }
+ forwardReferences.add(posixFile);
+
+ let referencing = this.#referencingFiles.get(posixFile);
+ if (!referencing) {
+ referencing = new Set();
+ this.#referencingFiles.set(posixFile, referencing);
+ }
+ referencing.add(posixContainingFile);
+ }
+ }
+
+ /**
+ * Clears previously recorded outgoing resource references for the given containing files
+ * before they are recompiled.
+ *
+ * @param containingFiles Paths of the containing or stylesheet files being recompiled.
+ */
+ clearFileReferences(containingFiles: Iterable): void {
+ for (const containingFile of containingFiles) {
+ const posixContainingFile = toPosixPath(containingFile);
+ const forwardReferences = this.#referencedByFile.get(posixContainingFile);
+ if (!forwardReferences) {
+ continue;
+ }
+
+ for (const prevRef of forwardReferences) {
+ const referencing = this.#referencingFiles.get(prevRef);
+ if (referencing) {
+ referencing.delete(posixContainingFile);
+ if (referencing.size === 0) {
+ this.#referencingFiles.delete(prevRef);
+ }
+ }
+ }
+
+ this.#referencedByFile.delete(posixContainingFile);
+ }
+ }
+
+ /**
+ * Returns the set of all files affected by the given changed files, including the
+ * changed files themselves and all transitively referencing files
+ * (e.g., partial `.scss` -> component `.scss` -> component `.ts`).
+ *
+ * @param files Initial changed file paths.
+ * @returns Set of POSIX paths including all transitively referencing files.
+ */
+ getAffectedFiles(files: Iterable): Set {
+ const affected = new Set();
+ for (const file of files) {
+ affected.add(toPosixPath(file));
+ }
+
+ for (const file of affected) {
+ const referencing = this.#referencingFiles.get(file);
+ if (referencing) {
+ for (const refFile of referencing) {
+ affected.add(refFile);
+ }
+ }
+ }
+
+ return affected;
+ }
+
+ /**
+ * Determines whether compilation and bundling need to run for the current build iteration.
+ * Also records incoming modified files so they are retained if the iteration aborts early.
+ *
+ * @param packageJsonPath Normalized POSIX path to the library's `package.json`.
+ * @param modifiedFiles Optional set of modified POSIX file paths in watch mode.
+ * @returns `true` if entry points should be compiled; otherwise `false`.
+ */
+ shouldCompileEntryPoints(packageJsonPath: string, modifiedFiles?: ReadonlySet): boolean {
+ if (modifiedFiles) {
+ for (const file of modifiedFiles) {
+ if (file !== packageJsonPath) {
+ this.#pendingCompilationFiles.add(file);
+ }
+ }
+ }
+
+ if (
+ !modifiedFiles ||
+ !this.#singleProgramCache ||
+ this.hasCompilationError ||
+ this.hasEntryPointsChanges ||
+ this.pendingChangedEsmFiles.size > 0 ||
+ this.pendingChangedDtsFiles.size > 0
+ ) {
+ return true;
+ }
+
+ for (const file of this.#pendingCompilationFiles) {
+ if (this.#watchedCompilationFiles.has(file)) {
+ return true;
+ }
+ }
+
+ this.#pendingCompilationFiles.clear();
+
+ return false;
+ }
+
+ /**
+ * Returns the effective set of modified POSIX file paths for compilation,
+ * merging any pending compilation files from earlier aborted iterations.
+ *
+ * @param modifiedFiles Optional set of modified POSIX file paths from the current iteration.
+ * @returns Merged set of modified POSIX file paths, or `undefined` for a full compilation.
+ */
+ getCompilationModifiedFiles(modifiedFiles?: ReadonlySet): Set | undefined {
+ if (!modifiedFiles) {
+ this.#pendingCompilationFiles.clear();
+
+ return undefined;
+ }
+
+ const files = new Set(modifiedFiles);
+ for (const file of this.#pendingCompilationFiles) {
+ files.add(file);
+ }
+
+ return files;
+ }
+
+ /**
+ * Records compilation output into the build state, updating the program cache,
+ * watched compilation files, and pending changed ESM/DTS file sets.
+ *
+ * @param output The compilation output produced by `compileLibrary`.
+ */
+ recordCompilationOutput(output: LibraryCompilationOutput): void {
+ this.#pendingCompilationFiles.clear();
+ this.#singleProgramCache = output.cache;
+ if (this.#compilationMode !== output.compilationMode) {
+ this.#compilationMode = output.compilationMode;
+ this.hasEmittedManifests = false;
+ }
+
+ for (const file of output.referencedFiles) {
+ this.#watchedCompilationFiles.add(file);
+ }
+ for (const file of output.changedEsmFiles) {
+ this.pendingChangedEsmFiles.add(file);
+ }
+ for (const file of output.changedDtsFiles) {
+ this.pendingChangedDtsFiles.add(file);
+ }
+ }
+
+ /**
+ * Records active bundle results across entry points after compilation and bundling succeed,
+ * clearing pending compilation/bundle flags.
+ *
+ * @param bundleResults Newly bundled results keyed by entry point name.
+ */
+ recordBundleOutput(bundleResults: ReadonlyMap): void {
+ this.hasCompilationError = false;
+ this.hasEntryPointsChanges = false;
+ this.pendingChangedEsmFiles.clear();
+ this.pendingChangedDtsFiles.clear();
+
+ for (const [name, bundleResult] of bundleResults) {
+ this.previousBundleResults.set(name, bundleResult);
+ }
+ }
+
+ /**
+ * Disposes active compilation resources and clears cached state.
+ */
+ async dispose(): Promise {
+ await this.#singleProgramCache?.compilationInstance.close?.();
+ this.#singleProgramCache = undefined;
+ this.#compilationMode = undefined;
+ this.hasEmittedTslib = false;
+ this.hasEmittedAssets = false;
+ this.hasCompilationError = false;
+ this.hasEmittedManifests = false;
+ this.hasEntryPointsChanges = false;
+ this.previousBundleResults.clear();
+ this.pendingChangedEsmFiles.clear();
+ this.pendingChangedDtsFiles.clear();
+ this.#pendingCompilationFiles.clear();
+ this.#referencingFiles.clear();
+ this.#referencedByFile.clear();
+ this.#watchedCompilationFiles.clear();
+ }
+}
diff --git a/packages/angular/build/src/builders/library/builder-state_spec.ts b/packages/angular/build/src/builders/library/builder-state_spec.ts
new file mode 100644
index 000000000000..ae84bbaa7331
--- /dev/null
+++ b/packages/angular/build/src/builders/library/builder-state_spec.ts
@@ -0,0 +1,207 @@
+/**
+ * @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 { BuilderState } from './builder-state';
+import type { LibraryCompilationOutput, SingleProgramCache } from './types';
+
+describe('BuilderState', () => {
+ const packageJsonPath = '/workspace/projects/my-lib/package.json';
+ const tsConfigPath = '/workspace/projects/my-lib/tsconfig.lib.json';
+ const entryFilePath = '/workspace/projects/my-lib/src/public-api.ts';
+
+ function createMockCache(closeSpy?: jasmine.Spy): SingleProgramCache {
+ return {
+ compilationInstance: {
+ close: closeSpy,
+ } as unknown as SingleProgramCache['compilationInstance'],
+ esmFiles: new Map(),
+ dtsFiles: new Map(),
+ failedFiles: new Set(),
+ };
+ }
+
+ function createMockCompilationOutput(
+ overrides: Partial = {},
+ ): LibraryCompilationOutput {
+ return {
+ esmFiles: new Map(),
+ dtsFiles: new Map(),
+ changedEsmFiles: new Set(),
+ changedDtsFiles: new Set(),
+ referencedFiles: new Set(),
+ cache: createMockCache(),
+ hasStylesheetErrors: false,
+ diagnosePromise: Promise.resolve(),
+ declarationMap: false,
+ compilationMode: 'partial',
+ ...overrides,
+ };
+ }
+
+ describe('ExecutionResult', () => {
+ it('should track logs, warnings, and errors and reset per iteration', () => {
+ const state = new BuilderState();
+ expect(state.executionResult.hasErrors).toBeFalse();
+ expect(state.executionResult.output).toEqual({ success: true });
+
+ state.executionResult.addLog('Bundling my-lib');
+ state.executionResult.addWarning('Unused import');
+ state.executionResult.addWarnings(['Deprecated API']);
+ state.executionResult.addError('Type error');
+ state.executionResult.addErrors(['Syntax error']);
+
+ expect(state.executionResult.logs).toEqual(['Bundling my-lib']);
+ expect(state.executionResult.warnings).toEqual(['Unused import', 'Deprecated API']);
+ expect(state.executionResult.errors).toEqual(['Type error', 'Syntax error']);
+ expect(state.executionResult.hasErrors).toBeTrue();
+ expect(state.executionResult.output).toEqual({ success: false });
+
+ const freshResult = state.resetExecutionResult();
+ expect(freshResult).toBe(state.executionResult);
+ expect(freshResult.hasErrors).toBeFalse();
+ expect(freshResult.logs).toEqual([]);
+ expect(freshResult.warnings).toEqual([]);
+ expect(freshResult.errors).toEqual([]);
+ });
+ });
+
+ describe('file reference tracking', () => {
+ it('should expand transitive multi-hop references and ignore self-references', () => {
+ const state = new BuilderState();
+ const compTs = '/workspace/projects/my-lib/src/lib/comp.ts';
+ const compScss = '/workspace/projects/my-lib/src/lib/comp.scss';
+ const varsScss = '/workspace/projects/my-lib/src/lib/_vars.scss';
+
+ state.addFileReferences(compTs, [compTs, compScss, varsScss]);
+ state.addFileReferences(compScss, [compScss, varsScss]);
+
+ expect(state.watchedCompilationFiles.has(compTs)).toBeTrue();
+ expect(state.watchedCompilationFiles.has(compScss)).toBeTrue();
+ expect(state.watchedCompilationFiles.has(varsScss)).toBeTrue();
+
+ const affected = state.getAffectedFiles([varsScss]);
+ expect(affected).toEqual(new Set([varsScss, compTs, compScss]));
+
+ // Subsequent getAffectedFiles calls preserve mappings when not yet overwritten
+ const affectedAgain = state.getAffectedFiles([varsScss]);
+ expect(affectedAgain).toEqual(new Set([varsScss, compTs, compScss]));
+ });
+
+ it('should accumulate references across multiple stylesheets for the same containing file', () => {
+ const state = new BuilderState();
+ const compTs = '/workspace/projects/my-lib/src/lib/comp.ts';
+ const firstPartial = '/workspace/projects/my-lib/src/lib/_first.scss';
+ const secondPartial = '/workspace/projects/my-lib/src/lib/_second.scss';
+
+ state.addFileReferences(compTs, [compTs, firstPartial]);
+ state.addFileReferences(compTs, [compTs, secondPartial]);
+
+ expect(state.getAffectedFiles([firstPartial])).toEqual(new Set([firstPartial, compTs]));
+ expect(state.getAffectedFiles([secondPartial])).toEqual(new Set([secondPartial, compTs]));
+ });
+
+ it('should prune stale references when a containing file is cleared and re-recorded', () => {
+ const state = new BuilderState();
+ const compTs = '/workspace/projects/my-lib/src/lib/comp.ts';
+ const oldPartial = '/workspace/projects/my-lib/src/lib/_old.scss';
+ const newPartial = '/workspace/projects/my-lib/src/lib/_new.scss';
+
+ state.addFileReferences(compTs, [compTs, oldPartial]);
+ expect(state.getAffectedFiles([oldPartial])).toEqual(new Set([oldPartial, compTs]));
+
+ // Clear and re-record references for compTs without oldPartial
+ state.clearFileReferences([compTs]);
+ state.addFileReferences(compTs, [compTs, newPartial]);
+ expect(state.getAffectedFiles([oldPartial])).toEqual(new Set([oldPartial]));
+ expect(state.getAffectedFiles([newPartial])).toEqual(new Set([newPartial, compTs]));
+ });
+ });
+
+ describe('shouldCompileEntryPoints & getCompilationModifiedFiles', () => {
+ it('should preserve pending compilation files across aborted iterations', () => {
+ const state = new BuilderState({
+ packageJsonPath,
+ tsConfigPath,
+ entryPoints: new Map([
+ [
+ '.',
+ {
+ subpath: '.',
+ name: '.',
+ displayName: 'my-lib',
+ bundleName: 'my-lib',
+ entryFilePath,
+ isPrimary: true,
+ },
+ ],
+ ]),
+ });
+
+ state.recordCompilationOutput(
+ createMockCompilationOutput({
+ referencedFiles: new Set([entryFilePath]),
+ }),
+ );
+
+ // Iteration 1: entryFilePath changes, but build aborts before recordCompilationOutput
+ expect(
+ state.shouldCompileEntryPoints(packageJsonPath, new Set([entryFilePath, packageJsonPath])),
+ ).toBeTrue();
+
+ // Iteration 2: only package.json changes on recovery
+ expect(
+ state.shouldCompileEntryPoints(packageJsonPath, new Set([packageJsonPath])),
+ ).toBeTrue();
+ expect(state.getCompilationModifiedFiles(new Set([packageJsonPath]))).toEqual(
+ new Set([packageJsonPath, entryFilePath]),
+ );
+
+ // Once compilation output is recorded, pending compilation files are cleared
+ state.recordCompilationOutput(createMockCompilationOutput());
+ expect(
+ state.shouldCompileEntryPoints(packageJsonPath, new Set([packageJsonPath])),
+ ).toBeFalse();
+ });
+
+ it('should invalidate hasEmittedManifests when compilationMode changes', () => {
+ const state = new BuilderState();
+ state.hasEmittedManifests = true;
+ state.recordCompilationOutput(createMockCompilationOutput({ compilationMode: 'partial' }));
+ expect(state.hasEmittedManifests).toBeFalse();
+
+ state.hasEmittedManifests = true;
+ state.recordCompilationOutput(createMockCompilationOutput({ compilationMode: 'partial' }));
+ expect(state.hasEmittedManifests).toBeTrue();
+
+ state.recordCompilationOutput(createMockCompilationOutput({ compilationMode: 'full' }));
+ expect(state.hasEmittedManifests).toBeFalse();
+ });
+ });
+
+ describe('dispose', () => {
+ it('should close compilationInstance and clear cached state on dispose', async () => {
+ const closeSpy = jasmine.createSpy('close').and.resolveTo();
+ const state = new BuilderState({ packageJsonPath });
+ state.recordCompilationOutput(
+ createMockCompilationOutput({
+ cache: createMockCache(closeSpy),
+ changedEsmFiles: new Set(['/a.js']),
+ changedDtsFiles: new Set(['/a.d.ts']),
+ }),
+ );
+
+ await state.dispose();
+
+ expect(closeSpy).toHaveBeenCalledTimes(1);
+ expect(state.singleProgramCache).toBeUndefined();
+ expect(state.pendingChangedEsmFiles).toHaveSize(0);
+ expect(state.pendingChangedDtsFiles).toHaveSize(0);
+ expect(state.watchedCompilationFiles).toHaveSize(0);
+ });
+ });
+});
diff --git a/packages/angular/build/src/builders/library/builder.ts b/packages/angular/build/src/builders/library/builder.ts
index 33df771fc6ab..42be7f99b211 100644
--- a/packages/angular/build/src/builders/library/builder.ts
+++ b/packages/angular/build/src/builders/library/builder.ts
@@ -8,6 +8,7 @@
import type { BuilderContext, BuilderOutput } from '@angular-devkit/architect';
import type { logging } from '@angular-devkit/core';
+import type { ComponentStylesheetBundler } from '../../tools/esbuild/angular/component-stylesheets';
import {
resetSassWorkerPoolCaches,
shutdownSassWorkerPool,
@@ -23,12 +24,14 @@ import { purgeStaleBuildCache } from '../../utils/purge-cache';
import { getSupportedBrowsers } from '../../utils/supported-browsers';
import { assertCompatibleAngularVersion } from '../../utils/version';
import type { BuildWatcher } from '../../utils/watcher';
+import { BuilderState } from './builder-state';
+import type { ExecutionResult } from './execution-result';
import { normalizeLibraryOptions } from './options';
+import type { BuildActionContext } from './pipeline/build-action';
import { updateWatchedEntryPoints } from './pipeline/entry-points';
-import type { createComponentStylesheetBundlerForLibrary } from './pipeline/stylesheet-bundler';
import { loadPackageJson } from './pipeline/utils';
import type { Schema as LibraryBuilderOptions } from './schema';
-import type { NormalizedLibraryOptions, SingleBuildState } from './types';
+import type { NormalizedLibraryOptions } from './types';
/**
* Executes the library builder to compile, bundle, and package an Angular library into the Angular Package Format (APF).
@@ -42,10 +45,6 @@ export async function* executeLibraryBuilder(
context: BuilderContext & { signal?: AbortSignal },
): AsyncIterableIterator {
assertCompatibleAngularVersion(context.workspaceRoot);
- await initializeHash();
-
- // Purge old build disk cache
- await purgeStaleBuildCache(context);
const projectName = context.target?.project;
if (!projectName) {
@@ -54,14 +53,18 @@ export async function* executeLibraryBuilder(
return;
}
- const normalizedOptions = await normalizeLibraryOptions(context, projectName, options);
+ const [normalizedOptions] = await Promise.all([
+ normalizeLibraryOptions(context, projectName, options),
+ initializeHash(),
+ // Purge old build disk cache
+ purgeStaleBuildCache(context),
+ ]);
+
const {
workspaceRoot,
projectRoot,
outputPath,
deleteOutputPath,
- packageJsonPath,
- tsConfigPath,
watch: isWatchMode,
poll,
cacheOptions,
@@ -86,17 +89,14 @@ export async function* executeLibraryBuilder(
}
// Dynamically lazy-loaded to prevent importing dependencies at the top level.
- const [
- { buildAction, createSingleBuildState, hasModifiedWatchedFile },
- { createComponentStylesheetBundlerForLibrary },
- ] = await Promise.all([
+ const [{ buildAction }, { createComponentStylesheetBundlerForLibrary }] = await Promise.all([
import('./pipeline/build-action'),
import('./pipeline/stylesheet-bundler'),
]);
- let stylesheetBundler: ReturnType | undefined;
+ let stylesheetBundler: ComponentStylesheetBundler | undefined;
let watcher: BuildWatcher | undefined;
- const buildState = createSingleBuildState();
+ const buildState = new BuilderState(normalizedOptions);
try {
const browsers = getSupportedBrowsers(projectRoot, logger);
@@ -107,21 +107,7 @@ export async function* executeLibraryBuilder(
target,
);
- // Track all referenced compilation files for watch mode
- const watchedCompilationFiles = new Set([
- toPosixPath(tsConfigPath),
- toPosixPath(packageJsonPath),
- ]);
-
- for (const entryPoint of normalizedOptions.entryPoints.values()) {
- watchedCompilationFiles.add(toPosixPath(entryPoint.entryFilePath));
- }
-
if (isWatchMode) {
- if (progress) {
- logger.info('Watch mode enabled. Watching for file changes...');
- }
-
const { setupWatcher } = await import('../../utils/watcher');
watcher = await setupWatcher({
workspaceRoot,
@@ -131,7 +117,10 @@ export async function* executeLibraryBuilder(
poll,
preserveSymlinks,
signal,
- watchFiles: watchedCompilationFiles,
+ watchFiles: [
+ ...buildState.watchedCompilationFiles,
+ ...normalizedOptions.assets.map((asset) => asset.input),
+ ],
});
context.addTeardown?.(() => void watcher?.close());
@@ -143,15 +132,19 @@ export async function* executeLibraryBuilder(
{
options: normalizedOptions,
stylesheetBundler,
- watchedCompilationFiles,
isWatchMode,
- context,
buildState,
},
+ logger,
withProgress,
watcher,
buildAction,
);
+
+ if (isWatchMode && progress) {
+ logger.info('Watch mode enabled. Watching for file changes...');
+ }
+
yield initialResult;
if (!isWatchMode || !watcher) {
@@ -162,12 +155,10 @@ export async function* executeLibraryBuilder(
watcher,
normalizedOptions,
stylesheetBundler,
- watchedCompilationFiles,
- context,
+ logger,
withProgress,
buildState,
buildAction,
- hasModifiedWatchedFile,
signal,
);
} finally {
@@ -177,37 +168,53 @@ export async function* executeLibraryBuilder(
await Promise.allSettled([
watcher?.close(),
stylesheetBundler?.dispose(),
- buildState.singleProgramCache?.compilationInstance.close?.(),
+ buildState.dispose(),
]);
}
}
+/**
+ * Executes a single build iteration with progress reporting, logs any resulting
+ * messages, and registers newly discovered files with the watcher.
+ *
+ * @param message Progress spinner message to display while building.
+ * @param actionContext The build action context and state.
+ * @param logger The Architect logger API.
+ * @param withProgress Progress wrapper function (`withSpinner` or `withNoProgress`).
+ * @param watcher Optional file watcher for watch mode.
+ * @param buildAction The library build action function to execute.
+ * @returns A promise resolving to the Architect `BuilderOutput`.
+ */
async function executeBuild(
message: string,
- actionContext: import('./pipeline/build-action').BuildActionContext,
+ actionContext: BuildActionContext,
+ logger: logging.LoggerApi,
withProgress: typeof withSpinner,
watcher: BuildWatcher | undefined,
buildAction: typeof import('./pipeline/build-action').buildAction,
): Promise {
const startTime = process.hrtime.bigint();
- const { context, watchedCompilationFiles, isWatchMode } = actionContext;
+ const { buildState, isWatchMode, options } = actionContext;
try {
- await withProgress(message, () => buildAction(actionContext));
- logBuildResult(context.logger, startTime, true);
- if (isWatchMode) {
+ const result = await withProgress(message, () => buildAction(actionContext));
+ logMessages(logger, result);
+
+ const { output } = result;
+ logBuildResult(logger, startTime, output.success, options.outputPath);
+ if (output.success && isWatchMode) {
logCumulativeDurations();
}
- return { success: true };
+ return output;
} catch (error) {
assertIsError(error);
- logBuildResult(context.logger, startTime, false);
+ logBuildResult(logger, startTime, false);
return { success: false, error: error.message };
} finally {
if (watcher) {
- watcher.add(Array.from(watchedCompilationFiles));
+ watcher.add(Array.from(buildState.watchedCompilationFiles));
const { assetsToEmit } = actionContext;
if (assetsToEmit?.length) {
@@ -219,26 +226,33 @@ async function executeBuild(
/**
* Runs the watch loop, rebuilding the library as watched files are modified.
+ *
+ * @param watcher The file watcher instance.
+ * @param options The normalized library builder options with POSIX paths.
+ * @param stylesheetBundler The component stylesheet bundler instance.
+ * @param logger The Architect logger API.
+ * @param withProgress Progress wrapper function (`withSpinner` or `withNoProgress`).
+ * @param buildState The state preserved across incremental builds.
+ * @param buildAction The library build action function to execute.
+ * @param signal Abort signal to terminate the watch loop.
+ * @returns An async iterator yielding builder output results.
*/
async function* runWatchLoop(
watcher: BuildWatcher,
options: NormalizedLibraryOptions,
- stylesheetBundler: ReturnType,
- watchedCompilationFiles: Set,
- context: BuilderContext,
+ stylesheetBundler: ComponentStylesheetBundler,
+ logger: logging.LoggerApi,
withProgress: typeof withSpinner,
- buildState: SingleBuildState,
+ buildState: BuilderState,
buildAction: typeof import('./pipeline/build-action').buildAction,
- hasModifiedWatchedFile: typeof import('./pipeline/build-action').hasModifiedWatchedFile,
- signal?: AbortSignal,
+ signal: AbortSignal,
): AsyncIterableIterator {
const { collectAssetsToEmit } = await import('./pipeline/assets');
const { workspaceRoot, packageJsonPath, assets, clearScreen } = options;
- const posixPackageJsonPath = toPosixPath(packageJsonPath);
for await (const changes of watcher) {
- if (signal?.aborted) {
+ if (signal.aborted) {
break;
}
@@ -247,56 +261,30 @@ async function* runWatchLoop(
console.clear();
}
- const changedFiles = new Set();
- let hasStyleChanges = false;
- let hasSassChanges = false;
- for (const file of changes.all) {
- const posixFile = toPosixPath(file);
- changedFiles.add(posixFile);
- if (/\.(?:scss|sass)$/i.test(posixFile)) {
- hasStyleChanges = true;
- hasSassChanges = true;
- } else if (/\.(?:less|css)$/i.test(posixFile)) {
- hasStyleChanges = true;
- }
- }
+ const rawChangedFiles = changes.all.map(toPosixPath);
+ stylesheetBundler.invalidate(rawChangedFiles);
+ const changedFiles = buildState.getAffectedFiles(rawChangedFiles);
- if (hasStyleChanges) {
- if (hasSassChanges) {
+ for (const posixFile of changedFiles) {
+ if (/\.(?:scss|sass)$/i.test(posixFile)) {
resetSassWorkerPoolCaches();
- }
- const invalidatedStyles = stylesheetBundler.invalidate(changedFiles);
- if (invalidatedStyles) {
- for (const styleFile of invalidatedStyles) {
- changedFiles.add(toPosixPath(styleFile));
- }
+ break;
}
}
// Check if package.json was modified
- let hasPackageJsonChanges = false;
- if (changedFiles.has(posixPackageJsonPath)) {
+ if (changedFiles.has(packageJsonPath)) {
+ buildState.hasEmittedManifests = false;
try {
const packageJson = await loadPackageJson(packageJsonPath);
- options.packageJson = packageJson;
- if (!packageJson.name) {
- throw new Error(`The package.json at '${packageJsonPath}' must contain a 'name'.`);
- }
- options.packageName = packageJson.name;
-
- updateWatchedEntryPoints(
- packageJson,
- options,
- buildState,
- watchedCompilationFiles,
- packageJsonPath,
- );
-
- hasPackageJsonChanges = true;
+ updateWatchedEntryPoints(packageJson, options, buildState);
} catch (error) {
assertIsError(error);
await buildState.singleProgramCache?.compilationInstance.update?.(changedFiles);
- buildState.hasEmittedManifests = false;
+ if (buildState.shouldCompileEntryPoints(packageJsonPath, changedFiles)) {
+ buildState.hasCompilationError = true;
+ }
+
yield {
success: false,
error: `Failed to reload 'package.json': ${error.message}`,
@@ -305,11 +293,10 @@ async function* runWatchLoop(
}
}
- const hasSourceChanges =
- !buildState.singleProgramCache ||
- buildState.hasCompilationError ||
- buildState.hasEntryPointsChanges ||
- hasModifiedWatchedFile(changedFiles, watchedCompilationFiles, posixPackageJsonPath);
+ const hasSourceChanges = buildState.shouldCompileEntryPoints(packageJsonPath, changedFiles);
+ if (!hasSourceChanges) {
+ await buildState.singleProgramCache?.compilationInstance.update?.(changedFiles);
+ }
const assetsToEmit = await collectAssetsToEmit(
assets,
@@ -317,7 +304,7 @@ async function* runWatchLoop(
buildState.hasEmittedAssets ? changedFiles : undefined,
);
- if (!hasSourceChanges && !hasPackageJsonChanges && assetsToEmit.length === 0) {
+ if (!hasSourceChanges && buildState.hasEmittedManifests && assetsToEmit.length === 0) {
continue;
}
@@ -326,13 +313,12 @@ async function* runWatchLoop(
{
options,
stylesheetBundler,
- watchedCompilationFiles,
isWatchMode: true,
- context,
buildState,
modifiedFiles: changedFiles,
assetsToEmit,
},
+ logger,
withProgress,
watcher,
buildAction,
@@ -340,17 +326,51 @@ async function* runWatchLoop(
}
}
+/**
+ * Logs informational, warning, and error messages produced during a build iteration.
+ *
+ * @param logger The Architect logger API.
+ * @param result The build execution result containing logs, warnings, and errors.
+ */
+function logMessages(logger: logging.LoggerApi, { logs, warnings, errors }: ExecutionResult): void {
+ if (logs.length) {
+ logger.info(logs.join('\n'));
+ }
+
+ if (warnings.length) {
+ logger.warn(warnings.join('\n'));
+ }
+
+ if (errors.length) {
+ logger.error(errors.join('\n'));
+ }
+}
+
/**
* Logs the build completion time and status.
+ *
+ * @param logger The Architect logger API.
+ * @param startTime High-resolution timestamp recorded when the build iteration started.
+ * @param success Whether the build iteration succeeded without errors.
+ * @param outputPath Optional POSIX output directory path to log on successful builds.
*/
-function logBuildResult(logger: logging.LoggerApi, startTime: bigint, success: boolean): void {
- const durationMs = Number(process.hrtime.bigint() - startTime) / 1_000_000;
- const durationSec = (durationMs / 1000).toFixed(2);
+function logBuildResult(
+ logger: logging.LoggerApi,
+ startTime: bigint,
+ success: boolean,
+ outputPath?: string,
+): void {
+ const buildTime = Number(process.hrtime.bigint() - startTime) / 10 ** 9;
+ const message =
+ `Library bundle generation ${success ? 'complete' : 'failed'}.` +
+ ` [${buildTime.toFixed(3)} seconds] - ${new Date().toISOString()}`;
if (success) {
- logger.info(`Build at: ${new Date().toISOString()} - Time: ${durationMs.toFixed(0)}ms`);
- logger.info(`Built Angular library in ${durationSec}s.`);
+ logger.info(message);
+ if (outputPath) {
+ logger.info(`Output location: ${outputPath}\n`);
+ }
} else {
- logger.error(`Build failed after ${durationSec}s.`);
+ logger.error(message);
}
}
diff --git a/packages/angular/build/src/builders/library/execution-result.ts b/packages/angular/build/src/builders/library/execution-result.ts
new file mode 100644
index 000000000000..4f9826360503
--- /dev/null
+++ b/packages/angular/build/src/builders/library/execution-result.ts
@@ -0,0 +1,75 @@
+/**
+ * @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 { BuilderOutput } from '@angular-devkit/architect';
+
+/**
+ * Encapsulates the diagnostic messages (`errors`, `warnings`, and `logs`) and
+ * builder output status for a single library build iteration.
+ */
+export class ExecutionResult {
+ readonly #errors: string[] = [];
+ readonly #warnings: string[] = [];
+ readonly #logs: string[] = [];
+
+ /** Formatted error messages produced during the build iteration. */
+ get errors(): readonly string[] {
+ return this.#errors;
+ }
+
+ /** Formatted warning messages produced during the build iteration. */
+ get warnings(): readonly string[] {
+ return this.#warnings;
+ }
+
+ /** Informational log messages produced during the build iteration. */
+ get logs(): readonly string[] {
+ return this.#logs;
+ }
+
+ /** Whether any errors have been recorded in the build iteration. */
+ get hasErrors(): boolean {
+ return this.#errors.length > 0;
+ }
+
+ /** Architect builder output status for the build iteration. */
+ get output(): BuilderOutput {
+ return {
+ success: !this.hasErrors,
+ };
+ }
+
+ /** Records an informational log message. */
+ addLog(value: string): void {
+ this.#logs.push(value);
+ }
+
+ /** Records a formatted error message. */
+ addError(error: string): void {
+ this.#errors.push(error);
+ }
+
+ /** Records multiple formatted error messages. */
+ addErrors(errors: Iterable): void {
+ for (const error of errors) {
+ this.#errors.push(error);
+ }
+ }
+
+ /** Records a formatted warning message. */
+ addWarning(warning: string): void {
+ this.#warnings.push(warning);
+ }
+
+ /** Records multiple formatted warning messages. */
+ addWarnings(warnings: Iterable): void {
+ for (const warning of warnings) {
+ this.#warnings.push(warning);
+ }
+ }
+}
diff --git a/packages/angular/build/src/builders/library/index.ts b/packages/angular/build/src/builders/library/index.ts
index 6a6ddf7a1ce7..da1f5d9385a3 100644
--- a/packages/angular/build/src/builders/library/index.ts
+++ b/packages/angular/build/src/builders/library/index.ts
@@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.dev/license
*/
-import { Builder, createBuilder } from '@angular-devkit/architect';
+import { type Builder, createBuilder } from '@angular-devkit/architect';
import { executeLibraryBuilder } from './builder';
import type { Schema as LibraryBuilderOptions } from './schema';
diff --git a/packages/angular/build/src/builders/library/options.ts b/packages/angular/build/src/builders/library/options.ts
index 450dce36cab5..23d18d6f4d8e 100644
--- a/packages/angular/build/src/builders/library/options.ts
+++ b/packages/angular/build/src/builders/library/options.ts
@@ -9,10 +9,11 @@
import type { BuilderContext } from '@angular-devkit/architect';
import path from 'node:path';
import type { StylesheetPluginsass } from '../../tools/esbuild/stylesheets/stylesheet-plugin-factory';
-import { normalizeAssetPatterns } from '../../utils';
import { supportColor } from '../../utils/color';
import { assertIsError } from '../../utils/error';
+import { normalizeAssetPatterns } from '../../utils/normalize-asset-patterns';
import { normalizeCacheOptions } from '../../utils/normalize-cache';
+import { toPosixPath } from '../../utils/path';
import {
generateSearchDirectories,
getTailwindConfig,
@@ -24,22 +25,33 @@ import { loadPackageJson } from './pipeline/utils';
import type { Schema as LibraryBuilderOptions } from './schema';
import type { NormalizedLibraryOptions, PackageJsonData } from './types';
+/**
+ * Normalizes raw library builder options into {@link NormalizedLibraryOptions} with all
+ * file and directory paths normalized to POSIX format.
+ *
+ * @param context The Architect builder context.
+ * @param projectName The name of the library project.
+ * @param options The raw library builder schema options.
+ * @returns A promise resolving to the normalized library options.
+ */
export async function normalizeLibraryOptions(
context: BuilderContext,
projectName: string,
options: LibraryBuilderOptions,
): Promise {
- const { workspaceRoot } = context;
+ const workspaceRoot = toPosixPath(context.workspaceRoot);
const projectMetadata = await context.getProjectMetadata(projectName);
- const { projectRoot, projectSourceRoot } = getProjectRootPaths(workspaceRoot, projectMetadata);
+ const projectRootPaths = getProjectRootPaths(workspaceRoot, projectMetadata);
+ const projectRoot = toPosixPath(projectRootPaths.projectRoot);
+ const projectSourceRoot = toPosixPath(projectRootPaths.projectSourceRoot);
const {
tsConfig,
assets: rawAssets,
stylePreprocessorOptions,
inlineStyleLanguage = 'css',
- compilationMode = 'partial',
- declarationMap = false,
+ compilationMode,
+ declarationMap,
allowedNonPeerDependencies: rawAllowedNonPeerDependencies = [],
keepLifecycleScripts = false,
watch = false,
@@ -50,8 +62,8 @@ export async function normalizeLibraryOptions(
clearScreen,
} = options;
- const resolvedTsConfigPath = path.resolve(workspaceRoot, tsConfig);
- const packageJsonPath = path.join(projectRoot, 'package.json');
+ const resolvedTsConfigPath = toPosixPath(path.resolve(workspaceRoot, tsConfig));
+ const packageJsonPath = path.posix.join(projectRoot, 'package.json');
let packageJson: PackageJsonData;
try {
@@ -99,7 +111,7 @@ export async function normalizeLibraryOptions(
}
defaultAssets.push({
glob: 'README.md',
- input: path.dirname(entryPoint.entryFilePath),
+ input: path.posix.dirname(entryPoint.entryFilePath),
output: entryPoint.name,
});
}
@@ -109,7 +121,11 @@ export async function normalizeLibraryOptions(
workspaceRoot,
projectRoot,
projectSourceRoot,
- );
+ ).map((asset) => ({
+ ...asset,
+ input: toPosixPath(path.resolve(workspaceRoot, asset.input)),
+ output: toPosixPath(asset.output),
+ }));
const cacheOptions = normalizeCacheOptions(
projectMetadata,
@@ -119,21 +135,23 @@ export async function normalizeLibraryOptions(
);
const styleIncludePaths = (stylePreprocessorOptions?.includePaths ?? []).map((p: string) =>
- path.resolve(workspaceRoot, p),
+ toPosixPath(path.resolve(workspaceRoot, p)),
);
const searchDirectories = await generateSearchDirectories([projectRoot, workspaceRoot]);
const postcssConfiguration = await loadPostcssConfiguration(searchDirectories);
const tailwindConfiguration = postcssConfiguration
? undefined
- : await getTailwindConfig(searchDirectories, workspaceRoot, context.logger);
+ : getTailwindConfig(searchDirectories, workspaceRoot, context.logger);
return {
workspaceRoot,
projectRoot,
packageName,
packageJson,
- outputPath: path.resolve(workspaceRoot, options.outputPath ?? path.join('dist', projectName)),
+ outputPath: toPosixPath(
+ path.resolve(workspaceRoot, options.outputPath ?? path.posix.join('dist', projectName)),
+ ),
deleteOutputPath,
packageJsonPath,
tsConfigPath: resolvedTsConfigPath,
diff --git a/packages/angular/build/src/builders/library/pipeline/assets.ts b/packages/angular/build/src/builders/library/pipeline/assets.ts
index e1e46f4b9f08..7b8329a7865a 100644
--- a/packages/angular/build/src/builders/library/pipeline/assets.ts
+++ b/packages/angular/build/src/builders/library/pipeline/assets.ts
@@ -9,7 +9,6 @@
import { statSync } from 'node:fs';
import path from 'node:path';
import picomatch from 'picomatch';
-import { toPosixPath } from '../../../utils/path';
import { DEFAULT_ASSET_IGNORE, resolveAssets } from '../../../utils/resolve-assets';
import type { NormalizedLibraryOptions } from '../types';
import { type DiskOutputFile, createDiskOutputFile } from './utils';
@@ -17,9 +16,9 @@ import { type DiskOutputFile, createDiskOutputFile } from './utils';
/**
* Resolves and collects configured library assets to be emitted to disk.
*
- * @param assets The normalized asset patterns.
- * @param workspaceRoot The workspace root directory path.
- * @param modifiedFiles Optional set of modified file paths for incremental copying in watch mode.
+ * @param assets The normalized asset patterns with POSIX paths.
+ * @param workspaceRoot The normalized POSIX workspace root directory path.
+ * @param modifiedFiles Optional set of modified POSIX file paths for incremental copying in watch mode.
* @returns An array of disk file emission descriptors.
*/
export async function collectAssetsToEmit(
@@ -32,25 +31,22 @@ export async function collectAssetsToEmit(
}
if (modifiedFiles) {
- const matchers = createAssetMatchers(assets, workspaceRoot);
+ const matchers = createAssetMatchers(assets);
const filesToEmit: DiskOutputFile[] = [];
for (const file of modifiedFiles) {
- const resolvedFile = path.isAbsolute(file) ? file : path.resolve(workspaceRoot, file);
- const posixFile = toPosixPath(resolvedFile);
-
- for (const { asset, posixInputPrefix, isMatch } of matchers) {
- if (!posixFile.startsWith(posixInputPrefix)) {
+ for (const { asset, prefix, isMatch } of matchers) {
+ if (!file.startsWith(prefix)) {
continue;
}
- const relative = posixFile.slice(posixInputPrefix.length);
+ const relative = file.slice(prefix.length);
if (!isMatch(relative)) {
continue;
}
- if (statSync(resolvedFile, { throwIfNoEntry: false })?.isFile()) {
- filesToEmit.push(createDiskOutputFile(resolvedFile, path.join(asset.output, relative)));
+ if (statSync(file, { throwIfNoEntry: false })?.isFile()) {
+ filesToEmit.push(createDiskOutputFile(file, path.posix.join(asset.output, relative)));
}
}
}
@@ -63,15 +59,14 @@ export async function collectAssetsToEmit(
return resolvedAssets.map(({ source, destination }) => createDiskOutputFile(source, destination));
}
-function createAssetMatchers(assets: NormalizedLibraryOptions['assets'], workspaceRoot: string) {
+function createAssetMatchers(assets: NormalizedLibraryOptions['assets']) {
return assets.map((asset) => {
- const absInput = path.resolve(workspaceRoot, asset.input);
- const posixInput = toPosixPath(absInput).replace(/\/+$/, '');
const isMatch = picomatch(asset.glob, {
dot: true,
ignore: [...DEFAULT_ASSET_IGNORE, ...(asset.ignore ?? [])],
});
+ const prefix = asset.input.endsWith('/') ? asset.input : `${asset.input}/`;
- return { asset, posixInputPrefix: `${posixInput}/`, isMatch };
+ return { asset, prefix, isMatch };
});
}
diff --git a/packages/angular/build/src/builders/library/pipeline/build-action.ts b/packages/angular/build/src/builders/library/pipeline/build-action.ts
index 19718a793deb..734ea23c544e 100644
--- a/packages/angular/build/src/builders/library/pipeline/build-action.ts
+++ b/packages/angular/build/src/builders/library/pipeline/build-action.ts
@@ -6,67 +6,44 @@
* found in the LICENSE file at https://angular.dev/license
*/
-import type { BuilderContext } from '@angular-devkit/architect';
-import { constants, copyFile, mkdir, writeFile } from 'node:fs/promises';
import path from 'node:path';
import type { ComponentStylesheetBundler } from '../../../tools/esbuild/angular/component-stylesheets';
-import { emitFilesToDisk } from '../../../tools/esbuild/utils';
-import { toPosixPath } from '../../../utils/path';
-import type { NormalizedLibraryOptions, SingleBuildState } from '../types';
+import { emitFilesToDisk } from '../../../utils/disk-files';
+import { assertIsError } from '../../../utils/error';
+import type { BuilderState } from '../builder-state';
+import type { ExecutionResult } from '../execution-result';
+import type { NormalizedLibraryOptions } from '../types';
import { collectAssetsToEmit } from './assets';
-import { type BundleEntryPointInput, bundleEntryPoints } from './bundler';
+import { type BundleEntryPointsOutput, bundleEntryPoints } from './bundler';
import { compileLibrary } from './compilation';
+import { collectEntryPointsToBundle } from './entry-points';
import { generatePackageManifests } from './package-manifests';
import type { DiskOutputFile, OutputFile } from './utils';
-/**
- * Creates a fresh {@link SingleBuildState} instance.
- */
-export function createSingleBuildState(): SingleBuildState {
- return {
- previousBundleResults: new Map(),
- pendingChangedEsmFiles: new Set(),
- pendingChangedDtsFiles: new Set(),
- directoryExists: new Set(),
- };
-}
-
/**
* Context required to execute a single library build iteration.
*/
export interface BuildActionContext {
- /** Normalized options for the library build. */
+ /** Normalized options for the library build with POSIX paths. */
options: NormalizedLibraryOptions;
- /** The Architect builder context. */
- context: BuilderContext;
-
/** Bundler instance used to process component stylesheets. */
stylesheetBundler: ComponentStylesheetBundler;
/** Whether the builder is running in watch mode. */
isWatchMode: boolean;
- /**
- * Set of file paths tracked for compilation and configuration
- * (including `tsconfig.json`, `package.json`, entry points, and referenced source,
- * template, and stylesheet files). Updated during compilation and used to determine
- * whether file changes require recompiling entry points, excluding asset files so
- * asset-only changes do not trigger code compilation.
- */
- watchedCompilationFiles: Set;
-
- /** State preserved across incremental builds in watch mode. */
- buildState: SingleBuildState;
+ /** Build state tracking compilation caches and emitted outputs. */
+ buildState: BuilderState;
- /** Set of file paths modified since the last build iteration. */
+ /** Set of POSIX file paths modified since the last build iteration. */
modifiedFiles?: Set;
/**
- * Asset files to emit to disk for the current build iteration.
+ * Asset files to emit for the current build iteration.
* Pre-collected in the watch loop to avoid redundant asset matching, or resolved and
* populated by `buildAction` when omitted (such as during the initial build) so the
- * caller can register their source paths with the file watcher.
+ * caller can register their POSIX source paths with the file watcher.
*/
assetsToEmit?: DiskOutputFile[];
}
@@ -77,205 +54,145 @@ export interface BuildActionContext {
* manifest generation, and asset copying.
*
* @param actionContext The build action state and configuration.
+ * @returns A promise resolving to the build iteration's `ExecutionResult`.
*/
-export async function buildAction(actionContext: BuildActionContext): Promise {
- const {
- options,
- context,
- stylesheetBundler,
- isWatchMode,
- watchedCompilationFiles,
- buildState,
- modifiedFiles,
- } = actionContext;
-
- const posixPackageJsonPath = toPosixPath(options.packageJsonPath);
- const { pendingChangedEsmFiles, pendingChangedDtsFiles, directoryExists } = buildState;
-
- if (!modifiedFiles || modifiedFiles.has(posixPackageJsonPath)) {
- buildState.hasEmittedManifests = false;
- }
+export async function buildAction(actionContext: BuildActionContext): Promise {
+ const { options, stylesheetBundler, isWatchMode, buildState, modifiedFiles } = actionContext;
+ const result = buildState.resetExecutionResult();
- const shouldCompileEntryPoints =
- !modifiedFiles ||
- !buildState.singleProgramCache ||
- buildState.hasCompilationError ||
- buildState.hasEntryPointsChanges ||
- pendingChangedEsmFiles.size > 0 ||
- pendingChangedDtsFiles.size > 0 ||
- hasModifiedWatchedFile(modifiedFiles, watchedCompilationFiles, posixPackageJsonPath);
- const shouldGenerateManifests = !buildState.hasEmittedManifests;
+ const { packageJsonPath } = options;
- if (shouldGenerateManifests) {
- verifyAllowedDependencies(options);
- }
-
- const filesToEmit: OutputFile[] = [];
-
- if (shouldCompileEntryPoints) {
- buildState.hasCompilationError = true;
- buildState.hasEntryPointsChanges = false;
-
- const {
- esmFiles,
- dtsFiles,
- changedEsmFiles,
- changedDtsFiles,
- referencedFiles,
- cache,
- diagnosePromise,
- } = await compileLibrary(
- options.entryPoints.values(),
- options,
- stylesheetBundler,
- buildState.singleProgramCache,
- modifiedFiles,
- );
- buildState.singleProgramCache = cache;
+ const shouldCompileEntryPoints = buildState.shouldCompileEntryPoints(
+ packageJsonPath,
+ modifiedFiles,
+ );
- for (const file of referencedFiles) {
- watchedCompilationFiles.add(file);
+ try {
+ if (!buildState.hasEmittedManifests && !verifyAllowedDependencies(options, result)) {
+ return result;
}
- for (const file of changedEsmFiles) {
- pendingChangedEsmFiles.add(file);
- }
- for (const file of changedDtsFiles) {
- pendingChangedDtsFiles.add(file);
- }
+ const filesToEmit: OutputFile[] = [];
- const itemsToBundle: BundleEntryPointInput[] = [];
+ if (shouldCompileEntryPoints) {
+ buildState.hasCompilationError = true;
- for (const entryPoint of options.entryPoints.values()) {
- const previousBundleResult = buildState.previousBundleResults.get(entryPoint.name);
- const hasEsmChanges =
- !previousBundleResult ||
- hasEntryPointChanges(previousBundleResult.esmModuleIds, pendingChangedEsmFiles);
- const hasDtsChanges =
- !previousBundleResult ||
- hasEntryPointChanges(previousBundleResult.dtsModuleIds, pendingChangedDtsFiles);
-
- if (hasEsmChanges || hasDtsChanges) {
- context.logger.info(`Compiling ${entryPoint.displayName}...`);
- itemsToBundle.push({
- entryPoint,
- hasEsmChanges,
- hasDtsChanges,
- previousBundleResult,
- });
- }
- }
+ const compilationOutput = await compileLibrary(
+ options,
+ stylesheetBundler,
+ buildState,
+ buildState.getCompilationModifiedFiles(modifiedFiles),
+ );
+ buildState.recordCompilationOutput(compilationOutput);
- let bundleOutput: Awaited>;
- let warnings: string[];
- try {
- [bundleOutput, warnings] = await Promise.all([
- bundleEntryPoints(itemsToBundle, esmFiles, dtsFiles, options),
+ const {
+ esmFiles,
+ dtsFiles,
+ hasStylesheetErrors,
diagnosePromise,
- ]);
- } catch (error) {
- // Prioritize TypeScript/Angular diagnostic errors over secondary bundler failures.
- await diagnosePromise;
- throw error;
- }
-
- buildState.hasCompilationError = false;
- pendingChangedEsmFiles.clear();
- pendingChangedDtsFiles.clear();
+ declarationMap,
+ compilationMode,
+ } = compilationOutput;
- for (const warning of [...warnings, ...bundleOutput.warnings]) {
- context.logger.warn(warning);
- }
-
- filesToEmit.push(...bundleOutput.filesToEmit);
- for (const [name, bundleResult] of bundleOutput.bundleResults) {
- buildState.previousBundleResults.set(name, bundleResult);
- }
- }
+ if (hasStylesheetErrors) {
+ await diagnosePromise;
- let hasTslibImport = false;
- for (const entryPoint of options.entryPoints.values()) {
- if (buildState.previousBundleResults.get(entryPoint.name)?.hasTslibImport) {
- hasTslibImport = true;
- break;
- }
- }
+ return result;
+ }
- if (shouldGenerateManifests || buildState.hasEmittedTslib !== hasTslibImport) {
- filesToEmit.push(...(await generatePackageManifests(options, isWatchMode, hasTslibImport)));
- }
+ const itemsToBundle = collectEntryPointsToBundle(options, buildState);
+ let bundleOutput: BundleEntryPointsOutput;
+ try {
+ [bundleOutput] = await Promise.all([
+ bundleEntryPoints(itemsToBundle, esmFiles, dtsFiles, {
+ ...options,
+ declarationMap,
+ compilationMode,
+ }),
+ diagnosePromise,
+ ]);
+ } catch (error) {
+ assertIsError(error);
+ // Prioritize TypeScript/Angular diagnostic errors over secondary bundler failures.
+ await diagnosePromise;
+ if (!result.hasErrors) {
+ result.addError(error.message);
+ }
+
+ return result;
+ }
- const resolvedAssetsToEmit = (actionContext.assetsToEmit ??= await collectAssetsToEmit(
- options.assets,
- options.workspaceRoot,
- buildState.hasEmittedAssets ? modifiedFiles : undefined,
- ));
- filesToEmit.push(...resolvedAssetsToEmit);
+ result.addWarnings(bundleOutput.warnings);
+ if (result.hasErrors) {
+ return result;
+ }
- await emitFilesToDisk(filesToEmit, async (file) => {
- const fullFilePath = path.join(options.outputPath, file.path);
- const fileBasePath = path.dirname(fullFilePath);
- if (fileBasePath && !directoryExists.has(fileBasePath)) {
- await mkdir(fileBasePath, { recursive: true });
- directoryExists.add(fileBasePath);
+ filesToEmit.push(...bundleOutput.filesToEmit);
+ buildState.recordBundleOutput(bundleOutput.bundleResults);
}
- if (file.type === 'memory') {
- await writeFile(fullFilePath, file.contents);
- } else {
- await copyFile(file.source, fullFilePath, constants.COPYFILE_FICLONE);
+ const { hasTslibImport } = buildState;
+ if (!buildState.hasEmittedManifests || buildState.hasEmittedTslib !== hasTslibImport) {
+ filesToEmit.push(
+ ...(await generatePackageManifests(
+ {
+ ...options,
+ compilationMode: buildState.compilationMode ?? options.compilationMode ?? 'partial',
+ },
+ isWatchMode,
+ hasTslibImport,
+ )),
+ );
}
- });
-
- buildState.hasEmittedManifests = true;
- buildState.hasEmittedTslib = hasTslibImport;
- buildState.hasEmittedAssets = true;
-}
-export function hasModifiedWatchedFile(
- modifiedFiles: ReadonlySet,
- watchedCompilationFiles: ReadonlySet,
- posixPackageJsonPath: string,
-): boolean {
- for (const file of modifiedFiles) {
- if (file !== posixPackageJsonPath && watchedCompilationFiles.has(file)) {
- return true;
- }
+ const resolvedAssetsToEmit = (actionContext.assetsToEmit ??= await collectAssetsToEmit(
+ options.assets,
+ options.workspaceRoot,
+ buildState.hasEmittedAssets ? modifiedFiles : undefined,
+ ));
+ filesToEmit.push(...resolvedAssetsToEmit);
+
+ await emitFilesToDisk(filesToEmit, (file) => path.posix.join(options.outputPath, file.path));
+
+ buildState.hasEmittedManifests = true;
+ buildState.hasEmittedTslib = hasTslibImport;
+ buildState.hasEmittedAssets = true;
+ } catch (error) {
+ assertIsError(error);
+ result.addError(error.message);
}
- return false;
+ return result;
}
-function hasEntryPointChanges(
- moduleIds: ReadonlySet,
- changedFiles: ReadonlySet,
+/**
+ * Validates that all direct and optional dependencies in `package.json` are
+ * permitted by `allowedNonPeerDependencies`.
+ *
+ * @param options The normalized library builder options.
+ * @param result The execution result to record any disallowed dependency errors into.
+ * @returns `true` if all dependencies are allowed; otherwise `false`.
+ */
+function verifyAllowedDependencies(
+ options: NormalizedLibraryOptions,
+ result: ExecutionResult,
): boolean {
- if (changedFiles.size === 0) {
- return false;
- }
-
- for (const file of changedFiles) {
- if (moduleIds.has(file)) {
- return true;
- }
- }
-
- return false;
-}
-
-function verifyAllowedDependencies(options: NormalizedLibraryOptions): void {
const { packageJson, allowedNonPeerDependencies } = options;
const dependencies = {
...(packageJson.dependencies ?? {}),
...(packageJson.optionalDependencies ?? {}),
};
+ let isValid = true;
for (const dep of Object.keys(dependencies)) {
if (!allowedNonPeerDependencies.some((regex) => regex.test(dep))) {
- throw new Error(
+ result.addError(
`Dependency '${dep}' must be explicitly allowed using the 'allowedNonPeerDependencies' option, ` +
`or moved to 'peerDependencies' in 'package.json'.`,
);
+ isValid = false;
}
}
+
+ return isValid;
}
diff --git a/packages/angular/build/src/builders/library/pipeline/bundler.ts b/packages/angular/build/src/builders/library/pipeline/bundler.ts
index d05f8b7e814f..c48942885083 100644
--- a/packages/angular/build/src/builders/library/pipeline/bundler.ts
+++ b/packages/angular/build/src/builders/library/pipeline/bundler.ts
@@ -60,7 +60,7 @@ interface MultiBundleOutput {
/** In-memory files generated by the bundle invocation. */
filesToEmit: MemoryOutputFile[];
- /** Map of bundle entry names to the set of virtual module IDs included in the bundle. */
+ /** Map of bundle entry names to the set of virtual POSIX module IDs included in the bundle. */
moduleIdsByBundle: Map>;
/** Set of bundle entry names that import 'tslib'. */
@@ -75,9 +75,9 @@ interface MultiBundleOutput {
* using at most 2 Rolldown instances total (1 for all .mjs bundles, 1 for all .d.ts bundles).
*
* @param items The collection of entry point inputs with change statuses.
- * @param esmFiles Map of virtual ESM output file paths to their content.
- * @param dtsFiles Map of virtual TypeScript declaration file paths to their content.
- * @param options The normalized library builder options.
+ * @param esmFiles Map of virtual POSIX ESM output file paths to their content.
+ * @param dtsFiles Map of virtual POSIX TypeScript declaration file paths to their content.
+ * @param options The normalized library builder options with POSIX paths.
* @returns A promise resolving to the bundled output files and bundle cache results.
*/
export async function bundleEntryPoints(
@@ -135,7 +135,7 @@ export async function bundleEntryPoints(
*
* @param entryPoints The entry points to include in the bundle input map.
* @param dtsMode Whether the input map is for declaration files (.d.ts) rather than ESM files (.js).
- * @returns A record mapping bundle names to virtual entry file paths.
+ * @returns A record mapping bundle names to virtual POSIX entry file paths.
*/
function resolveEntryInputMap(
entryPoints: readonly NormalizedEntryPoint[],
@@ -143,20 +143,18 @@ function resolveEntryInputMap(
): Record {
const input: Record = {};
for (const { bundleName, entryFilePath } of entryPoints) {
- const posixPath = toPosixPath(entryFilePath);
input[bundleName] = dtsMode
- ? posixPath.replace(/\.([cm]?ts)$/, '.d.$1')
- : posixPath.replace(/\.([cm]?)ts$/, '.$1js');
+ ? entryFilePath.replace(/\.([cm]?ts)$/, '.d.$1')
+ : entryFilePath.replace(/\.([cm]?)ts$/, '.$1js');
}
return input;
}
/**
- * Creates a Rolldown plugin that loads modules from an in-memory file map
- * and prevents illegal cross-entry-point sibling imports.
+ * Creates a Rolldown plugin that resolves and loads modules from an in-memory file map.
*
- * @param files Map of virtual file paths to their content.
+ * @param files Map of virtual POSIX file paths to their content.
* @param extensions Candidate extensions to probe when resolving extensionless module specifiers.
* @param includeMap Whether source map files should also be loaded from the memory map.
* @returns A Rolldown plugin instance.
@@ -183,12 +181,7 @@ function createMemoryFileLoaderPlugin(
return { id, external: true };
}
- const posixId = toPosixPath(id);
- const importerPosix = toPosixPath(importer);
- const resolved =
- posixId[0] === '.'
- ? path.posix.join(path.posix.dirname(importerPosix), posixId)
- : posixId;
+ const resolved = id[0] === '.' ? path.posix.join(path.posix.dirname(importer), id) : id;
let resolvedCandidate: string | undefined;
if (files.has(resolved)) {
@@ -230,7 +223,7 @@ function createMemoryFileLoaderPlugin(
* the transitive set of module IDs belonging to each entry point bundle.
*
* @param output The array of output chunks and assets from Rolldown.
- * @param dir The destination output directory prefix.
+ * @param dir The destination POSIX output directory prefix.
* @returns The processed multi-bundle output.
*/
function processRolldownOutput(
@@ -300,13 +293,22 @@ function processRolldownOutput(
return { filesToEmit, moduleIdsByBundle, tslibBundles };
}
+/**
+ * Set of Rolldown warning codes that should be ignored.
+ */
+const IGNORED_ROLLDOWN_WARNING_CODES: ReadonlySet = new Set([
+ 'EMPTY_BUNDLE',
+ 'UNUSED_EXTERNAL_IMPORT',
+ 'THIS_IS_UNDEFINED',
+]);
+
/**
* Executes a Rolldown bundle build across all provided entry inputs.
*
- * @param input Map of bundle names to virtual entry file paths.
+ * @param input Map of bundle names to virtual POSIX entry file paths.
* @param plugins Rolldown plugins to use during bundling.
* @param extension Output file extension ('mjs' or 'd.ts').
- * @param options The normalized library options.
+ * @param options The normalized library options with POSIX paths.
* @returns A promise resolving to the multi-bundle output.
*/
async function executeMultiBundle(
@@ -323,7 +325,7 @@ async function executeMultiBundle(
if (isDts) {
dir = TYPES_OUTPUT_DIR;
- sourcemap = declarationMap;
+ sourcemap = !!declarationMap;
} else {
dir = FESM_OUTPUT_DIR;
// FESM (.mjs) sourcemaps are always enabled.
@@ -341,7 +343,12 @@ async function executeMultiBundle(
resolve: { symlinks: !preserveSymlinks },
checks: { circularDependency: false },
onLog(level, log) {
+ // Ignore specified warning codes
if (level === 'warn') {
+ if (log.code && IGNORED_ROLLDOWN_WARNING_CODES.has(log.code)) {
+ return;
+ }
+
warnings.push(log.message);
}
},
@@ -353,12 +360,12 @@ async function executeMultiBundle(
try {
const { output } = await bundle.generate({
format: 'es',
- dir: path.join(outputPath, dir),
+ dir: path.posix.join(outputPath, dir),
entryFileNames: `[name].${extension}`,
chunkFileNames: `[name]-[hash].${extension}`,
sourcemap,
hoistTransitiveImports: false,
- comments: { jsdoc: isDts, legal: true, annotation: true },
+ comments: { jsdoc: isDts, legal: true, annotation: !isDts },
});
return {
@@ -374,8 +381,8 @@ async function executeMultiBundle(
* Bundles JavaScript ESM output files for all provided entry points.
*
* @param entryPoints The entry points to bundle.
- * @param esmFiles Map of virtual ESM output file paths to contents.
- * @param options The normalized library options.
+ * @param esmFiles Map of virtual POSIX ESM output file paths to contents.
+ * @param options The normalized library options with POSIX paths.
* @returns A promise resolving to the multi-bundle output.
*/
async function bundleAllEsm(
@@ -404,8 +411,8 @@ async function bundleAllEsm(
* Bundles TypeScript declaration (.d.ts) output files for all provided entry points.
*
* @param entryPoints The entry points to bundle.
- * @param dtsFiles Map of virtual declaration output file paths to contents.
- * @param options The normalized library options.
+ * @param dtsFiles Map of virtual POSIX declaration output file paths to contents.
+ * @param options The normalized library options with POSIX paths.
* @returns A promise resolving to the multi-bundle output.
*/
async function bundleAllDts(
@@ -425,9 +432,12 @@ async function bundleAllDts(
// Ensure Rolldown's native binding is initialized via `loadRolldown()` before evaluating
// `rolldown-plugin-dts`, which has top-level imports of `rolldown/experimental`.
await loadRolldown();
- const { dts } = await import('rolldown-plugin-dts');
+ const { dts } = (await import('rolldown-plugin-dts' as string)) as typeof import(
+ 'rolldown-plugin-dts',
+ { with: { 'resolution-mode': 'import' } }
+ );
- const dtsSourcemap = options.declarationMap;
+ const dtsSourcemap = !!options.declarationMap;
// Filter out `rolldown-plugin-dts:resolver` because all `.d.ts` files are already emitted
// in-memory by the Angular/TypeScript compilation and resolved via `createMemoryFileLoaderPlugin`.
// The default `rolldown-plugin-dts:resolver` plugin performs filesystem resolution (`oxc-resolver`)
diff --git a/packages/angular/build/src/builders/library/pipeline/compilation.ts b/packages/angular/build/src/builders/library/pipeline/compilation.ts
index b8b89fc41e24..1c026c5e9fec 100644
--- a/packages/angular/build/src/builders/library/pipeline/compilation.ts
+++ b/packages/angular/build/src/builders/library/pipeline/compilation.ts
@@ -15,59 +15,41 @@ import {
import type { ComponentStylesheetBundler } from '../../../tools/esbuild/angular/component-stylesheets';
import { useTypeChecking } from '../../../utils/environment-options';
import { toPosixPath } from '../../../utils/path';
-import type { NormalizedEntryPoint, NormalizedLibraryOptions, SingleProgramCache } from '../types';
+import type { BuilderState } from '../builder-state';
+import type { LibraryCompilationOutput, NormalizedLibraryOptions } from '../types';
import { isDeclarationFile, isDeclarationSourceMapFile } from './utils';
const EMITTED_EXTENSIONS = ['.js', '.mjs', '.cjs', '.d.ts', '.d.mts', '.d.cts'];
-/**
- * Output of the unified library compilation step.
- */
-export interface LibraryCompilationOutput {
- /** Read-only map of emitted JavaScript files. */
- readonly esmFiles: ReadonlyMap;
-
- /** Read-only map of emitted TypeScript declaration files. */
- readonly dtsFiles: ReadonlyMap;
-
- /** Set of JavaScript file paths that were modified or newly emitted in this iteration. */
- readonly changedEsmFiles: ReadonlySet;
-
- /** Set of declaration file paths that were modified or newly emitted in this iteration. */
- readonly changedDtsFiles: ReadonlySet;
-
- /** Set of all source and dependency file paths referenced during compilation. */
- readonly referencedFiles: ReadonlySet;
-
- /** Cached compilation state for subsequent incremental builds. */
- readonly cache: SingleProgramCache;
-
- /** Promise that resolves to formatted compilation warnings or rejects on diagnostic errors. */
- readonly diagnosePromise: Promise;
-}
-
/**
* Compiles all library entry points in a single TypeScript and Angular compilation pass.
*
- * @param entryPoints The collection of normalized library entry points to compile.
- * @param options The normalized library builder options.
+ * @param options The normalized library builder options with POSIX paths.
* @param stylesheetBundler The component stylesheet bundler instance.
- * @param cached Optional cached compilation state from a previous build iteration.
- * @param modifiedFiles Optional set of modified file paths for incremental compilation.
- * @returns A promise resolving to the compilation output containing emitted files and diagnostics.
+ * @param buildState The build state tracking compilation caches, file references, and diagnostics.
+ * @param modifiedFiles Optional set of modified POSIX file paths for incremental compilation.
+ * @returns A promise resolving to the compilation output containing emitted files and cache state.
*/
export async function compileLibrary(
- entryPoints: Iterable,
options: NormalizedLibraryOptions,
stylesheetBundler: ComponentStylesheetBundler,
- cached?: SingleProgramCache,
+ buildState: BuilderState,
modifiedFiles?: Set,
): Promise {
- const { tsConfigPath, compilationMode, preserveSymlinks, colors, declarationMap } = options;
+ const {
+ tsConfigPath,
+ entryPoints,
+ compilationMode,
+ preserveSymlinks,
+ colors,
+ declarationMap,
+ cacheOptions,
+ } = options;
+ const cached = buildState.singleProgramCache;
const entryPathsMap: Record = {};
const rootFiles: string[] = [];
- for (const ep of entryPoints) {
+ for (const ep of entryPoints.values()) {
entryPathsMap[ep.displayName] = [ep.entryFilePath];
rootFiles.push(ep.entryFilePath);
}
@@ -77,19 +59,20 @@ export async function compileLibrary(
try {
let effectiveModifiedFiles = modifiedFiles;
- if (cached?.failedFiles?.size) {
+ if (cached && cached.failedFiles.size > 0) {
stylesheetBundler.invalidate(cached.failedFiles);
- effectiveModifiedFiles = new Set(modifiedFiles);
+ const merged = new Set(modifiedFiles);
for (const file of cached.failedFiles) {
- effectiveModifiedFiles.add(file);
+ merged.add(file);
}
+ effectiveModifiedFiles = merged;
}
if (effectiveModifiedFiles && effectiveModifiedFiles.size > 0) {
await compilationInstance.update?.(effectiveModifiedFiles);
+ buildState.clearFileReferences(effectiveModifiedFiles);
}
- const allReferencedFiles = new Set();
const stylesheetWarnings: PartialMessage[] = [];
const stylesheetErrors: PartialMessage[] = [];
const failedFiles = new Set();
@@ -105,7 +88,13 @@ export async function compileLibrary(
? await stylesheetBundler.bundleFile(stylesheetFile)
: await stylesheetBundler.bundleInline(data, containingFile);
- result.referencedFiles?.forEach((f) => allReferencedFiles.add(toPosixPath(f)));
+ if (result.referencedFiles) {
+ buildState.addFileReferences(containingFile, result.referencedFiles);
+ if (stylesheetFile) {
+ buildState.addFileReferences(stylesheetFile, result.referencedFiles);
+ }
+ }
+
if (result.warnings.length > 0) {
stylesheetWarnings.push(...result.warnings);
}
@@ -125,7 +114,7 @@ export async function compileLibrary(
processWebWorker: () => '',
};
- const { referencedFiles } = await compilationInstance.initialize(
+ const { referencedFiles, compilerOptions } = await compilationInstance.initialize(
tsConfigPath,
hostOptions,
{
@@ -135,40 +124,35 @@ export async function compileLibrary(
declarationMap,
compilationMode,
paths: entryPathsMap,
+ cachePath: cacheOptions.enabled ? cacheOptions.path : undefined,
},
'library',
);
- const emittedFiles =
- stylesheetErrors.length === 0 ? await compilationInstance.emitAffectedFiles() : [];
+ const hasStylesheetErrors = stylesheetErrors.length > 0;
+ const emittedFiles = hasStylesheetErrors ? [] : await compilationInstance.emitAffectedFiles();
const diagnosePromise = runDiagnosticsAndFormat(
compilationInstance,
stylesheetErrors,
stylesheetWarnings,
colors,
+ buildState,
);
- // Prevent unhandled promise rejection if an error occurs before diagnosePromise is awaited.
- diagnosePromise.catch(() => {});
-
const esmFiles = cached?.esmFiles ?? new Map();
const dtsFiles = cached?.dtsFiles ?? new Map();
const changedEsmFiles = new Set();
const changedDtsFiles = new Set();
+ const posixReferencedFiles = new Set(referencedFiles.map(toPosixPath));
- for (const ref of referencedFiles) {
- allReferencedFiles.add(toPosixPath(ref));
- }
-
- if (effectiveModifiedFiles) {
+ if (cached && effectiveModifiedFiles) {
for (const modifiedFile of effectiveModifiedFiles) {
- const posixModified = toPosixPath(modifiedFile);
- if (allReferencedFiles.has(posixModified)) {
+ if (posixReferencedFiles.has(modifiedFile)) {
continue;
}
- const basePathWithoutExt = posixModified.replace(/(?:\.d\.[cm]?ts|\.[cm]?[jt]sx?)$/i, '');
- if (basePathWithoutExt === posixModified || existsSync(posixModified)) {
+ const basePathWithoutExt = modifiedFile.replace(/(?:\.d\.[cm]?ts|\.[cm]?[jt]sx?)$/i, '');
+ if (basePathWithoutExt === modifiedFile || existsSync(modifiedFile)) {
continue;
}
@@ -189,21 +173,15 @@ export async function compileLibrary(
for (const { filename, contents } of emittedFiles) {
const normalized = toPosixPath(filename);
- if (normalized.endsWith('.map')) {
- const isDtsMap = isDeclarationSourceMapFile(normalized);
- const targetMap = isDtsMap ? dtsFiles : esmFiles;
- if (targetMap.get(normalized) !== contents) {
- targetMap.set(normalized, contents);
- (isDtsMap ? changedDtsFiles : changedEsmFiles).add(normalized.slice(0, -4));
- }
- } else if (isDeclarationFile(normalized)) {
- if (dtsFiles.get(normalized) !== contents) {
- changedDtsFiles.add(normalized);
- dtsFiles.set(normalized, contents);
- }
- } else if (esmFiles.get(normalized) !== contents) {
- changedEsmFiles.add(normalized);
- esmFiles.set(normalized, contents);
+ const isMap = normalized.endsWith('.map');
+ const isDts = isMap ? isDeclarationSourceMapFile(normalized) : isDeclarationFile(normalized);
+ const targetFiles = isDts ? dtsFiles : esmFiles;
+
+ if (targetFiles.get(normalized) !== contents) {
+ targetFiles.set(normalized, contents);
+ (isDts ? changedDtsFiles : changedEsmFiles).add(
+ isMap ? normalized.slice(0, -4) : normalized,
+ );
}
}
@@ -212,14 +190,17 @@ export async function compileLibrary(
dtsFiles,
changedEsmFiles,
changedDtsFiles,
- referencedFiles: allReferencedFiles,
+ referencedFiles: posixReferencedFiles,
cache: {
compilationInstance,
esmFiles,
dtsFiles,
- failedFiles: failedFiles.size > 0 ? failedFiles : undefined,
+ failedFiles,
},
+ hasStylesheetErrors,
diagnosePromise,
+ declarationMap: !!compilerOptions.declarationMap,
+ compilationMode: compilerOptions.compilationMode === 'full' ? 'full' : 'partial',
};
} catch (error) {
if (!cached) {
@@ -230,49 +211,43 @@ export async function compileLibrary(
}
/**
- * Validates stylesheet bundling results and runs TypeScript/Angular diagnostics.
+ * Formats stylesheet bundling diagnostics and TypeScript/Angular diagnostics
+ * and records them on the build state's execution result.
*
* @param compilationInstance The active Angular compilation instance.
* @param stylesheetErrors List of stylesheet bundling errors.
* @param stylesheetWarnings List of stylesheet bundling warnings.
* @param colors Whether diagnostic messages should be formatted with ANSI colors.
- * @returns A promise resolving to formatted warning messages.
- * @throws If stylesheet bundling errors or compilation errors occur.
+ * @param buildState The build state whose execution result receives the formatted diagnostics.
*/
async function runDiagnosticsAndFormat(
compilationInstance: AngularCompilation,
stylesheetErrors: PartialMessage[],
stylesheetWarnings: PartialMessage[],
colors: boolean,
-): Promise {
- if (stylesheetErrors.length > 0) {
- const formatted = await formatMessages(stylesheetErrors, { kind: 'error', color: colors });
-
- throw new Error(`Failed to bundle stylesheet:\n${formatted.join('\n')}`);
- }
-
- const warningsOut: string[] = [];
-
- if (useTypeChecking) {
- const { errors, warnings } = await compilationInstance.diagnoseFiles();
- if (errors?.length) {
- const errorMessages = await formatMessages(errors, { kind: 'error', color: colors });
- throw new Error(`Compilation failed with errors:\n${errorMessages.join('\n')}`);
+ buildState: BuilderState,
+): Promise {
+ const { executionResult } = buildState;
+ const errors = [...stylesheetErrors];
+ const warnings: PartialMessage[] = [];
+
+ if (errors.length === 0 && useTypeChecking) {
+ const diagnostics = await compilationInstance.diagnoseFiles();
+ if (diagnostics.errors?.length) {
+ errors.push(...diagnostics.errors);
}
-
- if (warnings?.length) {
- const formatted = await formatMessages(warnings, { kind: 'warning', color: colors });
- warningsOut.push(...formatted);
+ if (diagnostics.warnings?.length) {
+ warnings.push(...diagnostics.warnings);
}
}
- if (stylesheetWarnings.length > 0) {
- const formattedStyleWarnings = await formatMessages(stylesheetWarnings, {
- kind: 'warning',
- color: colors,
- });
- warningsOut.push(...formattedStyleWarnings);
+ warnings.push(...stylesheetWarnings);
+
+ if (errors.length > 0) {
+ executionResult.addErrors(await formatMessages(errors, { kind: 'error', color: colors }));
}
- return warningsOut;
+ if (warnings.length > 0) {
+ executionResult.addWarnings(await formatMessages(warnings, { kind: 'warning', color: colors }));
+ }
}
diff --git a/packages/angular/build/src/builders/library/pipeline/entry-points.ts b/packages/angular/build/src/builders/library/pipeline/entry-points.ts
index 93a96307d9e4..f50824c5d9f3 100644
--- a/packages/angular/build/src/builders/library/pipeline/entry-points.ts
+++ b/packages/angular/build/src/builders/library/pipeline/entry-points.ts
@@ -8,12 +8,9 @@
import path from 'node:path';
import { toPosixPath } from '../../../utils/path';
-import type {
- NormalizedEntryPoint,
- NormalizedLibraryOptions,
- PackageJsonData,
- SingleBuildState,
-} from '../types';
+import type { BuilderState } from '../builder-state';
+import type { NormalizedEntryPoint, NormalizedLibraryOptions, PackageJsonData } from '../types';
+import type { BundleEntryPointInput } from './bundler';
/**
* Computes the base bundle file name for an entry point.
@@ -23,7 +20,7 @@ import type {
* @returns The sanitized bundle base name.
*/
export function getEntryPointBundleName(packageName: string, entryPointName = '.'): string {
- const isPrimary = !entryPointName || entryPointName === '.';
+ const isPrimary = entryPointName === '.';
const pkgName = packageName[0] === '@' ? packageName.slice(1) : packageName;
const epName = isPrimary ? pkgName : `${pkgName}-${entryPointName}`;
@@ -37,9 +34,9 @@ export function getEntryPointBundleName(packageName: string, entryPointName = '.
* @param posixKey Normalized POSIX key without trailing slashes.
* @param isPrimary Whether this is the primary entry point.
* @param targetPath The relative file path string from exports.
- * @param projectRoot The library project root directory.
+ * @param projectRoot The library project root POSIX directory path.
* @param packageName The root package name (e.g. `@my/lib`).
- * @returns The normalized entry point descriptor.
+ * @returns The normalized entry point descriptor with POSIX paths.
*/
function normalizeEntryPoint(
key: string,
@@ -49,11 +46,7 @@ function normalizeEntryPoint(
projectRoot: string,
packageName: string,
): NormalizedEntryPoint {
- const name = isPrimary
- ? '.'
- : posixKey[0] === '.' && posixKey[1] === '/'
- ? posixKey.slice(2)
- : posixKey;
+ const name = isPrimary ? '.' : posixKey.startsWith('./') ? posixKey.slice(2) : posixKey;
if (name !== '.' && (path.posix.isAbsolute(name) || name.includes('..'))) {
throw new Error(
@@ -64,7 +57,7 @@ function normalizeEntryPoint(
const subpath = isPrimary ? '.' : `./${name}`;
const displayName = (isPrimary ? packageName : `${packageName}/${name}`).toLowerCase();
const bundleName = getEntryPointBundleName(packageName, name);
- const entryFilePath = path.resolve(projectRoot, targetPath);
+ const entryFilePath = toPosixPath(path.resolve(projectRoot, targetPath));
if (!/(? k.startsWith('.'));
+ const hasSubpathKeys = Object.keys(rawExports).some((k) => k.startsWith('.'));
exportsRecord = hasSubpathKeys ? (rawExports as Record) : { '.': rawExports };
}
@@ -189,10 +182,7 @@ export function normalizeEntryPoints(
usedBundleNames.set(entryPoint.bundleName, key);
entryPoints.set(entryPoint.name, entryPoint);
-
- if (entryPoint.isPrimary) {
- hasPrimary = true;
- }
+ hasPrimary ||= isPrimary;
}
if (!hasPrimary) {
@@ -205,7 +195,12 @@ export function normalizeEntryPoints(
}
/**
- * Determines whether two sets of normalized entry points differ in keys, paths, or subpaths.
+ * Determines whether two sets of normalized entry points differ in keys, POSIX entry paths,
+ * subpaths, bundle names, or display names.
+ *
+ * @param oldEntryPoints The previous map of normalized entry points.
+ * @param newEntryPoints The new map of normalized entry points.
+ * @returns `true` if any entry point was added, removed, or modified; otherwise `false`.
*/
export function haveEntryPointsChanged(
oldEntryPoints: ReadonlyMap,
@@ -233,27 +228,40 @@ export function haveEntryPointsChanged(
/**
* Updates watched files, entry points in options, and cached bundle results when package.json entry points change.
+ *
+ * @param packageJson The reloaded `package.json` data.
+ * @param options The normalized library builder options.
+ * @param buildState The state preserved across incremental builds.
*/
export function updateWatchedEntryPoints(
packageJson: PackageJsonData,
options: NormalizedLibraryOptions,
- buildState: SingleBuildState,
- watchedCompilationFiles: Set,
- packageJsonPath: string,
+ buildState: BuilderState,
): void {
+ const { packageJsonPath } = options;
+ if (!packageJson.name) {
+ throw new Error(`The package.json at '${packageJsonPath}' must contain a 'name'.`);
+ }
+
const newEntryPoints = normalizeEntryPoints(
packageJson.exports,
options.projectRoot,
packageJsonPath,
- options.packageName,
+ packageJson.name,
);
+ const { watchedCompilationFiles, previousBundleResults } = buildState;
+
if (haveEntryPointsChanged(options.entryPoints, newEntryPoints)) {
+ for (const oldEntryPoint of options.entryPoints.values()) {
+ watchedCompilationFiles.delete(oldEntryPoint.entryFilePath);
+ }
+
for (const entryPoint of newEntryPoints.values()) {
- watchedCompilationFiles.add(toPosixPath(entryPoint.entryFilePath));
+ watchedCompilationFiles.add(entryPoint.entryFilePath);
}
- for (const name of buildState.previousBundleResults.keys()) {
+ for (const name of previousBundleResults.keys()) {
const oldEp = options.entryPoints.get(name);
const newEp = newEntryPoints.get(name);
if (
@@ -262,11 +270,77 @@ export function updateWatchedEntryPoints(
newEp.entryFilePath !== oldEp.entryFilePath ||
newEp.bundleName !== oldEp.bundleName
) {
- buildState.previousBundleResults.delete(name);
+ previousBundleResults.delete(name);
}
}
options.entryPoints = newEntryPoints;
buildState.hasEntryPointsChanges = true;
}
+
+ options.packageJson = packageJson;
+ options.packageName = packageJson.name;
+}
+
+/**
+ * Determines which entry points have modified JavaScript or declaration files
+ * and collects them for bundling.
+ *
+ * @param options The normalized library builder options.
+ * @param buildState The state preserved across incremental builds.
+ * @returns The list of entry points that require bundling in the current build iteration.
+ */
+export function collectEntryPointsToBundle(
+ options: NormalizedLibraryOptions,
+ buildState: BuilderState,
+): BundleEntryPointInput[] {
+ const { pendingChangedEsmFiles, pendingChangedDtsFiles, previousBundleResults, executionResult } =
+ buildState;
+ const itemsToBundle: BundleEntryPointInput[] = [];
+
+ for (const entryPoint of options.entryPoints.values()) {
+ const previousBundleResult = previousBundleResults.get(entryPoint.name);
+ const hasEsmChanges =
+ !previousBundleResult ||
+ hasEntryPointChanges(previousBundleResult.esmModuleIds, pendingChangedEsmFiles);
+ const hasDtsChanges =
+ !previousBundleResult ||
+ hasEntryPointChanges(previousBundleResult.dtsModuleIds, pendingChangedDtsFiles);
+
+ if (hasEsmChanges || hasDtsChanges) {
+ executionResult.addLog(`Compiling ${entryPoint.displayName}...`);
+ itemsToBundle.push({
+ entryPoint,
+ hasEsmChanges,
+ hasDtsChanges,
+ previousBundleResult,
+ });
+ }
+ }
+
+ return itemsToBundle;
+}
+
+/**
+ * Checks whether any file in `changedFiles` belongs to the given entry point's `moduleIds`.
+ *
+ * @param moduleIds Set of virtual POSIX module IDs referenced by the entry point's previous bundle.
+ * @param changedFiles Set of POSIX file paths that changed during compilation.
+ * @returns `true` if at least one changed file is part of `moduleIds`; otherwise `false`.
+ */
+function hasEntryPointChanges(
+ moduleIds: ReadonlySet,
+ changedFiles: ReadonlySet,
+): boolean {
+ if (changedFiles.size === 0) {
+ return false;
+ }
+
+ for (const file of changedFiles) {
+ if (moduleIds.has(file)) {
+ return true;
+ }
+ }
+
+ return false;
}
diff --git a/packages/angular/build/src/builders/library/pipeline/entry-points_spec.ts b/packages/angular/build/src/builders/library/pipeline/entry-points_spec.ts
index 834b7aec6835..e4653ef56e2b 100644
--- a/packages/angular/build/src/builders/library/pipeline/entry-points_spec.ts
+++ b/packages/angular/build/src/builders/library/pipeline/entry-points_spec.ts
@@ -6,16 +6,16 @@
* found in the LICENSE file at https://angular.dev/license
*/
-import { join, resolve } from 'node:path';
-import { toPosixPath } from '../../../utils/path';
+import { join } from 'node:path';
+import { BuilderState } from '../builder-state';
import type {
BundleResult,
NormalizedEntryPoint,
NormalizedLibraryOptions,
PackageJsonData,
- SingleBuildState,
} from '../types';
import {
+ collectEntryPointsToBundle,
getEntryPointBundleName,
haveEntryPointsChanged,
normalizeEntryPoints,
@@ -23,10 +23,19 @@ import {
} from './entry-points';
describe('entry-points pipeline', () => {
- const projectRoot = resolve('/workspace/projects/my-lib');
+ const projectRoot = '/workspace/projects/my-lib';
const packageJsonPath = join(projectRoot, 'package.json');
const packageName = '@my-scope/my-lib';
+ function createBundleResult(overrides: Partial = {}): BundleResult {
+ return {
+ esmModuleIds: new Set(),
+ dtsModuleIds: new Set(),
+ hasTslibImport: false,
+ ...overrides,
+ };
+ }
+
describe('getEntryPointBundleName', () => {
it('should compute bundle name for primary entry point without scope', () => {
expect(getEntryPointBundleName('my-lib')).toBe('my-lib');
@@ -505,6 +514,8 @@ describe('entry-points pipeline', () => {
});
describe('updateWatchedEntryPoints', () => {
+ const tsConfigPath = join(projectRoot, 'tsconfig.lib.json');
+
it('should update options, watched files, build state, and prune removed bundles when entry points change', () => {
const initialEntryPoints = normalizeEntryPoints(
{
@@ -520,17 +531,14 @@ describe('entry-points pipeline', () => {
entryPoints: initialEntryPoints,
projectRoot,
packageName,
+ packageJsonPath,
+ tsConfigPath,
+ assets: [],
} as unknown as NormalizedLibraryOptions;
- const buildState = {
- previousBundleResults: new Map([
- ['.', { esmModuleIds: new Set(), dtsModuleIds: new Set() }],
- ['old-feature', { esmModuleIds: new Set(), dtsModuleIds: new Set() }],
- ]),
- hasEntryPointsChanges: false,
- } as unknown as SingleBuildState;
-
- const watchedCompilationFiles = new Set();
+ const buildState = new BuilderState(options);
+ buildState.previousBundleResults.set('.', createBundleResult());
+ buildState.previousBundleResults.set('old-feature', createBundleResult());
const newPackageJson: PackageJsonData = {
name: packageName,
@@ -540,13 +548,7 @@ describe('entry-points pipeline', () => {
},
};
- updateWatchedEntryPoints(
- newPackageJson,
- options,
- buildState,
- watchedCompilationFiles,
- packageJsonPath,
- );
+ updateWatchedEntryPoints(newPackageJson, options, buildState);
expect(buildState.hasEntryPointsChanges).toBeTrue();
expect(options.entryPoints.has('new-feature')).toBeTrue();
@@ -554,16 +556,17 @@ describe('entry-points pipeline', () => {
expect(buildState.previousBundleResults.has('old-feature')).toBeFalse();
expect(buildState.previousBundleResults.has('.')).toBeTrue();
expect(
- watchedCompilationFiles.has(toPosixPath(join(projectRoot, 'src/public-api.ts'))),
+ buildState.watchedCompilationFiles.has(join(projectRoot, 'src/public-api.ts')),
).toBeTrue();
expect(
- watchedCompilationFiles.has(
- toPosixPath(join(projectRoot, 'new-feature/src/public-api.ts')),
- ),
+ buildState.watchedCompilationFiles.has(join(projectRoot, 'old-feature/src/public-api.ts')),
+ ).toBeFalse();
+ expect(
+ buildState.watchedCompilationFiles.has(join(projectRoot, 'new-feature/src/public-api.ts')),
).toBeTrue();
});
- it('should not mutate buildState or options when entry points do not change', () => {
+ it('should not mutate buildState or options.entryPoints when entry points do not change', () => {
const initialEntryPoints = normalizeEntryPoints(
{
'.': './src/public-api.ts',
@@ -578,17 +581,14 @@ describe('entry-points pipeline', () => {
entryPoints: initialEntryPoints,
projectRoot,
packageName,
+ packageJsonPath,
+ tsConfigPath,
+ assets: [],
} as unknown as NormalizedLibraryOptions;
- const buildState = {
- previousBundleResults: new Map([
- ['.', { esmModuleIds: new Set(), dtsModuleIds: new Set() }],
- ['feature', { esmModuleIds: new Set(), dtsModuleIds: new Set() }],
- ]),
- hasEntryPointsChanges: false,
- } as unknown as SingleBuildState;
-
- const watchedCompilationFiles = new Set();
+ const buildState = new BuilderState(options);
+ buildState.previousBundleResults.set('.', createBundleResult());
+ buildState.previousBundleResults.set('feature', createBundleResult());
const samePackageJson: PackageJsonData = {
name: packageName,
@@ -598,17 +598,10 @@ describe('entry-points pipeline', () => {
},
};
- updateWatchedEntryPoints(
- samePackageJson,
- options,
- buildState,
- watchedCompilationFiles,
- packageJsonPath,
- );
+ updateWatchedEntryPoints(samePackageJson, options, buildState);
expect(buildState.hasEntryPointsChanges).toBeFalse();
expect(options.entryPoints).toBe(initialEntryPoints);
- expect(watchedCompilationFiles).toHaveSize(0);
expect(buildState.previousBundleResults).toHaveSize(2);
});
@@ -626,16 +619,13 @@ describe('entry-points pipeline', () => {
entryPoints: initialEntryPoints,
projectRoot,
packageName,
+ packageJsonPath,
+ tsConfigPath,
+ assets: [],
} as unknown as NormalizedLibraryOptions;
- const buildState = {
- previousBundleResults: new Map([
- ['.', { esmModuleIds: new Set(), dtsModuleIds: new Set() }],
- ]),
- hasEntryPointsChanges: false,
- } as unknown as SingleBuildState;
-
- const watchedCompilationFiles = new Set();
+ const buildState = new BuilderState(options);
+ buildState.previousBundleResults.set('.', createBundleResult());
const updatedPackageJson: PackageJsonData = {
name: packageName,
@@ -644,13 +634,7 @@ describe('entry-points pipeline', () => {
},
};
- updateWatchedEntryPoints(
- updatedPackageJson,
- options,
- buildState,
- watchedCompilationFiles,
- packageJsonPath,
- );
+ updateWatchedEntryPoints(updatedPackageJson, options, buildState);
expect(buildState.hasEntryPointsChanges).toBeTrue();
expect(buildState.previousBundleResults.has('.')).toBeFalse();
@@ -658,7 +642,7 @@ describe('entry-points pipeline', () => {
join(projectRoot, 'src/other-api.ts'),
);
expect(
- watchedCompilationFiles.has(toPosixPath(join(projectRoot, 'src/other-api.ts'))),
+ buildState.watchedCompilationFiles.has(join(projectRoot, 'src/other-api.ts')),
).toBeTrue();
});
@@ -676,16 +660,13 @@ describe('entry-points pipeline', () => {
entryPoints: initialEntryPoints,
projectRoot,
packageName,
+ packageJsonPath,
+ tsConfigPath,
+ assets: [],
} as unknown as NormalizedLibraryOptions;
- const buildState = {
- previousBundleResults: new Map([
- ['.', { esmModuleIds: new Set(), dtsModuleIds: new Set() }],
- ]),
- hasEntryPointsChanges: false,
- } as unknown as SingleBuildState;
-
- const watchedCompilationFiles = new Set();
+ const buildState = new BuilderState(options);
+ buildState.previousBundleResults.set('.', createBundleResult());
const updatedPackageJson: PackageJsonData = {
name: '@renamed-scope/my-lib',
@@ -694,19 +675,108 @@ describe('entry-points pipeline', () => {
},
};
- options.packageName = updatedPackageJson.name;
-
- updateWatchedEntryPoints(
- updatedPackageJson,
- options,
- buildState,
- watchedCompilationFiles,
- packageJsonPath,
- );
+ updateWatchedEntryPoints(updatedPackageJson, options, buildState);
expect(buildState.hasEntryPointsChanges).toBeTrue();
expect(buildState.previousBundleResults.has('.')).toBeFalse();
+ expect(options.packageName).toBe('@renamed-scope/my-lib');
expect(options.entryPoints.get('.')?.bundleName).toBe('renamed-scope-my-lib');
});
+
+ it('should throw when updated packageJson is missing a name field', () => {
+ const options = {
+ entryPoints: new Map(),
+ projectRoot,
+ packageName,
+ packageJsonPath,
+ assets: [],
+ } as unknown as NormalizedLibraryOptions;
+ const buildState = new BuilderState(options);
+
+ expect(() =>
+ updateWatchedEntryPoints({} as PackageJsonData, options, buildState),
+ ).toThrowError(/must contain a 'name'/);
+ });
+ });
+
+ describe('collectEntryPointsToBundle', () => {
+ it('should return all entry points with ESM and DTS changes on initial build', () => {
+ const entryPoints = normalizeEntryPoints(
+ {
+ '.': './src/public-api.ts',
+ './testing': './testing/src/public-api.ts',
+ },
+ projectRoot,
+ packageJsonPath,
+ packageName,
+ );
+ const options = { entryPoints } as unknown as NormalizedLibraryOptions;
+ const buildState = new BuilderState(options);
+
+ const items = collectEntryPointsToBundle(options, buildState);
+
+ expect(items).toHaveSize(2);
+ expect(items[0]).toEqual({
+ entryPoint: jasmine.objectContaining({ name: '.' }),
+ previousBundleResult: undefined,
+ hasEsmChanges: true,
+ hasDtsChanges: true,
+ });
+ expect(items[1]).toEqual({
+ entryPoint: jasmine.objectContaining({ name: 'testing' }),
+ previousBundleResult: undefined,
+ hasEsmChanges: true,
+ hasDtsChanges: true,
+ });
+ expect(buildState.executionResult.logs).toEqual([
+ 'Compiling @my-scope/my-lib...',
+ 'Compiling @my-scope/my-lib/testing...',
+ ]);
+ });
+
+ it('should only return entry points whose ESM or DTS module IDs intersect pending changes', () => {
+ const entryPoints = normalizeEntryPoints(
+ {
+ '.': './src/public-api.ts',
+ './testing': './testing/src/public-api.ts',
+ },
+ projectRoot,
+ packageJsonPath,
+ packageName,
+ );
+ const options = { entryPoints } as unknown as NormalizedLibraryOptions;
+ const buildState = new BuilderState(options);
+
+ const primaryEntryJs = join(projectRoot, 'src/public-api.js');
+ const primaryEntryDts = join(projectRoot, 'src/public-api.d.ts');
+ const testingEntryJs = join(projectRoot, 'testing/src/public-api.js');
+ const testingEntryDts = join(projectRoot, 'testing/src/public-api.d.ts');
+
+ buildState.previousBundleResults.set(
+ '.',
+ createBundleResult({
+ esmModuleIds: new Set([primaryEntryJs]),
+ dtsModuleIds: new Set([primaryEntryDts]),
+ }),
+ );
+ buildState.previousBundleResults.set(
+ 'testing',
+ createBundleResult({
+ esmModuleIds: new Set([testingEntryJs]),
+ dtsModuleIds: new Set([testingEntryDts]),
+ }),
+ );
+
+ buildState.pendingChangedEsmFiles.add(testingEntryJs);
+
+ const items = collectEntryPointsToBundle(options, buildState);
+
+ expect(items).toHaveSize(1);
+ expect(items[0]?.entryPoint.name).toBe('testing');
+ expect(items[0]?.hasEsmChanges).toBeTrue();
+ expect(items[0]?.hasDtsChanges).toBeFalse();
+ expect(items[0]?.previousBundleResult).toBe(buildState.previousBundleResults.get('testing'));
+ expect(buildState.executionResult.logs).toEqual(['Compiling @my-scope/my-lib/testing...']);
+ });
});
});
diff --git a/packages/angular/build/src/builders/library/pipeline/package-manifests.ts b/packages/angular/build/src/builders/library/pipeline/package-manifests.ts
index 90e5d5bbd94a..5238ccca76c2 100644
--- a/packages/angular/build/src/builders/library/pipeline/package-manifests.ts
+++ b/packages/angular/build/src/builders/library/pipeline/package-manifests.ts
@@ -78,13 +78,10 @@ export async function generatePackageManifests(
};
if (hasTslibImport && !rawPackageJson.dependencies?.['tslib']) {
- const tslibVersion = await getAngularTslibRange(options.workspaceRoot);
- if (tslibVersion) {
- distPackageJson.dependencies = {
- ...rawPackageJson.dependencies,
- tslib: tslibVersion,
- };
- }
+ distPackageJson.dependencies = {
+ ...rawPackageJson.dependencies,
+ tslib: await getAngularTslibRange(options.workspaceRoot),
+ };
}
// Retain scripts if keepLifecycleScripts is set
@@ -159,6 +156,11 @@ export async function generatePackageManifests(
/**
* Creates or updates export conditions for an entry point, preserving custom user-defined conditions.
+ *
+ * @param existingConditions Existing export conditions from the user's `package.json`.
+ * @param dtsPath Relative POSIX path to the bundled `.d.ts` file.
+ * @param fesmPath Relative POSIX path to the bundled FESM `.mjs` file.
+ * @returns The merged export conditions object.
*/
function createExportConditions(
existingConditions: unknown,
@@ -188,7 +190,7 @@ let cachedTslibRange: string | undefined;
/**
* Get the tslib range used by the Angular compiler.
- * @param workspaceRoot path to the workspace root
+ * @param workspaceRoot path to the workspace root.
* @returns tslib range
*/
async function getAngularTslibRange(workspaceRoot: string): Promise {
diff --git a/packages/angular/build/src/builders/library/pipeline/stylesheet-bundler.ts b/packages/angular/build/src/builders/library/pipeline/stylesheet-bundler.ts
index 74c44f3a1491..971741d7a2e2 100644
--- a/packages/angular/build/src/builders/library/pipeline/stylesheet-bundler.ts
+++ b/packages/angular/build/src/builders/library/pipeline/stylesheet-bundler.ts
@@ -10,6 +10,9 @@ import { ComponentStylesheetBundler } from '../../../tools/esbuild/angular/compo
import type { BundleStylesheetOptions } from '../../../tools/esbuild/stylesheets/bundle-options';
import type { NormalizedLibraryOptions } from '../types';
+/**
+ * Subset of normalized library options required to configure the component stylesheet bundler.
+ */
export type LibraryStylesheetBundlerOptions = Pick<
NormalizedLibraryOptions,
| 'workspaceRoot'
@@ -25,7 +28,7 @@ export type LibraryStylesheetBundlerOptions = Pick<
/**
* Creates a stylesheet bundler instance configured for library compilation.
*
- * @param options The normalized library builder options.
+ * @param options The normalized library builder options with POSIX paths.
* @param incremental Whether incremental watch mode is enabled.
* @param target The esbuild target environments derived from browserslist.
* @returns A new ComponentStylesheetBundler instance.
diff --git a/packages/angular/build/src/builders/library/pipeline/types.d.ts b/packages/angular/build/src/builders/library/pipeline/types.d.ts
deleted file mode 100644
index 100c539f098c..000000000000
--- a/packages/angular/build/src/builders/library/pipeline/types.d.ts
+++ /dev/null
@@ -1,54 +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
- */
-
-declare module 'rolldown-plugin-dts' {
- import type { Plugin } from 'rolldown';
- import type { IsolatedDeclarationsOptions } from 'rolldown/experimental';
-
- interface Logger {
- info: (...args: unknown[]) => void;
- warn: (...args: unknown[]) => void;
- error: (...args: unknown[]) => void;
- }
- interface GeneralOptions {
- generator?: 'tsc' | 'oxc' | 'tsgo';
- entry?: string | string[];
- cwd?: string;
- dtsInput?: boolean;
- emitDtsOnly?: boolean;
- tsconfig?: string | boolean;
- tsconfigRaw?: unknown;
- compilerOptions?: unknown;
- sourcemap?: boolean;
- resolver?: 'oxc' | 'tsc';
- cjsDefault?: boolean;
- sideEffects?: boolean;
- logger?: Logger;
- }
-
- interface TscOptions {
- build?: boolean;
- incremental?: boolean;
- parallel?: boolean;
- eager?: boolean;
- newContext?: boolean;
- emitJs?: boolean;
- }
-
- interface Options extends GeneralOptions, TscOptions {
- oxc?: Omit;
- tsgo?: TsgoOptions;
- customLanguages?: unknown[];
- }
-
- interface TsgoOptions {
- path?: string;
- }
-
- export declare function dts(options?: Options): Plugin[];
-}
diff --git a/packages/angular/build/src/builders/library/pipeline/utils.ts b/packages/angular/build/src/builders/library/pipeline/utils.ts
index 8258c8874e42..8ef8cf7fe9f3 100644
--- a/packages/angular/build/src/builders/library/pipeline/utils.ts
+++ b/packages/angular/build/src/builders/library/pipeline/utils.ts
@@ -7,6 +7,7 @@
*/
import fs from 'node:fs/promises';
+import { toPosixPath } from '../../../utils/path';
import type { PackageJsonData } from '../types';
const IS_DTS_FILE_REGEXP = /\.d\.[cm]?ts$/i;
@@ -26,9 +27,9 @@ export const TYPES_OUTPUT_DIR = 'types';
* Represents an in-memory file to be emitted to disk.
*/
export interface MemoryOutputFile {
- type: 'memory';
+ origin: 'memory';
- /** The destination path where the file should be written. */
+ /** The relative POSIX destination path where the file should be written. */
path: string;
/** The contents of the file as either a string or byte array. */
@@ -39,12 +40,12 @@ export interface MemoryOutputFile {
* Represents an existing file on disk to be copied to a destination path.
*/
export interface DiskOutputFile {
- type: 'disk';
+ origin: 'disk';
- /** The path to the source file on disk. */
+ /** The POSIX path to the source file on disk. */
source: string;
- /** The destination path where the file should be copied. */
+ /** The relative POSIX destination path where the file should be copied. */
path: string;
}
@@ -54,34 +55,34 @@ export interface DiskOutputFile {
export type OutputFile = MemoryOutputFile | DiskOutputFile;
/**
- * Creates an output file descriptor for an existing file on disk.
+ * Creates an output file descriptor for an existing file on disk with POSIX paths.
*
* @param source The path to the source file on disk.
- * @param path The destination path where the file should be copied.
- * @returns A {@link DiskOutputFile} descriptor.
+ * @param path The relative destination path where the file should be copied.
+ * @returns A {@link DiskOutputFile} descriptor with POSIX `source` and `path`.
*/
export function createDiskOutputFile(source: string, path: string): DiskOutputFile {
return {
- type: 'disk',
- source,
- path,
+ origin: 'disk',
+ source: toPosixPath(source),
+ path: toPosixPath(path),
};
}
/**
- * Creates an output file descriptor for an in-memory file.
+ * Creates an output file descriptor for an in-memory file with a POSIX destination path.
*
- * @param path The destination path where the file should be written.
+ * @param path The relative destination path where the file should be written.
* @param contents The contents of the file as either a string, byte array, or JSON object.
- * @returns A {@link MemoryOutputFile} descriptor.
+ * @returns A {@link MemoryOutputFile} descriptor with a POSIX `path`.
*/
export function createMemoryOutputFile(
path: string,
contents: string | Uint8Array | Record,
): MemoryOutputFile {
return {
- type: 'memory',
- path,
+ origin: 'memory',
+ path: toPosixPath(path),
contents:
typeof contents === 'string' || contents instanceof Uint8Array
? contents
diff --git a/packages/angular/build/src/builders/library/schema.json b/packages/angular/build/src/builders/library/schema.json
index bac9944091f6..ee34936bdd62 100644
--- a/packages/angular/build/src/builders/library/schema.json
+++ b/packages/angular/build/src/builders/library/schema.json
@@ -71,14 +71,12 @@
},
"declarationMap": {
"type": "boolean",
- "description": "Generates a sourcemap for each corresponding '.d.ts' file.",
- "default": false
+ "description": "Generates a sourcemap for each corresponding '.d.ts' file."
},
"compilationMode": {
"type": "string",
"description": "Angular compilation mode. Use 'partial' when publishing to npm (APF requirement). Use 'full' only during development or for private, internal monorepo packages that are never published.",
- "enum": ["partial", "full"],
- "default": "partial"
+ "enum": ["partial", "full"]
},
"allowedNonPeerDependencies": {
"description": "A list of package names allowed in the 'dependencies' and 'optionalDependencies' sections of package.json. Values can be regular expression patterns.",
diff --git a/packages/angular/build/src/builders/library/tests/behavior/build_spec.ts b/packages/angular/build/src/builders/library/tests/behavior/build_spec.ts
index 74150e57acb7..0b6de2a26c7f 100644
--- a/packages/angular/build/src/builders/library/tests/behavior/build_spec.ts
+++ b/packages/angular/build/src/builders/library/tests/behavior/build_spec.ts
@@ -74,6 +74,47 @@ describeLibraryBuilder(executeLibraryBuilder, LIBRARY_BUILDER_INFO, (harness) =>
);
});
+ it('should not log EMPTY_BUNDLE warnings for type-only entry points', async () => {
+ await harness.writeFile(
+ 'projects/lib/src/public-api.ts',
+ `export interface OnlyType { id: string; }`,
+ );
+
+ harness.useTarget('build', {
+ ...BASE_OPTIONS,
+ });
+
+ const { result, logs } = await harness.executeOnce();
+ expect(result?.success).toBeTrue();
+ expect(logs.some((l) => l.level === 'warn')).toBeFalse();
+ });
+
+ it('should preserve JSDoc comments in .d.ts and annotation comments in .mjs bundles', async () => {
+ await harness.writeFile(
+ 'projects/lib/src/public-api.ts',
+ `
+ function identity(x: T): T { return x; }
+ /** Public API JSDoc comment */
+ export const VALUE = /* @__PURE__ */ identity('test');
+ `,
+ );
+
+ harness.useTarget('build', {
+ ...BASE_OPTIONS,
+ });
+
+ const { result } = await harness.executeOnce();
+ expect(result?.success).toBeTrue();
+
+ const fesmContent = harness.readFile('dist/lib/fesm2022/lib.mjs');
+ expect(fesmContent).toContain('@__PURE__');
+ expect(fesmContent).not.toContain('Public API JSDoc comment');
+
+ const dtsContent = harness.readFile('dist/lib/types/lib.d.ts');
+ expect(dtsContent).toContain('Public API JSDoc comment');
+ expect(dtsContent).not.toContain('@__PURE__');
+ });
+
it('should automatically add tslib to dependencies when output chunks import tslib', async () => {
await harness.writeFile(
'projects/lib/src/public-api.ts',
@@ -139,5 +180,103 @@ describeLibraryBuilder(executeLibraryBuilder, LIBRARY_BUILDER_INFO, (harness) =>
tslib: '^2.0.0',
});
});
+
+ it('should log completion and output location', async () => {
+ harness.useTarget('build', {
+ ...BASE_OPTIONS,
+ });
+
+ const { result, logs } = await harness.executeOnce();
+ expect(result?.success).toBeTrue();
+ expect(logs).toContain(
+ jasmine.objectContaining({
+ level: 'info',
+ message: jasmine.stringMatching(
+ /Library bundle generation complete\. \[\d+\.\d{3} seconds\] - \d{4}-\d{2}-\d{2}T/,
+ ),
+ }),
+ );
+ expect(logs).toContain(
+ jasmine.objectContaining({
+ level: 'info',
+ message: jasmine.stringMatching(/Output location: .*dist[/\\]lib/),
+ }),
+ );
+ });
+
+ it('should log failure on build error', async () => {
+ await harness.writeFile(
+ 'projects/lib/src/public-api.ts',
+ `export const title: number = 'invalid type';`,
+ );
+
+ harness.useTarget('build', {
+ ...BASE_OPTIONS,
+ });
+
+ const { result, logs } = await harness.executeOnce({ outputLogsOnFailure: false });
+ expect(result?.success).toBeFalse();
+ expect(logs).toContain(
+ jasmine.objectContaining({
+ level: 'error',
+ message: jasmine.stringContaining('TS2322'),
+ }),
+ );
+ expect(logs).toContain(
+ jasmine.objectContaining({
+ level: 'error',
+ message: jasmine.stringMatching(
+ /Library bundle generation failed\. \[\d+\.\d{3} seconds\] - \d{4}-\d{2}-\d{2}T/,
+ ),
+ }),
+ );
+ expect(logs).not.toContain(
+ jasmine.objectContaining({
+ message: jasmine.stringMatching(/Output location:/),
+ }),
+ );
+ });
+
+ it('should write and reuse .tsbuildinfo in the persistent cache directory when cache is enabled', async () => {
+ harness.useProject('lib', {
+ root: 'projects/lib',
+ sourceRoot: 'projects/lib/src',
+ cli: {
+ cache: {
+ enabled: true,
+ environment: 'all',
+ path: '.angular/cache',
+ },
+ },
+ });
+
+ harness.useTarget('build', {
+ ...BASE_OPTIONS,
+ });
+
+ const firstBuild = await harness.executeOnce();
+ expect(firstBuild.result?.success).toBeTrue();
+ harness
+ .expectFile('.angular/cache/0.0.0-PLACEHOLDER/lib/angular-build-library/.tsbuildinfo')
+ .toExist();
+
+ await harness.writeFile(
+ 'projects/lib/src/public-api.ts',
+ `
+ export * from './lib/lib.service';
+ export * from './lib/lib.component';
+ export const CACHED_BUILD = true;
+ `,
+ );
+
+ const secondBuild = await harness.executeOnce();
+ expect(secondBuild.result?.success).toBeTrue();
+ const fesmContent = harness.readFile('dist/lib/fesm2022/lib.mjs');
+ expect(fesmContent).toContain('LibComponent');
+ expect(fesmContent).toContain('CACHED_BUILD');
+ const dtsContent = harness.readFile('dist/lib/types/lib.d.ts');
+ expect(dtsContent).toContain('LibComponent');
+ expect(dtsContent).toContain('CACHED_BUILD');
+ });
});
});
diff --git a/packages/angular/build/src/builders/library/tests/behavior/watch_spec.ts b/packages/angular/build/src/builders/library/tests/behavior/watch_spec.ts
index 2533da417909..e9b7e57ddd9f 100644
--- a/packages/angular/build/src/builders/library/tests/behavior/watch_spec.ts
+++ b/packages/angular/build/src/builders/library/tests/behavior/watch_spec.ts
@@ -6,7 +6,9 @@
* found in the LICENSE file at https://angular.dev/license
*/
+import { rm } from 'node:fs/promises';
import { executeLibraryBuilder } from '../../builder';
+import { InlineStyleLanguage } from '../../schema';
import { BASE_OPTIONS, LIBRARY_BUILDER_INFO, describeLibraryBuilder } from '../setup';
describeLibraryBuilder(executeLibraryBuilder, LIBRARY_BUILDER_INFO, (harness) => {
@@ -563,5 +565,89 @@ describeLibraryBuilder(executeLibraryBuilder, LIBRARY_BUILDER_INFO, (harness) =>
},
]);
});
+
+ it('should recreate deleted output directories on subsequent watch rebuilds', async () => {
+ harness.useTarget('build', {
+ ...BASE_OPTIONS,
+ watch: true,
+ });
+
+ await harness.executeWithCases([
+ async ({ result }) => {
+ expect(result?.success).toBeTrue();
+ expect(harness.hasFile('dist/lib/fesm2022/lib.mjs')).toBeTrue();
+
+ // Remove output subdirectory externally between rebuilds
+ await rm(harness.resolvePath('dist/lib/fesm2022'), { recursive: true, force: true });
+ expect(harness.hasFile('dist/lib/fesm2022/lib.mjs')).toBeFalse();
+
+ // Trigger a rebuild
+ await harness.writeFile(
+ 'projects/lib/src/lib/lib.component.ts',
+ `
+ import { Component } from '@angular/core';
+
+ @Component({
+ selector: 'lib-recreated',
+ template: 'Recreated',
+ })
+ export class LibComponent {}
+ `,
+ );
+ },
+ ({ result }) => {
+ expect(result?.success).toBeTrue();
+ const content = harness.readFile('dist/lib/fesm2022/lib.mjs');
+ expect(content).toContain('lib-recreated');
+ },
+ ]);
+ });
+
+ it('should rebuild when a Sass partial imported by an inline component stylesheet is modified in watch mode', async () => {
+ await harness.writeFiles({
+ 'projects/lib/src/lib/_vars.scss': '$primary-color: rgb(10, 20, 30);',
+ 'projects/lib/src/lib/_spacing.scss': '$pad: 12px;',
+ 'projects/lib/src/lib/lib.component.ts': `
+ import { Component } from '@angular/core';
+
+ @Component({
+ selector: 'lib-inline-sass',
+ template: 'Inline Sass',
+ styles: [
+ '@use "./vars"; :host { color: vars.$primary-color; }',
+ '@use "./spacing"; :host { padding: spacing.$pad; }',
+ ],
+ })
+ export class LibComponent {}
+ `,
+ });
+
+ harness.useTarget('build', {
+ ...BASE_OPTIONS,
+ inlineStyleLanguage: InlineStyleLanguage.Scss,
+ watch: true,
+ });
+
+ await harness.executeWithCases([
+ async ({ result }) => {
+ expect(result?.success).toBeTrue();
+ const content = harness.readFile('dist/lib/fesm2022/lib.mjs');
+ expect(content).toMatch(/color:\s*(?:#0a141e|rgb\(10,\s*20,\s*30\))/);
+ expect(content).toMatch(/padding:\s*12px/);
+
+ // Modify the Sass partial referenced by the first inline component style
+ await harness.writeFile(
+ 'projects/lib/src/lib/_vars.scss',
+ '$primary-color: rgb(200, 100, 50);',
+ );
+ },
+ ({ result }) => {
+ expect(result?.success).toBeTrue();
+ const content = harness.readFile('dist/lib/fesm2022/lib.mjs');
+ expect(content).toMatch(/color:\s*(?:#c86432|rgb\(200,\s*100,\s*50\))/);
+ expect(content).toMatch(/padding:\s*12px/);
+ },
+ ]);
+ });
});
});
diff --git a/packages/angular/build/src/builders/library/tests/options/allowed-non-peer-dependencies_spec.ts b/packages/angular/build/src/builders/library/tests/options/allowed-non-peer-dependencies_spec.ts
index caca7c594f26..c75699d068a3 100644
--- a/packages/angular/build/src/builders/library/tests/options/allowed-non-peer-dependencies_spec.ts
+++ b/packages/angular/build/src/builders/library/tests/options/allowed-non-peer-dependencies_spec.ts
@@ -24,10 +24,14 @@ describeLibraryBuilder(executeLibraryBuilder, LIBRARY_BUILDER_INFO, (harness) =>
...BASE_OPTIONS,
});
- const { result } = await harness.executeOnce();
+ const { result, logs } = await harness.executeOnce({ outputLogsOnFailure: false });
expect(result?.success).toBeFalse();
- expect(result?.error).toContain('allowedNonPeerDependencies');
- expect(result?.error).toContain('lodash-es');
+ expect(logs).toContain(
+ jasmine.objectContaining({
+ level: 'error',
+ message: jasmine.stringMatching(/lodash-es.*allowedNonPeerDependencies/),
+ }),
+ );
});
it('should succeed build when dependency matches allowedNonPeerDependencies pattern', async () => {
diff --git a/packages/angular/build/src/builders/library/tests/options/assets_spec.ts b/packages/angular/build/src/builders/library/tests/options/assets_spec.ts
index ded7743675ff..a596cbfe4e62 100644
--- a/packages/angular/build/src/builders/library/tests/options/assets_spec.ts
+++ b/packages/angular/build/src/builders/library/tests/options/assets_spec.ts
@@ -15,6 +15,7 @@ describeLibraryBuilder(executeLibraryBuilder, LIBRARY_BUILDER_INFO, (harness) =>
await harness.writeFiles({
'projects/lib/assets-dir/file-a.png': 'PNG_A',
'projects/lib/assets-dir/file-b.png': 'PNG_B',
+ 'projects/lib/assets-dir/ignored.png': 'PNG_IGNORED',
'projects/lib/assets-dir/file-c.svg': 'SVG_C',
});
@@ -25,6 +26,7 @@ describeLibraryBuilder(executeLibraryBuilder, LIBRARY_BUILDER_INFO, (harness) =>
glob: '**/*.png',
input: 'projects/lib/assets-dir',
output: 'assets',
+ ignore: ['ignored.png'],
},
],
});
@@ -34,6 +36,7 @@ describeLibraryBuilder(executeLibraryBuilder, LIBRARY_BUILDER_INFO, (harness) =>
expect(harness.readFile('dist/lib/assets/file-a.png')).toBe('PNG_A');
expect(harness.readFile('dist/lib/assets/file-b.png')).toBe('PNG_B');
+ expect(harness.hasFile('dist/lib/assets/ignored.png')).toBeFalse();
expect(harness.hasFile('dist/lib/assets/file-c.svg')).toBeFalse();
});
diff --git a/packages/angular/build/src/builders/library/tests/options/compilation-mode_spec.ts b/packages/angular/build/src/builders/library/tests/options/compilation-mode_spec.ts
index cd794206960d..0efedef5708f 100644
--- a/packages/angular/build/src/builders/library/tests/options/compilation-mode_spec.ts
+++ b/packages/angular/build/src/builders/library/tests/options/compilation-mode_spec.ts
@@ -37,5 +37,53 @@ describeLibraryBuilder(executeLibraryBuilder, LIBRARY_BUILDER_INFO, (harness) =>
const fesm = harness.readFile('dist/lib/fesm2022/lib.mjs');
expect(fesm).toContain('ɵɵdefineComponent');
});
+
+ it('should respect angularCompilerOptions.compilationMode from tsconfig when not set in builder options', async () => {
+ await harness.modifyFile('projects/lib/tsconfig.lib.json', (content) => {
+ const tsconfig = JSON.parse(content);
+ tsconfig.angularCompilerOptions = {
+ ...tsconfig.angularCompilerOptions,
+ compilationMode: 'full',
+ };
+
+ return JSON.stringify(tsconfig, null, 2);
+ });
+
+ harness.useTarget('build', {
+ ...BASE_OPTIONS,
+ });
+
+ const { result } = await harness.executeOnce();
+ expect(result?.success).toBeTrue();
+
+ const fesm = harness.readFile('dist/lib/fesm2022/lib.mjs');
+ expect(fesm).toContain('ɵɵdefineComponent');
+
+ const pkgJson = JSON.parse(harness.readFile('dist/lib/package.json'));
+ expect(pkgJson.scripts?.prepublishOnly).toContain('full compilation mode');
+ });
+
+ it('should override angularCompilerOptions.compilationMode from tsconfig when set in builder options', async () => {
+ await harness.modifyFile('projects/lib/tsconfig.lib.json', (content) => {
+ const tsconfig = JSON.parse(content);
+ tsconfig.angularCompilerOptions = {
+ ...tsconfig.angularCompilerOptions,
+ compilationMode: 'full',
+ };
+
+ return JSON.stringify(tsconfig, null, 2);
+ });
+
+ harness.useTarget('build', {
+ ...BASE_OPTIONS,
+ compilationMode: CompilationMode.Partial,
+ });
+
+ const { result } = await harness.executeOnce();
+ expect(result?.success).toBeTrue();
+
+ const fesm = harness.readFile('dist/lib/fesm2022/lib.mjs');
+ expect(fesm).toContain('ɵɵngDeclareComponent');
+ });
});
});
diff --git a/packages/angular/build/src/builders/library/tests/options/declaration-map_spec.ts b/packages/angular/build/src/builders/library/tests/options/declaration-map_spec.ts
index a37e2f0dd255..2e30109d6a03 100644
--- a/packages/angular/build/src/builders/library/tests/options/declaration-map_spec.ts
+++ b/packages/angular/build/src/builders/library/tests/options/declaration-map_spec.ts
@@ -44,5 +44,43 @@ describeLibraryBuilder(executeLibraryBuilder, LIBRARY_BUILDER_INFO, (harness) =>
expect(dtsMap.sources).toContain('../../../projects/lib/src/lib/lib.component.ts');
harness.expectFile(join('dist/lib/types', dtsMap.sources[0])).toExist();
});
+
+ it('should respect declarationMap from tsconfig when not set in builder options', async () => {
+ await harness.modifyFile('projects/lib/tsconfig.lib.json', (content) => {
+ const tsconfig = JSON.parse(content);
+ tsconfig.compilerOptions.declarationMap = true;
+
+ return JSON.stringify(tsconfig, null, 2);
+ });
+
+ harness.useTarget('build', {
+ ...BASE_OPTIONS,
+ });
+
+ const { result } = await harness.executeOnce();
+ expect(result?.success).toBeTrue();
+
+ harness.expectFile('dist/lib/types/lib.d.ts.map').toExist();
+ });
+
+ it('should override declarationMap from tsconfig when declarationMap is false', async () => {
+ await harness.modifyFile('projects/lib/tsconfig.lib.json', (content) => {
+ const tsconfig = JSON.parse(content);
+ tsconfig.compilerOptions.declarationMap = true;
+
+ return JSON.stringify(tsconfig, null, 2);
+ });
+
+ harness.useTarget('build', {
+ ...BASE_OPTIONS,
+ declarationMap: false,
+ });
+
+ const { result } = await harness.executeOnce();
+ expect(result?.success).toBeTrue();
+
+ harness.expectFile('dist/lib/fesm2022/lib.mjs.map').toExist();
+ harness.expectFile('dist/lib/types/lib.d.ts.map').toNotExist();
+ });
});
});
diff --git a/packages/angular/build/src/builders/library/types.ts b/packages/angular/build/src/builders/library/types.ts
index dfe91c36f3c5..2d2d9f61891d 100644
--- a/packages/angular/build/src/builders/library/types.ts
+++ b/packages/angular/build/src/builders/library/types.ts
@@ -9,7 +9,7 @@
import type { AngularCompilation } from '../../tools/angular/compilation';
import type { StylesheetPluginsass } from '../../tools/esbuild/stylesheets/stylesheet-plugin-factory';
import type { normalizeAssetPatterns } from '../../utils';
-import type { normalizeCacheOptions } from '../../utils/normalize-cache';
+import type { NormalizedCachedOptions } from '../../utils/normalize-cache';
import type { PostcssConfiguration } from '../../utils/postcss-configuration';
/**
@@ -28,7 +28,7 @@ export interface NormalizedEntryPoint {
/** Base name of the output bundle (e.g. 'my-lib' or 'my-lib-testing'). */
bundleName: string;
- /** Absolute path to entry file. */
+ /** Absolute POSIX path to the entry file. */
entryFilePath: string;
/** Is this the primary entry point ('.')? */
@@ -59,33 +59,85 @@ export interface PackageJsonData {
/**
* Normalized options for the library builder.
+ * All file and directory paths are normalized to POSIX format.
*/
export interface NormalizedLibraryOptions {
+ /** Absolute POSIX path to the workspace root directory. */
workspaceRoot: string;
+
+ /** Absolute POSIX path to the library project root directory. */
projectRoot: string;
+
+ /** Name of the npm package from the library's `package.json`. */
packageName: string;
+
+ /** Parsed contents of the library's `package.json`. */
packageJson: PackageJsonData;
+
+ /** Absolute POSIX path to the build output directory. */
outputPath: string;
+
+ /** Whether to delete the output directory before building. */
deleteOutputPath: boolean;
+
+ /** Absolute POSIX path to the library's `package.json`. */
packageJsonPath: string;
+
+ /** Absolute POSIX path to the TypeScript configuration file. */
tsConfigPath: string;
+
+ /** Map of normalized entry points keyed by entry point name. */
entryPoints: Map;
+
+ /** Default stylesheet language for inline component styles. */
inlineStyleLanguage: 'css' | 'less' | 'sass' | 'scss';
+
+ /** Absolute POSIX paths to style preprocessor include directories. */
styleIncludePaths: string[];
+
+ /** Optional Sass preprocessor configuration. */
sass?: StylesheetPluginsass;
+
+ /** Normalized asset patterns with POSIX `input` and `output` paths. */
assets: ReturnType;
- compilationMode: 'partial' | 'full';
- declarationMap: boolean;
+
+ /** Angular compilation mode (`'partial'` or `'full'`). */
+ compilationMode?: 'partial' | 'full';
+
+ /** Whether to generate source maps for TypeScript declaration files. */
+ declarationMap?: boolean;
+
+ /** Regular expressions matching allowed non-peer dependencies. */
allowedNonPeerDependencies: RegExp[];
+
+ /** Whether to preserve lifecycle scripts in the emitted `package.json`. */
keepLifecycleScripts: boolean;
+
+ /** Whether to run the build in watch mode. */
watch: boolean;
+
+ /** Optional file watching polling interval in milliseconds. */
poll?: number;
+
+ /** Whether to preserve symbolic links during resolution and bundling. */
preserveSymlinks: boolean;
+
+ /** Whether to display build progress in the terminal. */
progress: boolean;
+
+ /** Whether to clear the terminal screen before watch rebuilds. */
clearScreen?: boolean;
- cacheOptions: ReturnType;
+
+ /** Normalized build cache configuration. */
+ cacheOptions: NormalizedCachedOptions;
+
+ /** Resolved PostCSS configuration, if present in the workspace. */
postcssConfiguration?: { config: PostcssConfiguration; configPath: string };
+
+ /** Resolved Tailwind CSS configuration, if applicable. */
tailwindConfiguration?: { file: string; package: string };
+
+ /** Whether terminal color output is enabled. */
colors: boolean;
}
@@ -93,10 +145,10 @@ export interface NormalizedLibraryOptions {
* Cached module ID sets for a bundled entry point.
*/
export interface BundleResult {
- /** Exact set of virtual ESM module IDs bundled into this entry point. */
+ /** Exact set of virtual POSIX ESM module IDs bundled into this entry point. */
esmModuleIds: ReadonlySet;
- /** Exact set of virtual DTS module IDs bundled into this entry point. */
+ /** Exact set of virtual POSIX DTS module IDs bundled into this entry point. */
dtsModuleIds: ReadonlySet;
/** Whether this entry point bundle imports 'tslib'. */
@@ -110,47 +162,47 @@ export interface SingleProgramCache {
/** The active Angular compilation instance. */
readonly compilationInstance: AngularCompilation;
- /** In-memory map of emitted JavaScript files keyed by relative output path. */
+ /** In-memory map of emitted JavaScript files keyed by POSIX path. */
readonly esmFiles: Map;
- /** In-memory map of emitted TypeScript declaration files keyed by relative output path. */
+ /** In-memory map of emitted TypeScript declaration files keyed by POSIX path. */
readonly dtsFiles: Map;
- /** Set of file paths that failed during stylesheet bundling or compilation. */
- readonly failedFiles?: ReadonlySet;
+ /** Set of POSIX file paths that failed during stylesheet bundling. */
+ readonly failedFiles: ReadonlySet;
}
/**
- * State preserved across incremental builds in watch mode.
+ * Output of the unified library compilation step.
*/
-export interface SingleBuildState {
- /** Cached unified TypeScript and Angular compilation state. */
- singleProgramCache?: SingleProgramCache;
+export interface LibraryCompilationOutput {
+ /** Read-only map of emitted JavaScript files keyed by POSIX path. */
+ readonly esmFiles: ReadonlyMap;
- /** Map of entry point names to their previous bundle results. */
- previousBundleResults: Map;
+ /** Read-only map of emitted TypeScript declaration files keyed by POSIX path. */
+ readonly dtsFiles: ReadonlyMap;
- /** Set of changed ESM file paths pending bundling. */
- pendingChangedEsmFiles: Set;
+ /** Set of POSIX JavaScript file paths that were added, modified, or deleted in this iteration. */
+ readonly changedEsmFiles: ReadonlySet;
- /** Set of changed TypeScript declaration file paths pending bundling. */
- pendingChangedDtsFiles: Set;
+ /** Set of POSIX declaration file paths that were added, modified, or deleted in this iteration. */
+ readonly changedDtsFiles: ReadonlySet;
- /** Whether the previous build iteration encountered a compilation or diagnostic error. */
- hasCompilationError?: boolean;
+ /** Set of all POSIX source and dependency file paths referenced during compilation. */
+ readonly referencedFiles: ReadonlySet;
- /** Whether package.json and secondary entry point manifests have been emitted. */
- hasEmittedManifests?: boolean;
+ /** Cached compilation state for subsequent incremental builds. */
+ readonly cache: SingleProgramCache;
- /** Whether the last emitted root package.json included a tslib dependency. */
- hasEmittedTslib?: boolean;
+ /** Whether any component stylesheet bundling errors occurred. */
+ readonly hasStylesheetErrors: boolean;
- /** Whether static assets have been emitted in a prior iteration. */
- hasEmittedAssets?: boolean;
+ /** Promise that resolves when compilation diagnostics have been formatted and recorded. */
+ readonly diagnosePromise: Promise;
- /** Whether entry points in package.json changed since the last compilation. */
- hasEntryPointsChanges?: boolean;
+ /** Effective declarationMap setting resolved from builder options and tsconfig. */
+ readonly declarationMap: boolean;
- /** Cache of output directory paths known to exist on disk. */
- directoryExists: Set;
+ /** Effective compilationMode setting resolved from builder options and tsconfig. */
+ readonly compilationMode: 'partial' | 'full';
}
diff --git a/packages/angular/build/src/builders/unit-test/runners/vitest/executor.ts b/packages/angular/build/src/builders/unit-test/runners/vitest/executor.ts
index aa201e24c578..b5c7841c799b 100644
--- a/packages/angular/build/src/builders/unit-test/runners/vitest/executor.ts
+++ b/packages/angular/build/src/builders/unit-test/runners/vitest/executor.ts
@@ -398,11 +398,6 @@ export class VitestExecutor implements TestExecutor {
const vitestServerConfig = {
// Note `.vitest` is auto appended to the path.
cacheDir: cacheOptions.path,
- server: {
- // Disable the actual file watcher. The boolean watch option above should still
- // be enabled as it controls other internal behavior related to rerunning tests.
- watch: null,
- },
plugins: [
await createVitestConfigPlugin({
browser: browserOptions.browser,
diff --git a/packages/angular/build/src/builders/unit-test/runners/vitest/plugins.ts b/packages/angular/build/src/builders/unit-test/runners/vitest/plugins.ts
index 6be4c6e8ebe3..72308b6b57d6 100644
--- a/packages/angular/build/src/builders/unit-test/runners/vitest/plugins.ts
+++ b/packages/angular/build/src/builders/unit-test/runners/vitest/plugins.ts
@@ -164,6 +164,16 @@ export async function createVitestConfigPlugin(
return {
name: 'angular:vitest-configuration',
+ enforce: 'post',
+ configResolved: {
+ order: 'post',
+ handler(config: Vite.ResolvedConfig) {
+ // Vitest's internal post-configResolved hook resets `server.watch` to `{}` when
+ // `watch` is enabled (`server.watch ??= {}`). Force it back to `null` so Vite uses
+ // a no-op watcher and relies solely on the Angular CLI build watcher.
+ config.server.watch = null;
+ },
+ },
async config(config: UserWorkspaceConfig & Vite.UserConfig) {
const testConfig = config.test;
@@ -271,6 +281,7 @@ export async function createVitestConfigPlugin(
test: {
name: projectName,
include,
+ fsModuleCache: false,
// CLI provider browser options override, if present
...(browser ? { browser } : {}),
// Only override if the user explicitly set it via CLI
@@ -290,6 +301,7 @@ export async function createVitestConfigPlugin(
return {
test: {
+ fsModuleCache: false,
coverage: await generateCoverageOption(
options.coverage,
testConfig?.coverage,
@@ -310,7 +322,7 @@ async function loadResultFile(file: ResultFile): Promise {
return textDecoder.decode(file.contents);
}
- return readFile(file.inputPath, 'utf-8');
+ return readFile(file.source, 'utf-8');
}
export function createVitestPlugins(pluginOptions: PluginOptions): Vite.Plugin[] {
diff --git a/packages/angular/build/src/builders/unit-test/test-discovery.ts b/packages/angular/build/src/builders/unit-test/test-discovery.ts
index f2fc8c221646..2452675a9abf 100644
--- a/packages/angular/build/src/builders/unit-test/test-discovery.ts
+++ b/packages/angular/build/src/builders/unit-test/test-discovery.ts
@@ -74,8 +74,10 @@ export async function findTests(
}
}
- // 3. Combine and de-duplicate results
- return [...resolvedTestFiles];
+ // 3. Combine, de-duplicate and sort the results. The glob crawls directories asynchronously and
+ // returns matches in a varying order; the order feeds the build entry points, so an unsorted list
+ // makes the output (chunk contents and names) differ between two builds of the same sources.
+ return [...resolvedTestFiles].sort();
}
interface TestEntrypointsOptions {
diff --git a/packages/angular/build/src/builders/unit-test/test-discovery_spec.ts b/packages/angular/build/src/builders/unit-test/test-discovery_spec.ts
index 764924d9552b..91c33fd0120a 100644
--- a/packages/angular/build/src/builders/unit-test/test-discovery_spec.ts
+++ b/packages/angular/build/src/builders/unit-test/test-discovery_spec.ts
@@ -6,8 +6,40 @@
* found in the LICENSE file at https://angular.dev/license
*/
+import assert from 'node:assert';
+import { promises as fs } from 'node:fs';
+import { join } from 'node:path';
import { initializeHash } from '../../utils/hash';
-import { generateNameFromPath, getTestEntrypoints } from './test-discovery';
+import { toPosixPath } from '../../utils/path';
+import { findTests, generateNameFromPath, getTestEntrypoints } from './test-discovery';
+
+describe('findTests', () => {
+ let projectSourceRoot: string;
+
+ beforeEach(async () => {
+ const baseTmpDir = process.env['TEST_TMPDIR'];
+ assert(baseTmpDir, 'TEST_TMPDIR is not set');
+ projectSourceRoot = await fs.mkdtemp(join(baseTmpDir, 'angular-find-tests-'));
+ });
+
+ afterEach(async () => {
+ await fs.rm(projectSourceRoot, { recursive: true, force: true });
+ });
+
+ it('should return the test files sorted, regardless of the crawl order', async () => {
+ const files = ['z/z.spec.ts', 'a/b/c.spec.ts', 'm.spec.ts', 'a/a.spec.ts', 'b/x/y.spec.ts'];
+ for (const file of files) {
+ const path = join(projectSourceRoot, file);
+ await fs.mkdir(join(path, '..'), { recursive: true });
+ await fs.writeFile(path, '');
+ }
+
+ const result = await findTests(['**/*.spec.ts'], [], projectSourceRoot, projectSourceRoot);
+
+ const expected = files.map((file) => toPosixPath(join(projectSourceRoot, file))).sort();
+ expect(result).toEqual(expected);
+ });
+});
describe('getTestEntrypoints', () => {
beforeAll(async () => {
diff --git a/packages/angular/build/src/builders/unit-test/tests/behavior/runner-config-vitest_spec.ts b/packages/angular/build/src/builders/unit-test/tests/behavior/runner-config-vitest_spec.ts
index 95107d1baec2..53039adf53e8 100644
--- a/packages/angular/build/src/builders/unit-test/tests/behavior/runner-config-vitest_spec.ts
+++ b/packages/angular/build/src/builders/unit-test/tests/behavior/runner-config-vitest_spec.ts
@@ -614,5 +614,43 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => {
const { result } = await harness.executeOnce();
expect(result?.success).toBeTrue();
});
+
+ it('should not serve stale cached modules across runs when an imported file changes', async () => {
+ harness.useTarget('test', {
+ ...BASE_OPTIONS,
+ runnerConfig: 'vitest.config.mts',
+ });
+
+ await harness.writeFiles({
+ 'vitest.config.mts': `
+ import { defineConfig } from 'vitest/config';
+ export default defineConfig({
+ test: {
+ fsModuleCache: true,
+ fsModuleCachePath: './.vitest-cache',
+ },
+ });
+ `,
+ 'src/app/value.ts': `export const VALUE = 'initial';`,
+ 'src/app/app.component.spec.ts': `
+ import { test, expect } from 'vitest';
+ import { VALUE } from './value';
+
+ test('should use the latest value from imported module', () => {
+ expect(VALUE).toBe('updated');
+ });
+ `,
+ });
+
+ const firstRun = await harness.executeOnce();
+ expect(firstRun.result?.success).toBeFalse();
+
+ // Update the imported application file without modifying the .spec.ts file on disk
+ await harness.writeFile('src/app/value.ts', `export const VALUE = 'updated';`);
+
+ const secondRun = await harness.executeOnce();
+ expect(secondRun.result?.success).toBeTrue();
+ harness.expectDirectory('.vitest-cache').toNotExist();
+ });
});
});
diff --git a/packages/angular/build/src/builders/unit-test/tests/behavior/watch_rebuild_spec.ts b/packages/angular/build/src/builders/unit-test/tests/behavior/watch_rebuild_spec.ts
index 6ff753c7eac7..cab5afd48a2c 100644
--- a/packages/angular/build/src/builders/unit-test/tests/behavior/watch_rebuild_spec.ts
+++ b/packages/angular/build/src/builders/unit-test/tests/behavior/watch_rebuild_spec.ts
@@ -28,11 +28,11 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => {
await harness.executeWithCases([
// 1. Initial success
- ({ result }) => {
+ async ({ result }) => {
expect(result?.success).toBeTrue();
// 2. Introduce compilation error
- harness.writeFiles({
+ await harness.writeFiles({
'src/app/app.component.spec.ts': `
import { describe, expect, test } from 'vitest'
describe('AppComponent', () => {
@@ -44,11 +44,11 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => {
});
},
// 3. Expect compilation error
- ({ result }) => {
+ async ({ result }) => {
expect(result?.success).toBeFalse();
// 4. Fix compilation error BUT introduce test failure
- harness.writeFiles({
+ await harness.writeFiles({
'src/app/app.component.spec.ts': `
import { describe, expect, test } from 'vitest'
describe('AppComponent', () => {
diff --git a/packages/angular/build/src/builders/unit-test/tests/options/include_spec.ts b/packages/angular/build/src/builders/unit-test/tests/options/include_spec.ts
index d3d4e19a30f9..4ba7c9eaa051 100644
--- a/packages/angular/build/src/builders/unit-test/tests/options/include_spec.ts
+++ b/packages/angular/build/src/builders/unit-test/tests/options/include_spec.ts
@@ -110,5 +110,172 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => {
const { result } = await harness.executeOnce();
expect(result?.success).toBeTrue();
});
+
+ it('should not compile unimported application files when testing standalone code', async () => {
+ await harness.writeFiles({
+ 'src/tsconfig.spec.json': JSON.stringify({
+ extends: '../tsconfig.json',
+ compilerOptions: {
+ outDir: '../out-tsc/spec',
+ types: ['jasmine', '@angular/localize'],
+ },
+ files: ['polyfills.ts'],
+ include: ['**/*.ts', '**/*.d.ts'],
+ }),
+ 'src/app/services/test.service.spec.ts': `
+ describe('TestService', () => {
+ it('should succeed', () => {
+ expect(true).toBe(true);
+ });
+ });`,
+ 'src/app/unused-broken.ts': `
+ // This unimported file has a TypeScript error and should not be compiled for standalone tests
+ export const invalidNumber: number = 'not a number';
+ `,
+ });
+
+ harness.useTarget('test', {
+ ...BASE_OPTIONS,
+ include: ['src/app/services/test.service.spec.ts'],
+ });
+
+ const { result } = await harness.executeOnce();
+ expect(result?.success).toBeTrue();
+ });
+
+ it('should resolve NgModule scope when testing a non-standalone component without importing the NgModule', async () => {
+ await harness.writeFiles({
+ 'src/tsconfig.spec.json': JSON.stringify({
+ extends: '../tsconfig.json',
+ compilerOptions: {
+ outDir: '../out-tsc/spec',
+ types: ['jasmine', '@angular/localize'],
+ },
+ files: ['polyfills.ts'],
+ include: ['**/*.ts', '**/*.d.ts'],
+ }),
+ 'src/app/app.ts': `
+ import { Component } from '@angular/core';
+
+ @Component({
+ selector: 'app-root',
+ template: 'Hello, {{ title }}
',
+ standalone: false,
+ })
+ export class App {
+ title = 'test';
+ }
+ `,
+ 'src/app/app-module.ts': `
+ import { NgModule } from '@angular/core';
+ import { BrowserModule } from '@angular/platform-browser';
+ import { RouterModule } from '@angular/router';
+ import { App } from './app';
+
+ @NgModule({
+ declarations: [App],
+ imports: [BrowserModule, RouterModule.forRoot([])],
+ bootstrap: [App],
+ })
+ export class AppModule {}
+ `,
+ 'src/app/app.spec.ts': `
+ import { TestBed } from '@angular/core/testing';
+ import { RouterModule } from '@angular/router';
+ import { App } from './app';
+
+ describe('App', () => {
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [RouterModule.forRoot([])],
+ declarations: [App],
+ }).compileComponents();
+ });
+
+ it('should create the app', () => {
+ const fixture = TestBed.createComponent(App);
+ expect(fixture.componentInstance).toBeTruthy();
+ });
+ });
+ `,
+ });
+
+ harness.useTarget('test', {
+ ...BASE_OPTIONS,
+ include: ['src/app/app.spec.ts'],
+ });
+
+ const { result } = await harness.executeOnce();
+ expect(result?.success).toBeTrue();
+ });
+
+ it('should not compile unimported files when a non-standalone component NgModule is imported by the test', async () => {
+ await harness.writeFiles({
+ 'src/tsconfig.spec.json': JSON.stringify({
+ extends: '../tsconfig.json',
+ compilerOptions: {
+ outDir: '../out-tsc/spec',
+ types: ['jasmine', '@angular/localize'],
+ },
+ files: ['polyfills.ts'],
+ include: ['**/*.ts', '**/*.d.ts'],
+ }),
+ 'src/app/app.ts': `
+ import { Component } from '@angular/core';
+
+ @Component({
+ selector: 'app-root',
+ template: 'Hello, {{ title }}
',
+ standalone: false,
+ })
+ export class App {
+ title = 'test';
+ }
+ `,
+ 'src/app/app-module.ts': `
+ import { NgModule } from '@angular/core';
+ import { BrowserModule } from '@angular/platform-browser';
+ import { RouterModule } from '@angular/router';
+ import { App } from './app';
+
+ @NgModule({
+ declarations: [App],
+ imports: [BrowserModule, RouterModule.forRoot([])],
+ bootstrap: [App],
+ })
+ export class AppModule {}
+ `,
+ 'src/app/app.spec.ts': `
+ import { TestBed } from '@angular/core/testing';
+ import { App } from './app';
+ import { AppModule } from './app-module';
+
+ describe('App', () => {
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [AppModule],
+ }).compileComponents();
+ });
+
+ it('should create the app', () => {
+ const fixture = TestBed.createComponent(App);
+ expect(fixture.componentInstance).toBeTruthy();
+ });
+ });
+ `,
+ 'src/app/unused-broken.ts': `
+ // This unimported file has a TypeScript error and should not be compiled when AppModule is already imported
+ export const invalidNumber: number = 'not a number';
+ `,
+ });
+
+ harness.useTarget('test', {
+ ...BASE_OPTIONS,
+ include: ['src/app/app.spec.ts'],
+ });
+
+ const { result } = await harness.executeOnce();
+ expect(result?.success).toBeTrue();
+ });
});
});
diff --git a/packages/angular/build/src/builders/unit-test/tests/options/watch_spec.ts b/packages/angular/build/src/builders/unit-test/tests/options/watch_spec.ts
index d1840beb4a96..79e25ca84b27 100644
--- a/packages/angular/build/src/builders/unit-test/tests/options/watch_spec.ts
+++ b/packages/angular/build/src/builders/unit-test/tests/options/watch_spec.ts
@@ -55,5 +55,38 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => {
},
]);
});
+
+ it('should disable the Vite server file watcher when watch is true', async () => {
+ harness.useTarget('test', {
+ ...BASE_OPTIONS,
+ watch: true,
+ runnerConfig: 'vitest.config.mts',
+ });
+
+ await harness.writeFile(
+ 'vitest.config.mts',
+ `
+ import { defineConfig } from 'vitest/config';
+ export default defineConfig({
+ plugins: [
+ {
+ name: 'assert-watch-disabled',
+ configureVitest({ vitest, project }) {
+ if (vitest.vite.config.server.watch !== null || project.vite.config.server.watch !== null) {
+ throw new Error('Expected Vite server.watch to be null');
+ }
+ },
+ },
+ ],
+ });
+ `,
+ );
+
+ await harness.executeWithCases([
+ ({ result }) => {
+ expect(result?.success).toBeTrue();
+ },
+ ]);
+ });
});
});
diff --git a/packages/angular/build/src/private.ts b/packages/angular/build/src/private.ts
index 9db709640b57..e95ad26af3fc 100644
--- a/packages/angular/build/src/private.ts
+++ b/packages/angular/build/src/private.ts
@@ -34,7 +34,6 @@ export {
// Tools
export type { ExternalResultMetadata } from './tools/esbuild/bundler-execution-result';
-export { emitFilesToDisk } from './tools/esbuild/utils';
export { transformSupportedBrowsersToTargets } from './tools/esbuild/target';
export { SassCompiler } from './tools/sass/sass-service';
@@ -73,6 +72,7 @@ export { ComponentStylesheetBundler } from './tools/esbuild/angular/component-st
export * from './utils/bundle-calculator';
export { checkPort } from './utils/check-port';
export { deleteOutputDir } from './utils/delete-output-dir';
+export { emitFilesToDisk } from './utils/disk-files';
export { type I18nOptions, createI18nOptions, loadTranslations } from './utils/i18n-options';
export {
IndexHtmlGenerator,
diff --git a/packages/angular/build/src/tools/angular/angular-host.ts b/packages/angular/build/src/tools/angular/angular-host.ts
index 9322b5683dc5..f30df5bab64d 100644
--- a/packages/angular/build/src/tools/angular/angular-host.ts
+++ b/packages/angular/build/src/tools/angular/angular-host.ts
@@ -35,7 +35,10 @@ export interface AngularHostOptions {
* field. The `version` field is required when used with a TypeScript BuilderProgram.
* @param program The TypeScript Program instance to patch.
*/
-export function ensureSourceFileVersions(program: ts.Program): void {
+export function ensureSourceFileVersions(
+ program: ts.Program,
+ previousProgram?: ts.BuilderProgram,
+): void {
const baseGetSourceFiles = program.getSourceFiles;
// TODO: Update Angular compiler to add versions to all internal files and remove this
program.getSourceFiles = function (...parameters) {
@@ -45,7 +48,11 @@ export function ensureSourceFileVersions(program: ts.Program): void {
for (const file of files) {
if (file.version === undefined) {
- file.version = calculateHash(file.text);
+ const previousFile: (ts.SourceFile & { version?: string }) | undefined =
+ previousProgram && !file.fileName.endsWith('.ngtypecheck.ts')
+ ? previousProgram.getSourceFile(file.fileName)
+ : undefined;
+ file.version = previousFile?.version ?? calculateHash(file.text);
}
}
diff --git a/packages/angular/build/src/tools/angular/compilation/angular-compilation.ts b/packages/angular/build/src/tools/angular/compilation/angular-compilation.ts
index d766680d1674..3da78cdf0275 100644
--- a/packages/angular/build/src/tools/angular/compilation/angular-compilation.ts
+++ b/packages/angular/build/src/tools/angular/compilation/angular-compilation.ts
@@ -23,6 +23,7 @@ export interface FileTransformResult {
export interface AngularCompilationOptions {
allowJs?: boolean;
+ compilationMode?: 'full' | 'partial' | 'experimental-local';
declarationMap?: boolean;
isolatedModules?: boolean;
sourceMap?: boolean;
diff --git a/packages/angular/build/src/tools/angular/compilation/angular-compilation_spec.ts b/packages/angular/build/src/tools/angular/compilation/angular-compilation_spec.ts
index 2d001dfeff7c..3c09b87f69d7 100644
--- a/packages/angular/build/src/tools/angular/compilation/angular-compilation_spec.ts
+++ b/packages/angular/build/src/tools/angular/compilation/angular-compilation_spec.ts
@@ -91,8 +91,12 @@ describe('AngularCompilation', () => {
return this.sourceFiles;
}
- public async testLoadConfiguration(tsconfig: string, overrides?: CompilerOptionOverrides) {
- return this.loadConfiguration(tsconfig, overrides);
+ public async testLoadConfiguration(
+ tsconfig: string,
+ overrides?: CompilerOptionOverrides,
+ buildType?: 'application' | 'library',
+ ) {
+ return this.loadConfiguration(tsconfig, overrides, buildType);
}
}
@@ -162,12 +166,83 @@ describe('AngularCompilation', () => {
jasmine.any(Map),
);
expect(result.rootNames).toEqual(['/src/main.ts']);
+ expect(result.fallbackRootNames).toBeUndefined();
expect(result.compilerOptions.target).toBe(ts.ScriptTarget.ES2022);
expect(result.compilerOptions.inlineSources).toBe(true);
expect(result.warnings.length).toBeGreaterThan(0);
expect(result.tsConfigFiles).toEqual(['tsconfig.json']);
});
+ it('filters rootNames to rootFiles while retaining ambient declaration files and setting fallbackRootNames', async () => {
+ const compilation = new MockTypeScriptCompilation();
+ const mockReadConfig = jasmine.createSpy('readConfiguration').and.returnValue({
+ options: { target: ts.ScriptTarget.ES2022 },
+ rootNames: [
+ '/src/app/included.spec.ts',
+ '/src/app/excluded.spec.ts',
+ '/src/app/app-module.ts',
+ '/src/env.d.ts',
+ '/src/types.d.mts',
+ '/src/legacy.d.cts',
+ ],
+ errors: [],
+ });
+ spyOn(TypeScriptCompilation, 'loadCompilerCli').and.resolveTo({
+ readConfiguration: mockReadConfig,
+ } as unknown as typeof import('@angular/compiler-cli'));
+
+ const result = await compilation.testLoadConfiguration('tsconfig.spec.json', {
+ rootFiles: ['/src/app/included.spec.ts'],
+ });
+
+ expect(result.rootNames).toEqual([
+ '/src/app/included.spec.ts',
+ '/src/env.d.ts',
+ '/src/types.d.mts',
+ '/src/legacy.d.cts',
+ ]);
+ expect(result.fallbackRootNames).toEqual([
+ '/src/app/included.spec.ts',
+ '/src/app/excluded.spec.ts',
+ '/src/app/app-module.ts',
+ '/src/env.d.ts',
+ '/src/types.d.mts',
+ '/src/legacy.d.cts',
+ ]);
+ });
+
+ it('omits fallbackRootNames when buildType is "library" or when rootFiles covers all tsconfig files', async () => {
+ const compilation = new MockTypeScriptCompilation();
+ const mockReadConfig = jasmine.createSpy('readConfiguration').and.returnValue({
+ options: { target: ts.ScriptTarget.ES2022 },
+ rootNames: ['/src/public-api.ts', '/src/internal.ts', '/src/env.d.ts'],
+ errors: [],
+ });
+ spyOn(TypeScriptCompilation, 'loadCompilerCli').and.resolveTo({
+ readConfiguration: mockReadConfig,
+ } as unknown as typeof import('@angular/compiler-cli'));
+
+ const libraryResult = await compilation.testLoadConfiguration(
+ 'tsconfig.lib.json',
+ { rootFiles: ['/src/public-api.ts'] },
+ 'library',
+ );
+ expect(libraryResult.rootNames).toEqual(['/src/public-api.ts', '/src/env.d.ts']);
+ expect(libraryResult.fallbackRootNames).toBeUndefined();
+
+ const fullSetResult = await compilation.testLoadConfiguration(
+ 'tsconfig.app.json',
+ { rootFiles: ['/src/public-api.ts', '/src/internal.ts'] },
+ 'application',
+ );
+ expect(fullSetResult.rootNames).toEqual([
+ '/src/public-api.ts',
+ '/src/internal.ts',
+ '/src/env.d.ts',
+ ]);
+ expect(fullSetResult.fallbackRootNames).toBeUndefined();
+ });
+
it('passes extendedConfigCache to readConfiguration and invalidates entries on config change', async () => {
const compilation = new MockTypeScriptCompilation();
let passedCache: Map | undefined;
diff --git a/packages/angular/build/src/tools/angular/compilation/aot-compilation.ts b/packages/angular/build/src/tools/angular/compilation/aot-compilation.ts
index 6f45199d1421..4ca1480f646c 100644
--- a/packages/angular/build/src/tools/angular/compilation/aot-compilation.ts
+++ b/packages/angular/build/src/tools/angular/compilation/aot-compilation.ts
@@ -37,16 +37,42 @@ import { printSourceFileWithMap } from './typescript-printer';
*/
const HMR_MODIFIED_FILE_LIMIT = 32;
+/**
+ * Extension for Angular type-checking files.
+ */
+const TTC_EXTENSION = '.ngtypecheck.ts';
+
+/**
+ * Length of the `.ngtypecheck.ts` extension.
+ */
+const TTC_EXTENSION_LENGTH = TTC_EXTENSION.length;
+
+/**
+ * Checks if a file is an Angular type-checking shim file.
+ */
+function isNgTypeCheckFile(fileName: string): boolean {
+ return fileName.endsWith(TTC_EXTENSION);
+}
+
+/**
+ * Returns the original filename for a type-checking shim file.
+ */
+function getOriginalFilename(fileName: string): string {
+ return fileName.slice(0, -TTC_EXTENSION_LENGTH) + '.ts';
+}
+
class AngularCompilationState {
constructor(
public readonly angularProgram: ng.NgtscProgram,
public readonly compilerHost: ng.CompilerHost,
- public readonly typeScriptProgram: ts.EmitAndSemanticDiagnosticsBuilderProgram,
+ public typeScriptProgram: ts.EmitAndSemanticDiagnosticsBuilderProgram,
public readonly affectedFiles: ReadonlySet,
public readonly templateDiagnosticsOptimization: ng.OptimizeFor,
public readonly webWorkerTransform: ts.TransformerFactory,
public readonly useTypeScriptTranspilation: boolean,
public readonly diagnosticCache = new WeakMap(),
+ public readonly filesWithoutDtsSignature = new Set(),
+ public readonly useFallbackRootNames = false,
) {}
get angularCompiler() {
@@ -75,6 +101,7 @@ export class AotCompilation extends TypeScriptCompilation {
const {
compilerOptions,
rootNames,
+ fallbackRootNames,
errors: configurationDiagnostics,
warnings,
tsConfigFiles,
@@ -103,8 +130,8 @@ export class AotCompilation extends TypeScriptCompilation {
if (hostOptions.modifiedFiles) {
this.invalidateFiles(hostOptions.modifiedFiles);
- for (const modifiedFile of hostOptions.modifiedFiles) {
- if (this.#state) {
+ if (this.#state && hostOptions.modifiedFiles.size > 0) {
+ for (const modifiedFile of hostOptions.modifiedFiles) {
// Clear package.json cache if a node modules file was modified
if (!clearPackageJsonCache && modifiedFile.includes('node_modules')) {
clearPackageJsonCache = true;
@@ -120,6 +147,14 @@ export class AotCompilation extends TypeScriptCompilation {
}
}
}
+
+ if (useTypeChecking || useTypeScriptTranspilation) {
+ populatePreviousDtsSignatures(
+ this.#state.typeScriptProgram,
+ hostOptions.modifiedFiles,
+ this.#state.filesWithoutDtsSignature,
+ );
+ }
}
}
@@ -132,13 +167,48 @@ export class AotCompilation extends TypeScriptCompilation {
this.sourceFiles,
);
+ // If a previous watch rebuild already fell back to the full tsconfig root file set,
+ // start directly with fallbackRootNames to avoid repeating the two-step check.
+ let useFallbackRootNames = this.#state?.useFallbackRootNames ?? false;
+
// Create the Angular specific program that contains the Angular compiler
- const angularProgram = profileSync(
+ let angularProgram = profileSync(
'NG_CREATE_PROGRAM',
- () => new NgtscProgram(rootNames, compilerOptions, host, this.#state?.angularProgram),
+ () =>
+ new NgtscProgram(
+ (useFallbackRootNames && fallbackRootNames) || rootNames,
+ compilerOptions,
+ host,
+ this.#state?.angularProgram,
+ ),
);
- const angularCompiler = angularProgram.compiler;
- const angularTypeScriptProgram = angularProgram.getTsProgram();
+ let angularCompiler = angularProgram.compiler;
+
+ await profileAsync('NG_ANALYZE_PROGRAM', () => angularCompiler.analyzeAsync());
+
+ let angularTypeScriptProgram = angularProgram.getTsProgram();
+
+ // When rootFiles filtering is active and a non-standalone component without a resolved
+ // NgModule scope is encountered, its declaring NgModule may not be directly imported by
+ // the test entry points. Fall back to the full tsconfig root file set if it contains
+ // additional uncompiled files so the Angular compiler can discover all NgModules and
+ // resolve component compilation scopes.
+ if (
+ !useFallbackRootNames &&
+ fallbackRootNames?.some((file) => !angularTypeScriptProgram.getSourceFile(file)) &&
+ hasUnscopedComponent(angularCompiler)
+ ) {
+ useFallbackRootNames = true;
+ angularProgram = profileSync(
+ 'NG_CREATE_PROGRAM_FALLBACK',
+ () => new NgtscProgram(fallbackRootNames, compilerOptions, host, angularProgram),
+ );
+ angularCompiler = angularProgram.compiler;
+
+ await profileAsync('NG_ANALYZE_PROGRAM_FALLBACK', () => angularCompiler.analyzeAsync());
+ angularTypeScriptProgram = angularProgram.getTsProgram();
+ }
+
ensureSourceFileVersions(angularTypeScriptProgram);
let oldProgram = this.#state?.typeScriptProgram;
@@ -155,7 +225,17 @@ export class AotCompilation extends TypeScriptCompilation {
configurationDiagnostics,
);
- await profileAsync('NG_ANALYZE_PROGRAM', () => angularCompiler.analyzeAsync());
+ const filesWithoutDtsSignature = this.#state?.filesWithoutDtsSignature ?? new Set();
+ if (!this.#state) {
+ for (const sourceFile of typeScriptProgram.getSourceFiles()) {
+ if (
+ !sourceFile.isDeclarationFile &&
+ !angularCompiler.ignoreForDiagnostics.has(sourceFile)
+ ) {
+ filesWithoutDtsSignature.add(sourceFile.fileName);
+ }
+ }
+ }
let templateUpdates;
if (useHmr && hostOptions.modifiedFiles && this.#state) {
@@ -203,38 +283,62 @@ export class AotCompilation extends TypeScriptCompilation {
const affectedFiles =
useTypeChecking || useTypeScriptTranspilation
? profileSync('NG_FIND_AFFECTED', () =>
- findAffectedFiles(typeScriptProgram, angularCompiler, usingBuildInfo),
+ findAffectedFiles(
+ typeScriptProgram,
+ angularCompiler,
+ usingBuildInfo,
+ this.#state?.typeScriptProgram,
+ filesWithoutDtsSignature,
+ ),
)
: new Set();
const componentResourcesDependencies = new Map();
// Get all files referenced in the TypeScript/Angular program including component resources
- const referencedFiles = [
- ...tsConfigFiles,
- ...typeScriptProgram
- .getSourceFiles()
- .filter((sourceFile) => !angularCompiler.ignoreForEmit.has(sourceFile))
- .flatMap((sourceFile) => {
- const resourceDependencies = angularCompiler.getResourceDependencies(sourceFile);
- componentResourcesDependencies.set(sourceFile.fileName, resourceDependencies);
- // Also invalidate Angular diagnostics for a source file if component resources are modified
- if (this.#state && hostOptions.modifiedFiles?.size) {
- for (const resourceDependency of resourceDependencies) {
- if (
- hostOptions.modifiedFiles.has(resourceDependency) &&
- !/\.(?:css|scss|sass|less)$/i.test(resourceDependency)
- ) {
- this.#state.diagnosticCache.delete(sourceFile);
- // Also mark as affected in case changed template affects diagnostics
- affectedFiles.add(sourceFile);
- }
- }
+ const referencedFiles = [...tsConfigFiles];
+ for (const sourceFile of typeScriptProgram.getSourceFiles()) {
+ if (angularCompiler.ignoreForEmit.has(sourceFile)) {
+ continue;
+ }
+
+ referencedFiles.push(sourceFile.fileName);
+ if (sourceFile.isDeclarationFile) {
+ continue;
+ }
+
+ const resourceDependencies = angularCompiler.getResourceDependencies(sourceFile);
+ componentResourcesDependencies.set(sourceFile.fileName, resourceDependencies);
+
+ if (resourceDependencies.length === 0) {
+ continue;
+ }
+
+ referencedFiles.push(...resourceDependencies);
+
+ // Also invalidate Angular diagnostics for a source file if component resources are modified
+ if (this.#state && hostOptions.modifiedFiles?.size) {
+ for (const resourceDependency of resourceDependencies) {
+ if (
+ !hostOptions.modifiedFiles.has(resourceDependency) ||
+ /\.(?:css|scss|sass|less)$/i.test(resourceDependency)
+ ) {
+ continue;
+ }
+
+ this.#state.diagnosticCache.delete(sourceFile);
+
+ const oldSourceFile = this.#state.typeScriptProgram.getSourceFile(sourceFile.fileName);
+ if (oldSourceFile) {
+ this.#state.diagnosticCache.delete(oldSourceFile);
}
- return [sourceFile.fileName, ...resourceDependencies];
- }),
- ];
+ // Also mark as affected in case changed template affects diagnostics
+ affectedFiles.add(sourceFile);
+ break;
+ }
+ }
+ }
this.#state = new AngularCompilationState(
angularProgram,
@@ -245,6 +349,8 @@ export class AotCompilation extends TypeScriptCompilation {
createWorkerTransformer(hostOptions.processWebWorker.bind(hostOptions)),
useTypeScriptTranspilation,
this.#state?.diagnosticCache,
+ filesWithoutDtsSignature,
+ useFallbackRootNames,
);
return {
@@ -270,61 +376,92 @@ export class AotCompilation extends TypeScriptCompilation {
const syntactic = modes & DiagnosticModes.Syntactic;
const semantic = modes & DiagnosticModes.Semantic;
- // Collect program level diagnostics
- if (modes & DiagnosticModes.Option) {
- yield* typeScriptProgram.getConfigFileParsingDiagnostics();
- yield* angularCompiler.getOptionDiagnostics();
- yield* typeScriptProgram.getOptionsDiagnostics();
- }
- if (syntactic) {
- yield* typeScriptProgram.getGlobalDiagnostics();
- }
-
- // Collect source file specific diagnostics
- for (const sourceFile of typeScriptProgram.getSourceFiles()) {
- if (angularCompiler.ignoreForDiagnostics.has(sourceFile)) {
- continue;
+ try {
+ // Collect program level diagnostics
+ if (modes & DiagnosticModes.Option) {
+ yield* typeScriptProgram.getConfigFileParsingDiagnostics();
+ yield* angularCompiler.getOptionDiagnostics();
+ yield* typeScriptProgram.getOptionsDiagnostics();
}
-
if (syntactic) {
- // TypeScript will use cached diagnostics for files that have not been
- // changed or affected for this build when using incremental building.
- yield* profileSync(
- 'NG_DIAGNOSTICS_SYNTACTIC',
- () => typeScriptProgram.getSyntacticDiagnostics(sourceFile),
- true,
- );
+ yield* typeScriptProgram.getGlobalDiagnostics();
}
- if (!semantic) {
- continue;
- }
+ // Collect source file specific diagnostics
+ for (const sourceFile of typeScriptProgram.getSourceFiles()) {
+ if (angularCompiler.ignoreForDiagnostics.has(sourceFile)) {
+ continue;
+ }
- yield* profileSync(
- 'NG_DIAGNOSTICS_SEMANTIC',
- () => typeScriptProgram.getSemanticDiagnostics(sourceFile),
- true,
- );
+ if (syntactic) {
+ // TypeScript will use cached diagnostics for files that have not been
+ // changed or affected for this build when using incremental building.
+ yield* profileSync(
+ 'NG_DIAGNOSTICS_SYNTACTIC',
+ () => typeScriptProgram.getSyntacticDiagnostics(sourceFile),
+ true,
+ );
+ }
- // Declaration files cannot have template diagnostics
- if (sourceFile.isDeclarationFile) {
- continue;
- }
+ if (!semantic) {
+ continue;
+ }
- // Only request Angular template diagnostics for affected files to avoid
- // overhead of template diagnostics for unchanged files.
- if (affectedFiles.has(sourceFile)) {
- const angularDiagnostics = profileSync(
- 'NG_DIAGNOSTICS_TEMPLATE',
- () => angularCompiler.getDiagnosticsForFile(sourceFile, templateDiagnosticsOptimization),
+ yield* profileSync(
+ 'NG_DIAGNOSTICS_SEMANTIC',
+ () => typeScriptProgram.getSemanticDiagnostics(sourceFile),
true,
);
- diagnosticCache.set(sourceFile, angularDiagnostics);
- yield* angularDiagnostics;
- } else {
- const angularDiagnostics = diagnosticCache.get(sourceFile);
- if (angularDiagnostics) {
+
+ // Declaration files cannot have template diagnostics
+ if (sourceFile.isDeclarationFile) {
+ continue;
+ }
+
+ // Only request Angular template diagnostics for affected files to avoid
+ // overhead of template diagnostics for unchanged files.
+ if (affectedFiles.has(sourceFile)) {
+ const angularDiagnostics = profileSync(
+ 'NG_DIAGNOSTICS_TEMPLATE',
+ () =>
+ angularCompiler.getDiagnosticsForFile(sourceFile, templateDiagnosticsOptimization),
+ true,
+ );
+ diagnosticCache.set(sourceFile, angularDiagnostics);
yield* angularDiagnostics;
+ } else {
+ const angularDiagnostics = diagnosticCache.get(sourceFile);
+ if (angularDiagnostics) {
+ yield* angularDiagnostics;
+ }
+ }
+ }
+ } finally {
+ // Angular's template typechecker lazily creates `.ngtypecheck.ts` shims in a new `ts.Program`
+ // during `getDiagnosticsForFile`. Sync the builder program with `angularCompiler.getCurrentProgram()`
+ // so the next incremental build does not treat all `.ngtypecheck.ts` files as newly added files.
+ const currentTsProgram = angularCompiler.getCurrentProgram();
+ if (currentTsProgram !== typeScriptProgram.getProgram()) {
+ ensureSourceFileVersions(currentTsProgram, typeScriptProgram);
+ this.#state.typeScriptProgram = ts.createEmitAndSemanticDiagnosticsBuilderProgram(
+ currentTsProgram,
+ this.#state.compilerHost,
+ typeScriptProgram,
+ );
+
+ const baseEmit = currentTsProgram.emit;
+ currentTsProgram.emit = () => ({ emitSkipped: true, diagnostics: [] });
+ try {
+ while (
+ this.#state.typeScriptProgram.getSemanticDiagnosticsOfNextAffectedFile(
+ undefined,
+ () => true,
+ )
+ ) {
+ /* empty */
+ }
+ } finally {
+ currentTsProgram.emit = baseEmit;
}
}
}
@@ -419,7 +556,7 @@ export class AotCompilation extends TypeScriptCompilation {
if (
angularCompiler.incrementalCompilation.safeToSkipEmit(sourceFile) &&
- !affectedFiles.has(sourceFile)
+ (!useTypeScriptTranspilation || !affectedFiles.has(sourceFile))
) {
continue;
}
@@ -483,40 +620,138 @@ export class AotCompilation extends TypeScriptCompilation {
function findAffectedFiles(
builder: ts.EmitAndSemanticDiagnosticsBuilderProgram,
- { ignoreForDiagnostics }: ng.NgtscProgram['compiler'],
+ { ignoreForDiagnostics, incrementalCompilation }: ng.NgtscProgram['compiler'],
includeTTC: boolean,
+ oldBuilder: ts.EmitAndSemanticDiagnosticsBuilderProgram | undefined,
+ filesWithoutDtsSignature: Set,
): Set {
const affectedFiles = new Set();
- // eslint-disable-next-line no-constant-condition
- while (true) {
- const result = builder.getSemanticDiagnosticsOfNextAffectedFile(undefined, (sourceFile) => {
- // If the affected file is a TTC shim, add the shim's original source file.
- // This ensures that changes that affect TTC are typechecked even when the changes
- // are otherwise unrelated from a TS perspective and do not result in Ivy codegen changes.
- // For example, changing @Input property types of a directive used in another component's
- // template.
- // A TTC shim is a file that has been ignored for diagnostics and has a filename ending in `.ngtypecheck.ts`.
- if (ignoreForDiagnostics.has(sourceFile) && sourceFile.fileName.endsWith('.ngtypecheck.ts')) {
- // This file name conversion relies on internal compiler logic and should be converted
- // to an official method when available. 15 is length of `.ngtypecheck.ts`
- const originalFilename = sourceFile.fileName.slice(0, -15) + '.ts';
- const originalSourceFile = builder.getSourceFile(originalFilename);
- if (originalSourceFile) {
- affectedFiles.add(originalSourceFile);
+ // Temporarily disable `isolatedModules` and `verbatimModuleSyntax` while walking affected
+ // files so TypeScript's `getFilesAffectedByUpdatedShapeWhenModuleEmit` yields dependent
+ // `.ngtypecheck.ts` shims to the `ignoreSourceFile` callback when a file's `.d.ts` shape
+ // changes, instead of returning only the modified file itself.
+ const compilerOptions = builder.getCompilerOptions();
+ const prevIsolatedModules = compilerOptions.isolatedModules;
+ const prevVerbatimModuleSyntax = compilerOptions.verbatimModuleSyntax;
+ compilerOptions.isolatedModules = false;
+ compilerOptions.verbatimModuleSyntax = false;
+
+ const program = builder.getProgram();
+ const baseEmit = program.emit;
+ const oldProgram = oldBuilder?.getProgram();
+ program.emit = (
+ targetSourceFile,
+ writeFile,
+ cancellationToken,
+ emitOnly,
+ customTransformers,
+ ...rest
+ ) => {
+ if (targetSourceFile) {
+ if (isNgTypeCheckFile(targetSourceFile.fileName)) {
+ return { emitSkipped: true, diagnostics: [] };
+ }
+
+ if (oldProgram && filesWithoutDtsSignature.has(targetSourceFile.fileName)) {
+ const oldSourceFile = oldProgram.getSourceFile(targetSourceFile.fileName);
+ if (oldSourceFile) {
+ let oldDtsText: string | undefined;
+ let oldHasDiagnostics = false;
+ oldProgram.emit(
+ oldSourceFile,
+ (_fileName, text, _bom, _onError, _sourceFiles, data) => {
+ oldDtsText = text;
+ oldHasDiagnostics = !!(data as { diagnostics?: unknown[] } | undefined)?.diagnostics
+ ?.length;
+ },
+ cancellationToken,
+ emitOnly,
+ customTransformers,
+ ...(rest as []),
+ );
+
+ return baseEmit.call(
+ program,
+ targetSourceFile,
+ (fileName, text, writeByteOrderMark, onError, sourceFiles, data) => {
+ const newHasDiagnostics = !!(data as { diagnostics?: unknown[] } | undefined)
+ ?.diagnostics?.length;
+ if (text !== oldDtsText || newHasDiagnostics !== oldHasDiagnostics) {
+ filesWithoutDtsSignature.delete(targetSourceFile.fileName);
+ writeFile?.(fileName, text, writeByteOrderMark, onError, sourceFiles, data);
+ }
+ },
+ cancellationToken,
+ emitOnly,
+ customTransformers,
+ ...(rest as []),
+ );
}
- return true;
+ filesWithoutDtsSignature.delete(targetSourceFile.fileName);
}
+ }
- return false;
- });
+ return baseEmit.call(
+ program,
+ targetSourceFile,
+ writeFile,
+ cancellationToken,
+ emitOnly,
+ customTransformers,
+ ...(rest as []),
+ );
+ };
+
+ try {
+ while (
+ builder.getSemanticDiagnosticsOfNextAffectedFile(undefined, (sourceFile) => {
+ if (ignoreForDiagnostics.has(sourceFile)) {
+ // If the affected file is a TTC shim, add the shim's original source file.
+ // This ensures that changes that affect TTC are typechecked even when the changes
+ // are otherwise unrelated from a TS perspective and do not result in Ivy codegen changes.
+ // For example, changing @Input property types of a directive used in another component's
+ // template.
+ // A TTC shim is a file that has been ignored for diagnostics and has a filename ending in `.ngtypecheck.ts`.
+ if (isNgTypeCheckFile(sourceFile.fileName)) {
+ // This file name conversion relies on internal compiler logic and should be converted
+ // to an official method when available. 15 is length of `.ngtypecheck.ts`
+ const originalFilename = getOriginalFilename(sourceFile.fileName);
+ const originalSourceFile = builder.getSourceFile(originalFilename);
+ if (originalSourceFile) {
+ affectedFiles.add(originalSourceFile);
+ }
+ }
+ } else {
+ affectedFiles.add(sourceFile);
+ }
+
+ return true;
+ })
+ ) {
+ /* empty */
+ }
+ } finally {
+ program.emit = baseEmit;
+ compilerOptions.isolatedModules = prevIsolatedModules;
+ compilerOptions.verbatimModuleSyntax = prevVerbatimModuleSyntax;
+ }
- if (!result) {
- break;
+ // Also include files identified by Angular's incremental compilation graph as needing
+ // re-emission or template re-typechecking (such as selector renames or required input changes
+ // that only affect Angular metadata without altering standard TypeScript `.d.ts` signatures).
+ for (const sourceFile of builder.getSourceFiles()) {
+ if (sourceFile.isDeclarationFile || ignoreForDiagnostics.has(sourceFile)) {
+ continue;
}
- affectedFiles.add(result.affected as ts.SourceFile);
+ if (
+ !incrementalCompilation.safeToSkipEmit(sourceFile) ||
+ incrementalCompilation.priorTypeCheckingResultsFor(sourceFile) === null
+ ) {
+ affectedFiles.add(sourceFile);
+ }
}
// Add all files with associated template type checking files.
@@ -525,10 +760,10 @@ function findAffectedFiles(
// info is present.
if (includeTTC) {
for (const sourceFile of builder.getSourceFiles()) {
- if (ignoreForDiagnostics.has(sourceFile) && sourceFile.fileName.endsWith('.ngtypecheck.ts')) {
+ if (ignoreForDiagnostics.has(sourceFile) && isNgTypeCheckFile(sourceFile.fileName)) {
// This file name conversion relies on internal compiler logic and should be converted
// to an official method when available. 15 is length of `.ngtypecheck.ts`
- const originalFilename = sourceFile.fileName.slice(0, -15) + '.ts';
+ const originalFilename = getOriginalFilename(sourceFile.fileName);
const originalSourceFile = builder.getSourceFile(originalFilename);
if (originalSourceFile) {
affectedFiles.add(originalSourceFile);
@@ -539,3 +774,129 @@ function findAffectedFiles(
return affectedFiles;
}
+
+/**
+ * Ensures `.d.ts` shape signatures are computed on the previous `BuilderProgram` for modified
+ * files before the next `BuilderProgram` is created.
+ *
+ * On the initial build (`oldProgram === undefined`), TypeScript initializes each file's shape
+ * signature to its `.ts` source version hash rather than emitting `.d.ts` declarations for every
+ * file. When a file is modified on a watch rebuild, TypeScript computes its new `.d.ts` signature
+ * and compares it against the previous program's stored signature. Emitting the `.d.ts` signature
+ * on `oldProgram` for the modified file replaces its initial `.ts` version hash with its true
+ * `.d.ts` signature prior to diffing, avoiding false-positive `.d.ts` cascades across importers.
+ */
+function populatePreviousDtsSignatures(
+ oldProgram: ts.EmitAndSemanticDiagnosticsBuilderProgram,
+ modifiedFiles: ReadonlySet,
+ filesWithoutDtsSignature: Set,
+): void {
+ const filesToUpdate: ts.SourceFile[] = [];
+ for (const modifiedFile of modifiedFiles) {
+ const sf = oldProgram.getSourceFile(modifiedFile);
+ if (sf && !sf.isDeclarationFile && filesWithoutDtsSignature.delete(sf.fileName)) {
+ filesToUpdate.push(sf);
+ }
+ }
+
+ if (filesToUpdate.length === 0) {
+ return;
+ }
+
+ const compilerOptions = oldProgram.getCompilerOptions();
+ const prevDeclaration = compilerOptions.declaration;
+ const prevComposite = compilerOptions.composite;
+ const prevNoEmit = compilerOptions.noEmit;
+ const prevNoEmitOnError = compilerOptions.noEmitOnError;
+
+ compilerOptions.declaration = true;
+ compilerOptions.composite = false;
+ compilerOptions.noEmit = false;
+ compilerOptions.noEmitOnError = false;
+
+ const program = oldProgram.getProgram();
+ const baseEmit = program.emit as (
+ targetSourceFile?: ts.SourceFile,
+ writeFile?: ts.WriteFileCallback,
+ cancellationToken?: ts.CancellationToken,
+ emitOnlyDtsFiles?: boolean | number,
+ customTransformers?: ts.CustomTransformers,
+ forceDtsEmit?: boolean,
+ ) => ts.EmitResult;
+ program.emit = (targetSourceFile, writeFile, cancellationToken) =>
+ baseEmit.call(
+ program,
+ targetSourceFile,
+ writeFile,
+ cancellationToken,
+ 2, // ts.EmitOnly.BuilderSignature
+ undefined,
+ true, // forceDtsEmit
+ );
+
+ try {
+ for (const sf of filesToUpdate) {
+ oldProgram.emit(sf, () => {}, undefined, true);
+ }
+ } finally {
+ program.emit = baseEmit;
+ compilerOptions.declaration = prevDeclaration;
+ compilerOptions.composite = prevComposite;
+ compilerOptions.noEmit = prevNoEmit;
+ compilerOptions.noEmitOnError = prevNoEmitOnError;
+ }
+}
+
+/**
+ * Checks whether the analyzed Angular program contains any non-standalone `@Component`
+ * declarations in user source files that lack an owning `NgModule` scope.
+ */
+function hasUnscopedComponent(angularCompiler: ng.NgCompiler): boolean {
+ // `incrementalCompilation.state` is typed as the `IncrementalState` union
+ // (`AnalyzedIncrementalState | DeltaIncrementalState | FreshIncrementalState`), where only
+ // `AnalyzedIncrementalState` (populated once `analyzeAsync()` completes) contains
+ // `priorAnalysis`. Because the `IncrementalStateKind` discriminant enum is not re-exported
+ // from `@angular/compiler-cli`, narrow the union via `'priorAnalysis' in state`.
+ const state = angularCompiler.incrementalCompilation.state;
+ if (!('priorAnalysis' in state)) {
+ return false;
+ }
+
+ let templateTypeChecker: ReturnType | undefined;
+
+ for (const [sourceFile, records] of state.priorAnalysis) {
+ if (records.length === 0 || angularCompiler.ignoreForEmit.has(sourceFile)) {
+ continue;
+ }
+
+ for (const { node } of records) {
+ if (!ts.isClassDeclaration(node)) {
+ continue;
+ }
+
+ const meta = angularCompiler.getMeta(node);
+ if (meta && 'isComponent' in meta && meta.isComponent && !meta.isStandalone) {
+ if (!templateTypeChecker) {
+ // `NgtscProgram` initializes `NgCompiler` with `enableTemplateTypeChecker = false`, which
+ // guards the public `getTemplateTypeChecker()` getter. Temporarily enable the flag after
+ // `analyzeAsync()` has already constructed `TemplateTypeCheckerImpl` so we can query
+ // `getOwningNgModule()` without altering `typeCheckingConfig.enableTemplateTypeChecker`.
+ const compiler = angularCompiler as { enableTemplateTypeChecker: boolean };
+ const previous = compiler.enableTemplateTypeChecker;
+ try {
+ compiler.enableTemplateTypeChecker = true;
+ templateTypeChecker = angularCompiler.getTemplateTypeChecker();
+ } finally {
+ compiler.enableTemplateTypeChecker = previous;
+ }
+ }
+
+ if (templateTypeChecker.getOwningNgModule(node) === null) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
diff --git a/packages/angular/build/src/tools/angular/compilation/compiler-options.ts b/packages/angular/build/src/tools/angular/compilation/compiler-options.ts
index 1720a8bb0516..b2c83d616f08 100644
--- a/packages/angular/build/src/tools/angular/compilation/compiler-options.ts
+++ b/packages/angular/build/src/tools/angular/compilation/compiler-options.ts
@@ -71,6 +71,8 @@ export function transformCompilerOptions(
compilerOptions.compilationMode = 'full';
} else if (overrides?.compilationMode) {
compilerOptions.compilationMode = overrides.compilationMode;
+ } else if (isLibrary) {
+ compilerOptions.compilationMode ??= 'partial';
}
// Enable incremental compilation by default if caching is enabled and incremental is not explicitly disabled
@@ -114,7 +116,9 @@ export function transformCompilerOptions(
compilerOptions.moduleResolution = typeScript.ModuleResolutionKind.Bundler;
compilerOptions.importHelpers = true;
compilerOptions.declaration = true;
- compilerOptions.declarationMap = overrides?.declarationMap;
+ compilerOptions.declarationMap = !!(
+ overrides?.declarationMap ?? compilerOptions.declarationMap
+ );
compilerOptions.declarationDir = undefined;
}
diff --git a/packages/angular/build/src/tools/angular/compilation/parallel-worker.ts b/packages/angular/build/src/tools/angular/compilation/parallel-worker.ts
index a74c032a1b70..475592bd478b 100644
--- a/packages/angular/build/src/tools/angular/compilation/parallel-worker.ts
+++ b/packages/angular/build/src/tools/angular/compilation/parallel-worker.ts
@@ -125,6 +125,7 @@ export async function initialize(request: InitRequest): Promise canonicalizePath(toPosixPath(file))),
);
+ const fallbackFilesSet = new Set(rootFilesSet);
for (const file of originalRootNames) {
+ const canonicalFile = canonicalizePath(toPosixPath(file));
+ // Ambient declaration files (.d.ts) are not imported directly, so they must always be
+ // retained from the tsconfig to preserve global type definitions.
if (/\.d\.[cm]?ts$/i.test(file)) {
- rootFilesSet.add(canonicalizePath(toPosixPath(file)));
+ rootFilesSet.add(canonicalFile);
}
+ fallbackFilesSet.add(canonicalFile);
}
rootNames = [...rootFilesSet];
+ // For application builds (including unit tests), preserve the full set of tsconfig root
+ // files as a fallback in case the AOT compilation encounters a non-standalone component
+ // whose declaring NgModule is not directly imported by the entry points. Note that when a
+ // test tsconfig uses broad globs (e.g., `src/**/*.ts`), this fallback set will also include
+ // non-included spec files; this is an acceptable trade-off to keep compilation agnostic of
+ // test-file naming conventions and only occurs for legacy non-standalone components lacking
+ // explicit NgModule imports. Library builds are excluded because all public NgModules must
+ // be reachable from the library entry points and should never resolve compilation scope from
+ // unexported tsconfig files.
+ if (buildType === 'application' && fallbackFilesSet.size > rootFilesSet.size) {
+ fallbackRootNames = [...fallbackFilesSet];
+ }
}
const { compilerOptions, warnings } = transformCompilerOptions(
@@ -94,6 +120,7 @@ export abstract class TypeScriptCompilation extends AngularCompilation {
return {
compilerOptions,
rootNames,
+ fallbackRootNames,
errors,
warnings,
tsConfigFiles,
diff --git a/packages/angular/build/src/tools/esbuild/bundler-context.ts b/packages/angular/build/src/tools/esbuild/bundler-context.ts
index a4228caa5782..202ab514cbfe 100644
--- a/packages/angular/build/src/tools/esbuild/bundler-context.ts
+++ b/packages/angular/build/src/tools/esbuild/bundler-context.ts
@@ -328,7 +328,11 @@ export class BundlerContext {
const initialFiles = new Map();
for (const outputFile of result.outputFiles) {
// Entries in the metafile are relative to the `absWorkingDir` option which is set to the workspaceRoot
- const relativeFilePath = relative(this.workspaceRoot, outputFile.path);
+ // `outputFile.path` may already be relative if the `OutputFile` instance was cached in `additionalResults`
+ // across an incremental rebuild.
+ const relativeFilePath = isAbsolute(outputFile.path)
+ ? relative(this.workspaceRoot, outputFile.path)
+ : outputFile.path;
const entryPoint = result.metafile.outputs[relativeFilePath]?.entryPoint;
outputFile.path = relativeFilePath;
diff --git a/packages/angular/build/src/tools/esbuild/persistent-load-result-cache.ts b/packages/angular/build/src/tools/esbuild/persistent-load-result-cache.ts
index c5dcee90ccf9..7eaf11806f1d 100644
--- a/packages/angular/build/src/tools/esbuild/persistent-load-result-cache.ts
+++ b/packages/angular/build/src/tools/esbuild/persistent-load-result-cache.ts
@@ -32,7 +32,7 @@ import { readFile, stat } from 'node:fs/promises';
import { isAbsolute } from 'node:path';
import { fileURLToPath } from 'node:url';
import type { Cache as PersistentCacheStore } from '../../utils/cache';
-import { mapConcurrent, runConcurrent } from '../../utils/concurrency';
+import { MAX_CONCURRENT_READS, mapConcurrent, runConcurrent } from '../../utils/concurrency';
import { calculateHash, createContentHash } from '../../utils/hash';
import { LoadResultCache, MemoryLoadResultCache } from './load-result-cache';
@@ -112,9 +112,6 @@ export function extractDiskFilePath(path: string): string | undefined {
return isAbsolute(path) ? path : undefined;
}
-/** Maximum number of concurrent file system read/stat operations to prevent OS file descriptor exhaustion. */
-const MAX_CONCURRENT_READS = 16;
-
/**
* Validates that all imported watch files exist on disk and their contents match.
* Performs a fast-path metadata check (mtime + size) first, falling back to content hashing.
diff --git a/packages/angular/build/src/tools/esbuild/stylesheets/sass-language_spec.ts b/packages/angular/build/src/tools/esbuild/stylesheets/sass-language_spec.ts
index cdd4d7e7c8db..216a2d18fc47 100644
--- a/packages/angular/build/src/tools/esbuild/stylesheets/sass-language_spec.ts
+++ b/packages/angular/build/src/tools/esbuild/stylesheets/sass-language_spec.ts
@@ -286,5 +286,69 @@ describe('sass-language', () => {
pathToFileURL(join(projectRoot, 'node_modules', 'theme', '_index.scss')).href,
);
});
+
+ it('should resolve imports when globalThis.Promise is replaced (e.g., by Zone.js)', async () => {
+ const originalPromise = globalThis.Promise;
+
+ // Simulate Zone.js replacing globalThis.Promise with a constructor where
+ // native V8 async function return values fail `instanceof globalThis.Promise`.
+ class ZoneLikePromise {
+ #inner: Promise;
+
+ constructor(
+ executor: (
+ resolve: (value: T | PromiseLike) => void,
+ reject: (reason?: unknown) => void,
+ ) => void,
+ ) {
+ this.#inner = new originalPromise(executor);
+ }
+
+ then(
+ onfulfilled?: ((value: T) => TResult1 | PromiseLike) | null,
+ onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null,
+ ): ZoneLikePromise {
+ return new ZoneLikePromise((resolve, reject) => {
+ this.#inner.then(onfulfilled, onrejected).then(resolve, reject);
+ });
+ }
+
+ catch(
+ onrejected?: ((reason: unknown) => TResult | PromiseLike) | null,
+ ): ZoneLikePromise {
+ return this.then(undefined, onrejected);
+ }
+
+ finally(onfinally?: (() => void) | null): ZoneLikePromise {
+ return new ZoneLikePromise((resolve, reject) => {
+ this.#inner.finally(onfinally).then(resolve, reject);
+ });
+ }
+
+ static resolve(value?: U | PromiseLike): ZoneLikePromise> {
+ if (value instanceof ZoneLikePromise) {
+ return value;
+ }
+
+ return new ZoneLikePromise((resolve) => resolve(value as Awaited));
+ }
+
+ static reject(reason?: unknown): ZoneLikePromise {
+ return new ZoneLikePromise((_, reject) => reject(reason));
+ }
+
+ static all(values: Iterable): ZoneLikePromise {
+ return ZoneLikePromise.resolve(originalPromise.all(values));
+ }
+ }
+
+ globalThis.Promise = ZoneLikePromise as unknown as PromiseConstructor;
+ try {
+ const application = await compile(buttonStylesheet);
+ expect(application).toContain('content: "project";');
+ } finally {
+ globalThis.Promise = originalPromise;
+ }
+ });
});
});
diff --git a/packages/angular/build/src/tools/esbuild/utils.ts b/packages/angular/build/src/tools/esbuild/utils.ts
index 3bbaabdd2400..e93bb295b439 100644
--- a/packages/angular/build/src/tools/esbuild/utils.ts
+++ b/packages/angular/build/src/tools/esbuild/utils.ts
@@ -17,11 +17,7 @@ import { OutputMode } from '../../builders/application/schema';
import { BudgetCalculatorResult } from '../../utils/bundle-calculator';
import { BundleStats, generateEsbuildBuildStatsTable } from '../../utils/stats-table';
-import {
- BuildOutputAsset,
- ExecutionResult,
- PrerenderedRoutesRecord,
-} from './bundler-execution-result';
+import { ExecutionResult, PrerenderedRoutesRecord } from './bundler-execution-result';
import { type BuildOutputFile, BuildOutputFileType, type InitialFileRecord } from './bundler-files';
export function logBuildStats(
@@ -212,24 +208,6 @@ export function getFeatureSupport(nativeAsyncAwait: boolean): BuildOptions['supp
};
}
-const MAX_CONCURRENT_WRITES = 64;
-export async function emitFilesToDisk(
- files: readonly T[],
- 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;) {
- const groupMax = Math.min(fileIndex + MAX_CONCURRENT_WRITES, files.length);
-
- const actions = [];
- while (fileIndex < groupMax) {
- actions.push(writeFileCallback(files[fileIndex++]));
- }
-
- await Promise.all(actions);
- }
-}
-
interface BuildManifest {
errors: string[];
warnings: string[];
diff --git a/packages/angular/build/src/tools/sass/rebasing-importer.ts b/packages/angular/build/src/tools/sass/rebasing-importer.ts
index 7198d8b74f1e..889d26ef567e 100644
--- a/packages/angular/build/src/tools/sass/rebasing-importer.ts
+++ b/packages/angular/build/src/tools/sass/rebasing-importer.ts
@@ -344,14 +344,18 @@ export class AsyncModuleUrlRebasingImporter implements Importer<'async'> {
this.load = this.load.bind(this);
}
- async canonicalize(url: string, options: CanonicalizeContext): Promise {
+ canonicalize(url: string, options: CanonicalizeContext): Promise | URL | null {
if (url.startsWith('file://')) {
return this.relativeImporter.canonicalize(url, options);
}
- const result = await this.finder(url, options);
-
- return result ? this.relativeImporter.canonicalize(result.href, options) : null;
+ // Use `Promise.resolve` instead of an `async` method so the returned promise is an
+ // instance of the current `globalThis.Promise` (e.g., `ZoneAwarePromise` when Zone.js
+ // is loaded during SSR). `sass-embedded` checks `result instanceof Promise`, which fails
+ // for native `async` function return values when `globalThis.Promise` has been replaced.
+ return Promise.resolve(this.finder(url, options)).then((result) =>
+ result ? this.relativeImporter.canonicalize(result.href, options) : null,
+ );
}
load(canonicalUrl: URL): ImporterResult | null {
diff --git a/packages/angular/build/src/tools/vite/middlewares/assets-middleware.ts b/packages/angular/build/src/tools/vite/middlewares/assets-middleware.ts
index 3c38d000b30c..a1aa19361c5c 100644
--- a/packages/angular/build/src/tools/vite/middlewares/assets-middleware.ts
+++ b/packages/angular/build/src/tools/vite/middlewares/assets-middleware.ts
@@ -236,7 +236,7 @@ export function createBuildAssetsMiddleware(
const outputFile = buildResultFiles.get(pathname.slice(1));
if (outputFile) {
const contents =
- outputFile.origin === 'memory' ? outputFile.contents : readHandler(outputFile.inputPath);
+ outputFile.origin === 'memory' ? outputFile.contents : readHandler(outputFile.source);
const etag = `W/${calculateHash(contents)}`;
if (checkAndHandleEtag(req, res, etag)) {
diff --git a/packages/angular/build/src/utils/concurrency.ts b/packages/angular/build/src/utils/concurrency.ts
index a38a9a57fa36..39f2b70c95df 100644
--- a/packages/angular/build/src/utils/concurrency.ts
+++ b/packages/angular/build/src/utils/concurrency.ts
@@ -6,6 +6,11 @@
* found in the LICENSE file at https://angular.dev/license
*/
+/**
+ * Maximum number of concurrent file system read/stat operations to prevent OS file descriptor exhaustion.
+ */
+export const MAX_CONCURRENT_READS = 16;
+
/**
* Executes an asynchronous function for each item in an array concurrently up to a specified limit.
*
diff --git a/packages/angular/build/src/utils/delete-output-dir.ts b/packages/angular/build/src/utils/delete-output-dir.ts
index 45084760793d..1f676e77b759 100644
--- a/packages/angular/build/src/utils/delete-output-dir.ts
+++ b/packages/angular/build/src/utils/delete-output-dir.ts
@@ -17,8 +17,9 @@ export async function deleteOutputDir(
outputPath: string,
emptyOnlyDirectories?: string[],
): Promise {
- const resolvedOutputPath = resolve(root, outputPath);
- if (resolvedOutputPath === root) {
+ const resolvedRoot = resolve(root);
+ const resolvedOutputPath = resolve(resolvedRoot, outputPath);
+ if (resolvedOutputPath === resolvedRoot) {
throw new Error('Output path MUST not be project root directory!');
}
diff --git a/packages/angular/build/src/utils/disk-files.ts b/packages/angular/build/src/utils/disk-files.ts
new file mode 100644
index 000000000000..dbbe34ee919e
--- /dev/null
+++ b/packages/angular/build/src/utils/disk-files.ts
@@ -0,0 +1,83 @@
+/**
+ * @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 { constants, cp, mkdir, rm, writeFile } from 'node:fs/promises';
+import { dirname } from 'node:path';
+import { runConcurrent } from './concurrency';
+
+/**
+ * Maximum number of concurrent file system write/copy operations to avoid open file descriptor exhaustion.
+ */
+const MAX_CONCURRENT_OPS = 64;
+
+/**
+ * Represents a file that can be emitted to disk from memory or copied from an existing path on disk.
+ */
+export type EmittableFile =
+ { origin: 'memory'; contents: string | Uint8Array } | { origin: 'disk'; source: string };
+
+/**
+ * Writes or copies a collection of files to disk with bounded concurrency,
+ * ensuring parent directories are created once per invocation.
+ *
+ * @param files The collection of files to emit.
+ * @param resolveDestinationPath Callback returning the absolute destination path for a file, or `undefined` to skip it.
+ */
+export async function emitFilesToDisk(
+ files: readonly T[],
+ resolveDestinationPath: (file: T) => string | undefined,
+): Promise {
+ if (files.length === 0) {
+ return;
+ }
+
+ const directoryCreationPromises = new Map>();
+
+ await runConcurrent(files, MAX_CONCURRENT_OPS, async (file) => {
+ const fullFilePath = resolveDestinationPath(file);
+ if (!fullFilePath) {
+ return;
+ }
+
+ // Ensure output subdirectories exist
+ const fileBasePath = dirname(fullFilePath);
+ if (fileBasePath) {
+ let mkdirPromise = directoryCreationPromises.get(fileBasePath);
+ if (!mkdirPromise) {
+ mkdirPromise = mkdir(fileBasePath, { recursive: true });
+ directoryCreationPromises.set(fileBasePath, mkdirPromise);
+ }
+ await mkdirPromise;
+ }
+
+ if (file.origin === 'memory') {
+ // Write file contents
+ await writeFile(fullFilePath, file.contents);
+
+ return;
+ }
+
+ // Copy file contents
+ await cp(file.source, fullFilePath, {
+ mode: constants.COPYFILE_FICLONE,
+ preserveTimestamps: true,
+ });
+ });
+}
+
+/**
+ * Deletes a collection of files from disk with bounded concurrency.
+ * @param files The collection of files to delete.
+ */
+export async function deleteFilesFromDisk(files: readonly string[]): Promise {
+ if (files.length === 0) {
+ return;
+ }
+
+ await runConcurrent(files, MAX_CONCURRENT_OPS, (file) => rm(file, { force: true }));
+}
diff --git a/packages/angular/build/src/utils/disk-files_spec.ts b/packages/angular/build/src/utils/disk-files_spec.ts
new file mode 100644
index 000000000000..4a9422bd4373
--- /dev/null
+++ b/packages/angular/build/src/utils/disk-files_spec.ts
@@ -0,0 +1,75 @@
+/**
+ * @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 { existsSync } from 'node:fs';
+import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
+import { join } from 'node:path';
+import { type EmittableFile, deleteFilesFromDisk, emitFilesToDisk } from './disk-files';
+
+describe('disk-files', () => {
+ let tempRoot: string;
+
+ beforeEach(async () => {
+ const baseTmpDir = process.env['TEST_TMPDIR'];
+ assert(baseTmpDir, 'TEST_TMPDIR is not set');
+ tempRoot = await mkdtemp(join(baseTmpDir, 'angular-cli-disk-files-test-'));
+ });
+
+ afterEach(async () => {
+ if (tempRoot) {
+ await rm(tempRoot, { recursive: true, force: true });
+ }
+ });
+
+ describe('emitFilesToDisk', () => {
+ it('should write memory files and copy disk files while creating nested directories', async () => {
+ const sourceFile = join(tempRoot, 'source-asset.txt');
+ await writeFile(sourceFile, 'from-disk');
+
+ const files: (EmittableFile & { path: string })[] = [
+ {
+ origin: 'memory',
+ path: 'nested/a/mem1.txt',
+ contents: new TextEncoder().encode('mem-1'),
+ },
+ { origin: 'memory', path: 'nested/a/mem2.txt', contents: 'mem-2' },
+ { origin: 'disk', path: 'nested/b/disk1.txt', source: sourceFile },
+ { origin: 'disk', path: 'nested/c/disk2.txt', source: sourceFile },
+ { origin: 'memory', path: 'skipped/file.txt', contents: 'should-not-exist' },
+ ];
+
+ const outDir = join(tempRoot, 'out');
+ await emitFilesToDisk(files, (file) =>
+ file.path.startsWith('skipped/') ? undefined : join(outDir, file.path),
+ );
+
+ expect(await readFile(join(outDir, 'nested/a/mem1.txt'), 'utf-8')).toBe('mem-1');
+ expect(await readFile(join(outDir, 'nested/a/mem2.txt'), 'utf-8')).toBe('mem-2');
+ expect(await readFile(join(outDir, 'nested/b/disk1.txt'), 'utf-8')).toBe('from-disk');
+ expect(await readFile(join(outDir, 'nested/c/disk2.txt'), 'utf-8')).toBe('from-disk');
+ expect(existsSync(join(outDir, 'skipped/file.txt'))).toBeFalse();
+ });
+ });
+
+ describe('deleteFilesFromDisk', () => {
+ it('should delete existing files and ignore non-existent files', async () => {
+ const fileA = join(tempRoot, 'a.txt');
+ const fileB = join(tempRoot, 'b.txt');
+ const nonExistent = join(tempRoot, 'missing.txt');
+
+ await writeFile(fileA, 'a');
+ await writeFile(fileB, 'b');
+
+ await deleteFilesFromDisk([fileA, nonExistent]);
+
+ expect(existsSync(fileA)).toBeFalse();
+ expect(existsSync(fileB)).toBeTrue();
+ });
+ });
+});
diff --git a/packages/angular/build/src/utils/normalize-asset-patterns.ts b/packages/angular/build/src/utils/normalize-asset-patterns.ts
index d97b6e605fa4..defa6511172f 100644
--- a/packages/angular/build/src/utils/normalize-asset-patterns.ts
+++ b/packages/angular/build/src/utils/normalize-asset-patterns.ts
@@ -6,32 +6,52 @@
* found in the LICENSE file at https://angular.dev/license
*/
-import assert from 'node:assert';
import { statSync } from 'node:fs';
-import * as path from 'node:path';
-import { AssetPattern, AssetPatternClass } from '../builders/application/schema';
+import path from 'node:path';
+import type { AssetPattern, AssetPatternClass } from '../builders/application/schema';
import { isSubDirectory } from './path';
+/**
+ * Asset pattern configuration normalized into its object form with a resolved `output` directory.
+ */
+export interface NormalizedAssetsPattern extends AssetPatternClass {
+ /** Relative output directory within the build output path. */
+ output: string;
+}
+
+/**
+ * Normalizes raw string and object asset patterns into {@link NormalizedAssetsPattern} objects
+ * and validates that all asset inputs and outputs stay within the workspace and output directories.
+ *
+ * @param assetPatterns Raw string or object asset patterns from builder options.
+ * @param workspaceRoot Workspace root directory path.
+ * @param projectRoot Project root directory path.
+ * @param projectSourceRoot Optional project source root directory path.
+ * @returns An array of normalized asset pattern configurations.
+ */
export function normalizeAssetPatterns(
assetPatterns: AssetPattern[],
workspaceRoot: string,
projectRoot: string,
projectSourceRoot: string | undefined,
-): (AssetPatternClass & { output: string })[] {
+): NormalizedAssetsPattern[] {
if (assetPatterns.length === 0) {
return [];
}
// When sourceRoot is not available, we default to ${projectRoot}/src.
const sourceRoot = projectSourceRoot || path.join(projectRoot, 'src');
- const resolvedSourceRoot = path.resolve(workspaceRoot, sourceRoot);
- const resolvedProjectRoot = path.resolve(workspaceRoot, projectRoot);
+ const resolvedWorkspaceRoot = path.resolve(workspaceRoot);
+ const resolvedSourceRoot = path.resolve(resolvedWorkspaceRoot, sourceRoot);
+ const resolvedProjectRoot = path.resolve(resolvedWorkspaceRoot, projectRoot);
return assetPatterns.map((assetPattern) => {
+ let normalized: NormalizedAssetsPattern;
+
// Normalize string asset patterns to objects.
if (typeof assetPattern === 'string') {
const assetPath = path.normalize(assetPattern);
- const resolvedAssetPath = path.resolve(workspaceRoot, assetPath);
+ const resolvedAssetPath = path.resolve(resolvedWorkspaceRoot, assetPath);
let root: string;
// Check if the string asset is within sourceRoot.
@@ -39,51 +59,38 @@ export function normalizeAssetPatterns(
root = resolvedSourceRoot;
} else if (resolvedAssetPath.startsWith(resolvedProjectRoot)) {
root = resolvedProjectRoot;
- } else if (resolvedAssetPath.startsWith(workspaceRoot)) {
- root = workspaceRoot;
+ } else if (resolvedAssetPath.startsWith(resolvedWorkspaceRoot)) {
+ root = resolvedWorkspaceRoot;
} else {
throw new Error(`The ${assetPattern} asset path must be within the workspace root.`);
}
- let glob: string, input: string;
- let isDirectory: boolean;
-
+ let isDirectory = true;
try {
- isDirectory = statSync(resolvedAssetPath).isDirectory();
- } catch {
- isDirectory = true;
- }
-
- if (isDirectory) {
- // Folders get a recursive star glob.
- glob = '**/*';
- // Input directory is their original path.
- input = assetPath;
- } else {
- // Files are their own glob.
- glob = path.basename(assetPath);
- // Input directory is their original dirname.
- input = path.dirname(assetPath);
- }
+ isDirectory = statSync(resolvedAssetPath, { throwIfNoEntry: false })?.isDirectory() ?? true;
+ } catch {}
+ const glob = isDirectory ? '**/*' : path.basename(assetPath);
+ const input = isDirectory ? assetPath : path.dirname(assetPath);
// Output directory for both is the relative path from the root to input.
- const output = path.relative(root, path.resolve(workspaceRoot, input));
+ const output = path.relative(root, path.resolve(resolvedWorkspaceRoot, input));
- assetPattern = { glob, input, output };
+ normalized = { glob, input, output };
} else {
- if (!isSubDirectory(workspaceRoot, assetPattern.input)) {
+ if (!isSubDirectory(resolvedWorkspaceRoot, assetPattern.input)) {
throw new Error(`The ${assetPattern.input} asset path must be within the workspace root.`);
}
- assetPattern.output = path.join('.', assetPattern.output ?? '');
+ normalized = {
+ ...assetPattern,
+ output: path.join('.', assetPattern.output ?? ''),
+ };
}
- assert(assetPattern.output !== undefined);
-
- if (assetPattern.output.startsWith('..')) {
+ if (normalized.output.startsWith('..')) {
throw new Error('An asset cannot be written to a location outside of the output path.');
}
- return assetPattern as AssetPatternClass & { output: string };
+ return normalized;
});
}
diff --git a/packages/angular/build/src/utils/normalize-cache.ts b/packages/angular/build/src/utils/normalize-cache.ts
index e24eaf8627c8..bb24f774f79b 100644
--- a/packages/angular/build/src/utils/normalize-cache.ts
+++ b/packages/angular/build/src/utils/normalize-cache.ts
@@ -140,7 +140,7 @@ export function normalizeCacheOptions(
const cacheBasePath = getCacheBasePath(workspaceRoot, path);
const localCacheBasePath = isAbsolute(path) ? path : resolve(workspaceRoot, path);
- const normalizedBuilderName = builderName.replaceAll(':', '-');
+ const normalizedBuilderName = builderName.replace('@', '').replaceAll(/[:/]/g, '-');
return {
enabled: cacheEnabled,
diff --git a/packages/angular/build/src/utils/normalize-cache_spec.ts b/packages/angular/build/src/utils/normalize-cache_spec.ts
index 18e75403756d..1a0520c96a96 100644
--- a/packages/angular/build/src/utils/normalize-cache_spec.ts
+++ b/packages/angular/build/src/utils/normalize-cache_spec.ts
@@ -283,10 +283,10 @@ describe('normalizeCacheOptions', () => {
const options = normalizeCacheOptions({}, workspaceRoot, 'my-app', '@angular/build:unit-test');
expect(options.path).toBe(
- resolve(workspaceRoot, '.angular/cache/0.0.0-PLACEHOLDER/my-app/@angular/build-unit-test'),
+ resolve(workspaceRoot, '.angular/cache/0.0.0-PLACEHOLDER/my-app/angular-build-unit-test'),
);
expect(options.localPath).toBe(
- resolve(workspaceRoot, '.angular/cache/0.0.0-PLACEHOLDER/my-app/@angular/build-unit-test'),
+ resolve(workspaceRoot, '.angular/cache/0.0.0-PLACEHOLDER/my-app/angular-build-unit-test'),
);
});
});
diff --git a/packages/angular/build/src/utils/postcss-configuration.ts b/packages/angular/build/src/utils/postcss-configuration.ts
index abde0e632b30..e5a4076232a0 100644
--- a/packages/angular/build/src/utils/postcss-configuration.ts
+++ b/packages/angular/build/src/utils/postcss-configuration.ts
@@ -31,8 +31,8 @@ export interface SearchDirectory {
files: Set;
}
-export async function generateSearchDirectories(roots: string[]): Promise {
- return await Promise.all(
+export function generateSearchDirectories(roots: string[]): Promise {
+ return Promise.all(
roots.map((root) =>
readdir(root, { withFileTypes: true }).then((entries) => ({
root,
@@ -63,11 +63,11 @@ export function findTailwindConfiguration(
return findFile(searchDirectories, tailwindConfigFiles);
}
-export async function getTailwindConfig(
+export function getTailwindConfig(
searchDirectories: SearchDirectory[],
workspaceRoot: string,
logger?: { warn(message: string): void },
-): Promise<{ file: string; package: string } | undefined> {
+): { file: string; package: string } | undefined {
const tailwindConfigurationPath = findTailwindConfiguration(searchDirectories);
if (!tailwindConfigurationPath) {
return undefined;
diff --git a/packages/angular/build/src/utils/resolve-assets.ts b/packages/angular/build/src/utils/resolve-assets.ts
index 79ddd8548266..06a6c6c157e9 100644
--- a/packages/angular/build/src/utils/resolve-assets.ts
+++ b/packages/angular/build/src/utils/resolve-assets.ts
@@ -6,8 +6,10 @@
* found in the LICENSE file at https://angular.dev/license
*/
+import { lstat, stat } from 'node:fs/promises';
import path from 'node:path';
-import { glob } from 'tinyglobby';
+import { glob, isDynamicPattern } from 'tinyglobby';
+import { MAX_CONCURRENT_READS, mapConcurrent } from './concurrency';
import { isSubDirectory } from './path';
/**
@@ -26,15 +28,34 @@ export async function resolveAssets(
}[],
root: string,
): Promise<{ source: string; destination: string }[]> {
- const outputFiles: { source: string; destination: string }[] = [];
-
- for (const entry of entries) {
+ const resolvedEntries = await mapConcurrent(entries, MAX_CONCURRENT_READS, async (entry) => {
if (!isSubDirectory(root, entry.input)) {
throw new Error(`The ${entry.input} asset path must be within the workspace root.`);
}
const cwd = path.resolve(root, entry.input);
+ if (!entry.ignore?.length && !isDynamicPattern(entry.glob)) {
+ const src = path.join(cwd, entry.glob);
+ if (isSubDirectory(cwd, src)) {
+ try {
+ const stats = await (entry.followSymlinks ? stat(src) : lstat(src));
+ if (stats.isFile()) {
+ const filePath = entry.flatten ? path.basename(entry.glob) : entry.glob;
+
+ return [{ source: src, destination: path.join(entry.output, filePath) }];
+ }
+
+ if (!stats.isSymbolicLink()) {
+ return [];
+ }
+ } catch {
+ // File does not exist or cannot be accessed.
+ return [];
+ }
+ }
+ }
+
const files = await glob(entry.glob, {
cwd,
dot: true,
@@ -42,13 +63,11 @@ export async function resolveAssets(
followSymbolicLinks: entry.followSymlinks ?? false,
});
- for (const file of files) {
- const src = path.join(cwd, file);
- const filePath = entry.flatten ? path.basename(file) : file;
-
- outputFiles.push({ source: src, destination: path.join(entry.output, filePath) });
- }
- }
+ return files.map((file) => ({
+ source: path.join(cwd, file),
+ destination: path.join(entry.output, entry.flatten ? path.basename(file) : file),
+ }));
+ });
- return outputFiles;
+ return resolvedEntries.flat();
}
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 6f21bfbc739b..6ff4c8f8191c 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
@@ -8,7 +8,7 @@
import assert from 'node:assert';
import { randomUUID } from 'node:crypto';
-import { readFile } from 'node:fs/promises';
+import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
@@ -110,7 +110,7 @@ export function resolve(
});
}
-export async function load(url: string, context: { format?: string | null }, nextLoad: Function) {
+export function load(url: string, context: { format?: string | null }, nextLoad: Function) {
const { format } = context;
// Load the file from memory if the URL is based in the virtual root
@@ -137,7 +137,7 @@ export async function load(url: string, context: { format?: string | null }, nex
}
const filePath = fileURLToPath(url);
- const fileBytes = await readFile(filePath);
+ const fileBytes = readFileSync(filePath);
const source = Buffer.concat([NG_SERVER_MODE_INIT_BYTES, fileBytes]);
return {
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
index 2b7622145378..0b32c2248b10 100644
--- 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
@@ -6,6 +6,10 @@
* 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 { join } from 'node:path';
+import { pathToFileURL } from 'node:url';
import { initialize, load, resolve } from './loader-hooks';
import { createSharedServerFiles } from './utils';
@@ -124,12 +128,12 @@ describe('esm-in-memory-loader loader-hooks', () => {
});
describe('load', () => {
- it('should load in-memory file source from SharedArrayBuffer backed Uint8Array', async () => {
+ it('should load in-memory file source from SharedArrayBuffer backed Uint8Array', () => {
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);
+ const result = load(rootResolve.url, { format: 'module' }, nextLoad);
expect(nextLoad).not.toHaveBeenCalled();
expect(result.format).toBe('module');
@@ -137,12 +141,12 @@ describe('esm-in-memory-loader loader-hooks', () => {
expect(result.source).toBe('export const main = true;');
});
- it('should load in-memory file with multi-byte UTF-8 characters', async () => {
+ it('should load in-memory file with multi-byte UTF-8 characters', () => {
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);
+ const result = load(rootResolve.url, { format: 'module' }, nextLoad);
expect(nextLoad).not.toHaveBeenCalled();
expect(result.format).toBe('module');
@@ -150,12 +154,12 @@ describe('esm-in-memory-loader loader-hooks', () => {
expect(result.source).toBe('export const text = "🔥 UTF-8 🚀";');
});
- it('should load in-memory file with empty content', async () => {
+ it('should load in-memory file with empty content', () => {
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);
+ const result = load(rootResolve.url, { format: 'module' }, nextLoad);
expect(nextLoad).not.toHaveBeenCalled();
expect(result.format).toBe('module');
@@ -163,7 +167,7 @@ describe('esm-in-memory-loader loader-hooks', () => {
expect(result.source).toBe('');
});
- it('should load in-memory file source with non-zero byteOffset in Uint8Array', async () => {
+ it('should load in-memory file source with non-zero byteOffset in Uint8Array', () => {
const target = 'export const sliced = 42;';
const fullBuffer = Buffer.from(`__PADDING__${target}__MORE__`);
const offset = Buffer.byteLength('__PADDING__', 'utf-8');
@@ -181,7 +185,7 @@ describe('esm-in-memory-loader loader-hooks', () => {
const rootResolve = resolve(memoryUrl, { parentURL: undefined }, () => {});
const nextLoad = jasmine.createSpy('nextLoad');
- const result = await load(rootResolve.url, { format: 'module' }, nextLoad);
+ const result = load(rootResolve.url, { format: 'module' }, nextLoad);
expect(nextLoad).not.toHaveBeenCalled();
expect(result.format).toBe('module');
@@ -189,7 +193,7 @@ describe('esm-in-memory-loader loader-hooks', () => {
expect(result.source).toBe(target);
});
- it('should load in-memory file source when outputFiles contain string values', async () => {
+ it('should load in-memory file source when outputFiles contain string values', () => {
initialize({
workspaceRoot,
outputFiles: {
@@ -201,7 +205,7 @@ describe('esm-in-memory-loader loader-hooks', () => {
const rootResolve = resolve(memoryUrl, { parentURL: undefined }, () => {});
const nextLoad = jasmine.createSpy('nextLoad');
- const result = await load(rootResolve.url, { format: 'module' }, nextLoad);
+ const result = load(rootResolve.url, { format: 'module' }, nextLoad);
expect(nextLoad).not.toHaveBeenCalled();
expect(result.format).toBe('module');
@@ -209,21 +213,46 @@ describe('esm-in-memory-loader loader-hooks', () => {
expect(result.source).toBe('export const fromString = 1;');
});
- it('should reject when in-memory file does not exist in outputFiles', async () => {
+ it('should throw when in-memory file does not exist in outputFiles', () => {
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(() => load(nonExistentVirtualUrl, { format: 'module' }, nextLoad)).toThrowError(
+ /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(
+ it('should prepend ngServerMode initialization for @angular/ file URLs', async () => {
+ const baseTmpDir = process.env['TEST_TMPDIR'];
+ assert(baseTmpDir, 'TEST_TMPDIR is not set');
+ const tmpDir = await mkdtemp(join(baseTmpDir, 'loader-hooks-test-'));
+
+ try {
+ const angularDir = join(tmpDir, '@angular/core');
+ await mkdir(angularDir, { recursive: true });
+ const filePath = join(angularDir, 'index.mjs');
+ await writeFile(filePath, 'export const VERSION = "1.0.0";');
+
+ const nextLoad = jasmine.createSpy('nextLoad');
+ const result = load(pathToFileURL(filePath).href, { format: 'module' }, nextLoad);
+
+ expect(nextLoad).not.toHaveBeenCalled();
+ expect(result.format).toBe('module');
+ expect(result.shortCircuit).toBeTrue();
+ expect(new TextDecoder().decode(result.source)).toBe(
+ 'var ngServerMode=true;export const VERSION = "1.0.0";',
+ );
+ } finally {
+ await rm(tmpDir, { recursive: true, force: true });
+ }
+ });
+
+ it('should delegate to nextLoad for non-angular file URLs', () => {
+ const nextLoad = jasmine.createSpy('nextLoad').and.returnValue({ format: 'module' });
+ const result = load(
'file:///workspace/node_modules/rxjs/index.js',
{ format: 'module' },
nextLoad,
@@ -235,9 +264,9 @@ describe('esm-in-memory-loader loader-hooks', () => {
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);
+ it('should delegate to nextLoad for non-memory non-file URLs', () => {
+ const nextLoad = jasmine.createSpy('nextLoad').and.returnValue({ format: 'builtin' });
+ const result = 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/register-hooks.ts b/packages/angular/build/src/utils/server-rendering/esm-in-memory-loader/register-hooks.ts
index b23fe297bc19..56747e17bd03 100644
--- a/packages/angular/build/src/utils/server-rendering/esm-in-memory-loader/register-hooks.ts
+++ b/packages/angular/build/src/utils/server-rendering/esm-in-memory-loader/register-hooks.ts
@@ -6,8 +6,9 @@
* found in the LICENSE file at https://angular.dev/license
*/
-import { register } from 'node:module';
-import { pathToFileURL } from 'node:url';
+import { registerHooks } from 'node:module';
import { workerData } from 'node:worker_threads';
+import { initialize, load, resolve } from './loader-hooks';
-register('./loader-hooks.js', { parentURL: pathToFileURL(__filename), data: workerData });
+initialize(workerData);
+registerHooks({ resolve, load });
diff --git a/packages/angular/build/src/utils/test-files.ts b/packages/angular/build/src/utils/test-files.ts
index 6790d007e220..763c762ac19f 100644
--- a/packages/angular/build/src/utils/test-files.ts
+++ b/packages/angular/build/src/utils/test-files.ts
@@ -6,11 +6,10 @@
* found in the LICENSE file at https://angular.dev/license
*/
-import * as fs from 'node:fs/promises';
import path from 'node:path';
import { ResultFile } from '../builders/application/results';
import { BuildOutputFileType } from '../tools/esbuild/bundler-files';
-import { emitFilesToDisk } from '../tools/esbuild/utils';
+import { emitFilesToDisk } from './disk-files';
/**
* Writes a collection of build result files to a specified directory.
@@ -20,29 +19,11 @@ import { emitFilesToDisk } from '../tools/esbuild/utils';
* @param files A collection of `ResultFile` objects, representing the build output.
* @param testDir The absolute path to the directory where the files should be written.
*/
-export async function writeTestFiles(files: readonly ResultFile[], testDir: string): Promise {
- const directoryExists = new Set();
+export function writeTestFiles(files: readonly ResultFile[], testDir: string): Promise {
// Writes the test related output files to disk and ensures the containing directories are present
- await emitFilesToDisk(files, async (file) => {
- if (file.type !== BuildOutputFileType.Browser && file.type !== BuildOutputFileType.Media) {
- return;
- }
-
- const fullFilePath = path.join(testDir, file.path);
-
- // Ensure output subdirectories exist
- const fileBasePath = path.dirname(fullFilePath);
- if (fileBasePath && !directoryExists.has(fileBasePath)) {
- await fs.mkdir(fileBasePath, { recursive: true });
- directoryExists.add(fileBasePath);
- }
-
- if (file.origin === 'memory') {
- // Write file contents
- await fs.writeFile(fullFilePath, file.contents);
- } else {
- // Copy file contents
- await fs.copyFile(file.inputPath, fullFilePath, fs.constants.COPYFILE_FICLONE);
- }
- });
+ return emitFilesToDisk(files, (file) =>
+ file.type === BuildOutputFileType.Browser || file.type === BuildOutputFileType.Media
+ ? path.join(testDir, file.path)
+ : undefined,
+ );
}
diff --git a/packages/angular/build/src/utils/watcher.ts b/packages/angular/build/src/utils/watcher.ts
index 610051c5dcc7..fd865ee80b56 100644
--- a/packages/angular/build/src/utils/watcher.ts
+++ b/packages/angular/build/src/utils/watcher.ts
@@ -8,7 +8,6 @@
import type * as ParcelWatcher from '@parcel/watcher';
import type * as Chokidar from 'chokidar';
-import { once } from 'node:events';
import * as fs from 'node:fs';
import * as path from 'node:path';
import picomatch from 'picomatch';
@@ -419,89 +418,364 @@ export function extractNodeModulesPackageDir(posixPath: string): string | undefi
return `${nodeModulesPath}/${segments[0]}`;
}
-class ParcelExternalManager {
- private readonly extraSubscriptions = new Map();
- private readonly pendingSubscriptions = new Map<
- string,
- Promise
- >();
- private readonly externalDirFiles = new Map }>();
+/**
+ * Maximum number of concurrent external directory subscriptions before coalescing
+ * sibling/cousin directories into common ancestor directories.
+ * Kept well below macOS's ~512 per-process FSEvents stream limit.
+ */
+const DEFAULT_MAX_EXTERNAL_SUBSCRIPTIONS = 256;
+
+/**
+ * Node in a directory prefix tree used to subsume nested directories
+ * and coalesce sibling/cousin directories into common ancestors.
+ */
+interface DirTrieNode {
+ /** Case-normalized POSIX path key for set/map lookups. */
+ dirKey: string;
+
+ /** Original-case POSIX directory path passed to `@parcel/watcher`. */
+ dirPath: string;
+
+ /** Depth of this directory node from the filesystem root (0 at root). */
+ depth: number;
+
+ /** Parent directory node, or `undefined` if this node is a filesystem root. */
+ parent: DirTrieNode | undefined;
+
+ /** Child directory nodes keyed by their `dirKey`. */
+ children: Map;
+
+ /** Whether this directory is selected as an active subscription target. */
+ isTarget: boolean;
+
+ /** Number of active target leaf directories within this node's subtree. */
+ leafCount: number;
+}
+
+/**
+ * Checks whether any strict ancestor of the given trie node is already marked as a target.
+ */
+function hasTargetAncestor(node: DirTrieNode): boolean {
+ let current = node.parent;
+ while (current) {
+ if (current.isTarget) {
+ return true;
+ }
+ current = current.parent;
+ }
+
+ return false;
+}
+
+/**
+ * Manages `@parcel/watcher` directory subscriptions for watched files located outside the
+ * primary `workspaceRoot`.
+ *
+ * Because `@parcel/watcher` watches directories recursively and macOS limits each process to
+ * ~512 concurrent `FSEvents` streams, this manager:
+ * - Normalizes external `node_modules` file paths to their package root directory.
+ * - Batches synchronous `watchFile` and `removeFile` calls within a microtask before subscribing.
+ * - Uses a directory prefix tree to subsume nested child directories and iteratively coalesce
+ * deepest branching subdirectories into common ancestors when the subscription budget is exceeded.
+ * - Dynamically lowers its subscription budget and coalesces further if `subscribe()` fails on
+ * an existing directory due to OS stream limits.
+ */
+export class ParcelExternalManager {
+ /** Active `@parcel/watcher` subscriptions keyed by subscribed directory lookup key. */
+ readonly #extraSubscriptions = new Map();
+
+ /** Reference-counted watched files grouped by their target external directory lookup key. */
+ readonly #externalDirFiles = new Map }>();
+
+ /** Reverse lookup mapping each watched file lookup key to its target directory lookup key. */
+ readonly #fileToDirKey = new Map();
+
+ /** The `@parcel/watcher` module instance. */
+ readonly #parcelWatcher: typeof ParcelWatcher;
+
+ /** Watcher configuration options including ignore patterns. */
+ readonly #options: WatcherOptions | undefined;
+
+ /** Normalized POSIX path of the primary watched workspace root. */
+ readonly #rootDirPosix: string;
+ /** Case-normalized lookup key of the primary watched workspace root. */
+ readonly #rootDirLookupKey: string;
+
+ /** Whether the underlying filesystem is case-sensitive. */
+ readonly #isCaseSensitive: boolean;
+
+ /** Callback invoked when `@parcel/watcher` emits filesystem events. */
+ readonly #handleEvents: (events: ParcelWatcher.Event[]) => void;
+
+ /** Current maximum number of concurrent external directory subscriptions allowed before coalescing. */
+ #maxSubscriptions: number;
+
+ /** Whether external directory state has changed and requires a reconciliation pass. */
+ #needsReconcile = false;
+
+ /** Whether obsolete subscriptions should be unsubscribed before creating new ones (used after stream limit errors). */
+ #shrinkBeforeSubscribe = false;
+
+ /** In-flight promise for the currently scheduled or running reconciliation loop. */
+ #reconcilePromise: Promise | undefined;
+
+ /** Whether this manager has been closed. */
+ #isClosed = false;
+
+ /**
+ * Creates a new external directory subscription manager for `@parcel/watcher`.
+ *
+ * @param parcelWatcher The `@parcel/watcher` module.
+ * @param options Watcher configuration options.
+ * @param rootDirPosix Normalized POSIX path of the primary workspace root.
+ * @param rootDirLookupKey Case-normalized lookup key of the primary workspace root.
+ * @param isCaseSensitive Whether the filesystem at the workspace root is case-sensitive.
+ * @param handleEvents Callback to process incoming `@parcel/watcher` events.
+ * @param maxSubscriptions Maximum number of concurrent external directory subscriptions before coalescing.
+ */
constructor(
- private readonly parcelWatcher: typeof ParcelWatcher,
- private readonly options: WatcherOptions | undefined,
- private readonly rootDirLookupKey: string,
- private readonly handleEvents: (events: ParcelWatcher.Event[]) => void,
- ) {}
+ parcelWatcher: typeof ParcelWatcher,
+ options: WatcherOptions | undefined,
+ rootDirPosix: string,
+ rootDirLookupKey: string,
+ isCaseSensitive: boolean,
+ handleEvents: (events: ParcelWatcher.Event[]) => void,
+ maxSubscriptions = DEFAULT_MAX_EXTERNAL_SUBSCRIPTIONS,
+ ) {
+ this.#parcelWatcher = parcelWatcher;
+ this.#options = options;
+ this.#rootDirPosix = rootDirPosix;
+ this.#rootDirLookupKey = rootDirLookupKey;
+ this.#isCaseSensitive = isCaseSensitive;
+ this.#handleEvents = handleEvents;
+ this.#maxSubscriptions = Math.max(1, maxSubscriptions);
+ }
- async ensureWatched(posixPath: string, lookupKey: string): Promise {
- if (isPathInside(lookupKey, this.rootDirLookupKey) || lookupKey === this.rootDirLookupKey) {
+ /**
+ * Registers a file path to be watched if it resides outside the primary workspace root,
+ * and schedules an asynchronous subscription reconciliation pass if needed.
+ *
+ * @param posixPath Normalized POSIX file path preserving original casing.
+ * @param lookupKey Case-normalized lookup key for the file path.
+ */
+ watchFile(posixPath: string, lookupKey: string): void {
+ if (
+ this.#isClosed ||
+ isPathInside(lookupKey, this.#rootDirLookupKey) ||
+ lookupKey === this.#rootDirLookupKey
+ ) {
return;
}
- const dirPath = getDirectoryPath(posixPath);
- const dirKey = getDirectoryPath(lookupKey);
- let dirEntry = this.externalDirFiles.get(dirKey);
+ const pkgDir = extractNodeModulesPackageDir(posixPath);
+ const dirPath = pkgDir ?? getDirectoryPath(posixPath);
+ const dirKey = pkgDir
+ ? toLookupKey(pkgDir, this.#isCaseSensitive)
+ : getDirectoryPath(lookupKey);
+
+ this.#fileToDirKey.set(lookupKey, dirKey);
+
+ let dirEntry = this.#externalDirFiles.get(dirKey);
+ const isNewDir = !dirEntry;
if (!dirEntry) {
dirEntry = { dirPath, files: new Set() };
- this.externalDirFiles.set(dirKey, dirEntry);
+ this.#externalDirFiles.set(dirKey, dirEntry);
}
dirEntry.files.add(lookupKey);
- await this.ensureDirWatched(dirPath, dirKey);
+ if (isNewDir || !this.#isCoveredByActiveSubscription(dirKey)) {
+ this.#scheduleReconcile();
+ }
}
+ /**
+ * Unregisters a previously watched external file and schedules a reconciliation pass
+ * if it was the last watched file in its target directory.
+ *
+ * @param lookupKey Case-normalized lookup key for the file path to remove.
+ */
removeFile(lookupKey: string): void {
- if (isPathInside(lookupKey, this.rootDirLookupKey) || lookupKey === this.rootDirLookupKey) {
+ const dirKey = this.#fileToDirKey.get(lookupKey);
+ if (!dirKey) {
return;
}
- const dirKey = getDirectoryPath(lookupKey);
- const dirEntry = this.externalDirFiles.get(dirKey);
+ this.#fileToDirKey.delete(lookupKey);
+ const dirEntry = this.#externalDirFiles.get(dirKey);
if (dirEntry) {
dirEntry.files.delete(lookupKey);
if (dirEntry.files.size === 0) {
- this.externalDirFiles.delete(dirKey);
- const sub = this.extraSubscriptions.get(dirKey);
- if (sub) {
- this.extraSubscriptions.delete(dirKey);
- sub.unsubscribe().catch(() => {});
-
- for (const [remainingDirKey, remainingDirEntry] of this.externalDirFiles.entries()) {
- if (!this.isCoveredByExistingExternal(remainingDirKey)) {
- this.ensureDirWatched(remainingDirEntry.dirPath, remainingDirKey).catch(() => {});
- }
- }
- }
+ this.#externalDirFiles.delete(dirKey);
+ this.#scheduleReconcile();
}
}
}
+ /**
+ * Waits for any scheduled or in-progress subscription reconciliation pass to complete.
+ */
+ async flush(): Promise {
+ if (this.#reconcilePromise) {
+ await this.#reconcilePromise;
+ }
+ }
+
+ /**
+ * Closes the manager, awaiting any pending reconciliation and unsubscribing all active
+ * external directory subscriptions.
+ */
async close(): Promise {
+ this.#isClosed = true;
+ this.#needsReconcile = false;
try {
- if (this.pendingSubscriptions.size > 0) {
- await Promise.allSettled(Array.from(this.pendingSubscriptions.values()));
+ if (this.#reconcilePromise) {
+ await this.#reconcilePromise.catch(() => {});
}
- if (this.extraSubscriptions.size > 0) {
+ if (this.#extraSubscriptions.size > 0) {
await Promise.allSettled(
- Array.from(this.extraSubscriptions.values()).map((sub) => sub.unsubscribe()),
+ Array.from(this.#extraSubscriptions.values(), (sub) => sub.unsubscribe()),
);
}
} finally {
- this.extraSubscriptions.clear();
- this.pendingSubscriptions.clear();
- this.externalDirFiles.clear();
+ this.#extraSubscriptions.clear();
+ this.#externalDirFiles.clear();
+ this.#fileToDirKey.clear();
}
}
- private isCoveredByExistingExternal(dirLookupKey: string): boolean {
- for (const existingDir of this.extraSubscriptions.keys()) {
- if (dirLookupKey === existingDir || isPathInside(dirLookupKey, existingDir)) {
- return true;
+ /**
+ * Schedules a microtask to reconcile active `@parcel/watcher` subscriptions with the
+ * current set of external directories.
+ */
+ #scheduleReconcile(): void {
+ if (this.#isClosed) {
+ return;
+ }
+
+ this.#needsReconcile = true;
+ this.#reconcilePromise ??= Promise.resolve()
+ .then(() => this.#runReconcileLoop())
+ .finally(() => {
+ this.#reconcilePromise = undefined;
+ });
+ }
+
+ /**
+ * Continuously executes reconciliation passes until no further changes are pending.
+ */
+ async #runReconcileLoop(): Promise {
+ while (this.#needsReconcile && !this.#isClosed) {
+ this.#needsReconcile = false;
+ await this.#reconcileOnce();
+ }
+ }
+
+ /**
+ * Performs a single reconciliation pass: computes the desired coalesced directory set,
+ * subscribes to newly required directories, unsubscribes obsolete directories, and
+ * triggers fallback coalescing if OS stream limits are encountered.
+ */
+ async #reconcileOnce(): Promise {
+ const desiredDirs = this.#computeDesiredDirectories();
+
+ if (this.#shrinkBeforeSubscribe) {
+ this.#shrinkBeforeSubscribe = false;
+ const toUnsubscribe: Promise[] = [];
+ for (const [existingKey, sub] of this.#extraSubscriptions.entries()) {
+ if (!desiredDirs.has(existingKey)) {
+ this.#extraSubscriptions.delete(existingKey);
+ toUnsubscribe.push(sub.unsubscribe().catch(() => {}));
+ }
+ }
+ if (toUnsubscribe.length > 0) {
+ await Promise.allSettled(toUnsubscribe);
+ }
+ }
+
+ if (this.#isClosed) {
+ return;
+ }
+
+ const toSubscribe: [string, string][] = [];
+ for (const [dirKey, dirPath] of desiredDirs.entries()) {
+ if (!this.#extraSubscriptions.has(dirKey)) {
+ toSubscribe.push([dirKey, dirPath]);
+ }
+ }
+
+ let hadExistingDirFailure = false;
+ if (toSubscribe.length > 0) {
+ await Promise.allSettled(
+ toSubscribe.map(async ([dirKey, dirPath]) => {
+ const ignore = isPathInside(this.#rootDirLookupKey, dirKey)
+ ? [...(this.#options?.ignored ?? []), this.#rootDirPosix, `${this.#rootDirPosix}/**`]
+ : this.#options?.ignored;
+
+ try {
+ const sub = await this.#parcelWatcher.subscribe(
+ dirPath,
+ (err, events) => {
+ if (!err) {
+ this.#handleEvents(events);
+ }
+ },
+ { ignore },
+ );
+
+ if (this.#isClosed) {
+ await sub.unsubscribe().catch(() => {});
+
+ return;
+ }
+
+ this.#extraSubscriptions.set(dirKey, sub);
+ } catch {
+ // Ignore errors for missing directories; if the directory exists on disk,
+ // mark failure so the manager can coalesce further if over OS stream limits.
+ if (!this.#isClosed && fs.existsSync(dirPath)) {
+ hadExistingDirFailure = true;
+ }
+ }
+ }),
+ );
+ }
+
+ if (this.#isClosed) {
+ return;
+ }
+
+ // Unsubscribe any previous subscriptions that are no longer desired and whose
+ // remaining watched files (if any) are now covered by another active subscription.
+ for (const [existingKey, sub] of this.#extraSubscriptions.entries()) {
+ if (!desiredDirs.has(existingKey) && this.#canRemoveSubscription(existingKey)) {
+ this.#extraSubscriptions.delete(existingKey);
+ sub.unsubscribe().catch(() => {});
}
}
- for (const pendingDir of this.pendingSubscriptions.keys()) {
- if (dirLookupKey === pendingDir || isPathInside(dirLookupKey, pendingDir)) {
+
+ // If subscribing to an existing directory failed (e.g. macOS FSEvents per-process limit),
+ // dynamically lower the subscription budget and re-reconcile to coalesce into ancestors.
+ if (hadExistingDirFailure && desiredDirs.size > 1 && this.#maxSubscriptions > 1) {
+ const nextMax =
+ this.#extraSubscriptions.size > 0
+ ? Math.max(1, Math.floor(this.#extraSubscriptions.size / 2))
+ : Math.max(1, Math.floor(Math.min(this.#maxSubscriptions, desiredDirs.size) / 2));
+
+ if (nextMax < desiredDirs.size && nextMax < this.#maxSubscriptions) {
+ this.#maxSubscriptions = nextMax;
+ this.#shrinkBeforeSubscribe = true;
+ this.#needsReconcile = true;
+ }
+ }
+ }
+
+ /**
+ * Checks whether a directory lookup key is already covered by an active subscription.
+ */
+ #isCoveredByActiveSubscription(dirLookupKey: string): boolean {
+ for (const existingDir of this.#extraSubscriptions.keys()) {
+ if (dirLookupKey === existingDir || isPathInside(dirLookupKey, existingDir)) {
return true;
}
}
@@ -509,47 +783,196 @@ class ParcelExternalManager {
return false;
}
- private async ensureDirWatched(dirPath: string, dirKey: string): Promise {
- if (this.isCoveredByExistingExternal(dirKey)) {
- return;
+ /**
+ * Determines whether an existing subscription can be safely removed without leaving
+ * any remaining watched target directories uncovered.
+ */
+ #canRemoveSubscription(subKey: string): boolean {
+ for (const targetDirKey of this.#externalDirFiles.keys()) {
+ if (targetDirKey === subKey || isPathInside(targetDirKey, subKey)) {
+ let coveredByOther = false;
+ for (const otherSubKey of this.#extraSubscriptions.keys()) {
+ if (
+ otherSubKey !== subKey &&
+ (targetDirKey === otherSubKey || isPathInside(targetDirKey, otherSubKey))
+ ) {
+ coveredByOther = true;
+ break;
+ }
+ }
+ if (!coveredByOther) {
+ return false;
+ }
+ }
}
- const subPromise = this.parcelWatcher.subscribe(
- dirPath,
- (err, events) => {
- if (!err) {
- this.handleEvents(events);
+ return true;
+ }
+
+ /**
+ * Computes the minimal set of external directories to subscribe to (mapped from `dirKey` to `dirPath`),
+ * subsuming nested directories and coalescing branching ancestors to stay within `#maxSubscriptions`.
+ */
+ #computeDesiredDirectories(): Map {
+ if (this.#externalDirFiles.size === 0) {
+ return new Map();
+ }
+
+ const nodesByKey = new Map();
+ const roots: DirTrieNode[] = [];
+
+ for (const [dirKey, { dirPath }] of this.#externalDirFiles.entries()) {
+ const chain: { dirKey: string; dirPath: string }[] = [];
+ let currentKey = dirKey;
+ let currentPath = dirPath;
+ while (true) {
+ chain.push({ dirKey: currentKey, dirPath: currentPath });
+ const parentKey = getDirectoryPath(currentKey);
+ if (parentKey === currentKey) {
+ break;
}
- },
- {
- ignore: this.options?.ignored,
- },
- );
+ currentKey = parentKey;
+ currentPath = getDirectoryPath(currentPath);
+ }
- this.pendingSubscriptions.set(dirKey, subPromise);
+ let parentNode: DirTrieNode | undefined;
+ for (let i = chain.length - 1; i >= 0; i--) {
+ const { dirKey: nodeKey, dirPath: nodePath } = chain[i];
+ const depth = chain.length - 1 - i;
+ let node = nodesByKey.get(nodeKey);
+ if (!node) {
+ node = {
+ dirKey: nodeKey,
+ dirPath: nodePath,
+ depth,
+ parent: parentNode,
+ children: new Map(),
+ isTarget: false,
+ leafCount: 0,
+ };
+ nodesByKey.set(nodeKey, node);
+ if (parentNode) {
+ parentNode.children.set(nodeKey, node);
+ } else {
+ roots.push(node);
+ }
+ }
+ parentNode = node;
+ }
- try {
- const sub = await subPromise;
- this.pendingSubscriptions.delete(dirKey);
+ if (parentNode) {
+ parentNode.isTarget = true;
+ }
+ }
+
+ const initSubtree = (node: DirTrieNode): number => {
+ if (node.isTarget) {
+ node.children.clear();
+ node.leafCount = 1;
+
+ return 1;
+ }
+
+ let count = 0;
+ for (const child of node.children.values()) {
+ count += initSubtree(child);
+ }
+ node.leafCount = count;
- if (this.externalDirFiles.has(dirKey) && !this.isCoveredByExistingExternal(dirKey)) {
- this.extraSubscriptions.set(dirKey, sub);
+ return count;
+ };
- // Subsume any nested child subscriptions that are now covered by this parent subscription
- for (const [childDir, childSub] of this.extraSubscriptions.entries()) {
- if (childDir !== dirKey && isPathInside(childDir, dirKey)) {
- this.extraSubscriptions.delete(childDir);
- childSub.unsubscribe().catch(() => {});
+ let totalLeaves = 0;
+ for (const root of roots) {
+ totalLeaves += initSubtree(root);
+ }
+
+ if (totalLeaves > this.#maxSubscriptions) {
+ // Tier 1: non-ancestors of workspaceRoot (e.g., /libs, /node_modules)
+ // Tier 2: ancestors of workspaceRoot (e.g., when sibling apps/libs are directly under it)
+ const tier1ByDepth = new Map();
+ const tier2ByDepth = new Map();
+
+ const collectInternalNodes = (node: DirTrieNode) => {
+ if (node.isTarget) {
+ return;
+ }
+ if (node.parent !== undefined && node.leafCount > 1) {
+ const isWorkspaceAncestor = isPathInside(this.#rootDirLookupKey, node.dirKey);
+ const bucketMap = isWorkspaceAncestor ? tier2ByDepth : tier1ByDepth;
+ let bucket = bucketMap.get(node.depth);
+ if (!bucket) {
+ bucket = [];
+ bucketMap.set(node.depth, bucket);
}
+ bucket.push(node);
}
- } else {
- sub.unsubscribe().catch(() => {});
+ for (const child of node.children.values()) {
+ collectInternalNodes(child);
+ }
+ };
+
+ for (const root of roots) {
+ collectInternalNodes(root);
}
- } catch {
- // Ignore subscription errors for missing or restricted external directories
- } finally {
- this.pendingSubscriptions.delete(dirKey);
+
+ const collapseTier = (byDepth: Map) => {
+ const sortedLevels = Array.from(byDepth.entries()).sort(([a], [b]) => b - a);
+ for (const [, nodes] of sortedLevels) {
+ if (totalLeaves <= this.#maxSubscriptions) {
+ return;
+ }
+
+ const candidates = nodes
+ .filter((n) => n.leafCount > 1 && !hasTargetAncestor(n))
+ .sort((a, b) => b.leafCount - a.leafCount || a.dirKey.localeCompare(b.dirKey));
+
+ for (const candidate of candidates) {
+ if (totalLeaves <= this.#maxSubscriptions) {
+ return;
+ }
+ if (candidate.leafCount <= 1 || hasTargetAncestor(candidate)) {
+ continue;
+ }
+
+ const reduction = candidate.leafCount - 1;
+ candidate.isTarget = true;
+ candidate.children.clear();
+ candidate.leafCount = 1;
+ totalLeaves -= reduction;
+
+ let ancestor = candidate.parent;
+ while (ancestor) {
+ ancestor.leafCount -= reduction;
+ ancestor = ancestor.parent;
+ }
+ }
+ }
+ };
+
+ collapseTier(tier1ByDepth);
+ if (totalLeaves > this.#maxSubscriptions) {
+ collapseTier(tier2ByDepth);
+ }
+ }
+
+ const desired = new Map();
+ const collectTargets = (node: DirTrieNode) => {
+ if (node.isTarget) {
+ desired.set(node.dirKey, node.dirPath);
+
+ return;
+ }
+ for (const child of node.children.values()) {
+ collectTargets(child);
+ }
+ };
+
+ for (const root of roots) {
+ collectTargets(root);
}
+
+ return desired;
}
}
@@ -609,7 +1032,9 @@ async function createParcelWatcher(
const externalManager = new ParcelExternalManager(
parcelWatcher,
options,
+ rootDirPosix,
rootDirLookupKey,
+ isCaseSensitive,
handleEvents,
);
@@ -629,7 +1054,7 @@ async function createParcelWatcher(
const lookupKey = toLookupKey(posixPath, isCaseSensitive);
if (!watchedFiles.has(lookupKey)) {
watchedFiles.add(lookupKey);
- void externalManager.ensureWatched(posixPath, lookupKey);
+ externalManager.watchFile(posixPath, lookupKey);
}
}
},
@@ -660,92 +1085,94 @@ async function createParcelWatcher(
return buildWatcher;
}
-/**
- * Manages selective node_modules watching for Chokidar.
- *
- * During Chokidar's initial scan, the allowed packages set is empty, causing Chokidar to prune the entire
- * node_modules directory immediately and avoid blocking the 'ready' event for minutes.
- * Packages are dynamically allowed and watched at the package root level as files are added via `watcher.add`.
- * Tracking files per package allows reference-counting so that package directories are unwatched when no
- * longer needed.
- */
-class ChokidarNodeModulesManager {
- private readonly allowedPackages = new Map>();
-
- constructor(private readonly isCaseSensitive: boolean) {}
-
- registerPackage(
- posixPath: string,
- lookupKey: string,
- ): { isPackage: boolean; newPkgDir?: string } {
- const packageDir = extractNodeModulesPackageDir(posixPath);
- if (!packageDir) {
- return { isPackage: false };
- }
-
- const packageKey = toLookupKey(packageDir, this.isCaseSensitive);
- let watchedInPkg = this.allowedPackages.get(packageKey);
- if (!watchedInPkg) {
- watchedInPkg = new Set();
- this.allowedPackages.set(packageKey, watchedInPkg);
- watchedInPkg.add(lookupKey);
-
- return { isPackage: true, newPkgDir: packageDir };
- }
-
- watchedInPkg.add(lookupKey);
+function createChokidarIgnored(
+ ignoredPatterns: string[] | undefined,
+ isCaseSensitive: boolean,
+ watchedFiles: ReadonlySet,
+): Chokidar.Matcher[] {
+ // Strip static node_modules ignore patterns (e.g. `**/node_modules/**` from setupWatcher).
+ // If left in place, picomatch would unconditionally ignore all node_modules files and prevent
+ // watching explicitly added files inside node_modules.
+ const customIgnored =
+ ignoredPatterns
+ ?.filter((pattern) => {
+ const base = toPosixPathNormalized(pattern).replace(/\/\*\*$/, '');
- return { isPackage: true };
- }
+ return base !== NODE_MODULES && !base.endsWith(`/${NODE_MODULES}`);
+ })
+ .map((pattern) => {
+ if (/[*?[\]{}()]/.test(pattern)) {
+ const isMatch = picomatch(pattern, { dot: true });
- removePackageFile(
- posixPath: string,
- lookupKey: string,
- ): { isPackage: boolean; unwatchPkgDir?: string } {
- const packageDir = extractNodeModulesPackageDir(posixPath);
- if (!packageDir) {
- return { isPackage: false };
- }
+ return (filePath: string) => isMatch(toPosixPathNormalized(filePath));
+ }
- const packageKey = toLookupKey(packageDir, this.isCaseSensitive);
- const watchedInPkg = this.allowedPackages.get(packageKey);
- if (watchedInPkg) {
- watchedInPkg.delete(lookupKey);
- if (watchedInPkg.size === 0) {
- this.allowedPackages.delete(packageKey);
+ return { path: toPosixPathNormalized(pattern), recursive: true };
+ }) ?? [];
- return { isPackage: true, unwatchPkgDir: packageDir };
+ // When watching a directory (e.g. projectRoot via NG_BUILD_WATCH_ROOT), prune `node_modules`
+ // directories unless explicitly added to `watchedFiles`. Explicitly added files inside
+ // `node_modules` do not end with `/node_modules` and remain watchable.
+ return [
+ ...customIgnored,
+ (filePath: string) => {
+ if (!filePath.includes(NODE_MODULES)) {
+ return false;
}
- }
-
- return { isPackage: true };
- }
-
- isIgnored(filePath: string): boolean {
- // Fast path: avoid expensive normalization for non-node_modules files
- if (!filePath.includes(NODE_MODULES)) {
- return false;
- }
- const posixPath = toPosixPathNormalized(filePath);
- const lookupKey = toLookupKey(posixPath, this.isCaseSensitive);
+ const posixPath = toPosixPathNormalized(filePath);
+ const lookupKey = toLookupKey(posixPath, isCaseSensitive);
- if (!`${lookupKey}/`.includes(NODE_MODULES_SEGMENT)) {
- return false;
- }
+ return (
+ (lookupKey === NODE_MODULES || lookupKey.endsWith(`/${NODE_MODULES}`)) &&
+ !watchedFiles.has(lookupKey)
+ );
+ },
+ ];
+}
- if (this.allowedPackages.has(lookupKey)) {
- return false;
- }
+interface ChokidarBaselineEntry {
+ posixPath: string;
+ mtimeMs?: number;
+ size?: number;
+}
- for (const pkg of this.allowedPackages.keys()) {
- if (isPathInside(lookupKey, pkg)) {
- return false;
+// Chokidar initializes file watchers asynchronously (`await stat(path)` followed by
+// `fs.watch` or `fs.watchFile`). If a file is modified or recreated immediately after
+// `watcher.add()` is called, Chokidar may capture the post-modification state as its initial
+// baseline (or suppress the initial `'add'` event due to `ignoreInitial: true`) and miss the
+// change. Re-statting after a short delay catches any modifications or recreations that occurred
+// during asynchronous watcher registration, while `fileStats` deduplicates if Chokidar also fired.
+async function checkChokidarBaselines(
+ baselineStats: ReadonlyMap,
+ watchedFiles: ReadonlySet,
+ fileStats: ReadonlyMap,
+ watcher: Chokidar.FSWatcher,
+ handleEvent: (type: 'added' | 'modified' | 'removed', rawPath: string) => void,
+): Promise {
+ await Promise.all(
+ Array.from(baselineStats, async ([lookupKey, baseline]) => {
+ if (!watchedFiles.has(lookupKey)) {
+ return;
+ }
+ const currentStat = await fs.promises.stat(baseline.posixPath).catch(() => null);
+ if (!watchedFiles.has(lookupKey) || !currentStat?.isFile()) {
+ return;
}
- }
- return true;
- }
+ if (baseline.mtimeMs === undefined || baseline.size === undefined) {
+ const recorded = fileStats.get(lookupKey);
+ if (!recorded) {
+ watcher.add(baseline.posixPath);
+ handleEvent('added', path.normalize(baseline.posixPath));
+ } else if (currentStat.mtimeMs !== recorded.mtimeMs || currentStat.size !== recorded.size) {
+ handleEvent('modified', path.normalize(baseline.posixPath));
+ }
+ } else if (currentStat.mtimeMs !== baseline.mtimeMs || currentStat.size !== baseline.size) {
+ handleEvent('modified', path.normalize(baseline.posixPath));
+ }
+ }),
+ );
}
async function createChokidarWatcher(
@@ -755,43 +1182,19 @@ async function createChokidarWatcher(
const chokidar = chokidarModule ?? (await import('chokidar'));
const watchedFiles = new Set();
const fileStats = new Map();
+ const pendingTimers = new Set>();
- let queue: WatcherQueue;
- if (options?.polling) {
- const pollingInterval = options.interval ?? 100;
- const debounceMs = Math.min(250, Math.max(100, Math.ceil(pollingInterval * 1.5)));
- const maxWaitMs = Math.max(500, debounceMs * 3);
- queue = new WatcherQueue(debounceMs, maxWaitMs);
- } else {
- queue = new WatcherQueue();
- }
+ const pollingInterval = options?.interval ?? 100;
+ const debounceMs = Math.min(250, Math.max(100, Math.ceil(pollingInterval * 1.5)));
+ const queue = options?.polling
+ ? new WatcherQueue(debounceMs, Math.max(500, debounceMs * 3))
+ : new WatcherQueue();
const rootDir = options?.cwd ?? process.cwd();
const isCaseSensitive = isFileSystemCaseSensitive(rootDir);
- const rootDirPosix = toPosixPathNormalized(rootDir);
- const rootDirLookupKey = toLookupKey(rootDirPosix, isCaseSensitive);
-
- const nodeModulesManager = new ChokidarNodeModulesManager(isCaseSensitive);
-
- // Strip static node_modules ignore patterns (e.g. `**/node_modules/**` from setupWatcher).
- // If left in place, picomatch would unconditionally ignore all node_modules files and override
- // our dynamic package allowlist above.
- const customIgnored =
- options?.ignored
- ?.filter((pattern) => !pattern.includes(NODE_MODULES))
- .map((pattern) => {
- if (/[*?[\]{}()]/.test(pattern)) {
- const isMatch = picomatch(pattern, { dot: true });
+ const ignored = createChokidarIgnored(options?.ignored, isCaseSensitive, watchedFiles);
- return (filePath: string) => isMatch(toPosixPathNormalized(filePath));
- }
-
- return { path: toPosixPathNormalized(pattern), recursive: true };
- }) ?? [];
-
- const ignored = [...customIgnored, (filePath: string) => nodeModulesManager.isIgnored(filePath)];
-
- const watcher = chokidar.watch(rootDir, {
+ const watcher = chokidar.watch([], {
ignoreInitial: true,
ignored,
followSymlinks: options?.followSymlinks,
@@ -799,13 +1202,10 @@ async function createChokidarWatcher(
interval: options?.interval,
});
- const initTime = Date.now();
+ // Prevent unhandled watcher errors (such as EMFILE or EACCES) from crashing the process.
+ watcher.on('error', () => {});
- // Wait for the watcher to complete its initial filesystem scan before returning.
- // With `ignoreInitial: true`, any file visited during the initial scan is treated as the initial baseline
- // and will not emit 'add' or 'change' events. Awaiting 'ready' ensures that rapid file modifications
- // made right after watcher setup (e.g. in rebuild tests) are not swallowed as initial files.
- await once(watcher, 'ready');
+ const initTime = Date.now();
const handleEvent = (type: 'added' | 'modified' | 'removed', rawPath: string) => {
const posixPath = toPosixPathNormalized(rawPath);
@@ -822,14 +1222,10 @@ async function createChokidarWatcher(
}
const stat = fs.statSync(rawPath, { throwIfNoEntry: false });
- if (!stat) {
- return;
- }
-
// Ignore historical events from before watcher initialization, but allow a 1000 ms window
// to account for coarse filesystem timestamp resolution (e.g., ext4/overlayfs integer second
// mtime truncation on Linux) where files modified during startup may have truncated .000 ms mtimes.
- if (stat.mtimeMs < initTime - 1000) {
+ if (!stat || stat.mtimeMs < initTime - 1000) {
return;
}
@@ -847,11 +1243,55 @@ async function createChokidarWatcher(
queue.addChange(type, rawPath);
};
+ const scheduleBaselineCheck = (baselineStats: ReadonlyMap) => {
+ if (baselineStats.size === 0) {
+ return;
+ }
+
+ const timer = setTimeout(() => {
+ pendingTimers.delete(timer);
+ void checkChokidarBaselines(baselineStats, watchedFiles, fileStats, watcher, handleEvent);
+ }, 50);
+ timer.unref();
+ pendingTimers.add(timer);
+ };
+
watcher.on('add', (path) => handleEvent('added', path));
watcher.on('change', (path) => handleEvent('modified', path));
- watcher.on('unlink', (path) => handleEvent('removed', path));
+ watcher.on('unlink', (rawPath) => {
+ const posixPath = toPosixPathNormalized(rawPath);
+ const lookupKey = toLookupKey(posixPath, isCaseSensitive);
+ if (!isPathWatched(lookupKey, watchedFiles)) {
+ return;
+ }
- const buildWatcher: BuildWatcher = {
+ // When Chokidar processes a file removal, it closes the underlying file watcher unless only a
+ // single directory is tracked (`_watched.size === 1`). Re-adding a directly watched path
+ // ensures Chokidar continues watching either the recreated file (if replaced within the atomic
+ // window) or its parent directory for future recreation.
+ if (watchedFiles.has(lookupKey)) {
+ fileStats.delete(lookupKey);
+ watcher.add(posixPath);
+ const stat = fs.statSync(rawPath, { throwIfNoEntry: false });
+ if (stat?.isFile()) {
+ handleEvent('modified', rawPath);
+ scheduleBaselineCheck(
+ new Map([[lookupKey, { posixPath, mtimeMs: stat.mtimeMs, size: stat.size }]]),
+ );
+
+ return;
+ }
+
+ handleEvent('removed', rawPath);
+ scheduleBaselineCheck(new Map([[lookupKey, { posixPath }]]));
+
+ return;
+ }
+
+ handleEvent('removed', rawPath);
+ });
+
+ return {
[Symbol.asyncIterator]() {
return this;
},
@@ -878,28 +1318,23 @@ async function createChokidarWatcher(
add(paths) {
const targets = typeof paths === 'string' ? [paths] : paths;
const newPaths: string[] = [];
+ const baselineStats = new Map();
+
for (const p of targets) {
const posixPath = toPosixPathNormalized(p);
const lookupKey = toLookupKey(posixPath, isCaseSensitive);
if (!watchedFiles.has(lookupKey)) {
watchedFiles.add(lookupKey);
-
- // For files inside node_modules, register their package directory. Only newly encountered
- // package directories need to be added to Chokidar.
- const { isPackage, newPkgDir } = nodeModulesManager.registerPackage(posixPath, lookupKey);
- if (newPkgDir) {
- newPaths.push(newPkgDir);
- } else if (
- !isPackage &&
- !isPathInside(lookupKey, rootDirLookupKey) &&
- lookupKey !== rootDirLookupKey
- ) {
- newPaths.push(posixPath);
+ newPaths.push(posixPath);
+ const stat = fs.statSync(posixPath, { throwIfNoEntry: false });
+ if (stat?.isFile()) {
+ baselineStats.set(lookupKey, { posixPath, mtimeMs: stat.mtimeMs, size: stat.size });
}
}
}
if (newPaths.length > 0) {
watcher.add(newPaths);
+ scheduleBaselineCheck(baselineStats);
}
},
@@ -912,21 +1347,7 @@ async function createChokidarWatcher(
if (watchedFiles.has(lookupKey)) {
watchedFiles.delete(lookupKey);
fileStats.delete(lookupKey);
-
- // When the last watched file in a package is removed, unwatch the package directory.
- const { isPackage, unwatchPkgDir } = nodeModulesManager.removePackageFile(
- posixPath,
- lookupKey,
- );
- if (unwatchPkgDir) {
- removePaths.push(unwatchPkgDir);
- } else if (
- !isPackage &&
- !isPathInside(lookupKey, rootDirLookupKey) &&
- lookupKey !== rootDirLookupKey
- ) {
- removePaths.push(posixPath);
- }
+ removePaths.push(posixPath);
}
}
if (removePaths.length > 0) {
@@ -935,13 +1356,15 @@ async function createChokidarWatcher(
},
async close() {
+ for (const timer of pendingTimers) {
+ clearTimeout(timer);
+ }
+ pendingTimers.clear();
try {
await watcher.close();
} finally {
queue.close();
}
},
- };
-
- return buildWatcher;
+ } satisfies BuildWatcher;
}
diff --git a/packages/angular/build/src/utils/watcher_spec.ts b/packages/angular/build/src/utils/watcher_spec.ts
index 547ad2695f90..ef7a14d831d2 100644
--- a/packages/angular/build/src/utils/watcher_spec.ts
+++ b/packages/angular/build/src/utils/watcher_spec.ts
@@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.dev/license
*/
+import type * as ParcelWatcher from '@parcel/watcher';
import assert from 'node:assert';
import * as fs from 'node:fs';
import * as path from 'node:path';
@@ -13,6 +14,7 @@ import { setTimeout } from 'node:timers/promises';
import {
type BuildWatcher,
ChangedFiles,
+ ParcelExternalManager,
createWatcher,
extractNodeModulesPackageDir,
getDirectoryPath,
@@ -773,7 +775,7 @@ describe('Watcher', () => {
}
}, 10000);
- it('should unwatch linked package directory when all its files are removed via watcher.remove', async () => {
+ it('should unwatch linked package file when removed via watcher.remove', async () => {
const externalDir = fs.mkdtempSync(path.join(TMP_DIR, 'watcher-remove-npm-link-'));
let watcher: BuildWatcher | undefined;
@@ -811,7 +813,7 @@ describe('Watcher', () => {
// Remove the linked file from the watcher
watcher.remove(linkedFile);
- // Allow a brief moment for Chokidar to asynchronously complete unwatching the package directory
+ // Allow a brief moment for Chokidar to asynchronously complete unwatching the file
await setTimeout(250);
// Modify both the removed linked file and the regular file
@@ -829,5 +831,456 @@ describe('Watcher', () => {
fs.rmSync(externalDir, { recursive: true, force: true });
}
}, 10000);
+
+ it('should detect changes across multiple external directories when using @parcel/watcher', async () => {
+ const externalRoot = fs.mkdtempSync(path.join(TMP_DIR, 'parcel-external-spec-'));
+ let watcher: BuildWatcher | undefined;
+
+ try {
+ const lib1Dir = path.join(externalRoot, 'libs', 'lib-1', 'src');
+ const lib2Dir = path.join(externalRoot, 'libs', 'lib-2', 'src');
+ fs.mkdirSync(lib1Dir, { recursive: true });
+ fs.mkdirSync(lib2Dir, { recursive: true });
+
+ const file1 = path.join(lib1Dir, 'index.ts');
+ const file2 = path.join(lib2Dir, 'index.ts');
+ fs.writeFileSync(file1, 'export const a = 1;');
+ fs.writeFileSync(file2, 'export const b = 1;');
+
+ // Backdate initial file timestamps to earlier than `initTime - 1000` so that any
+ // delayed initial FSEvents replay from file creation is ignored by the watcher.
+ const pastTime = new Date(Date.now() - 5000);
+ fs.utimesSync(file1, pastTime, pastTime);
+ fs.utimesSync(file2, pastTime, pastTime);
+
+ watcher = await createWatcher({ cwd: tempDir });
+ watcher.add([file1, file2]);
+
+ await setTimeout(150);
+
+ const iterator = watcher[Symbol.asyncIterator]();
+
+ let nextPromise = iterator.next();
+ fs.writeFileSync(file1, 'export const a = 2;');
+ let result = await nextPromise;
+ expect(result.done).toBeFalsy();
+ expect(result.value?.all.some((f: string) => f.includes('lib-1'))).toBeTrue();
+
+ nextPromise = iterator.next();
+ fs.writeFileSync(file2, 'export const b = 2;');
+ result = await nextPromise;
+ expect(result.done).toBeFalsy();
+ expect(result.value?.all.some((f: string) => f.includes('lib-2'))).toBeTrue();
+ } finally {
+ await watcher?.close();
+ fs.rmSync(externalRoot, { recursive: true, force: true });
+ }
+ }, 10000);
+
+ it('should detect file deletion and recreation when watching multiple files with followSymlinks: true', async () => {
+ const subDirA = path.join(tempDir, 'dir-a');
+ const subDirB = path.join(tempDir, 'dir-b');
+ fs.mkdirSync(subDirA);
+ fs.mkdirSync(subDirB);
+
+ const fileA = path.join(subDirA, 'a.ts');
+ const fileB = path.join(subDirB, 'b.ts');
+ fs.writeFileSync(fileA, 'export const a = 1;');
+ fs.writeFileSync(fileB, 'export const b = 1;');
+
+ const watcher = await createWatcher({
+ followSymlinks: true,
+ cwd: tempDir,
+ });
+
+ try {
+ watcher.add([fileA, fileB]);
+ await setTimeout(250);
+
+ const iterator = watcher[Symbol.asyncIterator]();
+
+ // Delete fileA and wait past Chokidar's atomic write window
+ fs.rmSync(fileA);
+ let result = await iterator.next();
+ expect(result.done).toBeFalsy();
+ expect(result.value?.removed.size).toBeGreaterThan(0);
+
+ await setTimeout(150);
+
+ // Recreate fileA and verify the watcher still detects it
+ fs.writeFileSync(fileA, 'export const a = 2;');
+ result = await iterator.next();
+ expect(result.done).toBeFalsy();
+ expect(result.value?.all.some((f: string) => f.includes('a.ts'))).toBeTrue();
+
+ // Modify recreated fileA again to ensure ongoing changes are tracked
+ await setTimeout(150);
+ fs.writeFileSync(fileA, 'export const a = 3;');
+ result = await iterator.next();
+ expect(result.done).toBeFalsy();
+ expect(result.value?.all.some((f: string) => f.includes('a.ts'))).toBeTrue();
+ } finally {
+ await watcher.close();
+ }
+ }, 10000);
+
+ it('should prune node_modules when watching root directory while watching added package files', async () => {
+ const nodeModulesDir = path.join(tempDir, 'node_modules');
+ const pkgDir = path.join(nodeModulesDir, 'some-pkg');
+ fs.mkdirSync(pkgDir, { recursive: true });
+
+ const watchedPkgFile = path.join(pkgDir, 'index.js');
+ const unwatchedPkgFile = path.join(pkgDir, 'other.js');
+ const rootFile = path.join(tempDir, 'main.ts');
+ fs.writeFileSync(watchedPkgFile, 'export const idx = 1;');
+ fs.writeFileSync(unwatchedPkgFile, 'export const other = 1;');
+ fs.writeFileSync(rootFile, 'export const main = 1;');
+
+ const pastTime = new Date(Date.now() - 5000);
+ fs.utimesSync(watchedPkgFile, pastTime, pastTime);
+ fs.utimesSync(unwatchedPkgFile, pastTime, pastTime);
+ fs.utimesSync(rootFile, pastTime, pastTime);
+
+ const watcher = await createWatcher({
+ followSymlinks: true,
+ cwd: tempDir,
+ });
+
+ try {
+ // Watch both the root directory and a specific file in node_modules
+ watcher.add([tempDir, watchedPkgFile]);
+ await setTimeout(250);
+
+ const iterator = watcher[Symbol.asyncIterator]();
+ const nextPromise = iterator.next();
+
+ // Modify unwatched file in node_modules (should be ignored even though tempDir is watched)
+ // and watched file in node_modules
+ fs.writeFileSync(unwatchedPkgFile, 'export const other = 2;');
+ fs.writeFileSync(watchedPkgFile, 'export const idx = 2;');
+
+ const result = await nextPromise;
+ expect(result.done).toBeFalsy();
+ const changed = result.value?.all ?? [];
+ expect(changed.some((f: string) => f.includes('index.js'))).toBeTrue();
+ expect(changed.some((f: string) => f.includes('other.js'))).toBeFalse();
+ } finally {
+ await watcher.close();
+ }
+ }, 10000);
+ });
+
+ describe('ParcelExternalManager', () => {
+ function createMockParcelWatcher(options?: {
+ failAfter?: number;
+ onSubscribe?: (dir: string, opts?: ParcelWatcher.Options) => void;
+ }) {
+ const activeDirs = new Set();
+ const subscribeHistory: { dir: string; options?: ParcelWatcher.Options }[] = [];
+ let totalCalls = 0;
+
+ const mockWatcher = {
+ subscribe: jasmine
+ .createSpy('subscribe')
+ .and.callFake(
+ async (
+ dir: string,
+ _cb: ParcelWatcher.SubscribeCallback,
+ opts?: ParcelWatcher.Options,
+ ): Promise => {
+ totalCalls++;
+ options?.onSubscribe?.(dir, opts);
+ if (options?.failAfter !== undefined && activeDirs.size >= options.failAfter) {
+ throw new Error('Error starting FSEvents stream');
+ }
+ activeDirs.add(dir);
+ subscribeHistory.push({ dir, options: opts });
+
+ return {
+ unsubscribe: async () => {
+ activeDirs.delete(dir);
+ },
+ };
+ },
+ ),
+ } as unknown as typeof ParcelWatcher;
+
+ return {
+ mockWatcher,
+ activeDirs,
+ subscribeHistory,
+ getTotalCalls: () => totalCalls,
+ };
+ }
+
+ it('should batch synchronous watchFile calls and subsume child directories added before parent', async () => {
+ const { mockWatcher, activeDirs, getTotalCalls } = createMockParcelWatcher();
+ const manager = new ParcelExternalManager(
+ mockWatcher,
+ undefined,
+ '/monorepo/apps/app',
+ '/monorepo/apps/app',
+ true,
+ () => {},
+ );
+
+ // Add deeper child directories first, then their parent directory in the same synchronous turn
+ manager.watchFile(
+ '/monorepo/libs/lib-1/src/components/button/button.ts',
+ '/monorepo/libs/lib-1/src/components/button/button.ts',
+ );
+ manager.watchFile(
+ '/monorepo/libs/lib-1/src/components/card/card.ts',
+ '/monorepo/libs/lib-1/src/components/card/card.ts',
+ );
+ manager.watchFile('/monorepo/libs/lib-1/src/index.ts', '/monorepo/libs/lib-1/src/index.ts');
+
+ await manager.flush();
+
+ // Should only ever have subscribed once to the parent '/monorepo/libs/lib-1/src'
+ expect(getTotalCalls()).toBe(1);
+ expect(Array.from(activeDirs)).toEqual(['/monorepo/libs/lib-1/src']);
+
+ await manager.close();
+ });
+
+ it('should normalize external node_modules paths to their package root directory', async () => {
+ const { mockWatcher, activeDirs, getTotalCalls } = createMockParcelWatcher();
+ const manager = new ParcelExternalManager(
+ mockWatcher,
+ undefined,
+ '/monorepo/apps/app',
+ '/monorepo/apps/app',
+ true,
+ () => {},
+ );
+
+ manager.watchFile(
+ '/monorepo/node_modules/my-pkg/fesm2022/my-pkg.mjs',
+ '/monorepo/node_modules/my-pkg/fesm2022/my-pkg.mjs',
+ );
+ manager.watchFile(
+ '/monorepo/node_modules/my-pkg/esm2022/sub/helper.mjs',
+ '/monorepo/node_modules/my-pkg/esm2022/sub/helper.mjs',
+ );
+ manager.watchFile(
+ '/monorepo/node_modules/@scope/scoped-pkg/fesm2022/index.mjs',
+ '/monorepo/node_modules/@scope/scoped-pkg/fesm2022/index.mjs',
+ );
+ manager.watchFile(
+ '/monorepo/node_modules/@scope/scoped-pkg/package.json',
+ '/monorepo/node_modules/@scope/scoped-pkg/package.json',
+ );
+
+ await manager.flush();
+
+ expect(getTotalCalls()).toBe(2);
+ expect(Array.from(activeDirs).sort()).toEqual([
+ '/monorepo/node_modules/@scope/scoped-pkg',
+ '/monorepo/node_modules/my-pkg',
+ ]);
+
+ // Removing one file from my-pkg should keep the package subscription active
+ manager.removeFile('/monorepo/node_modules/my-pkg/fesm2022/my-pkg.mjs');
+ await manager.flush();
+ expect(activeDirs.has('/monorepo/node_modules/my-pkg')).toBeTrue();
+
+ // Removing the last file from my-pkg should unsubscribe the package directory
+ manager.removeFile('/monorepo/node_modules/my-pkg/esm2022/sub/helper.mjs');
+ await manager.flush();
+ expect(activeDirs.has('/monorepo/node_modules/my-pkg')).toBeFalse();
+ expect(Array.from(activeDirs)).toEqual(['/monorepo/node_modules/@scope/scoped-pkg']);
+
+ await manager.close();
+ });
+
+ it('should coalesce large numbers of external library and node_modules directories into common ancestors within budget', async () => {
+ const { mockWatcher, activeDirs, getTotalCalls } = createMockParcelWatcher();
+ const manager = new ParcelExternalManager(
+ mockWatcher,
+ undefined,
+ '/monorepo/apps/app',
+ '/monorepo/apps/app',
+ true,
+ () => {},
+ 64,
+ );
+
+ // Simulate 600 sibling libraries and 200 hoisted node_modules packages (800 external dirs)
+ for (let i = 0; i < 600; i++) {
+ const file = `/monorepo/libs/lib-${i}/src/index.ts`;
+ manager.watchFile(file, file);
+ }
+ for (let i = 0; i < 200; i++) {
+ const file = `/monorepo/node_modules/pkg-${i}/dist/index.mjs`;
+ manager.watchFile(file, file);
+ }
+
+ await manager.flush();
+
+ // All 600 libs coalesce into '/monorepo/libs' and all 200 packages coalesce into '/monorepo/node_modules'
+ expect(getTotalCalls()).toBe(2);
+ expect(Array.from(activeDirs).sort()).toEqual(['/monorepo/libs', '/monorepo/node_modules']);
+
+ await manager.close();
+ });
+
+ it('should prioritize collapsing deeper branching subdirectories before broader ancestor directories', async () => {
+ const { mockWatcher, activeDirs } = createMockParcelWatcher();
+ const manager = new ParcelExternalManager(
+ mockWatcher,
+ undefined,
+ '/monorepo/apps/app',
+ '/monorepo/apps/app',
+ true,
+ () => {},
+ 3, // Budget of 3 subscriptions
+ );
+
+ // lib-1 has 4 component subdirectories, lib-2 and lib-3 have 1 each (total = 6 leaf dirs)
+ for (let c = 1; c <= 4; c++) {
+ const file = `/monorepo/libs/lib-1/src/comp-${c}/comp.ts`;
+ manager.watchFile(file, file);
+ }
+ manager.watchFile('/monorepo/libs/lib-2/src/index.ts', '/monorepo/libs/lib-2/src/index.ts');
+ manager.watchFile('/monorepo/libs/lib-3/src/index.ts', '/monorepo/libs/lib-3/src/index.ts');
+
+ await manager.flush();
+
+ // Collapsing lib-1/src reduces total leaves from 6 to 3, meeting the budget of 3
+ // without needing to collapse all of '/monorepo/libs'
+ expect(Array.from(activeDirs).sort()).toEqual([
+ '/monorepo/libs/lib-1/src',
+ '/monorepo/libs/lib-2/src',
+ '/monorepo/libs/lib-3/src',
+ ]);
+
+ await manager.close();
+ });
+
+ it('should ignore workspaceRoot when coalescing into an ancestor of workspaceRoot (Tier 2)', async () => {
+ const { mockWatcher, activeDirs, subscribeHistory } = createMockParcelWatcher();
+ const manager = new ParcelExternalManager(
+ mockWatcher,
+ { ignored: ['/monorepo/apps/app/dist'] },
+ '/monorepo/apps/app',
+ '/monorepo/apps/app',
+ true,
+ () => {},
+ 2, // Budget of 2 subscriptions
+ );
+
+ // Sibling apps/packages directly under /monorepo/apps (which is an ancestor of /monorepo/apps/app)
+ manager.watchFile(
+ '/monorepo/apps/shared-1/src/index.ts',
+ '/monorepo/apps/shared-1/src/index.ts',
+ );
+ manager.watchFile(
+ '/monorepo/apps/shared-2/src/index.ts',
+ '/monorepo/apps/shared-2/src/index.ts',
+ );
+ manager.watchFile(
+ '/monorepo/apps/shared-3/src/index.ts',
+ '/monorepo/apps/shared-3/src/index.ts',
+ );
+
+ await manager.flush();
+
+ expect(Array.from(activeDirs)).toEqual(['/monorepo/apps']);
+ expect(subscribeHistory.length).toBe(1);
+ expect(subscribeHistory[0].options?.ignore).toEqual([
+ '/monorepo/apps/app/dist',
+ '/monorepo/apps/app',
+ '/monorepo/apps/app/**',
+ ]);
+
+ await manager.close();
+ });
+
+ it('should dynamically lower budget and coalesce into ancestor when subscribe fails with FSEvents stream limit error', async () => {
+ const externalRoot = fs.mkdtempSync(path.join(TMP_DIR, 'parcel-fallback-spec-'));
+
+ try {
+ const rootPosix = toPosixPathNormalized(path.join(externalRoot, 'apps', 'app'));
+ const libFiles: string[] = [];
+ for (let i = 0; i < 6; i++) {
+ const libDir = path.join(externalRoot, 'libs', `lib-${i}`, 'src');
+ fs.mkdirSync(libDir, { recursive: true });
+ const file = toPosixPathNormalized(path.join(libDir, 'index.ts'));
+ fs.writeFileSync(file, 'export const x = 1;');
+ libFiles.push(file);
+ }
+
+ // Allow at most 2 active FSEvents streams even though manager budget starts at 64
+ const { mockWatcher, activeDirs } = createMockParcelWatcher({ failAfter: 2 });
+ const manager = new ParcelExternalManager(
+ mockWatcher,
+ undefined,
+ rootPosix,
+ rootPosix,
+ true,
+ () => {},
+ 64,
+ );
+
+ for (const file of libFiles) {
+ manager.watchFile(file, file);
+ }
+
+ await manager.flush();
+
+ // Should have shrunk and coalesced the 6 libraries into the single '/libs' ancestor directory
+ const expectedLibsDir = toPosixPathNormalized(path.join(externalRoot, 'libs'));
+ expect(Array.from(activeDirs)).toEqual([expectedLibsDir]);
+
+ await manager.close();
+ } finally {
+ fs.rmSync(externalRoot, { recursive: true, force: true });
+ }
+ });
+
+ it('should uncoalesce and subscribe to remaining leaf directories when removals bring count back within budget', async () => {
+ const { mockWatcher, activeDirs } = createMockParcelWatcher();
+ const manager = new ParcelExternalManager(
+ mockWatcher,
+ undefined,
+ '/monorepo/apps/app',
+ '/monorepo/apps/app',
+ true,
+ () => {},
+ 2, // Budget of 2 subscriptions
+ );
+
+ const file1 = '/monorepo/libs/lib-1/src/index.ts';
+ const file2 = '/monorepo/libs/lib-2/src/index.ts';
+ const file3 = '/monorepo/libs/lib-3/src/index.ts';
+
+ manager.watchFile(file1, file1);
+ manager.watchFile(file2, file2);
+ manager.watchFile(file3, file3);
+
+ await manager.flush();
+
+ // 3 directories exceed budget of 2, so they coalesce into '/monorepo/libs'
+ expect(Array.from(activeDirs)).toEqual(['/monorepo/libs']);
+
+ // Removing file3 brings remaining directories to 2, which fits within budget
+ manager.removeFile(file3);
+ await manager.flush();
+
+ expect(Array.from(activeDirs).sort()).toEqual([
+ '/monorepo/libs/lib-1/src',
+ '/monorepo/libs/lib-2/src',
+ ]);
+
+ // Removing the remaining files unsubscribes everything
+ manager.removeFile(file1);
+ manager.removeFile(file2);
+ await manager.flush();
+
+ expect(activeDirs.size).toBe(0);
+
+ await manager.close();
+ });
});
});
diff --git a/packages/angular/cli/package.json b/packages/angular/cli/package.json
index ef6e3407b670..f558e7a6293d 100644
--- a/packages/angular/cli/package.json
+++ b/packages/angular/cli/package.json
@@ -21,16 +21,16 @@
"@angular-devkit/core": "workspace:0.0.0-PLACEHOLDER",
"@angular-devkit/schematics": "workspace:0.0.0-PLACEHOLDER",
"@inquirer/prompts": "8.7.3",
- "@listr2/prompt-adapter-inquirer": "4.2.7",
+ "@listr2/prompt-adapter-inquirer": "4.3.1",
"@modelcontextprotocol/server": "2.3.1",
"@schematics/angular": "workspace:0.0.0-PLACEHOLDER",
"jsonc-parser": "3.3.1",
- "listr2": "11.1.1",
+ "listr2": "11.2.0",
"npm-package-arg": "14.0.0",
"parse5-html-rewriting-stream": "8.0.1",
"semver": "7.8.5",
"yargs": "18.2.0",
- "zod": "4.6.5"
+ "zod": "4.6.7"
},
"ng-update": {
"migrations": "@schematics/angular/migrations/migration-collection.json",
diff --git a/packages/angular/cli/src/commands/config/cli.ts b/packages/angular/cli/src/commands/config/cli.ts
index ae25f3839e22..ef7cfd95d5a5 100644
--- a/packages/angular/cli/src/commands/config/cli.ts
+++ b/packages/angular/cli/src/commands/config/cli.ts
@@ -133,9 +133,8 @@ export default class ConfigCommandModule
* ["a", 3, "foo", "bar", 2].
* @param path The JSON string to parse.
* @returns {(string|number)[]} The fragments for the string.
- * @private
*/
-function parseJsonPath(path: string): (string | number)[] {
+export function parseJsonPath(path: string): (string | number)[] {
const fragments = (path || '').split(/\./g);
const result: (string | number)[] = [];
@@ -155,7 +154,7 @@ function parseJsonPath(path: string): (string | number)[] {
const indices = match[2]
.slice(1, -1)
.split('][')
- .map((x) => (/^\d$/.test(x) ? +x : x.replace(/"|'/g, '')));
+ .map((x) => (/^\d+$/.test(x) ? +x : x.replace(/"|'/g, '')));
result.push(...indices);
}
}
diff --git a/packages/angular/cli/src/commands/config/cli_spec.ts b/packages/angular/cli/src/commands/config/cli_spec.ts
new file mode 100644
index 000000000000..dd8fe4790e16
--- /dev/null
+++ b/packages/angular/cli/src/commands/config/cli_spec.ts
@@ -0,0 +1,37 @@
+/**
+ * @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 { parseJsonPath } from './cli';
+
+describe('parseJsonPath', () => {
+ it('should parse single digit array indices', () => {
+ expect(parseJsonPath('a[3].foo.bar[2]')).toEqual(['a', 3, 'foo', 'bar', 2]);
+ });
+
+ it('should parse multi digit array indices', () => {
+ expect(parseJsonPath('projects.app.architect.build.options.styles[10]')).toEqual([
+ 'projects',
+ 'app',
+ 'architect',
+ 'build',
+ 'options',
+ 'styles',
+ 10,
+ ]);
+ expect(parseJsonPath('a[2][13].b')).toEqual(['a', 2, 13, 'b']);
+ });
+
+ it('should keep quoted keys as strings', () => {
+ expect(parseJsonPath('projects["test-project"].root')).toEqual([
+ 'projects',
+ 'test-project',
+ 'root',
+ ]);
+ expect(parseJsonPath(`a['10']`)).toEqual(['a', '10']);
+ });
+});
diff --git a/packages/angular/cli/src/commands/version/version-info.ts b/packages/angular/cli/src/commands/version/version-info.ts
index 128cc8ef5449..9709567e382b 100644
--- a/packages/angular/cli/src/commands/version/version-info.ts
+++ b/packages/angular/cli/src/commands/version/version-info.ts
@@ -104,6 +104,13 @@ export async function gatherVersionInfo(context: CommandContext): Promise {
+ let tempRoot: string;
+
+ beforeEach(async () => {
+ const baseTmpDir = process.env['TEST_TMPDIR'];
+ assert(baseTmpDir, 'TEST_TMPDIR is not set');
+ tempRoot = await mkdtemp(join(baseTmpDir, 'angular-cli-version-info-test-'));
+ });
+
+ afterEach(async () => {
+ await rm(tempRoot, { recursive: true, force: true });
+ });
+
+ function createContext(packageManager: PackageManager): CommandContext {
+ return { root: tempRoot, packageManager } as unknown as CommandContext;
+ }
+
+ it('should report the package manager version when it is available', async () => {
+ const packageManager = new PackageManager(
+ new MockHost(),
+ tempRoot,
+ SUPPORTED_PACKAGE_MANAGERS['npm'],
+ { version: '10.9.0' },
+ );
+
+ const info = await gatherVersionInfo(createContext(packageManager));
+
+ expect(info.system.packageManager).toEqual({ name: 'npm', version: '10.9.0' });
+ });
+
+ it('should not fail when the package manager is not installed', async () => {
+ const packageManager = new PackageManager(
+ new MockHost(),
+ tempRoot,
+ SUPPORTED_PACKAGE_MANAGERS['bun'],
+ {
+ initializationError: new Error(
+ `The project is configured to use 'bun', but it is not installed.`,
+ ),
+ },
+ );
+
+ const info = await gatherVersionInfo(createContext(packageManager));
+
+ expect(info.system.packageManager).toEqual({ name: 'bun', version: undefined });
+ });
+});
diff --git a/packages/angular/cli/src/package-managers/package-manager.ts b/packages/angular/cli/src/package-managers/package-manager.ts
index 234b54851232..272454c21cbd 100644
--- a/packages/angular/cli/src/package-managers/package-manager.ts
+++ b/packages/angular/cli/src/package-managers/package-manager.ts
@@ -393,25 +393,39 @@ export class PackageManager {
* Gets the name of the package in the current project.
*/
async getCurrentPackageName(): Promise {
+ try {
+ const content = await this.host.readFile(join(this.cwd, 'package.json'));
+ const { name } = JSON.parse(content) as { name?: unknown };
+ if (typeof name === 'string') {
+ return name;
+ }
+ } catch {
+ // Fall back to package manager command if reading file fails
+ }
+
if (this.descriptor.getPackageNameCommand) {
try {
const { stdout } = await this.#run(this.descriptor.getPackageNameCommand);
if (stdout) {
- return JSON.parse(stdout);
+ const name = JSON.parse(stdout);
+ if (typeof name === 'string') {
+ return name;
+ }
+
+ // In a workspace member npm prints an object keyed by workspace name instead of a string.
+ if (name && typeof name === 'object') {
+ const values = Object.values(name);
+ if (values.length === 1 && typeof values[0] === 'string') {
+ return values[0];
+ }
+ }
}
} catch {
- // Fall back to reading file if command fails
+ // Ignore command failure
}
}
- try {
- const content = await this.host.readFile(join(this.cwd, 'package.json'));
- const pkgJson = JSON.parse(content);
-
- return pkgJson.name;
- } catch {
- return undefined;
- }
+ return undefined;
}
/**
diff --git a/packages/angular/cli/src/package-managers/package-manager_spec.ts b/packages/angular/cli/src/package-managers/package-manager_spec.ts
index d500a435d0df..37e0d8aae113 100644
--- a/packages/angular/cli/src/package-managers/package-manager_spec.ts
+++ b/packages/angular/cli/src/package-managers/package-manager_spec.ts
@@ -378,6 +378,75 @@ describe('PackageManager', () => {
});
});
+ describe('getCurrentPackageName', () => {
+ it('should return the name from package.json without running the package manager command', async () => {
+ const pm = new PackageManager(host, '/repo/app', descriptor);
+ const readFileSpy = spyOn(host, 'readFile').and.resolveTo('{"name": "app"}');
+
+ expect(await pm.getCurrentPackageName()).toBe('app');
+ expect(readFileSpy).toHaveBeenCalledWith(jasmine.stringMatching(/package\.json$/));
+ expect(runCommandSpy).not.toHaveBeenCalled();
+ });
+
+ it('should fall back to the package manager command when reading package.json fails', async () => {
+ const pm = new PackageManager(host, '/repo/app/src', descriptor);
+ spyOn(host, 'readFile').and.rejectWith(new Error('ENOENT'));
+ runCommandSpy.and.resolveTo({ stdout: '"app"', stderr: '' });
+
+ expect(await pm.getCurrentPackageName()).toBe('app');
+ expect(runCommandSpy).toHaveBeenCalledWith(
+ descriptor.binary,
+ descriptor.getPackageNameCommand,
+ jasmine.objectContaining({ cwd: '/repo/app/src' }),
+ );
+ });
+
+ it('should extract the package name when npm prints a single-entry workspace object', async () => {
+ const pm = new PackageManager(host, '/repo/apps/app/src', descriptor);
+ spyOn(host, 'readFile').and.rejectWith(new Error('ENOENT'));
+ // Inside a workspace member, `npm pkg get name` prints `{ "app": "app" }` instead of `"app"`.
+ runCommandSpy.and.resolveTo({ stdout: '{\n "app": "app"\n}', stderr: '' });
+
+ expect(await pm.getCurrentPackageName()).toBe('app');
+ });
+
+ it('should return undefined when npm prints multiple workspace entries and package.json is unavailable', async () => {
+ const pm = new PackageManager(host, '/repo', descriptor);
+ spyOn(host, 'readFile').and.rejectWith(new Error('ENOENT'));
+ runCommandSpy.and.resolveTo({
+ stdout: '{\n "app-a": "app-a",\n "app-b": "app-b"\n}',
+ stderr: '',
+ });
+
+ expect(await pm.getCurrentPackageName()).toBeUndefined();
+ });
+ });
+
+ describe('getProjectDependencies', () => {
+ it('should list the dependencies of an npm workspace member', async () => {
+ const pm = new PackageManager(host, '/repo/apps/app', descriptor);
+ runCommandSpy.and.resolveTo({
+ stdout: JSON.stringify({
+ name: 'monorepo',
+ dependencies: {
+ app: {
+ version: '0.0.0',
+ resolved: 'file:../apps/app',
+ dependencies: { '@angular/core': { version: '22.0.0' } },
+ },
+ },
+ }),
+ stderr: '',
+ });
+ spyOn(host, 'readFile').and.resolveTo('{"name": "app"}');
+
+ const dependencies = await pm.getProjectDependencies();
+
+ expect([...dependencies.keys()]).toEqual(['@angular/core']);
+ expect(dependencies.get('@angular/core')?.version).toBe('22.0.0');
+ });
+ });
+
describe('initializationError', () => {
it('should throw initializationError when running commands', async () => {
const error = new Error('Not installed');
diff --git a/packages/angular/ssr/package.json b/packages/angular/ssr/package.json
index 6e3596ca6aae..a3049daf662d 100644
--- a/packages/angular/ssr/package.json
+++ b/packages/angular/ssr/package.json
@@ -22,7 +22,7 @@
"save": "dependencies"
},
"dependencies": {
- "beasties": "0.5.4",
+ "beasties": "0.5.5",
"tslib": "^2.3.0"
},
"peerDependencies": {
@@ -38,12 +38,12 @@
},
"devDependencies": {
"@angular-devkit/schematics": "workspace:*",
- "@angular/common": "22.3.0-next.1",
- "@angular/compiler": "22.3.0-next.1",
- "@angular/core": "22.3.0-next.1",
- "@angular/platform-browser": "22.3.0-next.1",
- "@angular/platform-server": "22.3.0-next.1",
- "@angular/router": "22.3.0-next.1",
+ "@angular/common": "22.3.0-next.2",
+ "@angular/compiler": "22.3.0-next.2",
+ "@angular/core": "22.3.0-next.2",
+ "@angular/platform-browser": "22.3.0-next.2",
+ "@angular/platform-server": "22.3.0-next.2",
+ "@angular/router": "22.3.0-next.2",
"@schematics/angular": "workspace:*"
},
"sideEffects": false,
diff --git a/packages/angular/ssr/src/app.ts b/packages/angular/ssr/src/app.ts
index 6c0202a8f9b3..517cf1e31727 100644
--- a/packages/angular/ssr/src/app.ts
+++ b/packages/angular/ssr/src/app.ts
@@ -163,14 +163,17 @@ export class AngularServerApp {
return null;
}
- const { redirectTo, status, renderMode, headers } = matchedRoute;
+ const { redirectTo, relativeRedirect, status, renderMode, headers } = matchedRoute;
if (redirectTo !== undefined) {
+ const location = joinUrlParts(
+ request.headers.get('X-Forwarded-Prefix') ?? '',
+ buildPathWithParams(redirectTo, url.pathname),
+ );
+
+ // Match Angular router behavior: relative redirects keep the query string.
return createRedirectResponse(
- joinUrlParts(
- request.headers.get('X-Forwarded-Prefix') ?? '',
- buildPathWithParams(redirectTo, url.pathname),
- ),
+ relativeRedirect ? location + url.search : location,
status,
headers,
);
diff --git a/packages/angular/ssr/src/routes/ng-routes.ts b/packages/angular/ssr/src/routes/ng-routes.ts
index ac83aae8cd4f..816155c4df01 100644
--- a/packages/angular/ssr/src/routes/ng-routes.ts
+++ b/packages/angular/ssr/src/routes/ng-routes.ts
@@ -31,7 +31,7 @@ import { AngularAppManifest, getAngularAppManifest } from '../manifest';
import { AngularBootstrap, isNgModule } from '../utils/ng';
import { promiseWithAbort } from '../utils/promise';
import { VALID_REDIRECT_RESPONSE_CODES, isValidRedirectResponseCode } from '../utils/redirect';
-import { addTrailingSlash, joinUrlParts, stripLeadingSlash } from '../utils/url';
+import { joinUrlParts, stripLeadingSlash } from '../utils/url';
import {
PrerenderFallback,
RenderMode,
@@ -146,6 +146,7 @@ type EntryPointToBrowserMapping = AngularAppManifest['entryPointToBrowserMapping
async function* handleRoute(options: {
metadata: ServerConfigRouteTreeNodeMetadata;
currentRoutePath: string;
+ parentRoute: string;
route: Route;
compiler: Compiler;
parentInjector: Injector;
@@ -158,6 +159,7 @@ async function* handleRoute(options: {
const {
metadata,
currentRoutePath,
+ parentRoute,
route,
compiler,
parentInjector,
@@ -168,19 +170,28 @@ async function* handleRoute(options: {
} = options;
const { redirectTo, loadChildren, loadComponent, children, ɵentryName } = route;
- if (ɵentryName && loadComponent) {
+ if (ɵentryName && (loadComponent || loadChildren)) {
appendPreloadToMetadata(ɵentryName, entryPointToBrowserMapping, metadata);
}
+ const parentRoutes = new Map();
+
if (metadata.renderMode === RenderMode.Prerender) {
- yield* handleSSGRoute(
+ for await (const result of handleSSGRoute(
serverConfigRouteTree,
typeof redirectTo === 'string' ? redirectTo : undefined,
+ parentRoute,
metadata,
parentInjector,
invokeGetPrerenderParams,
includePrerenderFallbackRoutes,
- );
+ )) {
+ if ('error' in result) {
+ yield result;
+ } else {
+ parentRoutes.set(result.route, result);
+ }
+ }
} else if (redirectTo !== undefined) {
if (metadata.status && !isValidRedirectResponseCode(metadata.status)) {
yield {
@@ -189,33 +200,23 @@ async function* handleRoute(options: {
`Please use one of the following redirect response codes: ${[...VALID_REDIRECT_RESPONSE_CODES.values()].join(', ')}.`,
};
} else if (typeof redirectTo === 'string') {
- yield {
+ parentRoutes.set(metadata.route, {
...metadata,
- redirectTo: resolveRedirectTo(metadata.route, redirectTo),
- };
+ redirectTo: resolveRedirectTo(parentRoute, redirectTo),
+ relativeRedirect: redirectTo[0] !== '/' ? true : undefined,
+ });
} else {
- yield metadata;
+ parentRoutes.set(metadata.route, metadata);
}
} else {
- yield metadata;
+ parentRoutes.set(metadata.route, metadata);
}
- // Recursively process child routes
- if (children?.length) {
- yield* traverseRoutesConfig({
- ...options,
- routes: children,
- parentRoute: currentRoutePath,
- parentPreloads: metadata.preload,
- });
- }
-
- // Load and process lazy-loaded child routes
- if (loadChildren) {
- if (ɵentryName) {
- appendPreloadToMetadata(ɵentryName, entryPointToBrowserMapping, metadata);
- }
+ // Recursively process child and lazy-loaded routes
+ let childRoutes: Route[] | undefined = children;
+ let childInjector = parentInjector;
+ if (!childRoutes?.length && loadChildren) {
const routeInjector = route.providers
? createEnvironmentInjector(
route.providers,
@@ -226,16 +227,48 @@ async function* handleRoute(options: {
const loadedChildRoutes = await loadChildrenHelper(route, compiler, routeInjector);
if (loadedChildRoutes) {
- const { routes: childRoutes, injector = routeInjector } = loadedChildRoutes;
- yield* traverseRoutesConfig({
- ...options,
- routes: childRoutes,
- parentInjector: injector,
- parentRoute: currentRoutePath,
- parentPreloads: metadata.preload,
- });
+ childRoutes = loadedChildRoutes.routes;
+ childInjector = loadedChildRoutes.injector ?? routeInjector;
+ }
+ }
+
+ if (!childRoutes?.length) {
+ yield* parentRoutes.values();
+
+ return;
+ }
+
+ const childResults: (RouteTreeNodeMetadata | { error: string })[] = [];
+ const overriddenParentRoutes = new Set();
+ const traverseChildRoutes = traverseRoutesConfig({
+ ...options,
+ routes: childRoutes,
+ parentInjector: childInjector,
+ parentRoute: currentRoutePath,
+ parentPreloads: metadata.preload,
+ });
+
+ for await (const result of traverseChildRoutes) {
+ if ('error' in result) {
+ childResults.push(result);
+ continue;
+ }
+
+ // If a child route resolves to the exact same path as the parent (i.e., an empty-path child),
+ // let the first matching child override the parent's metadata so accumulated preloads and
+ // redirects from the activated descendant chain are preserved.
+ if (parentRoutes.has(result.route)) {
+ if (!overriddenParentRoutes.has(result.route)) {
+ overriddenParentRoutes.add(result.route);
+ parentRoutes.set(result.route, result);
+ }
+ } else {
+ childResults.push(result);
}
}
+
+ yield* parentRoutes.values();
+ yield* childResults;
} catch (error) {
yield {
error: `Error in handleRoute for '${options.currentRoutePath}': ${(error as Error).message}`,
@@ -340,10 +373,7 @@ async function* traverseRoutesConfig(options: {
renderMode: RenderMode.Prerender,
...matchedMetaData,
preload: parentPreloads,
- // Match Angular router behavior
- // ['one', 'two', ''] -> 'one/two/'
- // ['one', 'two', 'three'] -> 'one/two/three'
- route: path === '' ? addTrailingSlash(currentRoutePath) : currentRoutePath,
+ route: currentRoutePath,
presentInClientRouter: undefined,
},
currentRoutePath,
@@ -392,6 +422,7 @@ function appendPreloadToMetadata(
*
* @param serverConfigRouteTree - The tree representing the server's routing setup.
* @param redirectTo - Optional path to redirect to, if specified.
+ * @param parentRoute - The path of the parent route.
* @param metadata - The metadata associated with the route tree node.
* @param parentInjector - The dependency injection container for the parent route.
* @param invokeGetPrerenderParams - A flag indicating whether to invoke the `getPrerenderParams` function.
@@ -401,6 +432,7 @@ function appendPreloadToMetadata(
async function* handleSSGRoute(
serverConfigRouteTree: RouteTree | undefined,
redirectTo: string | undefined,
+ parentRoute: string,
metadata: ServerConfigRouteTreeNodeMetadata,
parentInjector: Injector,
invokeGetPrerenderParams: boolean,
@@ -420,7 +452,8 @@ async function* handleSSGRoute(
}
if (redirectTo !== undefined) {
- meta.redirectTo = resolveRedirectTo(currentRoutePath, redirectTo);
+ meta.redirectTo = resolveRedirectTo(parentRoute, redirectTo);
+ meta.relativeRedirect = redirectTo[0] !== '/' ? true : undefined;
}
const isCatchAllRoute = CATCH_ALL_REGEXP.test(currentRoutePath);
@@ -478,7 +511,10 @@ async function* handleSSGRoute(
redirectTo:
redirectTo === undefined
? undefined
- : resolveRedirectTo(routeWithResolvedParams, redirectTo),
+ : resolveRedirectTo(
+ parentRoute.replace(URL_PARAMETER_GLOBAL_REGEXP, replacer),
+ redirectTo,
+ ),
};
}
} catch (error) {
@@ -533,24 +569,24 @@ function handlePrerenderParamsReplacement(
* Resolves the `redirectTo` property for a given route.
*
* This function processes the `redirectTo` property to ensure that it correctly
- * resolves relative to the current route path. If `redirectTo` is an absolute path,
- * it is returned as is. If it is a relative path, it is resolved based on the current route path.
+ * resolves relative to the parent route path. If `redirectTo` is an absolute path,
+ * it is returned as is. If it is a relative path, it is resolved based on the parent route path,
+ * and, like in the Angular router, its query and fragment are ignored.
*
- * @param routePath - The current route path.
+ * @param parentRoute - The path of the parent route.
* @param redirectTo - The target path for redirection.
* @returns The resolved redirect path as a string.
*/
-function resolveRedirectTo(routePath: string, redirectTo: string): string {
+function resolveRedirectTo(parentRoute: string, redirectTo: string): string {
if (redirectTo[0] === '/') {
// If the redirectTo path is absolute, return it as is.
return redirectTo;
}
- // Resolve relative redirectTo based on the current route path.
- const segments = routePath.replace(URL_PARAMETER_GLOBAL_REGEXP, '*').split('/');
- segments.pop(); // Remove the last segment to make it relative.
+ // Match Angular router behavior: replace all segments matched by the route.
+ const [path] = redirectTo.split(/[?#]/, 1);
- return joinUrlParts(...segments, redirectTo);
+ return joinUrlParts(parentRoute.replace(URL_PARAMETER_GLOBAL_REGEXP, '*'), path);
}
/**
diff --git a/packages/angular/ssr/src/routes/route-tree.ts b/packages/angular/ssr/src/routes/route-tree.ts
index ff689a3c90f5..253783a5f13c 100644
--- a/packages/angular/ssr/src/routes/route-tree.ts
+++ b/packages/angular/ssr/src/routes/route-tree.ts
@@ -31,6 +31,9 @@ export interface RouteTreeNodeMetadata {
*/
redirectTo?: string;
+ /** Indicates if `redirectTo` was defined as a relative path. */
+ relativeRedirect?: boolean;
+
/**
* The route path for this node.
*
diff --git a/packages/angular/ssr/test/app_spec.ts b/packages/angular/ssr/test/app_spec.ts
index b317f99f1d3a..8d8ee9add00b 100644
--- a/packages/angular/ssr/test/app_spec.ts
+++ b/packages/angular/ssr/test/app_spec.ts
@@ -88,6 +88,8 @@ describe('AngularServerApp', () => {
{ path: 'redirect/relative', redirectTo: 'home' },
{ path: 'redirect/:param/relative', redirectTo: 'home' },
{ path: 'redirect/absolute', redirectTo: '/home' },
+ { path: 'redirect-with-query', redirectTo: 'home?param=value' },
+ { path: 'redirect-nested/:param', children: [{ path: 'old', redirectTo: 'new' }] },
{
path: 'redirect-to-function',
redirectTo: () => 'home',
@@ -204,24 +206,52 @@ describe('AngularServerApp', () => {
expect(response?.status).toBe(302);
});
- it('should correctly handle relative nested redirects', async () => {
+ it('should correctly handle relative redirects on multi-segment routes', async () => {
const response = await app.handle(new Request('http://localhost/redirect/relative'));
- expect(response?.headers.get('location')).toBe('/redirect/home');
+ expect(response?.headers.get('location')).toBe('/home');
expect(response?.status).toBe(302);
});
- it('should correctly handle relative nested redirects with parameter', async () => {
+ it('should correctly handle relative redirects on multi-segment routes with parameter', async () => {
const response = await app.handle(new Request('http://localhost/redirect/param/relative'));
- expect(response?.headers.get('location')).toBe('/redirect/param/home');
+ expect(response?.headers.get('location')).toBe('/home');
expect(response?.status).toBe(302);
});
- it('should correctly handle absolute nested redirects', async () => {
+ it('should correctly handle relative redirects of parameterized parent routes', async () => {
+ const response = await app.handle(new Request('http://localhost/redirect-nested/x/old'));
+ expect(response?.headers.get('location')).toBe('/redirect-nested/x/new');
+ expect(response?.status).toBe(302);
+ });
+
+ it('should correctly handle absolute redirects on multi-segment routes', async () => {
const response = await app.handle(new Request('http://localhost/redirect/absolute'));
expect(response?.headers.get('location')).toBe('/home');
expect(response?.status).toBe(302);
});
+ it('should preserve query parameters on relative redirects', async () => {
+ const response = await app.handle(new Request('http://localhost/redirect?filter=test'));
+ expect(response?.headers.get('location')).toBe('/home?filter=test');
+ expect(response?.status).toBe(302);
+ });
+
+ it('should ignore query parameters of relative redirect targets', async () => {
+ const response = await app.handle(
+ new Request('http://localhost/redirect-with-query?filter=test'),
+ );
+ expect(response?.headers.get('location')).toBe('/home?filter=test');
+ expect(response?.status).toBe(302);
+ });
+
+ it('should not preserve query parameters on absolute redirects', async () => {
+ const response = await app.handle(
+ new Request('http://localhost/redirect/absolute?filter=test'),
+ );
+ expect(response?.headers.get('location')).toBe('/home');
+ expect(response?.status).toBe(302);
+ });
+
it('should handle request abortion gracefully', async () => {
const controller = new AbortController();
const request = new Request('http://localhost/home', { signal: controller.signal });
@@ -498,6 +528,16 @@ describe('AngularServerApp', () => {
expect(response?.headers.get('location')).toBe('/base/home');
expect(response?.status).toBe(302);
});
+
+ it('returns a 302 status and keeps the query string for relative redirects', async () => {
+ const response = await app.handle(
+ new Request('http://localhost/redirect?filter=test', {
+ headers,
+ }),
+ );
+ expect(response?.headers.get('location')).toBe('/base/home?filter=test');
+ expect(response?.status).toBe(302);
+ });
});
describe('Critical CSS inlining', () => {
diff --git a/packages/angular/ssr/test/routes/ng-routes_spec.ts b/packages/angular/ssr/test/routes/ng-routes_spec.ts
index e214c31eab71..93b8e446ccb4 100644
--- a/packages/angular/ssr/test/routes/ng-routes_spec.ts
+++ b/packages/angular/ssr/test/routes/ng-routes_spec.ts
@@ -51,7 +51,13 @@ describe('extractRoutesAndCreateRouteTree', () => {
expect(routeTree.toObject()).toEqual([
{ route: '/', renderMode: RenderMode.Server },
{ route: '/home', renderMode: RenderMode.Client },
- { route: '/redirect', renderMode: RenderMode.Server, status: 301, redirectTo: '/home' },
+ {
+ route: '/redirect',
+ renderMode: RenderMode.Server,
+ status: 301,
+ redirectTo: '/home',
+ relativeRedirect: true,
+ },
{ route: '/user/*', renderMode: RenderMode.Server },
]);
});
@@ -371,13 +377,118 @@ describe('extractRoutesAndCreateRouteTree', () => {
expect(errors).toHaveSize(0);
expect(routeTree.toObject()).toEqual([
- { route: '/', renderMode: RenderMode.Prerender, redirectTo: '/some' },
- { route: '/some', renderMode: RenderMode.Prerender, redirectTo: '/some/thing' },
+ {
+ route: '/',
+ renderMode: RenderMode.Prerender,
+ redirectTo: '/some',
+ relativeRedirect: true,
+ },
+ {
+ route: '/some',
+ renderMode: RenderMode.Prerender,
+ redirectTo: '/some/thing',
+ relativeRedirect: true,
+ },
{ route: '/some/thing', renderMode: RenderMode.Prerender },
- { redirectTo: '/*/thing', route: '/*', renderMode: RenderMode.Server },
+ {
+ redirectTo: '/*/thing',
+ relativeRedirect: true,
+ route: '/*',
+ renderMode: RenderMode.Server,
+ },
{ route: '/*/thing', renderMode: RenderMode.Server },
]);
});
+
+ it('should resolve multi-segment relative redirects of prerendered routes', async () => {
+ setAngularAppTestingManifest(
+ [
+ {
+ path: ':param',
+ children: [
+ { path: 'old/page', redirectTo: 'new/page' },
+ { path: 'new/page', component: DummyComponent },
+ ],
+ },
+ ],
+ [
+ {
+ path: ':param/old/page',
+ renderMode: RenderMode.Prerender,
+ async getPrerenderParams() {
+ return [{ param: 'some' }];
+ },
+ },
+ { path: '**', renderMode: RenderMode.Server },
+ ],
+ );
+
+ const { routeTree, errors } = await extractRoutesAndCreateRouteTree({
+ url,
+ invokeGetPrerenderParams: true,
+ includePrerenderFallbackRoutes: true,
+ });
+
+ expect(errors).toHaveSize(0);
+ expect(routeTree.toObject()).toEqual([
+ { route: '/*', renderMode: RenderMode.Server },
+ {
+ route: '/*/old/page',
+ renderMode: RenderMode.Server,
+ redirectTo: '/*/new/page',
+ relativeRedirect: true,
+ },
+ { route: '/*/new/page', renderMode: RenderMode.Server },
+ {
+ route: '/some/old/page',
+ renderMode: RenderMode.Prerender,
+ redirectTo: '/some/new/page',
+ relativeRedirect: true,
+ },
+ ]);
+ });
+
+ it('should resolve relative redirects of prerendered catch-all routes', async () => {
+ setAngularAppTestingManifest(
+ [
+ { path: 'docs/**', redirectTo: 'new' },
+ { path: 'new', component: DummyComponent },
+ ],
+ [
+ {
+ path: 'docs/**',
+ renderMode: RenderMode.Prerender,
+ async getPrerenderParams() {
+ return [{ '**': 'a/b' }];
+ },
+ },
+ { path: '**', renderMode: RenderMode.Server },
+ ],
+ );
+
+ const { routeTree, errors } = await extractRoutesAndCreateRouteTree({
+ url,
+ invokeGetPrerenderParams: true,
+ includePrerenderFallbackRoutes: true,
+ });
+
+ expect(errors).toHaveSize(0);
+ expect(routeTree.toObject()).toEqual([
+ {
+ route: '/docs/a/b',
+ renderMode: RenderMode.Prerender,
+ redirectTo: '/new',
+ relativeRedirect: true,
+ },
+ {
+ route: '/docs/**',
+ renderMode: RenderMode.Server,
+ redirectTo: '/new',
+ relativeRedirect: true,
+ },
+ { route: '/new', renderMode: RenderMode.Server },
+ ]);
+ });
});
it('should extract routes with a route level matcher', async () => {
@@ -496,8 +607,13 @@ describe('extractRoutesAndCreateRouteTree', () => {
const { routeTree, errors } = await extractRoutesAndCreateRouteTree({ url });
expect(errors).toHaveSize(0);
expect(routeTree.toObject()).toEqual([
- { route: '/', renderMode: RenderMode.Server, redirectTo: '/some' },
- { route: '/*', renderMode: RenderMode.Server, redirectTo: '/*/thing' },
+ { route: '/', renderMode: RenderMode.Server, redirectTo: '/some', relativeRedirect: true },
+ {
+ route: '/*',
+ renderMode: RenderMode.Server,
+ redirectTo: '/*/thing',
+ relativeRedirect: true,
+ },
{ route: '/*/thing', renderMode: RenderMode.Server },
]);
});
@@ -526,11 +642,98 @@ describe('extractRoutesAndCreateRouteTree', () => {
const { routeTree, errors } = await extractRoutesAndCreateRouteTree({ url });
expect(errors).toHaveSize(0);
expect(routeTree.toObject()).toEqual([
- { route: '/*/*', renderMode: RenderMode.Server, redirectTo: '/*/*/thing' },
+ {
+ route: '/*/*',
+ renderMode: RenderMode.Server,
+ redirectTo: '/*/*/thing',
+ relativeRedirect: true,
+ },
{ route: '/*/*/thing', renderMode: RenderMode.Server },
]);
});
+ it('should resolve multi-segment relative redirects against the parent route', async () => {
+ setAngularAppTestingManifest(
+ [
+ {
+ path: ':param',
+ children: [
+ { path: 'old/page', redirectTo: 'new/page' },
+ { path: 'new/page', component: DummyComponent },
+ ],
+ },
+ ],
+ [{ path: '**', renderMode: RenderMode.Server }],
+ );
+
+ const { routeTree, errors } = await extractRoutesAndCreateRouteTree({ url });
+ expect(errors).toHaveSize(0);
+ expect(routeTree.toObject()).toEqual([
+ { route: '/*', renderMode: RenderMode.Server },
+ {
+ route: '/*/old/page',
+ renderMode: RenderMode.Server,
+ redirectTo: '/*/new/page',
+ relativeRedirect: true,
+ },
+ { route: '/*/new/page', renderMode: RenderMode.Server },
+ ]);
+ });
+
+ it('should not mark absolute redirects as relative', async () => {
+ setAngularAppTestingManifest(
+ [
+ { path: 'server', redirectTo: '/home' },
+ { path: 'prerender', redirectTo: '/home' },
+ { path: 'home', component: DummyComponent },
+ ],
+ [
+ { path: 'prerender', renderMode: RenderMode.Prerender },
+ { path: '**', renderMode: RenderMode.Server },
+ ],
+ );
+
+ const { routeTree, errors } = await extractRoutesAndCreateRouteTree({ url });
+ expect(errors).toHaveSize(0);
+ expect(routeTree.toObject()).toEqual([
+ { route: '/server', renderMode: RenderMode.Server, redirectTo: '/home' },
+ { route: '/prerender', renderMode: RenderMode.Prerender, redirectTo: '/home' },
+ { route: '/home', renderMode: RenderMode.Server },
+ ]);
+ });
+
+ it('should ignore the query and fragment of relative redirect targets', async () => {
+ setAngularAppTestingManifest(
+ [
+ { path: 'server', redirectTo: 'home?param=value#fragment' },
+ { path: 'prerender', redirectTo: 'home?param=value#fragment' },
+ { path: 'home', component: DummyComponent },
+ ],
+ [
+ { path: 'prerender', renderMode: RenderMode.Prerender },
+ { path: '**', renderMode: RenderMode.Server },
+ ],
+ );
+
+ const { routeTree, errors } = await extractRoutesAndCreateRouteTree({ url });
+ expect(errors).toHaveSize(0);
+ expect(routeTree.toObject()).toEqual([
+ {
+ route: '/server',
+ renderMode: RenderMode.Server,
+ redirectTo: '/home',
+ relativeRedirect: true,
+ },
+ {
+ route: '/prerender',
+ renderMode: RenderMode.Prerender,
+ redirectTo: '/home',
+ relativeRedirect: true,
+ },
+ { route: '/home', renderMode: RenderMode.Server },
+ ]);
+ });
+
it('should not resolve parameterized routes for SSG when `invokeGetPrerenderParams` is false', async () => {
setAngularAppTestingManifest(
[
@@ -841,4 +1044,95 @@ describe('extractRoutesAndCreateRouteTree', () => {
expect(isDiscoveringRoutes).toBeTrue();
});
+
+ it('should preserve preload metadata for routes under nested empty-path routes', async () => {
+ setAngularAppTestingManifest(
+ [
+ {
+ path: '',
+ children: [
+ {
+ path: '',
+ pathMatch: 'full',
+ loadChildren: () => [
+ {
+ path: '',
+ loadComponent: () => DummyComponent,
+ ɵentryName: 'home-page',
+ } as Route,
+ ],
+ ɵentryName: 'home-routes',
+ } as Route,
+ {
+ path: '',
+ children: [
+ {
+ path: 'pricing',
+ loadChildren: () => [
+ {
+ path: '',
+ loadComponent: () => DummyComponent,
+ ɵentryName: 'pricing-page',
+ } as Route,
+ ],
+ ɵentryName: 'pricing-routes',
+ } as Route,
+ ],
+ },
+ ],
+ },
+ {
+ path: 'es',
+ children: [
+ {
+ path: '',
+ pathMatch: 'full',
+ loadChildren: () => [
+ {
+ path: '',
+ loadComponent: () => DummyComponent,
+ ɵentryName: 'home-page',
+ } as Route,
+ ],
+ ɵentryName: 'home-routes',
+ } as Route,
+ ],
+ },
+ ],
+ [{ path: '**', renderMode: RenderMode.Prerender }],
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ {
+ 'home-routes': ['chunk-home-routes.js'],
+ 'home-page': ['chunk-home-page.js'],
+ 'pricing-routes': ['chunk-pricing-routes.js'],
+ 'pricing-page': ['chunk-pricing-page.js'],
+ },
+ );
+
+ const { routeTree, errors } = await extractRoutesAndCreateRouteTree({ url });
+ expect(errors).toHaveSize(0);
+ expect(routeTree.toObject()).toEqual([
+ {
+ route: '/',
+ renderMode: RenderMode.Prerender,
+ preload: ['chunk-home-routes.js', 'chunk-home-page.js'],
+ },
+ {
+ route: '/pricing',
+ renderMode: RenderMode.Prerender,
+ preload: ['chunk-pricing-routes.js', 'chunk-pricing-page.js'],
+ },
+ {
+ route: '/es',
+ renderMode: RenderMode.Prerender,
+ preload: ['chunk-home-routes.js', 'chunk-home-page.js'],
+ },
+ ]);
+ });
});
diff --git a/packages/angular/ssr/test/routes/router_spec.ts b/packages/angular/ssr/test/routes/router_spec.ts
index 380bc659549a..95006eda5f5b 100644
--- a/packages/angular/ssr/test/routes/router_spec.ts
+++ b/packages/angular/ssr/test/routes/router_spec.ts
@@ -55,6 +55,7 @@ describe('ServerRouter', () => {
});
expect(router.match(new URL('http://localhost/redirect'))).toEqual({
redirectTo: '/home',
+ relativeRedirect: true,
route: '/redirect',
renderMode: RenderMode.Server,
status: 301,
@@ -89,6 +90,7 @@ describe('ServerRouter', () => {
});
expect(redirectMetadata).toEqual({
redirectTo: '/home',
+ relativeRedirect: true,
route: '/redirect',
status: 301,
renderMode: RenderMode.Server,
@@ -110,6 +112,7 @@ describe('ServerRouter', () => {
});
expect(redirectMetadata).toEqual({
redirectTo: '/home',
+ relativeRedirect: true,
route: '/redirect',
status: 301,
renderMode: RenderMode.Server,
diff --git a/packages/angular/ssr/test/testing-utils.ts b/packages/angular/ssr/test/testing-utils.ts
index 6f825507c7a3..dad622d2e802 100644
--- a/packages/angular/ssr/test/testing-utils.ts
+++ b/packages/angular/ssr/test/testing-utils.ts
@@ -17,7 +17,7 @@ import { bootstrapApplication } from '@angular/platform-browser';
import { RouterOutlet, Routes, provideRouter } from '@angular/router';
import { type CompactPlan, compileSheet, encodePlan } from 'beasties/compiler';
import { destroyAngularServerApp } from '../src/app';
-import { ServerAsset, setAngularAppManifest } from '../src/manifest';
+import { AngularAppManifest, ServerAsset, setAngularAppManifest } from '../src/manifest';
import { ServerRoute, provideServerRendering, withRoutes } from '../src/routes/route-config';
@Component({
@@ -44,6 +44,7 @@ class AppComponent {}
* root component and all its children.
* @param inlineCriticalCss - An optional record of stylesheet paths to CSS content to be compiled into critical CSS plans.
* @param nonce - An optional Content Security Policy (CSP) nonce to be used for inlined critical CSS.
+ * @param entryPointToBrowserMapping - An optional mapping of entry-point names to their associated browser bundles.
*/
export function setAngularAppTestingManifest(
routes: Routes,
@@ -55,6 +56,7 @@ export function setAngularAppTestingManifest(
extraProviders: Array = [],
inlineCriticalCss?: Record,
nonce?: string,
+ entryPointToBrowserMapping?: AngularAppManifest['entryPointToBrowserMapping'],
): void {
destroyAngularServerApp();
@@ -70,6 +72,7 @@ export function setAngularAppTestingManifest(
setAngularAppManifest({
criticalCssPlans,
nonce,
+ entryPointToBrowserMapping,
baseHref,
locale,
assets: {
diff --git a/packages/angular_devkit/build_angular/package.json b/packages/angular_devkit/build_angular/package.json
index 6976448a01c0..54a44f134b16 100644
--- a/packages/angular_devkit/build_angular/package.json
+++ b/packages/angular_devkit/build_angular/package.json
@@ -25,7 +25,7 @@
"ansi-colors": "4.1.3",
"autoprefixer": "10.6.1",
"babel-loader": "10.1.1",
- "beasties": "0.5.4",
+ "beasties": "0.5.5",
"browserslist": "^4.26.0",
"copy-webpack-plugin": "14.0.0",
"css-loader": "7.1.5",
@@ -43,7 +43,7 @@
"ora": "9.4.1",
"picomatch": "4.0.7",
"piscina": "5.3.2",
- "postcss": "8.5.29",
+ "postcss": "8.5.30",
"postcss-loader": "8.2.1",
"resolve-url-loader": "5.0.0",
"rxjs": "7.8.2",
@@ -68,7 +68,7 @@
"browser-sync": "3.0.4",
"ng-packagr": "22.3.0-next.2",
"sass": "1.105.1",
- "undici": "8.11.2"
+ "undici": "8.12.1"
},
"peerDependencies": {
"@angular/compiler-cli": "0.0.0-ANGULAR-FW-PEER-DEP",
diff --git a/packages/angular_devkit/build_angular/src/builders/extract-i18n/application-extraction.ts b/packages/angular_devkit/build_angular/src/builders/extract-i18n/application-extraction.ts
index 8de8b6863aaf..508b27e2d833 100644
--- a/packages/angular_devkit/build_angular/src/builders/extract-i18n/application-extraction.ts
+++ b/packages/angular_devkit/build_angular/src/builders/extract-i18n/application-extraction.ts
@@ -45,6 +45,7 @@ export async function extractMessages(
);
}
+ buildOptions.aot = true;
buildOptions.optimization = false;
buildOptions.sourceMap = { scripts: true, vendor: true, styles: false };
buildOptions.localize = false;
@@ -111,7 +112,7 @@ function setupLocalizeExtractor(
if (file?.origin === 'memory') {
content = textDecoder.decode(file.contents);
} else if (file?.origin === 'disk') {
- content = readFileSync(file.inputPath, 'utf-8');
+ content = readFileSync(file.source, 'utf-8');
}
if (content === undefined) {
throw new Error('Unknown file requested: ' + requestedPath);
diff --git a/packages/angular_devkit/schematics/src/rules/base.ts b/packages/angular_devkit/schematics/src/rules/base.ts
index ec380f2aeb0d..1f5d3023c28e 100644
--- a/packages/angular_devkit/schematics/src/rules/base.ts
+++ b/packages/angular_devkit/schematics/src/rules/base.ts
@@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.dev/license
*/
-import { Observable, concat, map, mapTo, toArray } from 'rxjs';
+import { concat, lastValueFrom, map, mapTo, toArray } from 'rxjs';
import { FileOperator, Rule, Source } from '../engine/interface';
import { SchematicsException } from '../exception/exception';
import { FilterHostTree, HostTree } from '../tree/host-tree';
@@ -34,18 +34,18 @@ export function empty(): Source {
*/
export function chain(rules: Iterable | AsyncIterable): Rule {
return async (initialTree, context) => {
- let intermediateTree: Observable | undefined;
+ let intermediateTree = initialTree;
if (Symbol.asyncIterator in rules) {
for await (const rule of rules) {
- intermediateTree = callRule(rule, intermediateTree ?? initialTree, context);
+ intermediateTree = await lastValueFrom(callRule(rule, intermediateTree, context));
}
} else {
for (const rule of rules) {
- intermediateTree = callRule(rule, intermediateTree ?? initialTree, context);
+ intermediateTree = await lastValueFrom(callRule(rule, intermediateTree, context));
}
}
- return () => intermediateTree;
+ return intermediateTree;
};
}
diff --git a/packages/angular_devkit/schematics/src/rules/base_spec.ts b/packages/angular_devkit/schematics/src/rules/base_spec.ts
index b3578ca8c00a..6eb299ef9890 100644
--- a/packages/angular_devkit/schematics/src/rules/base_spec.ts
+++ b/packages/angular_devkit/schematics/src/rules/base_spec.ts
@@ -140,6 +140,19 @@ describe('chain', () => {
expect(rulesCalled[2]).toBe(tree2);
expect(result).toBe(tree3);
});
+
+ it('works with a large number of rules', async () => {
+ const tree0 = empty();
+ let callCount = 0;
+ const rules: Rule[] = Array.from({ length: 20_000 }, () => () => {
+ callCount++;
+ });
+
+ const result = await lastValueFrom(callRule(chain(rules), tree0, context));
+
+ expect(result).toBe(tree0);
+ expect(callCount).toBe(20_000);
+ });
});
describe('apply', () => {
diff --git a/packages/ngtools/webpack/package.json b/packages/ngtools/webpack/package.json
index a7488b0d9316..13cea96fc202 100644
--- a/packages/ngtools/webpack/package.json
+++ b/packages/ngtools/webpack/package.json
@@ -17,8 +17,8 @@
},
"devDependencies": {
"@angular-devkit/core": "workspace:0.0.0-PLACEHOLDER",
- "@angular/compiler": "22.3.0-next.1",
- "@angular/compiler-cli": "22.3.0-next.1",
+ "@angular/compiler": "22.3.0-next.2",
+ "@angular/compiler-cli": "22.3.0-next.2",
"typescript": "6.0.3",
"webpack": "5.111.1"
}
diff --git a/packages/schematics/angular/library/schema.json b/packages/schematics/angular/library/schema.json
index bb3d227e5245..02c6c6f8acaa 100644
--- a/packages/schematics/angular/library/schema.json
+++ b/packages/schematics/angular/library/schema.json
@@ -19,7 +19,7 @@
"entryFile": {
"type": "string",
"format": "path",
- "description": "The path to the library's public API file, relative to the workspace root. This file defines what parts of the library are accessible to applications that import it.",
+ "description": "The name of the library's public API file, without the `.ts` extension, created in the library's `src` directory. This file defines what parts of the library are accessible to applications that import it.",
"default": "public-api"
},
"prefix": {
diff --git a/packages/schematics/angular/migrations/migration-collection.json b/packages/schematics/angular/migrations/migration-collection.json
index db1b95f987ef..9147e229b97c 100644
--- a/packages/schematics/angular/migrations/migration-collection.json
+++ b/packages/schematics/angular/migrations/migration-collection.json
@@ -29,6 +29,13 @@
"version": "22.0.0",
"factory": "./update-workspace-config/migration",
"description": "Update the angular workspace configuration."
+ },
+ "use-library-builder": {
+ "version": "22.3.0",
+ "factory": "./use-library-builder/migration",
+ "description": "Migrate library projects from 'ng-packagr' to the new '@angular/build:library' builder.",
+ "optional": true,
+ "recommended": false
}
}
}
diff --git a/packages/schematics/angular/migrations/use-application-builder/migration.ts b/packages/schematics/angular/migrations/use-application-builder/migration.ts
index b481c4f30034..dcf0526a3945 100644
--- a/packages/schematics/angular/migrations/use-application-builder/migration.ts
+++ b/packages/schematics/angular/migrations/use-application-builder/migration.ts
@@ -19,6 +19,7 @@ import {
DependencyType,
ExistingBehavior,
addDependency,
+ getDependency,
removeDependency,
} from '../../utility/dependency';
import { JSONFile } from '../../utility/json-file';
@@ -270,10 +271,14 @@ function updateProjects(tree: Tree, context: SchematicContext) {
}
// Add direct @angular/build dependencies and remove @angular-devkit/build-angular
+ // Keep the workspace version since this migration can run from a newer temporary CLI
+ const buildAngularVersion =
+ getDependency(tree, '@angular-devkit/build-angular')?.version ??
+ latestVersions.AngularBuild;
rules.push(
- addDependency('@angular/build', latestVersions.DevkitBuildAngular, {
+ addDependency('@angular/build', buildAngularVersion, {
type: DependencyType.Dev,
- existing: ExistingBehavior.Replace,
+ existing: ExistingBehavior.Skip,
}),
removeDependency('@angular-devkit/build-angular'),
);
diff --git a/packages/schematics/angular/migrations/use-application-builder/migration_spec.ts b/packages/schematics/angular/migrations/use-application-builder/migration_spec.ts
index fd10352c6eac..05259962dc5d 100644
--- a/packages/schematics/angular/migrations/use-application-builder/migration_spec.ts
+++ b/packages/schematics/angular/migrations/use-application-builder/migration_spec.ts
@@ -9,6 +9,7 @@
import { JsonObject } from '@angular-devkit/core';
import { EmptyTree } from '@angular-devkit/schematics';
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
+import { latestVersions } from '../../utility/latest-versions';
import { Builders, ProjectType, WorkspaceSchema } from '../../utility/workspace-models';
function createWorkSpaceConfig(tree: UnitTestTree) {
@@ -450,6 +451,47 @@ describe(`Migration to use the application builder`, () => {
expect(devDependencies['postcss']).toBeUndefined();
});
+ describe('"@angular/build" version', () => {
+ async function migrateWith(
+ manifest: object,
+ ): Promise<{ devDependencies: Record }> {
+ tree.overwrite('/package.json', JSON.stringify(manifest));
+ const newTree = await schematicRunner.runSchematic(schematicName, {}, tree);
+
+ return JSON.parse(newTree.readContent('/package.json'));
+ }
+
+ it('should follow the "@angular-devkit/build-angular" range of the workspace', async () => {
+ const { devDependencies } = await migrateWith({
+ devDependencies: { '@angular-devkit/build-angular': '~19.1.4' },
+ });
+
+ expect(devDependencies['@angular/build']).toBe('~19.1.4');
+ });
+
+ it('should read "@angular-devkit/build-angular" from "dependencies" as well', async () => {
+ const { devDependencies } = await migrateWith({
+ dependencies: { '@angular-devkit/build-angular': '18.2.1' },
+ });
+
+ expect(devDependencies['@angular/build']).toBe('18.2.1');
+ });
+
+ it('should keep an "@angular/build" that is already installed', async () => {
+ const { devDependencies } = await migrateWith({
+ devDependencies: { '@angular-devkit/build-angular': '^19.2.0', '@angular/build': '19.0.3' },
+ });
+
+ expect(devDependencies['@angular/build']).toBe('19.0.3');
+ });
+
+ it('should fall back to the latest "@angular/build" without "@angular-devkit/build-angular"', async () => {
+ const { devDependencies } = await migrateWith({});
+
+ expect(devDependencies['@angular/build']).toBe(latestVersions.AngularBuild);
+ });
+ });
+
it('it should not add esModuleInterop and moduleResolution when module is preserve', async () => {
tree.overwrite(
'tsconfig.json',
diff --git a/packages/schematics/angular/migrations/use-library-builder/migration.ts b/packages/schematics/angular/migrations/use-library-builder/migration.ts
new file mode 100644
index 000000000000..68f9e8738e25
--- /dev/null
+++ b/packages/schematics/angular/migrations/use-library-builder/migration.ts
@@ -0,0 +1,587 @@
+/**
+ * @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 JsonObject, type JsonValue, isJsonObject } from '@angular-devkit/core';
+import {
+ type Rule,
+ type SchematicContext,
+ SchematicsException,
+ type Tree,
+ chain,
+} from '@angular-devkit/schematics';
+import { dirname, join, normalize, relative } from 'node:path/posix';
+import {
+ DependencyType,
+ ExistingBehavior,
+ addDependency,
+ removeDependency,
+} from '../../utility/dependency';
+import { JSONFile } from '../../utility/json-file';
+import { latestVersions } from '../../utility/latest-versions';
+import {
+ type TargetDefinition,
+ allTargetOptions,
+ allWorkspaceTargets,
+ updateWorkspace,
+} from '../../utility/workspace';
+import { Builders, ProjectType } from '../../utility/workspace-models';
+
+/**
+ * Represents the configuration structure of an `ng-package.json` file or
+ * the `ngPackage` section within a `package.json` file.
+ */
+interface NgPackageConfig {
+ dest?: string;
+ assets?: (string | { glob: string; input: string; output: string })[];
+ allowedNonPeerDependencies?: string[];
+ inlineStyleLanguage?: string;
+ keepLifecycleScripts?: boolean;
+ deleteDestPath?: boolean;
+ lib?: {
+ entryFile?: string;
+ styleIncludePaths?: string[];
+ sass?: {
+ fatalDeprecations?: string[];
+ silenceDeprecations?: string[];
+ futureDeprecations?: string[];
+ };
+ };
+}
+
+/**
+ * Metadata describing a discovered secondary entry point in a library project.
+ */
+interface SecondaryEntryPoint {
+ subpath: string;
+ entryPoint: string;
+ configFile: string;
+}
+
+/**
+ * Normalizes a workspace-relative POSIX path, converting `'.'` or `'/'` to `''`.
+ *
+ * @param path The path string to normalize.
+ * @returns The normalized workspace-relative path.
+ */
+function normalizeRelativePath(path: string): string {
+ const normalized = normalize(path).replace(/^\/+|\/+$/g, '');
+
+ return normalized === '.' ? '' : normalized;
+}
+
+/**
+ * Reads and parses an `ng-packagr` configuration from either an `ng-package.json`
+ * file or the `ngPackage` property of a `package.json` file.
+ *
+ * @param tree The virtual file system tree.
+ * @param filePath The workspace-relative path to the configuration file.
+ * @returns The parsed `NgPackageConfig`, or `undefined` if the file does not exist or cannot be parsed.
+ */
+function parseNgPackageFile(tree: Tree, filePath: string): NgPackageConfig | undefined {
+ if (!tree.exists(filePath)) {
+ return undefined;
+ }
+
+ try {
+ const json = new JSONFile(tree, filePath);
+ if (filePath.endsWith('/package.json') || filePath === 'package.json') {
+ const ngPackage = json.get(['ngPackage']) as JsonValue;
+
+ return isJsonObject(ngPackage) ? (ngPackage as NgPackageConfig) : undefined;
+ }
+
+ const content = json.get([]) as JsonValue;
+
+ return isJsonObject(content) ? (content as NgPackageConfig) : undefined;
+ } catch {
+ return undefined;
+ }
+}
+
+/**
+ * Resolves the TypeScript entry file path for a library entry point directory.
+ * Uses the explicitly configured `entryFile` when provided, or checks common
+ * default locations.
+ *
+ * @param tree The virtual file system tree.
+ * @param dir The directory of the primary or secondary entry point.
+ * @param configuredEntry The optional `lib.entryFile` path from `ng-package.json`.
+ * @returns The resolved entry file path relative to `dir`.
+ */
+function resolveEntryFile(tree: Tree, dir: string, configuredEntry?: string): string {
+ if (configuredEntry) {
+ return configuredEntry;
+ }
+
+ const candidates = [
+ 'src/public-api.ts',
+ 'src/public_api.ts',
+ 'public-api.ts',
+ 'public_api.ts',
+ 'src/index.ts',
+ 'index.ts',
+ ];
+
+ for (const candidate of candidates) {
+ if (tree.exists(join(dir, candidate))) {
+ return candidate;
+ }
+ }
+
+ throw new SchematicsException(
+ `Could not find an entry file for library entry point at "${dir || '.'}".`,
+ );
+}
+
+/**
+ * Traverses a library project directory to discover all secondary entry points
+ * defined by nested `ng-package.json` files or `package.json` files containing an `ngPackage` field.
+ *
+ * @param tree The virtual file system tree.
+ * @param projectRoot The root directory of the library project.
+ * @param primaryProjectFile The workspace-relative path to the primary `ng-packagr` configuration file.
+ * @returns An array of discovered secondary entry points.
+ */
+function findSecondaryEntryPoints(
+ tree: Tree,
+ projectRoot: string,
+ primaryProjectFile: string,
+): SecondaryEntryPoint[] {
+ const secondaryEntryPoints: SecondaryEntryPoint[] = [];
+ const normalizedRoot = normalizeRelativePath(projectRoot);
+ const normalizedPrimary = primaryProjectFile ? normalizeRelativePath(primaryProjectFile) : '';
+ const rootDir = tree.getDir(normalizedRoot);
+ const directories = [rootDir];
+
+ for (const current of directories) {
+ const currentPath = normalizeRelativePath(current.path);
+
+ if (currentPath !== normalizedRoot) {
+ const ngPackageJsonPath = join(currentPath, 'ng-package.json');
+ const packageJsonPath = join(currentPath, 'package.json');
+
+ if (
+ current.subfiles.some((f) => f === 'ng-package.json') &&
+ ngPackageJsonPath !== normalizedPrimary
+ ) {
+ const config = parseNgPackageFile(tree, ngPackageJsonPath);
+ const subpath = relative(normalizedRoot, currentPath);
+ const entryFile = resolveEntryFile(tree, currentPath, config?.lib?.entryFile);
+ secondaryEntryPoints.push({
+ subpath,
+ entryPoint: join(currentPath, entryFile),
+ configFile: ngPackageJsonPath,
+ });
+ } else if (
+ current.subfiles.some((f) => f === 'package.json') &&
+ packageJsonPath !== normalizedPrimary
+ ) {
+ const config = parseNgPackageFile(tree, packageJsonPath);
+ if (config) {
+ const subpath = relative(normalizedRoot, currentPath);
+ const entryFile = resolveEntryFile(tree, currentPath, config.lib?.entryFile);
+ secondaryEntryPoints.push({
+ subpath,
+ entryPoint: join(currentPath, entryFile),
+ configFile: packageJsonPath,
+ });
+ }
+ }
+ }
+
+ for (const subdir of current.subdirs) {
+ if (
+ subdir === 'node_modules' ||
+ subdir === 'dist' ||
+ subdir === 'out-tsc' ||
+ subdir.startsWith('.')
+ ) {
+ continue;
+ }
+ directories.push(current.dir(subdir));
+ }
+ }
+
+ return secondaryEntryPoints;
+}
+
+/**
+ * Transfers `ng-packagr` configuration options onto the library's `build` target in `angular.json`.
+ *
+ * @param projectRoot The normalized root directory of the library project.
+ * @param projectDir The directory containing the primary `ng-packagr` configuration file.
+ * @param buildTarget The library's `build` target definition in `angular.json`.
+ * @param ngPackageConfig The parsed `NgPackageConfig`, if available.
+ * @param tree The virtual file system tree.
+ */
+function migrateTargetOptions(
+ projectRoot: string,
+ projectDir: string,
+ buildTarget: TargetDefinition,
+ ngPackageConfig: NgPackageConfig | undefined,
+ tree: Tree,
+): void {
+ buildTarget.builder = Builders.BuildLibrary;
+ buildTarget.options ??= {};
+
+ const devTsConfig = buildTarget.configurations?.['development']?.['tsConfig'];
+ if (typeof buildTarget.options['tsConfig'] !== 'string') {
+ if (typeof devTsConfig === 'string') {
+ buildTarget.options['tsConfig'] = devTsConfig;
+ delete buildTarget.configurations?.['development']?.['tsConfig'];
+ } else if (tree.exists(join(projectRoot, 'tsconfig.lib.json'))) {
+ buildTarget.options['tsConfig'] = join(projectRoot, 'tsconfig.lib.json');
+ }
+ } else if (devTsConfig === buildTarget.options['tsConfig']) {
+ delete buildTarget.configurations?.['development']?.['tsConfig'];
+ }
+
+ if (ngPackageConfig?.dest && typeof buildTarget.options['outputPath'] !== 'string') {
+ buildTarget.options['outputPath'] = join(projectDir, ngPackageConfig.dest);
+ }
+
+ if (ngPackageConfig?.assets?.length) {
+ const existingAssets = Array.isArray(buildTarget.options['assets'])
+ ? buildTarget.options['assets']
+ : [];
+ const migratedAssets = ngPackageConfig.assets.map((asset) => {
+ if (typeof asset === 'string') {
+ return join(projectDir, asset);
+ }
+ if (isJsonObject(asset) && typeof asset['input'] === 'string') {
+ return {
+ ...asset,
+ input: join(projectDir, asset['input']),
+ };
+ }
+
+ return asset;
+ });
+ buildTarget.options['assets'] = [...existingAssets, ...migratedAssets];
+ }
+
+ if (ngPackageConfig?.lib?.styleIncludePaths?.length || ngPackageConfig?.lib?.sass) {
+ const stylePreprocessorOptions = buildTarget.options['stylePreprocessorOptions'];
+ const existingPreprocessorOptions: JsonObject =
+ stylePreprocessorOptions && isJsonObject(stylePreprocessorOptions)
+ ? { ...stylePreprocessorOptions }
+ : {};
+
+ if (ngPackageConfig.lib.styleIncludePaths?.length) {
+ const existingIncludePaths = Array.isArray(existingPreprocessorOptions['includePaths'])
+ ? (existingPreprocessorOptions['includePaths'] as string[])
+ : [];
+ const migratedIncludePaths = ngPackageConfig.lib.styleIncludePaths.map((p) =>
+ join(projectDir, p),
+ );
+ existingPreprocessorOptions['includePaths'] = [
+ ...existingIncludePaths,
+ ...migratedIncludePaths,
+ ];
+ }
+ if (ngPackageConfig.lib.sass) {
+ existingPreprocessorOptions['sass'] = ngPackageConfig.lib.sass;
+ }
+
+ buildTarget.options['stylePreprocessorOptions'] = existingPreprocessorOptions;
+ }
+
+ if (ngPackageConfig?.allowedNonPeerDependencies?.length) {
+ buildTarget.options['allowedNonPeerDependencies'] = ngPackageConfig.allowedNonPeerDependencies;
+ }
+ if (ngPackageConfig?.inlineStyleLanguage) {
+ buildTarget.options['inlineStyleLanguage'] = ngPackageConfig.inlineStyleLanguage;
+ }
+ if (ngPackageConfig?.keepLifecycleScripts !== undefined) {
+ buildTarget.options['keepLifecycleScripts'] = ngPackageConfig.keepLifecycleScripts;
+ }
+ if (ngPackageConfig?.deleteDestPath !== undefined) {
+ buildTarget.options['deleteOutputPath'] = ngPackageConfig.deleteDestPath;
+ }
+
+ for (const [, options] of allTargetOptions(buildTarget, false)) {
+ delete options['project'];
+ }
+
+ // Configure development configuration with full compilation mode unless already specified in tsconfig
+ buildTarget.configurations ??= {};
+ buildTarget.configurations['development'] ??= {};
+
+ const effectiveDevTsConfig =
+ typeof buildTarget.configurations['development']['tsConfig'] === 'string'
+ ? buildTarget.configurations['development']['tsConfig']
+ : typeof buildTarget.options['tsConfig'] === 'string'
+ ? buildTarget.options['tsConfig']
+ : undefined;
+
+ let hasDevTsConfigCompilationMode = false;
+ if (effectiveDevTsConfig && tree.exists(effectiveDevTsConfig)) {
+ try {
+ const tsConfigJson = new JSONFile(tree, effectiveDevTsConfig);
+ hasDevTsConfigCompilationMode =
+ tsConfigJson.get(['angularCompilerOptions', 'compilationMode']) !== undefined;
+ } catch {
+ // Ignore parse errors
+ }
+ }
+
+ if (!hasDevTsConfigCompilationMode) {
+ buildTarget.configurations['development']['compilationMode'] ??= 'full';
+ }
+}
+
+/**
+ * Migrates a single library project's `build` target from `ng-packagr` to `@angular/build:library`,
+ * transferring configuration options to `angular.json`, writing entry points to `package.json#exports`,
+ * and cleaning up obsolete `ng-packagr` configuration files.
+ *
+ * @param projectRoot The root directory of the library project.
+ * @param buildTarget The library's `build` target definition in `angular.json`.
+ * @param tree The virtual file system tree.
+ * @param context The schematic execution context.
+ * @returns `true` if the library target was migrated, or `false` if it was skipped.
+ */
+function updateLibraryTarget(
+ projectRoot: string,
+ buildTarget: TargetDefinition,
+ tree: Tree,
+ context: SchematicContext,
+): boolean {
+ const normalizedProjectRoot = normalizeRelativePath(projectRoot);
+ let primaryProjectFile =
+ typeof buildTarget.options?.['project'] === 'string'
+ ? normalizeRelativePath(buildTarget.options['project'])
+ : '';
+ if (!primaryProjectFile) {
+ for (const [, options] of allTargetOptions(buildTarget, true)) {
+ if (typeof options['project'] === 'string') {
+ primaryProjectFile = normalizeRelativePath(options['project']);
+ break;
+ }
+ }
+ }
+ if (!primaryProjectFile) {
+ const defaultNgPackageJson = join(normalizedProjectRoot, 'ng-package.json');
+ const defaultPackageJson = join(normalizedProjectRoot, 'package.json');
+ if (tree.exists(defaultNgPackageJson)) {
+ primaryProjectFile = defaultNgPackageJson;
+ } else if (tree.exists(defaultPackageJson)) {
+ primaryProjectFile = defaultPackageJson;
+ }
+ }
+
+ if (/\.[cm]?js$/.test(primaryProjectFile)) {
+ context.logger.warn(
+ `Skipping project at "${projectRoot}" because JavaScript ng-packagr ` +
+ `configuration files ("${primaryProjectFile}") cannot be automatically migrated.`,
+ );
+
+ return false;
+ }
+
+ const ngPackageConfig = primaryProjectFile
+ ? parseNgPackageFile(tree, primaryProjectFile)
+ : undefined;
+
+ const projectDir = primaryProjectFile
+ ? normalizeRelativePath(dirname(primaryProjectFile))
+ : normalizedProjectRoot;
+ const primaryEntryFile = resolveEntryFile(tree, projectDir, ngPackageConfig?.lib?.entryFile);
+ const primaryEntryFilePath = join(projectDir, primaryEntryFile);
+ const secondaryEntryPoints = findSecondaryEntryPoints(
+ tree,
+ normalizedProjectRoot,
+ primaryProjectFile,
+ );
+
+ const toRelativeExportPath = (filePath: string): string => {
+ const rel = relative(normalizedProjectRoot, filePath);
+
+ return rel.startsWith('./') || rel.startsWith('../') ? rel : `./${rel}`;
+ };
+
+ const entryPointExports: Record = {
+ '.': toRelativeExportPath(primaryEntryFilePath),
+ };
+ for (const secondary of secondaryEntryPoints) {
+ const exportKey =
+ secondary.subpath.startsWith('./') || secondary.subpath.startsWith('../')
+ ? secondary.subpath
+ : `./${secondary.subpath}`;
+ entryPointExports[exportKey] = toRelativeExportPath(secondary.entryPoint);
+ }
+
+ migrateTargetOptions(normalizedProjectRoot, projectDir, buildTarget, ngPackageConfig, tree);
+
+ const packageJsonPath = join(normalizedProjectRoot, 'package.json');
+
+ // Delete primary ng-package.json if it exists
+ if (
+ primaryProjectFile &&
+ primaryProjectFile.endsWith('ng-package.json') &&
+ tree.exists(primaryProjectFile)
+ ) {
+ tree.delete(primaryProjectFile);
+ } else if (
+ primaryProjectFile &&
+ primaryProjectFile !== packageJsonPath &&
+ (primaryProjectFile.endsWith('/package.json') || primaryProjectFile === 'package.json') &&
+ tree.exists(primaryProjectFile)
+ ) {
+ const json = new JSONFile(tree, primaryProjectFile);
+ json.remove(['ngPackage']);
+ }
+
+ // Update library package.json with exports and remove ngPackage
+ if (tree.exists(packageJsonPath)) {
+ updateLibraryPackageJson(tree, packageJsonPath, entryPointExports);
+ }
+
+ // Delete secondary configuration files
+ for (const secondary of secondaryEntryPoints) {
+ if (secondary.configFile.endsWith('ng-package.json') && tree.exists(secondary.configFile)) {
+ tree.delete(secondary.configFile);
+ } else if (
+ (secondary.configFile.endsWith('/package.json') || secondary.configFile === 'package.json') &&
+ tree.exists(secondary.configFile)
+ ) {
+ const json = new JSONFile(tree, secondary.configFile);
+ json.remove(['ngPackage']);
+ const remaining = json.get([]) as JsonValue;
+ if (
+ isJsonObject(remaining) &&
+ Object.keys(remaining).filter((k) => k !== '$schema').length === 0
+ ) {
+ tree.delete(secondary.configFile);
+ }
+ }
+ }
+
+ context.logger.info(
+ `Updated project at "${projectRoot}" to use the new '@angular/build:library' builder with ${
+ Object.keys(entryPointExports).length
+ } entry point(s).`,
+ );
+
+ return true;
+}
+
+/**
+ * Updates the library's `package.json` file by removing the legacy `ngPackage` configuration
+ * and `tslib` dependency, and merging the discovered entry points into the `exports` map.
+ *
+ * @param tree The virtual file system tree.
+ * @param packageJsonPath The workspace-relative path to the library's `package.json`.
+ * @param entryPointExports Map of export subpaths to relative entry file paths.
+ */
+function updateLibraryPackageJson(
+ tree: Tree,
+ packageJsonPath: string,
+ entryPointExports: Record,
+): void {
+ const json = new JSONFile(tree, packageJsonPath);
+ json.remove(['ngPackage']);
+
+ for (const depType of [
+ 'dependencies',
+ 'peerDependencies',
+ 'devDependencies',
+ 'optionalDependencies',
+ ]) {
+ json.remove([depType, 'tslib']);
+ const deps = json.get([depType]) as JsonValue;
+ if (isJsonObject(deps) && Object.keys(deps).length === 0) {
+ json.remove([depType]);
+ }
+ }
+
+ const existingExports = json.get(['exports']) as JsonValue;
+ let existingExportsObj: Record = {};
+ if (isJsonObject(existingExports)) {
+ const keys = Object.keys(existingExports);
+ if (keys.some((k) => k.startsWith('.'))) {
+ existingExportsObj = existingExports;
+ } else if (keys.length > 0) {
+ existingExportsObj = { '.': existingExports };
+ }
+ }
+
+ const updatedExports: Record = {
+ ...existingExportsObj,
+ };
+
+ for (const [subpath, targetPath] of Object.entries(entryPointExports)) {
+ const current = updatedExports[subpath];
+ if (current && isJsonObject(current)) {
+ updatedExports[subpath] = {
+ ...current,
+ default: targetPath,
+ };
+ } else {
+ updatedExports[subpath] = targetPath;
+ }
+ }
+
+ json.modify(['exports'], updatedExports);
+}
+
+/**
+ * Migration main entrypoint for use-library-builder.
+ */
+export default function (): Rule {
+ return (tree, context) =>
+ updateWorkspace((workspace) => {
+ let hasMigratedLibrary = false;
+
+ for (const [, project] of workspace.projects) {
+ if (project.extensions.projectType !== ProjectType.Library) {
+ continue;
+ }
+
+ const buildTarget = project.targets.get('build');
+ if (
+ !buildTarget ||
+ buildTarget.builder === Builders.BuildLibrary ||
+ (buildTarget.builder !== Builders.NgPackagr &&
+ buildTarget.builder !== Builders.BuildNgPackagr)
+ ) {
+ continue;
+ }
+
+ if (updateLibraryTarget(project.root, buildTarget, tree, context)) {
+ hasMigratedLibrary = true;
+ }
+ }
+
+ if (!hasMigratedLibrary) {
+ return;
+ }
+
+ const rules: Rule[] = [
+ addDependency('@angular/build', latestVersions.AngularBuild, {
+ type: DependencyType.Dev,
+ existing: ExistingBehavior.Skip,
+ }),
+ ];
+
+ // Check if any targets still use ng-packagr across the workspace
+ let hasNgPackagrUsage = false;
+ for (const [, target] of allWorkspaceTargets(workspace)) {
+ if (target.builder === Builders.NgPackagr || target.builder === Builders.BuildNgPackagr) {
+ hasNgPackagrUsage = true;
+ break;
+ }
+ }
+
+ if (!hasNgPackagrUsage) {
+ rules.push(removeDependency('ng-packagr'));
+ }
+
+ return chain(rules);
+ });
+}
diff --git a/packages/schematics/angular/migrations/use-library-builder/migration_spec.ts b/packages/schematics/angular/migrations/use-library-builder/migration_spec.ts
new file mode 100644
index 000000000000..11192f8e5897
--- /dev/null
+++ b/packages/schematics/angular/migrations/use-library-builder/migration_spec.ts
@@ -0,0 +1,430 @@
+/**
+ * @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 { EmptyTree } from '@angular-devkit/schematics';
+import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
+import { Builders, ProjectType, type WorkspaceSchema } from '../../utility/workspace-models';
+
+function createWorkspaceConfig(tree: UnitTestTree) {
+ const angularConfig: WorkspaceSchema = {
+ version: 1,
+ projects: {
+ 'my-lib': {
+ root: 'projects/my-lib',
+ sourceRoot: 'projects/my-lib/src',
+ projectType: ProjectType.Library,
+ prefix: 'lib',
+ architect: {
+ build: {
+ builder: Builders.NgPackagr,
+ options: {
+ project: 'projects/my-lib/ng-package.json',
+ tsConfig: 'projects/my-lib/tsconfig.lib.json',
+ },
+ configurations: {
+ production: {
+ tsConfig: 'projects/my-lib/tsconfig.lib.prod.json',
+ },
+ },
+ },
+ },
+ },
+ },
+ };
+
+ tree.create('/angular.json', JSON.stringify(angularConfig, undefined, 2));
+ tree.create(
+ '/package.json',
+ JSON.stringify(
+ {
+ devDependencies: {
+ 'ng-packagr': '^18.0.0',
+ },
+ },
+ undefined,
+ 2,
+ ),
+ );
+ tree.create(
+ '/projects/my-lib/package.json',
+ JSON.stringify(
+ {
+ name: 'my-lib',
+ version: '0.0.1',
+ dependencies: {
+ tslib: '^2.3.0',
+ },
+ },
+ undefined,
+ 2,
+ ),
+ );
+ tree.create(
+ '/projects/my-lib/ng-package.json',
+ JSON.stringify(
+ {
+ dest: '../../dist/my-lib',
+ lib: {
+ entryFile: 'src/public-api.ts',
+ },
+ },
+ undefined,
+ 2,
+ ),
+ );
+}
+
+describe('Migration to use the library builder', () => {
+ const schematicName = 'use-library-builder';
+ const schematicRunner = new SchematicTestRunner(
+ 'migrations',
+ require.resolve('../migration-collection.json'),
+ );
+
+ let tree: UnitTestTree;
+ beforeEach(() => {
+ tree = new UnitTestTree(new EmptyTree());
+ createWorkspaceConfig(tree);
+ });
+
+ it('should migrate library project using ng-packagr to @angular/build:library', async () => {
+ const newTree = await schematicRunner.runSchematic(schematicName, {}, tree);
+ const {
+ projects: { 'my-lib': lib },
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } = newTree.readJson('/angular.json') as any;
+
+ const { builder, options, configurations } = lib.architect['build'];
+ expect(builder).toBe(Builders.BuildLibrary);
+ expect(options.project).toBeUndefined();
+ expect(options.entryPoints).toBeUndefined();
+ expect(options.tsConfig).toBe('projects/my-lib/tsconfig.lib.json');
+ expect(options.outputPath).toBe('dist/my-lib');
+ expect(configurations.development).toEqual({
+ compilationMode: 'full',
+ });
+
+ const libPkg = newTree.readJson('/projects/my-lib/package.json') as {
+ dependencies: unknown;
+ exports: unknown;
+ };
+ expect(libPkg.dependencies).toBeUndefined();
+ expect(libPkg.exports).toEqual({
+ '.': './src/public-api.ts',
+ });
+
+ expect(newTree.exists('/projects/my-lib/ng-package.json')).toBe(false);
+ });
+
+ it('should migrate @angular/build:ng-packagr and promote tsConfig from development configuration', async () => {
+ const angularJson = JSON.parse(tree.readContent('/angular.json'));
+ angularJson.projects['my-lib'].architect.build = {
+ builder: Builders.BuildNgPackagr,
+ configurations: {
+ production: {
+ tsConfig: 'projects/my-lib/tsconfig.lib.prod.json',
+ },
+ development: {
+ tsConfig: 'projects/my-lib/tsconfig.lib.json',
+ },
+ },
+ };
+ tree.overwrite('/angular.json', JSON.stringify(angularJson, undefined, 2));
+
+ const newTree = await schematicRunner.runSchematic(schematicName, {}, tree);
+ const {
+ projects: { 'my-lib': lib },
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } = newTree.readJson('/angular.json') as any;
+
+ const { builder, options, configurations } = lib.architect['build'];
+ expect(builder).toBe(Builders.BuildLibrary);
+ expect(options.tsConfig).toBe('projects/my-lib/tsconfig.lib.json');
+ expect(configurations.development).toEqual({
+ compilationMode: 'full',
+ });
+ });
+
+ it('should not set compilationMode in development configuration if already defined in tsconfig.lib.json', async () => {
+ tree.create(
+ '/projects/my-lib/tsconfig.lib.json',
+ JSON.stringify(
+ {
+ compilerOptions: {
+ declaration: true,
+ declarationMap: true,
+ },
+ angularCompilerOptions: {
+ compilationMode: 'partial',
+ },
+ },
+ undefined,
+ 2,
+ ),
+ );
+
+ const newTree = await schematicRunner.runSchematic(schematicName, {}, tree);
+ const {
+ projects: { 'my-lib': lib },
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } = newTree.readJson('/angular.json') as any;
+
+ const { configurations } = lib.architect['build'];
+ expect(configurations.development).toEqual({});
+ });
+
+ it('should discover and migrate secondary entry points into package.json exports', async () => {
+ tree.create(
+ '/projects/my-lib/testing/ng-package.json',
+ JSON.stringify(
+ {
+ lib: {
+ entryFile: 'src/public-api.ts',
+ },
+ },
+ undefined,
+ 2,
+ ),
+ );
+ tree.create(
+ '/projects/my-lib/schematics/package.json',
+ JSON.stringify(
+ {
+ ngPackage: {
+ lib: {
+ entryFile: 'index.ts',
+ },
+ },
+ },
+ undefined,
+ 2,
+ ),
+ );
+
+ const newTree = await schematicRunner.runSchematic(schematicName, {}, tree);
+ const {
+ projects: { 'my-lib': lib },
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } = newTree.readJson('/angular.json') as any;
+
+ const { options } = lib.architect['build'];
+ expect(options.entryPoints).toBeUndefined();
+
+ const libPkg = newTree.readJson('/projects/my-lib/package.json') as { exports: unknown };
+ expect(libPkg.exports).toEqual({
+ '.': './src/public-api.ts',
+ './schematics': './schematics/index.ts',
+ './testing': './testing/src/public-api.ts',
+ });
+
+ expect(newTree.exists('/projects/my-lib/testing/ng-package.json')).toBe(false);
+ expect(newTree.exists('/projects/my-lib/schematics/package.json')).toBe(false);
+ });
+
+ it('should preserve existing custom exports in package.json when adding entry points', async () => {
+ tree.overwrite(
+ '/projects/my-lib/package.json',
+ JSON.stringify(
+ {
+ name: 'my-lib',
+ version: '0.0.1',
+ exports: {
+ './theming': {
+ sass: './src/_theming.scss',
+ },
+ },
+ },
+ undefined,
+ 2,
+ ),
+ );
+
+ const newTree = await schematicRunner.runSchematic(schematicName, {}, tree);
+ const libPkg = newTree.readJson('/projects/my-lib/package.json') as { exports: unknown };
+ expect(libPkg.exports).toEqual({
+ './theming': {
+ sass: './src/_theming.scss',
+ },
+ '.': './src/public-api.ts',
+ });
+ });
+
+ it('should preserve root condition-only exports in package.json', async () => {
+ tree.overwrite(
+ '/projects/my-lib/package.json',
+ JSON.stringify(
+ {
+ name: 'my-lib',
+ version: '0.0.1',
+ exports: {
+ sass: './src/_index.scss',
+ },
+ },
+ undefined,
+ 2,
+ ),
+ );
+
+ const newTree = await schematicRunner.runSchematic(schematicName, {}, tree);
+ const libPkg = newTree.readJson('/projects/my-lib/package.json') as { exports: unknown };
+ expect(libPkg.exports).toEqual({
+ '.': {
+ sass: './src/_index.scss',
+ default: './src/public-api.ts',
+ },
+ });
+ });
+
+ it('should migrate assets, styleIncludePaths, and sass options from ng-package.json', async () => {
+ tree.overwrite(
+ '/projects/my-lib/ng-package.json',
+ JSON.stringify(
+ {
+ dest: '../../dist/my-lib',
+ assets: ['CHANGELOG.md'],
+ allowedNonPeerDependencies: ['lodash-es'],
+ inlineStyleLanguage: 'scss',
+ keepLifecycleScripts: true,
+ deleteDestPath: false,
+ lib: {
+ entryFile: 'src/public-api.ts',
+ styleIncludePaths: ['../theme'],
+ sass: {
+ silenceDeprecations: ['import'],
+ },
+ },
+ },
+ undefined,
+ 2,
+ ),
+ );
+
+ const newTree = await schematicRunner.runSchematic(schematicName, {}, tree);
+ const {
+ projects: { 'my-lib': lib },
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } = newTree.readJson('/angular.json') as any;
+
+ const { options } = lib.architect['build'];
+ expect(options.assets).toEqual(['projects/my-lib/CHANGELOG.md']);
+ expect(options.allowedNonPeerDependencies).toEqual(['lodash-es']);
+ expect(options.inlineStyleLanguage).toBe('scss');
+ expect(options.keepLifecycleScripts).toBe(true);
+ expect(options.deleteOutputPath).toBe(false);
+ expect(options.stylePreprocessorOptions).toEqual({
+ includePaths: ['projects/theme'],
+ sass: {
+ silenceDeprecations: ['import'],
+ },
+ });
+ });
+
+ it('should preserve existing stylePreprocessorOptions.includePaths when migrating styleIncludePaths', async () => {
+ const angularJson = JSON.parse(tree.readContent('/angular.json'));
+ angularJson.projects['my-lib'].architect.build.options.stylePreprocessorOptions = {
+ includePaths: ['existing/styles'],
+ };
+ tree.overwrite('/angular.json', JSON.stringify(angularJson, undefined, 2));
+
+ tree.overwrite(
+ '/projects/my-lib/ng-package.json',
+ JSON.stringify(
+ {
+ lib: {
+ entryFile: 'src/public-api.ts',
+ styleIncludePaths: ['../theme'],
+ },
+ },
+ undefined,
+ 2,
+ ),
+ );
+
+ const newTree = await schematicRunner.runSchematic(schematicName, {}, tree);
+ const {
+ projects: { 'my-lib': lib },
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } = newTree.readJson('/angular.json') as any;
+
+ expect(lib.architect['build'].options.stylePreprocessorOptions).toEqual({
+ includePaths: ['existing/styles', 'projects/theme'],
+ });
+ });
+
+ it('should throw an error when entry file is not configured and no default candidate exists', async () => {
+ tree.overwrite('/projects/my-lib/ng-package.json', JSON.stringify({}, undefined, 2));
+
+ await expectAsync(schematicRunner.runSchematic(schematicName, {}, tree)).toBeRejectedWithError(
+ 'Could not find an entry file for library entry point at "projects/my-lib".',
+ );
+ });
+
+ it('should migrate package.json with ngPackage configuration', async () => {
+ tree.overwrite(
+ '/projects/my-lib/package.json',
+ JSON.stringify(
+ {
+ name: 'my-lib',
+ ngPackage: {
+ lib: {
+ entryFile: 'src/public-api.ts',
+ },
+ },
+ },
+ undefined,
+ 2,
+ ),
+ );
+
+ // Point angular.json to package.json
+ const angularJson = JSON.parse(tree.readContent('/angular.json'));
+ angularJson.projects['my-lib'].architect.build.options.project = 'projects/my-lib/package.json';
+ tree.overwrite('/angular.json', JSON.stringify(angularJson, undefined, 2));
+
+ const newTree = await schematicRunner.runSchematic(schematicName, {}, tree);
+ const libPkg = newTree.readJson('/projects/my-lib/package.json') as {
+ ngPackage?: unknown;
+ name: string;
+ exports: unknown;
+ };
+ expect(libPkg.ngPackage).toBeUndefined();
+ expect(libPkg.name).toBe('my-lib');
+ expect(libPkg.exports).toEqual({
+ '.': './src/public-api.ts',
+ });
+ });
+
+ it('should skip libraries with JavaScript ng-packagr config files and retain ng-packagr dependency', async () => {
+ const angularJson = JSON.parse(tree.readContent('/angular.json'));
+ angularJson.projects['my-lib'].architect.build.options.project =
+ 'projects/my-lib/ng-package.cjs';
+ tree.overwrite('/angular.json', JSON.stringify(angularJson, undefined, 2));
+
+ const newTree = await schematicRunner.runSchematic(schematicName, {}, tree);
+ const {
+ projects: { 'my-lib': lib },
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } = newTree.readJson('/angular.json') as any;
+
+ expect(lib.architect['build'].builder).toBe(Builders.NgPackagr);
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const rootPkg = newTree.readJson('/package.json') as any;
+ expect(rootPkg.devDependencies['ng-packagr']).toBeDefined();
+ expect(rootPkg.devDependencies['@angular/build']).toBeUndefined();
+ });
+
+ it('should remove ng-packagr and add @angular/build when no library uses ng-packagr', async () => {
+ const newTree = await schematicRunner.runSchematic(schematicName, {}, tree);
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const rootPkg = newTree.readJson('/package.json') as any;
+
+ expect(rootPkg.devDependencies['ng-packagr']).toBeUndefined();
+ expect(rootPkg.devDependencies['@angular/build']).toBeDefined();
+ });
+});
diff --git a/packages/schematics/angular/ng-new/schema.json b/packages/schematics/angular/ng-new/schema.json
index 257628fcda9e..2c69fa84aaad 100644
--- a/packages/schematics/angular/ng-new/schema.json
+++ b/packages/schematics/angular/ng-new/schema.json
@@ -8,7 +8,7 @@
"properties": {
"directory": {
"type": "string",
- "description": "The directory where the new workspace and project should be created. If not specified, the workspace will be created in the current directory."
+ "description": "The directory where the new workspace and project should be created. If not specified, the workspace will be created in a subfolder within the current directory, using the workspace's name."
},
"name": {
"description": "The name for the new workspace and the initial project. This name will be used for the root directory and various identifiers throughout the project.",
diff --git a/packages/schematics/angular/package.json b/packages/schematics/angular/package.json
index 5d0cc7efef53..6025fad3bd99 100644
--- a/packages/schematics/angular/package.json
+++ b/packages/schematics/angular/package.json
@@ -20,10 +20,10 @@
"@angular-devkit/core": "workspace:0.0.0-PLACEHOLDER",
"@angular-devkit/schematics": "workspace:0.0.0-PLACEHOLDER",
"jsonc-parser": "3.3.1",
- "oxc-parser": "0.153.0",
+ "oxc-parser": "0.154.0",
"typescript": "6.0.3"
},
"devDependencies": {
- "@oxc-project/types": "0.153.0"
+ "@oxc-project/types": "0.154.0"
}
}
diff --git a/packages/schematics/angular/utility/find-module.ts b/packages/schematics/angular/utility/find-module.ts
index c98b52a0cbe2..e6ad0c5620e6 100644
--- a/packages/schematics/angular/utility/find-module.ts
+++ b/packages/schematics/angular/utility/find-module.ts
@@ -117,7 +117,7 @@ export function findModule(
const errorMsg = foundRoutingModule
? 'Could not find a non Routing NgModule.' +
- `\nModules with suffix '${routingModuleExt}' are strictly reserved for routing.` +
+ `\nModules with suffix '${routingModuleExtensions.join("' or '")}' are strictly reserved for routing.` +
`\nUse the '--skip-import' option to skip importing in NgModule.`
: `Could not find an NgModule. Use the '--skip-import' option to skip importing in NgModule.`;
diff --git a/packages/schematics/angular/utility/find-module_spec.ts b/packages/schematics/angular/utility/find-module_spec.ts
index 0db295ae384f..dcc8a7df057e 100644
--- a/packages/schematics/angular/utility/find-module_spec.ts
+++ b/packages/schematics/angular/utility/find-module_spec.ts
@@ -56,6 +56,9 @@ describe('find-module', () => {
expect(() => findModule(host, 'foo/src/app/anything-routing')).toThrowError(
/Could not find a non Routing NgModule/,
);
+ expect(() => findModule(host, 'foo/src/app/anything-routing')).toThrowError(
+ /Modules with suffix '-routing-module\.ts' or '-routing\.module\.ts' are strictly reserved/,
+ );
});
it('should throw if two modules found', () => {
diff --git a/packages/schematics/angular/utility/workspace-models.ts b/packages/schematics/angular/utility/workspace-models.ts
index d1ae1b146835..51c9c9dbdc9f 100644
--- a/packages/schematics/angular/utility/workspace-models.ts
+++ b/packages/schematics/angular/utility/workspace-models.ts
@@ -36,6 +36,7 @@ export enum Builders {
ExtractI18n = '@angular-devkit/build-angular:extract-i18n',
BuildExtractI18n = '@angular/build:extract-i18n',
BuildApplication = '@angular/build:application',
+ BuildLibrary = '@angular/build:library',
}
export interface FileReplacements {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index e6b9e456459e..81cbdf51aeb5 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -7,153 +7,153 @@ importers:
configDependencies: {}
packageManagerDependencies:
pnpm:
- specifier: 12.10.1
- version: 12.10.1
+ specifier: 12.11.2
+ version: 12.11.2
packages:
- '@pnpm/exe.android-arm64@12.10.1':
- resolution: {integrity: sha512-CVTlHPwNvadQCJD9bGSMzWIhFX8QpjtqC2c27dhdnn/9iKzEjZ3qL62o3gHpKbIuo6qn4WxTKRoaokgNdReBig==}
+ '@pnpm/exe.android-arm64@12.11.2':
+ resolution: {integrity: sha512-owLw13OfPkEoY+hLBNeeG+dCFhywr7q2d/EHPz4mNL2RhKnv8gNwMARkjkiDQu234aItVwFNDeGnmQXm+ikkAg==}
cpu: [arm64]
os: [android]
- '@pnpm/exe.android-x64@12.10.1':
- resolution: {integrity: sha512-NFiYLIaodY7da0XIebwcU3JoP7IK/lzF7zgKSSP+9H+QcFnQ1GDfBkuBKCYJzZ+Xu0WH54neIPLBBCaOjaaauA==}
+ '@pnpm/exe.android-x64@12.11.2':
+ resolution: {integrity: sha512-GYPkVebl4iokOA/4MPSpGoUVfFlsth7uqOCe1XiaiM23LAdvUOMJBObqHJijr89ZqjwHm9pO6vO45GRwJ2U2qA==}
cpu: [x64]
os: [android]
- '@pnpm/exe.darwin-arm64@12.10.1':
- resolution: {integrity: sha512-0O8tdQ8ijlPJudXspLMTcitMkdBEz6uUflazL5uQE0WMs85oQIp0U+5hfEktMFB64QqEhjqlvvujTwbzdr9oMg==}
+ '@pnpm/exe.darwin-arm64@12.11.2':
+ resolution: {integrity: sha512-n9M4On66y8FDxUAKgMO1FXt0qihyG4e+56p3/F0uo8Bx9KplW8BwKVnXigzCJ8aNM6sVVPkOE6M9XXbeVIxnZA==}
cpu: [arm64]
os: [darwin]
- '@pnpm/exe.darwin-x64@12.10.1':
- resolution: {integrity: sha512-ud+1/uZOKEo8P/AsPynOJc/LNwfI0j6WwCElibj71rU9l4nIBnsSn+wWTIPZPkZ4BBSH5+82azSnAARMyJ1lNA==}
+ '@pnpm/exe.darwin-x64@12.11.2':
+ resolution: {integrity: sha512-oSW7n3sBT0c0cyk4kj10T2Y6Mpm+OFEiCAWozgX039tdoI6yqJF1uaFD3sw7ugLdu6VV3+uY0pa1TUZIPdxDWA==}
cpu: [x64]
os: [darwin]
- '@pnpm/exe.freebsd-x64@12.10.1':
- resolution: {integrity: sha512-mj9PE5rf8uAfQQ2K66HSATMSut+lNiB4eSqFd5+azFVCMnxNSy/32xpZQJT21PhnN3Y4qbK+iKHe5nWAxSuRhw==}
+ '@pnpm/exe.freebsd-x64@12.11.2':
+ resolution: {integrity: sha512-qbzc3KoDpa/Lkf8vs3jnDe6dUUbso+6eLIyssYFMiliLpYNxn8dirk11YoNnOQcdHVB50v5RFls1Yid6ttT5pg==}
cpu: [x64]
os: [freebsd]
- '@pnpm/exe.linux-arm64-musl@12.10.1':
- resolution: {integrity: sha512-xba+00wZJ8Um6rBJJjWl88uJj0tydB8dtomvjlCLvi0uL32vpa9CRP8Vv26FIXvbiZ1bo2RCzYt/eChxJVV52w==}
+ '@pnpm/exe.linux-arm64-musl@12.11.2':
+ resolution: {integrity: sha512-uMEYDwKRktGwANubQ+kYCwmhNwg3Ik6qK89ahsbQ5cP30R/5FVJb/T99vr9XRUBC/A7mZI6eeT92oyVas9ACyg==}
cpu: [arm64]
os: [linux]
libc: [musl]
- '@pnpm/exe.linux-arm64@12.10.1':
- resolution: {integrity: sha512-oBdMp69ScC9UnniG4qZAQVr2fBDSXjm4yk/72vkEVyrlwS23yMxcRQl7Qdo3sgXPAygY6TWnPRKm4rXzjoyW7w==}
+ '@pnpm/exe.linux-arm64@12.11.2':
+ resolution: {integrity: sha512-6e8ZAQUwFXAWHHHv5FesWqf/kEK04wuitBv5f/gxzkC0DiBfaixr+f+6JQede8SF4Ji5LcMwVFJbzAtffpWxEg==}
cpu: [arm64]
os: [linux]
libc: [glibc]
- '@pnpm/exe.linux-ppc64@12.10.1':
- resolution: {integrity: sha512-Yyb3wu09h3c7mLme270uHFiVaAIUHC411Ru9LIU2BKUIstrGlXa9OqqVWoXaRgYRdFdOFknkwG7GNn6ygwLbnw==}
+ '@pnpm/exe.linux-ppc64@12.11.2':
+ resolution: {integrity: sha512-Ui8A4nepkVupx2VpuFfysEluMvWK6gTB5rgVts7Ss/+8dj0RD28x3F/seNeH/zSypgC6yKdV6qsKVQh/uffTuQ==}
cpu: [ppc64]
os: [linux]
libc: [glibc]
- '@pnpm/exe.linux-riscv64@12.10.1':
- resolution: {integrity: sha512-PdkeUFFkybknnGkWP0H22eMpIiS4OZXL5BcQzF4lh+vmrW3IaC2HOkbANKgot/PKO0Kl77pzA/6PKFxgbgfXIQ==}
+ '@pnpm/exe.linux-riscv64@12.11.2':
+ resolution: {integrity: sha512-i1yLdQ5bu+wjQ+srtFoJAaY2gN/+oXHFdjul4llCeoDxHE0rTIG3R41NhHfCjyFPW4+CpbBT58933CL9sMOCnA==}
cpu: [riscv64]
os: [linux]
libc: [glibc]
- '@pnpm/exe.linux-s390x@12.10.1':
- resolution: {integrity: sha512-1okKuHKJwJPAbofDxfhZWAUxEWtee4ZSf7Pah8kcvocaJkf2WxFJ5KVTiNIvDml5GLidDQsgf7Pcf/WHbCak7Q==}
+ '@pnpm/exe.linux-s390x@12.11.2':
+ resolution: {integrity: sha512-YS1/lhPjjTsN4QL50VaFZKRa3Uc/bDnhE8eKbJMFvuX06UuFS5YaiDg04APoZdfVSGqTfX27QAg7rfLMSWaqxA==}
cpu: [s390x]
os: [linux]
libc: [glibc]
- '@pnpm/exe.linux-x64-musl@12.10.1':
- resolution: {integrity: sha512-e6IqzVNkPa7srFKJKnY23uWJ+qz0LaRWiTUo/sHfFXRRMRzB5uNOr6qWWip/jqhdGwU91n9J7LrEYZ6e0tRczw==}
+ '@pnpm/exe.linux-x64-musl@12.11.2':
+ resolution: {integrity: sha512-7eIxQR05fvJxCujUSKp5KTtehJ7QqrgqP/HD1+BcB/SaV2Be4XI1PEHiOgA1zxsiMIeMvTF6E4G4dYHrFjeXRg==}
cpu: [x64]
os: [linux]
libc: [musl]
- '@pnpm/exe.linux-x64@12.10.1':
- resolution: {integrity: sha512-ZByV0DRgWzGaDSjT5ddRBASdwz+r/qPMYh7o6RGmPQjtRGNFbSl94xY2DcAM8mqCOZJUUDtAXQ+wpBXcdpKlkg==}
+ '@pnpm/exe.linux-x64@12.11.2':
+ resolution: {integrity: sha512-FK7QKe24AYgppJwO3mpooYptduuvIGqKJPi5ac7MdnWkjUy46JBfYhCW0grnkWKC8YOf0x+vGviuQqJEj3SpQQ==}
cpu: [x64]
os: [linux]
libc: [glibc]
- '@pnpm/exe.win32-arm64@12.10.1':
- resolution: {integrity: sha512-I7QZHcjioG7orFeCRUFUHByJ1G0zFPnAlaGGyrUvb6MGkv5oeNwNPl7t+Gp+7zHfnMcgLGJ1a+Wfim0IDw3lOw==}
+ '@pnpm/exe.win32-arm64@12.11.2':
+ resolution: {integrity: sha512-PCTjVDdJb6VvraZxrEeFv6EqEA0hhIsAySx28e95J2Tqpi88hLpgOXgNqV0vpxq9A+b8GLQfyk/D+1UlJPv/YQ==}
cpu: [arm64]
os: [win32]
- '@pnpm/exe.win32-x64@12.10.1':
- resolution: {integrity: sha512-4WJFdp58EKlCj0zLobrXU0vpszSZIr4X/3y/uNbAQqGW0zE+VdruZB0gFc3L2kzsUzVwTYbaCn+XEhnCYSAlTg==}
+ '@pnpm/exe.win32-x64@12.11.2':
+ resolution: {integrity: sha512-8sgX86OvRjJ3yZs/TvGR2L31wH9ScPZ+f+geKI3ikuB0RRiK3i4LlTRO8OXN6pdRqj8epMde4312MCjj7JsJdA==}
cpu: [x64]
os: [win32]
- pnpm@12.10.1:
- resolution: {integrity: sha512-ukCjfrGjcNYP6oxM8dNkwTvMzvUY6YrSvO6VT1OdONo3RY5YJho/pV4GUjRQ6g//+fSXsTW+QfLBXBZCusrObA==}
+ pnpm@12.11.2:
+ resolution: {integrity: sha512-JaUWUqGWeFr18ovabf6NxYLr76SsHRgCIc4TkCMcX7dmN4IupLbkYzznSs3LCnf3Ja8RutOBd/3t2u6BipVcuQ==}
engines: {node: '>=18.*'}
hasBin: true
snapshots:
- '@pnpm/exe.android-arm64@12.10.1':
+ '@pnpm/exe.android-arm64@12.11.2':
optional: true
- '@pnpm/exe.android-x64@12.10.1':
+ '@pnpm/exe.android-x64@12.11.2':
optional: true
- '@pnpm/exe.darwin-arm64@12.10.1':
+ '@pnpm/exe.darwin-arm64@12.11.2':
optional: true
- '@pnpm/exe.darwin-x64@12.10.1':
+ '@pnpm/exe.darwin-x64@12.11.2':
optional: true
- '@pnpm/exe.freebsd-x64@12.10.1':
+ '@pnpm/exe.freebsd-x64@12.11.2':
optional: true
- '@pnpm/exe.linux-arm64-musl@12.10.1':
+ '@pnpm/exe.linux-arm64-musl@12.11.2':
optional: true
- '@pnpm/exe.linux-arm64@12.10.1':
+ '@pnpm/exe.linux-arm64@12.11.2':
optional: true
- '@pnpm/exe.linux-ppc64@12.10.1':
+ '@pnpm/exe.linux-ppc64@12.11.2':
optional: true
- '@pnpm/exe.linux-riscv64@12.10.1':
+ '@pnpm/exe.linux-riscv64@12.11.2':
optional: true
- '@pnpm/exe.linux-s390x@12.10.1':
+ '@pnpm/exe.linux-s390x@12.11.2':
optional: true
- '@pnpm/exe.linux-x64-musl@12.10.1':
+ '@pnpm/exe.linux-x64-musl@12.11.2':
optional: true
- '@pnpm/exe.linux-x64@12.10.1':
+ '@pnpm/exe.linux-x64@12.11.2':
optional: true
- '@pnpm/exe.win32-arm64@12.10.1':
+ '@pnpm/exe.win32-arm64@12.11.2':
optional: true
- '@pnpm/exe.win32-x64@12.10.1':
+ '@pnpm/exe.win32-x64@12.11.2':
optional: true
- pnpm@12.10.1:
+ pnpm@12.11.2:
optionalDependencies:
- '@pnpm/exe.android-arm64': 12.10.1
- '@pnpm/exe.android-x64': 12.10.1
- '@pnpm/exe.darwin-arm64': 12.10.1
- '@pnpm/exe.darwin-x64': 12.10.1
- '@pnpm/exe.freebsd-x64': 12.10.1
- '@pnpm/exe.linux-arm64': 12.10.1
- '@pnpm/exe.linux-arm64-musl': 12.10.1
- '@pnpm/exe.linux-ppc64': 12.10.1
- '@pnpm/exe.linux-riscv64': 12.10.1
- '@pnpm/exe.linux-s390x': 12.10.1
- '@pnpm/exe.linux-x64': 12.10.1
- '@pnpm/exe.linux-x64-musl': 12.10.1
- '@pnpm/exe.win32-arm64': 12.10.1
- '@pnpm/exe.win32-x64': 12.10.1
+ '@pnpm/exe.android-arm64': 12.11.2
+ '@pnpm/exe.android-x64': 12.11.2
+ '@pnpm/exe.darwin-arm64': 12.11.2
+ '@pnpm/exe.darwin-x64': 12.11.2
+ '@pnpm/exe.freebsd-x64': 12.11.2
+ '@pnpm/exe.linux-arm64': 12.11.2
+ '@pnpm/exe.linux-arm64-musl': 12.11.2
+ '@pnpm/exe.linux-ppc64': 12.11.2
+ '@pnpm/exe.linux-riscv64': 12.11.2
+ '@pnpm/exe.linux-s390x': 12.11.2
+ '@pnpm/exe.linux-x64': 12.11.2
+ '@pnpm/exe.linux-x64-musl': 12.11.2
+ '@pnpm/exe.win32-arm64': 12.11.2
+ '@pnpm/exe.win32-x64': 12.11.2
---
lockfileVersion: '9.0'
@@ -172,8 +172,8 @@ importers:
.:
dependencies:
'@angular/compiler-cli':
- specifier: 22.3.0-next.1
- version: 22.3.0-next.1(@angular/compiler@22.3.0-next.1)(typescript@6.0.3)
+ specifier: 22.3.0-next.2
+ version: 22.3.0-next.2(@angular/compiler@22.3.0-next.2)(typescript@6.0.3)
typescript:
specifier: 6.0.3
version: 6.0.3
@@ -184,44 +184,44 @@ importers:
built: true
devDependencies:
'@angular/animations':
- specifier: 22.3.0-next.1
- version: 22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))
+ specifier: 22.3.0-next.2
+ version: 22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))
'@angular/cdk':
- specifier: 22.3.0-next.1
- version: 22.3.0-next.1(1e228ab395252fe57958c1335d3a301f)
+ specifier: 22.3.0-next.2
+ version: 22.3.0-next.2(e02572097466d520d7eb144e95d6bbd2)
'@angular/common':
- specifier: 22.3.0-next.1
- version: 22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2)
+ specifier: 22.3.0-next.2
+ version: 22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2)
'@angular/compiler':
- specifier: 22.3.0-next.1
- version: 22.3.0-next.1
+ specifier: 22.3.0-next.2
+ version: 22.3.0-next.2
'@angular/core':
- specifier: 22.3.0-next.1
- version: 22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)
+ specifier: 22.3.0-next.2
+ version: 22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)
'@angular/forms':
- specifier: 22.3.0-next.1
- version: 22.3.0-next.1(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(@angular/platform-browser@22.3.0-next.1(@angular/animations@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(rxjs@7.8.2)
+ specifier: 22.3.0-next.2
+ version: 22.3.0-next.2(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(@angular/platform-browser@22.3.0-next.2(@angular/animations@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(rxjs@7.8.2)
'@angular/localize':
- specifier: 22.3.0-next.1
- version: 22.3.0-next.1(@angular/compiler-cli@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(typescript@6.0.3))(@angular/compiler@22.3.0-next.1)
+ specifier: 22.3.0-next.2
+ version: 22.3.0-next.2(@angular/compiler-cli@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(typescript@6.0.3))(@angular/compiler@22.3.0-next.2)
'@angular/material':
- specifier: 22.3.0-next.1
- version: 22.3.0-next.1(837417520965053888cf2615dc986a27)
+ specifier: 22.3.0-next.2
+ version: 22.3.0-next.2(4016851894464b4783f4f873310c276b)
'@angular/ng-dev':
- specifier: https://github.com/angular/dev-infra-private-ng-dev-builds.git#89b8c002e5d47ba1cbc4483d3ec06b0ae0aaccb7
- version: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/89b8c002e5d47ba1cbc4483d3ec06b0ae0aaccb7
+ specifier: https://github.com/angular/dev-infra-private-ng-dev-builds.git#940c0beef0de4cb128e90962d47ff80e352a1cd8
+ version: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/940c0beef0de4cb128e90962d47ff80e352a1cd8
'@angular/platform-browser':
- specifier: 22.3.0-next.1
- version: 22.3.0-next.1(@angular/animations@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))
+ specifier: 22.3.0-next.2
+ version: 22.3.0-next.2(@angular/animations@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))
'@angular/platform-server':
- specifier: 22.3.0-next.1
- version: 22.3.0-next.1(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/compiler@22.3.0-next.1)(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(@angular/platform-browser@22.3.0-next.1(@angular/animations@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(rxjs@7.8.2)
+ specifier: 22.3.0-next.2
+ version: 22.3.0-next.2(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/compiler@22.3.0-next.2)(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(@angular/platform-browser@22.3.0-next.2(@angular/animations@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(rxjs@7.8.2)
'@angular/router':
- specifier: 22.3.0-next.1
- version: 22.3.0-next.1(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(@angular/platform-browser@22.3.0-next.1(@angular/animations@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(rxjs@7.8.2)
+ specifier: 22.3.0-next.2
+ version: 22.3.0-next.2(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(@angular/platform-browser@22.3.0-next.2(@angular/animations@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(rxjs@7.8.2)
'@angular/service-worker':
- specifier: 22.3.0-next.1
- version: 22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2)
+ specifier: 22.3.0-next.2
+ version: 22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2)
'@babel/core':
specifier: 8.0.7
version: 8.0.7
@@ -245,16 +245,16 @@ importers:
version: 10.0.1(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))
'@rollup/plugin-commonjs':
specifier: ^29.0.0
- version: 29.0.3(rollup@4.64.1)
+ version: 29.0.3(rollup@4.64.6)
'@rollup/plugin-json':
specifier: ^6.1.0
- version: 6.1.0(rollup@4.64.1)
+ version: 6.1.0(rollup@4.64.6)
'@rollup/plugin-node-resolve':
specifier: 16.0.3
- version: 16.0.3(rollup@4.64.1)
+ version: 16.0.3(rollup@4.64.6)
'@rollup/wasm-node':
- specifier: 4.64.1
- version: 4.64.1
+ specifier: 4.64.6
+ version: 4.64.6
'@stylistic/eslint-plugin':
specifier: ^5.0.0
version: 5.10.0(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))
@@ -293,7 +293,7 @@ importers:
version: 3.0.0(esbuild@0.28.2)(lightningcss@1.33.0)(uglify-js@3.19.3)
'@types/lodash':
specifier: ^4.17.0
- version: 4.17.25
+ version: 4.17.26
'@types/node':
specifier: ^22.12.0
version: 22.20.5
@@ -316,11 +316,11 @@ importers:
specifier: ^21.0.0
version: 21.0.3
'@typescript-eslint/eslint-plugin':
- specifier: 8.71.1
- version: 8.71.1(@typescript-eslint/parser@8.71.1(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3)
+ specifier: 8.71.2
+ version: 8.71.2(@typescript-eslint/parser@8.71.2(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3)
'@typescript-eslint/parser':
- specifier: 8.71.1
- version: 8.71.1(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3)
+ specifier: 8.71.2
+ version: 8.71.2(eslint@10.12.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
@@ -341,10 +341,10 @@ importers:
version: 10.1.8(eslint@10.12.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.71.1(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)
+ version: 2.32.0(@typescript-eslint/parser@8.71.2(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3))(eslint@10.12.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@11.0.0)
+ specifier: 5.3.0
+ version: 5.3.0(supports-color@11.0.0)
fast-glob:
specifier: 3.3.3
version: 3.3.3
@@ -398,22 +398,22 @@ importers:
version: 1.4.3
prettier:
specifier: ^3.0.0
- version: 3.9.9
+ version: 3.9.10
puppeteer:
- specifier: 25.12.0
- version: 25.12.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)
+ specifier: 25.14.0
+ version: 25.14.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)
quicktype-core:
specifier: 26.0.0
version: 26.0.0
rollup:
- specifier: 4.64.1
- version: 4.64.1
+ specifier: 4.64.6
+ version: 4.64.6
rollup-plugin-dts:
specifier: 6.5.1
- version: 6.5.1(rollup@4.64.1)(typescript@6.0.3)
+ version: 6.5.1(rollup@4.64.6)(typescript@6.0.3)
rollup-plugin-sourcemaps2:
specifier: 0.5.9
- version: 0.5.9(@types/node@22.20.5)(rollup@4.64.1)
+ version: 0.5.9(@types/node@22.20.5)(rollup@4.64.6)
semver:
specifier: 7.8.5
version: 7.8.5
@@ -424,14 +424,14 @@ importers:
specifier: 2.8.1
version: 2.8.1
undici:
- specifier: 8.11.2
- version: 8.11.2
+ specifier: 8.12.1
+ version: 8.12.1
verdaccio:
specifier: 6.10.5
version: 6.10.5(encoding@0.1.13)(supports-color@11.0.0)
verdaccio-auth-memory:
specifier: ^13.0.0
- version: 13.1.5(supports-color@11.0.0)
+ version: 13.1.6(supports-color@11.0.0)
zone.js:
specifier: ^0.16.0
version: 0.16.3
@@ -451,8 +451,8 @@ importers:
specifier: workspace:*
version: link:../../../packages/angular/ssr
'@vitest/coverage-v8':
- specifier: 5.0.3
- version: 5.0.3(vitest@5.0.3)
+ specifier: 5.0.4
+ version: 5.0.4(vitest@5.0.4)
browser-sync:
specifier: 3.0.4
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)
@@ -464,13 +464,13 @@ importers:
version: 30.1.2(@noble/hashes@1.8.0)
ng-packagr:
specifier: 22.3.0-next.2
- version: 22.3.0-next.2(@angular/compiler-cli@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(typescript@6.0.3))(supports-color@11.0.0)(tslib@2.8.1)(typescript@6.0.3)
+ version: 22.3.0-next.2(@angular/compiler-cli@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(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: 5.0.3
- version: 5.0.3(@opentelemetry/api@1.9.1)(@types/node@22.20.5)(@vitest/coverage-v8@5.0.3)(jsdom@30.1.2(@noble/hashes@1.8.0))(vite@8.3.3(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1))
+ specifier: 5.0.4
+ version: 5.0.4(@opentelemetry/api@1.9.1)(@types/node@22.20.5)(@vitest/coverage-v8@5.0.4)(jsdom@30.1.2(@noble/hashes@1.8.0))(vite@8.3.4(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1))
packages/angular/build:
dependencies:
@@ -491,10 +491,10 @@ importers:
version: 2.6.0
'@vitejs/plugin-basic-ssl':
specifier: 2.3.0
- version: 2.3.0(vite@8.3.3(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1))
+ version: 2.3.0(vite@8.3.4(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1))
beasties:
- specifier: 0.5.4
- version: 0.5.4
+ specifier: 0.5.5
+ version: 0.5.5
browserslist:
specifier: ^4.26.0
version: 4.29.3
@@ -511,8 +511,8 @@ importers:
specifier: 3.3.1
version: 3.3.1
listr2:
- specifier: 11.1.1
- version: 11.1.1
+ specifier: 11.2.0
+ version: 11.2.0
magic-string:
specifier: 1.4.3
version: 1.4.3
@@ -520,8 +520,8 @@ importers:
specifier: 2.0.1
version: 2.0.1
oxc-parser:
- specifier: 0.153.0
- version: 0.153.0
+ specifier: 0.154.0
+ version: 0.154.0
parse5-html-rewriting-stream:
specifier: 8.0.1
version: 8.0.1
@@ -532,11 +532,11 @@ importers:
specifier: 5.3.2
version: 5.3.2
rolldown:
- specifier: 1.2.12
- version: 1.2.12
+ specifier: 1.2.14
+ version: 1.2.14
rolldown-plugin-dts:
- specifier: 0.28.6
- version: 0.28.6(rolldown@1.2.12)(typescript@6.0.3)
+ specifier: 0.28.8
+ version: 0.28.8(rolldown@1.2.14)(typescript@6.0.3)
sass:
specifier: 1.105.1
version: 1.105.1
@@ -553,8 +553,8 @@ importers:
specifier: 0.2.17
version: 0.2.17
vite:
- specifier: 8.3.3
- version: 8.3.3(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1)
+ specifier: 8.3.4
+ version: 8.3.4(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1)
xxhash-wasm:
specifier: 1.1.0
version: 1.1.0
@@ -566,11 +566,11 @@ importers:
specifier: workspace:*
version: link:../ssr
'@oxc-project/types':
- specifier: 0.153.0
- version: 0.153.0
+ specifier: 0.154.0
+ version: 0.154.0
'@vitest/coverage-v8':
- specifier: 5.0.3
- version: 5.0.3(vitest@5.0.3)
+ specifier: 5.0.4
+ version: 5.0.4(vitest@5.0.4)
istanbul-lib-instrument:
specifier: 6.0.3
version: 6.0.3(supports-color@11.0.0)
@@ -582,19 +582,19 @@ importers:
version: 4.9.1(supports-color@11.0.0)
ng-packagr:
specifier: 22.3.0-next.2
- version: 22.3.0-next.2(@angular/compiler-cli@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(typescript@6.0.3))(supports-color@11.0.0)(tslib@2.8.1)(typescript@6.0.3)
+ version: 22.3.0-next.2(@angular/compiler-cli@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(typescript@6.0.3))(supports-color@11.0.0)(tslib@2.8.1)(typescript@6.0.3)
postcss:
- specifier: 8.5.29
- version: 8.5.29
+ specifier: 8.5.30
+ version: 8.5.30
rollup:
- specifier: 4.64.1
- version: 4.64.1
+ specifier: 4.64.6
+ version: 4.64.6
rxjs:
specifier: 7.8.2
version: 7.8.2
vitest:
- specifier: 5.0.3
- version: 5.0.3(@opentelemetry/api@1.9.1)(@types/node@22.20.5)(@vitest/coverage-v8@5.0.3)(jsdom@30.1.2(@noble/hashes@1.8.0))(vite@8.3.3(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1))
+ specifier: 5.0.4
+ version: 5.0.4(@opentelemetry/api@1.9.1)(@types/node@22.20.5)(@vitest/coverage-v8@5.0.4)(jsdom@30.1.2(@noble/hashes@1.8.0))(vite@8.3.4(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1))
optionalDependencies:
lmdb:
specifier: 3.5.7
@@ -615,8 +615,8 @@ importers:
specifier: 8.7.3
version: 8.7.3(@types/node@22.20.5)
'@listr2/prompt-adapter-inquirer':
- specifier: 4.2.7
- version: 4.2.7(@inquirer/prompts@8.7.3(@types/node@22.20.5))(@types/node@22.20.5)(listr2@11.1.1)
+ specifier: 4.3.1
+ version: 4.3.1(@inquirer/prompts@8.7.3(@types/node@22.20.5))(@types/node@22.20.5)(listr2@11.2.0)
'@modelcontextprotocol/server':
specifier: 2.3.1
version: 2.3.1
@@ -627,8 +627,8 @@ importers:
specifier: 3.3.1
version: 3.3.1
listr2:
- specifier: 11.1.1
- version: 11.1.1
+ specifier: 11.2.0
+ version: 11.2.0
npm-package-arg:
specifier: 14.0.0
version: 14.0.0
@@ -642,8 +642,8 @@ importers:
specifier: 18.2.0
version: 18.2.0
zod:
- specifier: 4.6.5
- version: 4.6.5
+ specifier: 4.6.7
+ version: 4.6.7
packages/angular/pwa:
dependencies:
@@ -660,8 +660,8 @@ importers:
packages/angular/ssr:
dependencies:
beasties:
- specifier: 0.5.4
- version: 0.5.4
+ specifier: 0.5.5
+ version: 0.5.5
tslib:
specifier: ^2.3.0
version: 2.8.1
@@ -670,23 +670,23 @@ importers:
specifier: workspace:*
version: link:../../angular_devkit/schematics
'@angular/common':
- specifier: 22.3.0-next.1
- version: 22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2)
+ specifier: 22.3.0-next.2
+ version: 22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2)
'@angular/compiler':
- specifier: 22.3.0-next.1
- version: 22.3.0-next.1
+ specifier: 22.3.0-next.2
+ version: 22.3.0-next.2
'@angular/core':
- specifier: 22.3.0-next.1
- version: 22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)
+ specifier: 22.3.0-next.2
+ version: 22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)
'@angular/platform-browser':
- specifier: 22.3.0-next.1
- version: 22.3.0-next.1(@angular/animations@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))
+ specifier: 22.3.0-next.2
+ version: 22.3.0-next.2(@angular/animations@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))
'@angular/platform-server':
- specifier: 22.3.0-next.1
- version: 22.3.0-next.1(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/compiler@22.3.0-next.1)(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(@angular/platform-browser@22.3.0-next.1(@angular/animations@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(rxjs@7.8.2)
+ specifier: 22.3.0-next.2
+ version: 22.3.0-next.2(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/compiler@22.3.0-next.2)(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(@angular/platform-browser@22.3.0-next.2(@angular/animations@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(rxjs@7.8.2)
'@angular/router':
- specifier: 22.3.0-next.1
- version: 22.3.0-next.1(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(@angular/platform-browser@22.3.0-next.1(@angular/animations@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(rxjs@7.8.2)
+ specifier: 22.3.0-next.2
+ version: 22.3.0-next.2(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(@angular/platform-browser@22.3.0-next.2(@angular/animations@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(rxjs@7.8.2)
'@schematics/angular':
specifier: workspace:*
version: link:../../schematics/angular
@@ -755,22 +755,22 @@ importers:
version: 4.1.3
autoprefixer:
specifier: 10.6.1
- version: 10.6.1(postcss@8.5.29)
+ version: 10.6.1(postcss@8.5.30)
babel-loader:
specifier: 10.1.1
- version: 10.1.1(@babel/core@8.0.7)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3))
+ version: 10.1.1(@babel/core@8.0.7)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3))
beasties:
- specifier: 0.5.4
- version: 0.5.4
+ specifier: 0.5.5
+ version: 0.5.5
browserslist:
specifier: ^4.26.0
version: 4.29.3
copy-webpack-plugin:
specifier: 14.0.0
- version: 14.0.0(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3))
+ version: 14.0.0(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3))
css-loader:
specifier: 7.1.5
- version: 7.1.5(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3))
+ version: 7.1.5(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3))
esbuild-wasm:
specifier: 0.28.2
version: 0.28.2
@@ -791,16 +791,16 @@ importers:
version: 4.9.1(supports-color@11.0.0)
less-loader:
specifier: 13.0.0
- version: 13.0.0(less@4.9.1(supports-color@11.0.0))(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3))
+ version: 13.0.0(less@4.9.1(supports-color@11.0.0))(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3))
license-webpack-plugin:
specifier: 4.0.2
- version: 4.0.2(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3))
+ version: 4.0.2(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(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.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3))
+ version: 2.10.2(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3))
open:
specifier: 11.0.4
version: 11.0.4
@@ -814,11 +814,11 @@ importers:
specifier: 5.3.2
version: 5.3.2
postcss:
- specifier: 8.5.29
- version: 8.5.29
+ specifier: 8.5.30
+ version: 8.5.30
postcss-loader:
specifier: 8.2.1
- version: 8.2.1(postcss@8.5.29)(typescript@6.0.3)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3))
+ version: 8.2.1(postcss@8.5.30)(typescript@6.0.3)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3))
resolve-url-loader:
specifier: 5.0.0
version: 5.0.0
@@ -827,13 +827,13 @@ importers:
version: 7.8.2
sass-loader:
specifier: 17.0.1
- version: 17.0.1(sass-embedded@1.105.1)(sass@1.105.1)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3))
+ version: 17.0.1(sass-embedded@1.105.1)(sass@1.105.1)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(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.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3))
+ version: 5.0.0(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3))
source-map-support:
specifier: 0.5.21
version: 0.5.21
@@ -848,19 +848,19 @@ importers:
version: 2.8.1
webpack:
specifier: 5.111.1
- version: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)
+ version: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)
webpack-dev-middleware:
specifier: 8.3.0
- version: 8.3.0(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3))
+ version: 8.3.0(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3))
webpack-dev-server:
specifier: 6.0.0
- version: 6.0.0(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3))
+ version: 6.0.0(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(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.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3))
+ version: 5.1.0(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3))
devDependencies:
'@angular/ssr':
specifier: workspace:*
@@ -870,13 +870,13 @@ importers:
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.3.0-next.2
- version: 22.3.0-next.2(@angular/compiler-cli@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(typescript@6.0.3))(supports-color@11.0.0)(tslib@2.8.1)(typescript@6.0.3)
+ version: 22.3.0-next.2(@angular/compiler-cli@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(typescript@6.0.3))(supports-color@11.0.0)(tslib@2.8.1)(typescript@6.0.3)
sass:
specifier: 1.105.1
version: 1.105.1
undici:
- specifier: 8.11.2
- version: 8.11.2
+ specifier: 8.12.1
+ version: 8.12.1
optionalDependencies:
esbuild:
specifier: 0.28.2
@@ -899,10 +899,10 @@ importers:
version: link:../../ngtools/webpack
webpack:
specifier: 5.111.1
- version: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.28)(uglify-js@3.19.3)
+ version: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)
webpack-dev-server:
specifier: 6.0.0
- version: 6.0.0(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.28)(uglify-js@3.19.3))
+ version: 6.0.0(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3))
packages/angular_devkit/core:
dependencies:
@@ -965,17 +965,17 @@ importers:
specifier: workspace:0.0.0-PLACEHOLDER
version: link:../../angular_devkit/core
'@angular/compiler':
- specifier: 22.3.0-next.1
- version: 22.3.0-next.1
+ specifier: 22.3.0-next.2
+ version: 22.3.0-next.2
'@angular/compiler-cli':
- specifier: 22.3.0-next.1
- version: 22.3.0-next.1(@angular/compiler@22.3.0-next.1)(typescript@6.0.3)
+ specifier: 22.3.0-next.2
+ version: 22.3.0-next.2(@angular/compiler@22.3.0-next.2)(typescript@6.0.3)
typescript:
specifier: 6.0.3
version: 6.0.3
webpack:
specifier: 5.111.1
- version: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.28)(uglify-js@3.19.3)
+ version: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)
packages/schematics/angular:
dependencies:
@@ -989,15 +989,15 @@ importers:
specifier: 3.3.1
version: 3.3.1
oxc-parser:
- specifier: 0.153.0
- version: 0.153.0
+ specifier: 0.154.0
+ version: 0.154.0
typescript:
specifier: 6.0.3
version: 6.0.3
devDependencies:
'@oxc-project/types':
- specifier: 0.153.0
- version: 0.153.0
+ specifier: 0.154.0
+ version: 0.154.0
tests:
devDependencies:
@@ -1029,14 +1029,15 @@ packages:
resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
engines: {node: '>=6.0.0'}
- '@angular/animations@22.3.0-next.1':
- resolution: {integrity: sha512-YdJE9xE7EO9xJtXNcWFXCatofYRXmkZm5oPOaKBCTHvX12Iw3SQsybxXr23Lq1gHscAZnqffEfhQ78TdnSl5wA==}
+ '@angular/animations@22.3.0-next.2':
+ resolution: {integrity: sha512-YJCMY2lUtiIQNfqTXnwbKjePHAEq4sION4i+66eH7Fhog55eust9BQ7zVCp8CtfPUF2kNwhiMyU6DbZQCxmN1w==}
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.3.0-next.1
+ '@angular/core': 22.3.0-next.2
- '@angular/cdk@22.3.0-next.1':
- resolution: {integrity: sha512-WAOIXq+8KtLn59xdt7rRKgdxO3VUCGSlSzoUJQez4EM+/MFa8GPMTHZ392ewBA3R2XpEJNFbSIH61A0+yfNBMg==}
+ '@angular/cdk@22.3.0-next.2':
+ resolution: {integrity: sha512-UlleZDkYVds93nKOJ32g393Ca7XyrG+c8r5XoQG3aQHKe5L+lc5HjmPGAJ1Y80iotUQG3NFsgwLnweCGV12yWw==}
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
@@ -1044,33 +1045,33 @@ packages:
'@angular/platform-browser': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0
rxjs: ^6.5.3 || ^7.4.0
- '@angular/common@22.3.0-next.1':
- resolution: {integrity: sha512-vJ4X+f43MIfOMKJc53ttkwxKSP6pfOFgfZ1m+W6fAIF5Ydy49/GnXIUbM2rtcbhsSYgh+95YMs3lhUrgyMXEUw==}
+ '@angular/common@22.3.0-next.2':
+ resolution: {integrity: sha512-w4oG/QGNTC5oY+vBf4WnODDr56vvPt8Y0TgLpDy6mW6ephWaIx8dAgvFdlpohU5R1cOYAABeLboQHtS6pdP8Fg==}
engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0}
peerDependencies:
- '@angular/core': 22.3.0-next.1
+ '@angular/core': 22.3.0-next.2
rxjs: ^6.5.3 || ^7.4.0
- '@angular/compiler-cli@22.3.0-next.1':
- resolution: {integrity: sha512-yfJ4jfjdTjTJYhWT3A8aEWZsk4xwTTB/S0oVi9VWm7HAb2trn5c3F5B/nWUJSSX5CXQ8TAnzN27mca2ZhyUPLw==}
+ '@angular/compiler-cli@22.3.0-next.2':
+ resolution: {integrity: sha512-r0Cq0n88GBn/iOFAL/oLGC3uBAGMINAYtZDA0gvIG+WZPuyo0CPeUEmAndAFDzuiAPegfXVi8yPlfzLS6uP5mw==}
engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0}
hasBin: true
peerDependencies:
- '@angular/compiler': 22.3.0-next.1
+ '@angular/compiler': 22.3.0-next.2
typescript: '>=6.0 <6.1'
peerDependenciesMeta:
typescript:
optional: true
- '@angular/compiler@22.3.0-next.1':
- resolution: {integrity: sha512-58W3f6lwfMwAlmoKfK4qigYuRQkRF0ZGZiSjAEXFhU1sV48pgQaADiz/2cfNGD3pEcb99sW9853XzDA9zzcbqA==}
+ '@angular/compiler@22.3.0-next.2':
+ resolution: {integrity: sha512-ayaEJt1ZDS9qKmAvQHq47m3FSMt2Au95KL+ucElgBHGV0TIuXjLdc25smiRj6Jr47U9D1zbEnFoVgWhKBuCl7g==}
engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0}
- '@angular/core@22.3.0-next.1':
- resolution: {integrity: sha512-6Y4bgGkZmje+7Ct8L3PARXfpm5ZrUYuWYKNz4Xtlr08Fsx1Fp2oroUQ8BsPgZGgfzmHaWyTBE/fvK7ZbybKcjw==}
+ '@angular/core@22.3.0-next.2':
+ resolution: {integrity: sha512-9onGgNA0v0q9UI31uVAk3K5Q2r/ye82qwKsQv5FesyZ1hnEyrMMc0kdTzHkgDDRS2xpwVHchZH8BTgJA6A+SGQ==}
engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0}
peerDependencies:
- '@angular/compiler': 22.3.0-next.1
+ '@angular/compiler': 22.3.0-next.2
rxjs: ^6.5.3 || ^7.4.0
zone.js: ~0.15.0 || ~0.16.0
peerDependenciesMeta:
@@ -1079,78 +1080,78 @@ packages:
zone.js:
optional: true
- '@angular/forms@22.3.0-next.1':
- resolution: {integrity: sha512-dssi5/s/DekmNKDA8zFDgfDVLrK2akZxg0lFO+e/pDeSYBKoalbljtAssPFEdGCiDdfmz6pFasvRw50TYI1ErQ==}
+ '@angular/forms@22.3.0-next.2':
+ resolution: {integrity: sha512-1NF2giTkXbULCVTNV8fPooKa8HKYEozWdgzZdCHvtrgIF6C2aW+PN/4ZJTddQjFBjH/4XnQ2xfM7nFCm/SQJuw==}
engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0}
peerDependencies:
- '@angular/common': 22.3.0-next.1
- '@angular/core': 22.3.0-next.1
- '@angular/platform-browser': 22.3.0-next.1
+ '@angular/common': 22.3.0-next.2
+ '@angular/core': 22.3.0-next.2
+ '@angular/platform-browser': 22.3.0-next.2
rxjs: ^6.5.3 || ^7.4.0
- '@angular/localize@22.3.0-next.1':
- resolution: {integrity: sha512-KPZuMWghal8+ZQn3N8s6shDZTyKTFSyw55ooxxhJNt+bOQ++mmjPJ7JCen39qAAILYpgI3IriLnswsbhGnGDNQ==}
+ '@angular/localize@22.3.0-next.2':
+ resolution: {integrity: sha512-Q0+i9GURr6A6jUIi5N4b/2ev8ZKDKfcZ1e1B9u6jT+wb1/mryB+8sJnFD3sT7a+E/2wRkNk5GCQuT+HjYzi+HQ==}
engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0}
hasBin: true
peerDependencies:
- '@angular/compiler': 22.3.0-next.1
- '@angular/compiler-cli': 22.3.0-next.1
+ '@angular/compiler': 22.3.0-next.2
+ '@angular/compiler-cli': 22.3.0-next.2
- '@angular/material@22.3.0-next.1':
- resolution: {integrity: sha512-iQrlvYiHEwY9p7c8CIa9pPXfWDuE+4cU3c64X3w8i7ChDBSj/dzsGK31X4EstZ+PXozDzcLH+JXuHkWPg81CVQ==}
+ '@angular/material@22.3.0-next.2':
+ resolution: {integrity: sha512-4l6+DzUtwIH+SYrZdT54Lg7sNvFu6+MmLxlQQB8TtC5V5EijqOv1rjLmp+mFFgpVFmwlZwdGS8vJfRvkzKLY2w==}
peerDependencies:
- '@angular/cdk': 22.3.0-next.1
+ '@angular/cdk': 22.3.0-next.2
'@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
rxjs: ^6.5.3 || ^7.4.0
- '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/89b8c002e5d47ba1cbc4483d3ec06b0ae0aaccb7':
- resolution: {gitHosted: true, integrity: sha512-vfMwQfoXYY5dX8IISR/9DpsLT+py7Zm2Nqj6CybryjFosxMxW4ajXKfJ3Zywu2k0wPfRVoQY+PMZ78vfPji+qQ==, tarball: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/89b8c002e5d47ba1cbc4483d3ec06b0ae0aaccb7}
- version: 0.0.0-8b6cbbca278a26f2495275c5d9d0d8633573162d
+ '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/940c0beef0de4cb128e90962d47ff80e352a1cd8':
+ resolution: {gitHosted: true, integrity: sha512-6d8sBwbru5J4TsfMlHneqn1PD+K2p5l5HGKOba3Y/Ygl+bUEtxIJyM8aRgX88WWgVwjcaKSByQ6gClVxjqNznw==, tarball: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/940c0beef0de4cb128e90962d47ff80e352a1cd8}
+ version: 0.0.0-f8062d1d0f50e59fcb36a9375a596f416204ee28
hasBin: true
- '@angular/platform-browser@22.3.0-next.1':
- resolution: {integrity: sha512-2mhIqbG0U75M3m2zICdF1qInDsuwiS+asx/xHWXPNAC1Igsiiq2DrCo9lGfKAuYpORvRWJfppXSD88atBeiDJw==}
+ '@angular/platform-browser@22.3.0-next.2':
+ resolution: {integrity: sha512-/KrZjns+lbZx9pMpWLI1E7C5y8B5veA8D/5dWJnNuiUmbAWevaEGpsMl1xGnopuE8JrJvUEOI2aSU4oT729FIQ==}
engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0}
peerDependencies:
- '@angular/animations': 22.3.0-next.1
- '@angular/common': 22.3.0-next.1
- '@angular/core': 22.3.0-next.1
+ '@angular/animations': 22.3.0-next.2
+ '@angular/common': 22.3.0-next.2
+ '@angular/core': 22.3.0-next.2
peerDependenciesMeta:
'@angular/animations':
optional: true
- '@angular/platform-server@22.3.0-next.1':
- resolution: {integrity: sha512-sGX0TGZMoN2c5j3kC6egIoTaD8lNurzIlRbbOAlFhkv6I8NJuyStk74pXn9yTsi2co+i/b8eAQe7Jw0mRXa6gA==}
+ '@angular/platform-server@22.3.0-next.2':
+ resolution: {integrity: sha512-AyegJGA+qdjqUJGPX8IysYKqt5XUoLYnjmVzzBV3bYrN0kt0g9SRirm4QCExQB30v/g+AKiVI9Fib50VyU/O9Q==}
engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0}
peerDependencies:
- '@angular/common': 22.3.0-next.1
- '@angular/compiler': 22.3.0-next.1
- '@angular/core': 22.3.0-next.1
- '@angular/platform-browser': 22.3.0-next.1
+ '@angular/common': 22.3.0-next.2
+ '@angular/compiler': 22.3.0-next.2
+ '@angular/core': 22.3.0-next.2
+ '@angular/platform-browser': 22.3.0-next.2
rxjs: ^6.5.3 || ^7.4.0
- '@angular/router@22.3.0-next.1':
- resolution: {integrity: sha512-Syu0u+mWinMzwLYidzi1yy2wbXmljRucsLE1jwaaf97rZ6Lqqc8cgnfWBSwxVdZ1r8qhR5zlauvAN/+cbiMF3g==}
+ '@angular/router@22.3.0-next.2':
+ resolution: {integrity: sha512-b5Sn7sokZxL5rdN0M8Hf0FYexYo+l5vA7gcxpoJld00QPtv6Uq75mqjhp6MFIk8pWhANY3RoKEjHMdUoNgO4kA==}
engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0}
peerDependencies:
- '@angular/common': 22.3.0-next.1
- '@angular/core': 22.3.0-next.1
- '@angular/platform-browser': 22.3.0-next.1
+ '@angular/common': 22.3.0-next.2
+ '@angular/core': 22.3.0-next.2
+ '@angular/platform-browser': 22.3.0-next.2
rxjs: ^6.5.3 || ^7.4.0
- '@angular/service-worker@22.3.0-next.1':
- resolution: {integrity: sha512-KStwvrt0vE8UAfXEE1GtIJm1b/oKu5XNSzCMqF/xE+VjSTrhnwNaKfyqXbK+7dVwr42AcUifTkOKJLq8zlz8fQ==}
+ '@angular/service-worker@22.3.0-next.2':
+ resolution: {integrity: sha512-L4a2at4NHToTNHwD03ir3w1ZXSrM/aARE2j4y7tcYBQXPQlSqwC7Bg4QHQecZ8Ua+eh8ssdVdpb8kPL4A+85pQ==}
engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0}
hasBin: true
peerDependencies:
- '@angular/core': 22.3.0-next.1
+ '@angular/core': 22.3.0-next.2
rxjs: ^6.5.3 || ^7.4.0
- '@asamuzakjp/css-color@7.1.3':
- resolution: {integrity: sha512-1t1U8Cm3RBl9vh3RAZhjkPaduzLSvQJRToRrxpGR/eDRW99mOREleuu+mWfiFa795bUzjwht7NgphCKTs2ianQ==}
+ '@asamuzakjp/css-color@7.1.5':
+ resolution: {integrity: sha512-jCpAvj8apa7SKHZYogk0rbXB3Kb0hLFrpkWF+Ap+vBA5rirItnpv9NKyAyEuDuFizvl0qwnj6JWR70RGJ0rOlw==}
engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0}
'@asamuzakjp/dom-selector@9.2.4':
@@ -1177,10 +1178,6 @@ packages:
resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==}
engines: {node: '>=6.9.0'}
- '@babel/core@8.0.6':
- resolution: {integrity: sha512-5zwYt1V4ji3mXKKRIAkohSJ29WepxNwxQi+7y7P5AcVPh1dcxnZBU2cfxHnPwS+u9+lZnXPsv30TQaF2xg+Tfg==}
- engines: {node: ^22.18.0 || >=24.11.0}
-
'@babel/core@8.0.7':
resolution: {integrity: sha512-ZIsZWBG6Y1oa+8fkQVp0xeCdjCHBkXFCCIWrmg9SvejVvfcVQgKKRmGrBDWfM7rilhvnRoEuaqa5dkK7KB3pHA==}
engines: {node: ^22.18.0 || >=24.11.0}
@@ -1201,22 +1198,18 @@ packages:
resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==}
engines: {node: '>=6.9.0'}
- '@babel/helper-compilation-targets@8.0.6':
- resolution: {integrity: sha512-HTrtZ4+iA0+kzdbCgvdSk1U4pEl3BvpGnlUbualCGNbrVhhQvhgBzurTUmqpWyvyHbWYWaIfdx2mOlL9LJjsew==}
- engines: {node: ^22.18.0 || >=24.11.0}
-
'@babel/helper-compilation-targets@8.0.7':
resolution: {integrity: sha512-ilAZCdOOlOVA7dQbaFNw2f/59p6GW33NxTopc3DvEE3efp3ZXTrGX/yZScaKw8/vd9bq31Ag0EcXiLw32bAgJg==}
engines: {node: ^22.18.0 || >=24.11.0}
- '@babel/helper-create-class-features-plugin@8.0.6':
- resolution: {integrity: sha512-Hy7wG2Pk1LnAkFMq0CbBk789XMTYVzYGxR7tKgk+TOpZckQRME3Tdou4mMT/8DFjJFxFZ8R6UsS4DR/duBKlVA==}
+ '@babel/helper-create-class-features-plugin@8.0.7':
+ resolution: {integrity: sha512-7ug3KrOhNVPPxFFLTel0/pMzimKzU/vTlNJKVL/dKguCpmNJZjjibyFbWg+Qs8QHmiIZPNuZ2UNnDGdHWGEpOg==}
engines: {node: ^22.18.0 || >=24.11.0}
peerDependencies:
'@babel/core': ^8.0.0
- '@babel/helper-create-regexp-features-plugin@8.0.5':
- resolution: {integrity: sha512-TWnIgw21pAv/FbBKB8ks26DMxQ+A3aBdi1HUBp+QhqSE8QdOqJgSK/FEvdMYPTZcHBBJPZ5pN6DDKmC5ZYPJbg==}
+ '@babel/helper-create-regexp-features-plugin@8.0.7':
+ resolution: {integrity: sha512-pyia4a5cQ9fmUuimPO4pl3p8aX9aGBBMqZyNUmwhJGO/e3bIbbt/26Zun6SE1CRvNaUWiTsfLuZeaLX6EIIUWQ==}
engines: {node: ^22.18.0 || >=24.11.0}
peerDependencies:
'@babel/core': ^8.0.0
@@ -1317,8 +1310,8 @@ packages:
resolution: {integrity: sha512-Qpm8+wi5xfDkBfollanwriCcKniFfBmMmaKB01GVM6VGzKXo1fdxosZp04qEr5HM+LKhwr3hG1yRy8+ORsficA==}
engines: {node: ^22.18.0 || >=24.11.0}
- '@babel/helpers@7.29.7':
- resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==}
+ '@babel/helpers@7.29.10':
+ resolution: {integrity: sha512-EMCx3AGZ3WfAl6ht7AyQoPm2Lh+BGYEMdc4Q6Hf7uSCDOZFuLq44qNwL+iaim8VlyYhRAo4X43+weadK8ZB4Yg==}
engines: {node: '>=6.9.0'}
'@babel/helpers@8.0.7':
@@ -1330,11 +1323,6 @@ packages:
engines: {node: '>=6.0.0'}
hasBin: true
- '@babel/parser@8.0.6':
- resolution: {integrity: sha512-LpGDIYJAzc3Y3PT9x+FxBrGYu2PlWxLmyN7SwPTzaX0LSwEmFJBsRnPBqmaXF2r1v+Zhz6lNiEJ+7yKtM5+Ugg==}
- engines: {node: ^22.18.0 || >=24.11.0}
- hasBin: true
-
'@babel/parser@8.0.7':
resolution: {integrity: sha512-UkDwEbPO1px2JQSrdh4qIgaH1JgG7GO/pFeJkpxhDxIETkT/QvGpnigXIw75ViHYPtIgKITmVUJqLjiO+JuWjA==}
engines: {node: ^22.18.0 || >=24.11.0}
@@ -1710,14 +1698,10 @@ packages:
resolution: {integrity: sha512-eAD0QW/AlbamBbw0FeGiwasbCVPq5ncW0HNVyLP3B9czqLyh4gvw+5JTSNt6le9+ziAU7mqDZsKTHf3jTb4chQ==}
engines: {node: ^22.18.0 || >=24.11.0}
- '@babel/traverse@7.29.8':
- resolution: {integrity: sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==}
+ '@babel/traverse@7.29.10':
+ resolution: {integrity: sha512-B3lYAs2nkKskbgQ1nfy8Ma9ao9Q1rntTAQHrzzyDuj+TSO+X3le6PfWwqDvodsb+OumE10eMFfuMCTQSQ5iuIQ==}
engines: {node: '>=6.9.0'}
- '@babel/traverse@8.0.6':
- resolution: {integrity: sha512-ilYV+qLStGzSKLipJlETdvdtpK3rAuwfCmCoGKv15MU4EoeIuLkespSNoNLFGOPSciEHx9TLWtN5mv0fz5w5mQ==}
- engines: {node: ^22.18.0 || >=24.11.0}
-
'@babel/traverse@8.0.7':
resolution: {integrity: sha512-bVV0brinsTWgc6ptSIoQo3GbITtl0VZAqEUJbHHcyfDPEu+q/fEvlYEa+6H85HoK8IdksKBFtKJbJFZ6Kff+zg==}
engines: {node: ^22.18.0 || >=24.11.0}
@@ -1746,8 +1730,8 @@ packages:
resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==}
engines: {node: '>=18'}
- '@bramus/specificity@2.4.2':
- resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==}
+ '@bramus/specificity@2.4.3':
+ resolution: {integrity: sha512-0GEz8qJWokkUVYQYRukmkSHIFNoBH8QTreeHrAFbvz1XFYc3Y+puhMs8PQ5x8GNugiC2l5jvDBXKLbBIByeSBw==}
hasBin: true
'@bufbuild/protobuf@2.16.0':
@@ -1763,12 +1747,12 @@ packages:
resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
engines: {node: '>=0.1.90'}
- '@conventional-changelog/git-client@3.1.2':
- resolution: {integrity: sha512-jZqwnJwf7nboIlAcw/mkOjVa6DexCcUOgT2oOQgkoi3z9vR8tGFkcMy2BFcYwjhL9sYcDDXkRQDayiDieCoW7A==}
+ '@conventional-changelog/git-client@3.2.0':
+ resolution: {integrity: sha512-sD/E0vzpkoDz/dqM1Hhv0ihC4KBw6RXjefeO8SG1XrX+wGkMxe1pKeedkKDPCtr2JjuhbuS9aJNgOvnT8hbeBw==}
engines: {node: '>=22'}
peerDependencies:
conventional-commits-filter: ^6.0.1
- conventional-commits-parser: ^7.1.2
+ conventional-commits-parser: ^7.1.3
peerDependenciesMeta:
conventional-commits-filter:
optional: true
@@ -2036,9 +2020,9 @@ packages:
'@noble/hashes':
optional: true
- '@firebase/ai@2.16.0':
- resolution: {integrity: sha512-WRVxl58B61Orwf7st7949ZIW2L4huV80Gpaum1z8v2eH+m2xaxWtC8mOjQyVAOirr6O/yf89cBjlPvoyBpBfTg==}
- engines: {node: '>=20.0.0'}
+ '@firebase/ai@3.0.0':
+ resolution: {integrity: sha512-66jJAi6JUmyXna89xaDONmfvupO1wNc3f2BegPwUImagbbpKdVeycE3kMqbU4jiDLL14N5PHzadovvxpaqD2hw==}
+ engines: {node: '>=24.12.0'}
peerDependencies:
'@firebase/app': 0.x
'@firebase/app-types': 0.x
@@ -2076,20 +2060,20 @@ packages:
peerDependencies:
'@firebase/app': 0.x
- '@firebase/app-compat@0.5.18':
- resolution: {integrity: sha512-77H57WuGEsgrv59HdtuhHG+eQdP8di6myz7O93yW6yTZlR/tLSmsCxCq5vHp6AWWDwSV0EVtKUvizXQiQZVBWA==}
- engines: {node: '>=20.0.0'}
+ '@firebase/app-compat@0.5.19':
+ resolution: {integrity: sha512-pdT+THcv3h43LcawVJ+MUTzofL7umBaCvCgdbr01fnTXrbQU2RSHb0Po/YsF7w+tgjCycg84zCgZbd51NmoIaA==}
+ engines: {node: '>=24.12.0'}
'@firebase/app-types@0.9.6':
resolution: {integrity: sha512-yPLahy7Esfu2w/yme3msVK4xTkDXQqq6szfQn8yVOQpCKiT5GVFjqNpLbuz6NkX0WuTwUidkmPewW3r4xkvpeg==}
- '@firebase/app@0.16.2':
- resolution: {integrity: sha512-fyCLPahl3r0Zb7Wzm+JLWcOOH3SaDgAyJzJ8EWIDiv51aNiv+2Pjbpa6myEuP7iXxjmJqrcbVm0GUF7h229T1Q==}
- engines: {node: '>=20.0.0'}
+ '@firebase/app@0.16.3':
+ resolution: {integrity: sha512-L2mYqVV2ilnek+W4JG7yasA97TsXCwx+f7/abweX5uSp3dkPa5Luiglt3s9YWfh1fBR3SWH/AkRgAwUpDGyCjg==}
+ engines: {node: '>=24.12.0'}
- '@firebase/auth-compat@0.6.11':
- resolution: {integrity: sha512-L+xp3DTJQrBV08Vt0UhcL/ofUOSjXom7JOJfbT6oas4o7gCrQnTYFKs8wfiuKLmHoo8BxMr5LdgjAs7o6aAsqQ==}
- engines: {node: '>=20.0.0'}
+ '@firebase/auth-compat@0.6.12':
+ resolution: {integrity: sha512-Vspo2zx1RR6LB7zuM7TduD1clMLT/x3Wr97u2jf9s2JrhYArJAFKeEu8bRWF1DoX54z6W9N77SdPRbPAiLKPpg==}
+ engines: {node: '>=24.12.0'}
peerDependencies:
'@firebase/app': 0.x
'@firebase/app-compat': 0.x
@@ -2103,9 +2087,9 @@ packages:
'@firebase/app-types': 0.x
'@firebase/util': 1.x
- '@firebase/auth@1.13.6':
- resolution: {integrity: sha512-MKRLvF72HJ/irNn2fJR0Gv5FOZNtqv1IBeJHRwK8l8pZ/wi9vuUw8ecyCMvQDDNxfS6uW0MWACL5KC4Y8Pp+fA==}
- engines: {node: '>=20.0.0'}
+ '@firebase/auth@1.13.7':
+ resolution: {integrity: sha512-00wn8cMrh1ZyEPF6RO5G081Xq1b57FN0QxChiAda0hy/D3Q5TrMk30qhWszRWCgXPRipw6yM6qtqUew3u3qEjA==}
+ engines: {node: '>=24.12.0'}
peerDependencies:
'@firebase/app': 0.x
'@react-native-async-storage/async-storage': ^2.2.0 || ^3.0.0
@@ -2141,9 +2125,9 @@ packages:
resolution: {integrity: sha512-/JGpvszLoNXNgzilRXocigGfFF4hbcPA9wN1i1kjJx6oKkXgkHteZYl3lQs1lJX3ETDf6bv7zI15lPMVUp4sAQ==}
engines: {node: '>=20.0.0'}
- '@firebase/firestore-compat@0.4.14':
- resolution: {integrity: sha512-HJ2HBNgNPrRsWIJ4E+Kc0u0h1U7HlF7If8AtYjie9HZXlMUmwYSJaXBj9VFm6gkSj5dlKZNcOQ0Ou25CVVG6rA==}
- engines: {node: '>=20.0.0'}
+ '@firebase/firestore-compat@0.4.15':
+ resolution: {integrity: sha512-/hWibRTNFsWkZZi1dbDS1hiJIMezYUMPrRjMmBXevel5b368XWY+NvfOaSxgy3+fDb6I+uZ7SKGFyL06gW3vTA==}
+ engines: {node: '>=24.12.0'}
peerDependencies:
'@firebase/app': 0.x
'@firebase/app-compat': 0.x
@@ -2154,9 +2138,9 @@ packages:
'@firebase/app-types': 0.x
'@firebase/util': 1.x
- '@firebase/firestore@4.17.2':
- resolution: {integrity: sha512-SiyQEK1dYPOjItFVA+kZGdvOoRAtMebDBvUaSxJPNZMkKcRwYYK2kzWo5UXTZZj523uMxJnkr+KKVySEMme3kQ==}
- engines: {node: '>=20.0.0'}
+ '@firebase/firestore@4.18.0':
+ resolution: {integrity: sha512-28aKMUeM+L4fuxx5hurvQK31KLh/KRutaP1544avVWuR4mNTAC0FQoHg8gbkN5NoJj3yN9/ZFGSFSVPR8/x/BQ==}
+ engines: {node: '>=24.12.0'}
peerDependencies:
'@firebase/app': 0.x
@@ -2224,8 +2208,8 @@ packages:
peerDependencies:
'@firebase/app': 0.x
- '@firebase/remote-config-compat@0.2.29':
- resolution: {integrity: sha512-mY7JtTISK6F4g4T0x3kVepr5cp0NXL7f5yjIUXXGaTrg4qUlFBWRbENaHaqZ78dwmNcLm24h/yPsOVRlDXEXhA==}
+ '@firebase/remote-config-compat@0.2.30':
+ resolution: {integrity: sha512-Q4sQKhQ8TPEMOcCUvUBfGeAP1DfcG7FGBfA9yFUn/XRr4vSToY0DTmK28Nh7lgLQYzs6D5Ng6knSoXH+aGn1Tg==}
peerDependencies:
'@firebase/app': 0.x
'@firebase/app-compat': 0.x
@@ -2233,14 +2217,14 @@ packages:
'@firebase/remote-config-types@0.5.2':
resolution: {integrity: sha512-i8k1omVfoAnaT1ZPv2FFjxMZrATYsO/GnFgHEj5+7fAJLzi8wLnGGv1WK06oEAD6ltrWXSO1HzeNyajn/NjMWw==}
- '@firebase/remote-config@0.9.2':
- resolution: {integrity: sha512-Rii93DkXjM+RE/ytHdYa7EIiQLJbdBr+W8EEiqd/vbLCOC+1FdkDuRiumJBp6t3yewHGbdqbpjB3fk3z0cZ+8g==}
+ '@firebase/remote-config@0.9.3':
+ resolution: {integrity: sha512-9DbuFNAFeUbVJQZmwLZfdoLRNFWV43V4UqaRpDkaSIdTmVWhzctPeISGkWe4sKTsqpoyldRumquS0gqWZg05fQ==}
peerDependencies:
'@firebase/app': 0.x
- '@firebase/storage-compat@0.4.5':
- resolution: {integrity: sha512-vO0tFPxXbKDKdlTu8tYT08S9t9ezUTJYEdLCULpWxWq2aq6zojwN1QmAB+1a50AI/g47GlWUJn1XPncm/PDZsw==}
- engines: {node: '>=20.0.0'}
+ '@firebase/storage-compat@0.4.6':
+ resolution: {integrity: sha512-te0IsqX1bM+OZCJF7jNSKXcMqCA2yYmpshRHjX4axy0lI/P9ZP9GLjEZMVL8wrjUWF4e3cZxMZTbck3Zd5E1hA==}
+ engines: {node: '>=24.12.0'}
peerDependencies:
'@firebase/app': 0.x
'@firebase/app-compat': 0.x
@@ -2251,9 +2235,9 @@ packages:
'@firebase/app-types': 0.x
'@firebase/util': 1.x
- '@firebase/storage@0.14.5':
- resolution: {integrity: sha512-r2tozN/BlEewLi70tJNUQPzWwbex9GM7NgXZsamHKQrjKEfcR0i4jGgHBKAKA4hbwiPE9eNMb3hcxWnDpeJZwg==}
- engines: {node: '>=20.0.0'}
+ '@firebase/storage@0.14.6':
+ resolution: {integrity: sha512-9WjohxpjbfcySjCp8kIbd1ZhtmCQFQLqPtDQ+wmZ5PVXimTDjDsSx/RZjwwK89MjCTXB9fCdmvZkJxplZn4W1A==}
+ engines: {node: '>=24.12.0'}
peerDependencies:
'@firebase/app': 0.x
@@ -2295,8 +2279,8 @@ packages:
resolution: {integrity: sha512-IJn+8A3QZJfe7FUtWqHVNo3xJs7KFpurCWGWCiCz3oEh+BkRymKZ1QxfAbU2yGMDzTytLGQ2IV6T2r3cuo75/w==}
engines: {node: '>=18'}
- '@google/genai@2.25.0':
- resolution: {integrity: sha512-g1hyidWxahzIg+hh+lLqPeBJl+Fu6051we2QKhFXdWgE4yGYf8PWOS8S3mMAdpe3eLx3KCWmhQR7GWyd3LYT1A==}
+ '@google/genai@2.29.1':
+ resolution: {integrity: sha512-keU+JsY11fT4ykdFA6Q8iQHBgOAAVssFLxPtXRjCIEr5Zt2GzE75c22bBmq87XbhgtpuKaObnSgsrG60rj0ZMA==}
engines: {node: '>=20.0.0'}
peerDependencies:
'@modelcontextprotocol/sdk': ^1.25.2
@@ -2304,8 +2288,8 @@ packages:
'@modelcontextprotocol/sdk':
optional: true
- '@grpc/grpc-js@1.14.5':
- resolution: {integrity: sha512-7VZM+SVdEcUUqSQeNI3zM8Qs/BhQKZndPo2h5VkYkAM8Iz0wJIa8mKV5ekQGqG8UUsnkQ0NMxIxwkIHYvj0qOw==}
+ '@grpc/grpc-js@1.14.6':
+ resolution: {integrity: sha512-SgC/B3/VZ8lTyOZ4Cwk6f1skWhmkNAaVfiX90qd5u1rRXGKk1//8FTUEN9GvOUq7rfWIqAYkA3CoyumYVpOS6g==}
engines: {node: '>=12.10.0'}
'@grpc/grpc-js@1.9.16':
@@ -2358,15 +2342,6 @@ packages:
'@types/node':
optional: true
- '@inquirer/confirm@6.3.2':
- resolution: {integrity: sha512-Xvr/0HggjddPtGppuqVmxhTw+Hr8PvsZ/k0HmOEaAqQEt80OITNkFWnsdNmyT0/eM4Ab+iJLx2R8rctlEyfSVg==}
- engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'}
- peerDependencies:
- '@types/node': '>=18'
- peerDependenciesMeta:
- '@types/node':
- optional: true
-
'@inquirer/confirm@6.3.3':
resolution: {integrity: sha512-ImOBgpl/sJTFp8naeSkNu4S0Sf8F8pxv3/CUx+LoBAdQvCVqFz6rSB2A/oZYsJge3+yphbEDxEkfaRNYq1OU0A==}
engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'}
@@ -2443,15 +2418,6 @@ packages:
'@types/node':
optional: true
- '@inquirer/prompts@8.7.2':
- resolution: {integrity: sha512-QoRB4wFIjgH5iOhSjoIKMkTvSHDuV+O3OITlIqAYO0oK5x364GJILXiMBvlPiE+klg7Xx9tq5XVqQHcGUDYYPA==}
- engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'}
- peerDependencies:
- '@types/node': '>=18'
- peerDependenciesMeta:
- '@types/node':
- optional: true
-
'@inquirer/prompts@8.7.3':
resolution: {integrity: sha512-DHK20kO+H5k/XcJQpHQUpVQbMYHHhZchlGWhZVMUV4WIuRuBW5744hipOtriE1vMqPLgnIyXFMHWKkIbTepa4Q==}
engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'}
@@ -2488,15 +2454,6 @@ packages:
'@types/node':
optional: true
- '@inquirer/type@4.1.1':
- resolution: {integrity: sha512-yJoHYrMnxIsJZCY+0Vb66Dy3he3kL3e2wOBKhoSwWWAzZAY82emlxwgprCtp6yRixvNRNq9ztfRWQYPNr3Go7A==}
- engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'}
- peerDependencies:
- '@types/node': '>=18'
- peerDependenciesMeta:
- '@types/node':
- optional: true
-
'@inquirer/type@4.2.0':
resolution: {integrity: sha512-2rnHX8RPo4glJYqnFc/v3nQeIhDcjyRRyaT7MGcfL/8xv/8K03SXYoA2tX06WVSKywWOE/ncbG3dtuzLjR5TCQ==}
engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'}
@@ -2674,12 +2631,12 @@ packages:
'@leichtgewicht/ip-codec@2.0.5':
resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==}
- '@listr2/prompt-adapter-inquirer@4.2.7':
- resolution: {integrity: sha512-k180vxSv2KqmnDxoato6pCqEJsov4U5C0EVmldZkAdNeVBxY48A/LM6TCNPGIzDK/iZSfsZP0Mw+gbWc5hXLyA==}
+ '@listr2/prompt-adapter-inquirer@4.3.1':
+ resolution: {integrity: sha512-NnKK9IrkBPr3v9DxXz/MTxQ989bJEfH1Q6Qr+MA9XU0QRXEgAQJO4XjFs8OzPQI5WYScz0kXi9WNDkANr2bRVw==}
engines: {node: '>=22.13.0'}
peerDependencies:
'@inquirer/prompts': '>= 3 < 9'
- listr2: 11.1.0
+ listr2: ^11.0.0
'@lmdb/lmdb-darwin-arm64@3.5.7':
resolution: {integrity: sha512-Y0CUvoj3ToaPQGdiqtodR0yrbAToNV74ylGQGSsNzmACO6iqKIUdU2OyFhkB+AAYpyfCA6oYh8hxbtc7eZhklA==}
@@ -2754,9 +2711,9 @@ packages:
cpu: [x64]
os: [win32]
- '@mswjs/interceptors@0.41.9':
- resolution: {integrity: sha512-VVPPgHyQ6ShqnrmDWuxjmUIsO9gWyOZFmuOfLd9LfBGQJwZfy0gvv9pbHSJuoFNIYC7ZDX9aoFwowjcdSC4E8w==}
- engines: {node: '>=18'}
+ '@mswjs/interceptors@0.44.0':
+ resolution: {integrity: sha512-IYHevRStF4ijM20GI9c9Ndhw483NSAjCydQhUr4/zIB0BNLsTVw3vFAxTo6TlvX4QnV60wEHttUa9539TTAq+A==}
+ engines: {node: '>=22'}
'@napi-rs/lzma-linux-x64-gnu@1.5.1':
resolution: {integrity: sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==}
@@ -2952,12 +2909,6 @@ packages:
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'}
@@ -2997,27 +2948,21 @@ packages:
'@octokit/types@18.0.0':
resolution: {integrity: sha512-l6bAF43PNxkJp6g+W4PjoUSSkxHomXw2nOum5CTftJz1NlV3vu93NImgOYtLf6CbBUb5j+fiuzW0PPQ5JTSvZA==}
- '@open-draft/deferred-promise@2.2.0':
- resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==}
-
- '@open-draft/logger@0.3.0':
- resolution: {integrity: sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==}
-
- '@open-draft/until@2.1.0':
- resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==}
+ '@open-draft/until@3.0.1':
+ resolution: {integrity: sha512-s7/9ELP4aP9YZtW7RJaa0Xf3RISaRH9+EFN18FtykJYRHGNrl8f9ymvoNXzjhrjmftFvkQudtuDU9RYhk0xs3A==}
'@opentelemetry/api@1.9.1':
resolution: {integrity: sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==}
engines: {node: '>=8.0.0'}
- '@opentelemetry/context-async-hooks@2.11.0':
- resolution: {integrity: sha512-Tr79DyWI8itsBdg+jH+opjfrwLzX+erk1/ExkIwhWoAVjVrJIn2y5+cGjTC0Vy8fyNIA/y8wuJPZwr1T3xCZeQ==}
+ '@opentelemetry/context-async-hooks@2.12.0':
+ resolution: {integrity: sha512-iK/1nD7mmZVkuYjVjkdFBiCvzntJdFny1S3CYbUYyOq7V5enL6XX+gJ7eh965L1LnS11VA8mQ7Ej/ck04SB0MQ==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': '>=1.0.0 <1.10.0'
- '@opentelemetry/core@2.11.0':
- resolution: {integrity: sha512-7YP44XH0tV6+Mb54x2YGf84i7yi+31MBZlE8JwvozkxyTvXbSp10X7cI7YE49ChJ3shMJoBmCJF3+1QFBJctGA==}
+ '@opentelemetry/core@2.12.0':
+ resolution: {integrity: sha512-1HsSAuvT4/my0QrXWsyXFdWjKaPeCHsismKZgEEIb8NK13LP6DrMRlsUbvD/0F9mDWK3xDom9AMv3IscxgOnOQ==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': '>=1.0.0 <1.10.0'
@@ -3026,136 +2971,133 @@ packages:
resolution: {integrity: sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==}
engines: {node: '>=14'}
- '@oxc-parser/binding-android-arm-eabi@0.153.0':
- resolution: {integrity: sha512-BcWu25dMwMjHpaDCEidmpAi7rGg1qZoihJeUUH9bD55pVZ0z4Wa5CQgqSTo0R41H81oozisQKW3WqvAN2m77IQ==}
+ '@oxc-parser/binding-android-arm-eabi@0.154.0':
+ resolution: {integrity: sha512-sDdEtDl7vKdCvf54j72RJbowE3jCmyRz/+oOB6IAwQxAHZ0eI+Dcj4hvVnm0b9Dy31plUkdmfds9C+/Zt895Tg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [android]
- '@oxc-parser/binding-android-arm64@0.153.0':
- resolution: {integrity: sha512-9l5rdp2DhRqVriBHsNpu5cEf+hizZ4B58rt93HzyQEBUgZiC6qe2oFpaAAnXGCxHGnQExI1s7S2G0QhFacUZ6w==}
+ '@oxc-parser/binding-android-arm64@0.154.0':
+ resolution: {integrity: sha512-UHrDPELzvWZoVkIDdSycj4bzcTMCJG3IbN++mSUgVBaUtNtWHjQ98U6Vz5bpF/1Ic3FYJyYhMr74huO5tVvpZw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [android]
- '@oxc-parser/binding-darwin-arm64@0.153.0':
- resolution: {integrity: sha512-EcpsyRXHhENDpekpG4QNaSZj2F/BAz4Gh4o89zZwNss86R8KyRSQ6sXbAj74Xyeb4z3j/yBZZ6joQZhraIWyfw==}
+ '@oxc-parser/binding-darwin-arm64@0.154.0':
+ resolution: {integrity: sha512-mokYzajOSXxtSRDWCdHARGdntrKH+rZZ24Jzo8AtafyNzz0NARmpMm26Tc5B6qiGrr6UliWibHCOif1qRN2vaA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [darwin]
- '@oxc-parser/binding-darwin-x64@0.153.0':
- resolution: {integrity: sha512-hlj80HUQy07/2lYp6rmxH+3u+H2ik3rjLR52CUdPApxmZCNxASDUf/+ykTzAHS/fehftmVMATKvPaWmuLHuasg==}
+ '@oxc-parser/binding-darwin-x64@0.154.0':
+ resolution: {integrity: sha512-WbtUBrclOVItWfLRSvs+Z/WLtXxJ2Ctv50PyuX894HzDN5/e0qzxVpTNPIVMzOerBhgKtFsSMcfxlYIAbvdVgg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [darwin]
- '@oxc-parser/binding-freebsd-x64@0.153.0':
- resolution: {integrity: sha512-fWRcv2pMSh1qtez46MOu8vuUJ5fiaQZPHSphbWulbL7SHBMKfRgZl2PzjXZYQJbq7NEXyXbgIuIuUm+/Rmkv8w==}
+ '@oxc-parser/binding-freebsd-x64@0.154.0':
+ resolution: {integrity: sha512-YooHZSLawOe2fqm+lDdG8oAaQh2NYV/RMYTYzWRLy72stm2BgE9O/8Al6kFENjkmzyyBccDLLBirGxVtpzQfrw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [freebsd]
- '@oxc-parser/binding-linux-arm-gnueabihf@0.153.0':
- resolution: {integrity: sha512-paZeUK1GXShl/bOJQET1/8AQxayFeuN4SIWAkgTRxE7ZQwv9uYSB2n0648smygP22N7jcI3zxAm0Z+ALNiIKxg==}
+ '@oxc-parser/binding-linux-arm-gnueabihf@0.154.0':
+ resolution: {integrity: sha512-hKOwhZbrXdTwc4bGVfbLCXl9f2swl6zWdISocLQSNX9MgPmwHE3qGzOUkCrkuGpwdCVHPnkfOwsqTuYsrP5uNg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [linux]
- '@oxc-parser/binding-linux-arm-musleabihf@0.153.0':
- resolution: {integrity: sha512-qFPp5NwMf4K1C0O+DCVGmcbOaYyYAq98Rvv9p4VSfb777iUwlJCqMUxf6QG9N5f5ls4TEX6LitOZHi+6GL6rYQ==}
+ '@oxc-parser/binding-linux-arm-musleabihf@0.154.0':
+ resolution: {integrity: sha512-tnjiooXEU013349O/yxKbF5Cusp1CfHWQ8kYR8tGeRzR/P4sOpQGQo21fsS71M0fMD6ESLq+lbvXFWi43PuKeQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [linux]
- '@oxc-parser/binding-linux-arm64-gnu@0.153.0':
- resolution: {integrity: sha512-oufEhZCX7saeo27Logra8cvBR1jQ/yw2zUI2hHmWw3qA/XYqEW31FOvLQBv7DWN32NjVdlcaP11WBBZTJo4k9g==}
+ '@oxc-parser/binding-linux-arm64-gnu@0.154.0':
+ resolution: {integrity: sha512-Cao2kj+8d7BT6XJU1gV9eVQjV+Cr+e8vQm3tddDRZiM2hHrMDxwy3j6t+ofaSl0idyuPPCZ4AlpmQoj8yOT1QA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
libc: [glibc]
- '@oxc-parser/binding-linux-arm64-musl@0.153.0':
- resolution: {integrity: sha512-zXYzuAqng85h6+LI3iRm0zeMLX1/K2z41ZAMWxVRgt0D10VvZUaV5q+TEB46KDhoKBpdexoTLC6QoB/EiP2oqQ==}
+ '@oxc-parser/binding-linux-arm64-musl@0.154.0':
+ resolution: {integrity: sha512-uiwA0V3q8llWA7/8r+a9BBjk4j5YMDmi6wfOsyQfGOJMQSLHEiZ3HI8ulea766ykUa9wJFWk9XWEl4uJrZLQqw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
libc: [musl]
- '@oxc-parser/binding-linux-ppc64-gnu@0.153.0':
- resolution: {integrity: sha512-J7+NLwLEzdkKM9cKyPHH/AjXXstWOs98KYgLrPPnO4N9MO8EZRBfPNnBcS3S67uMOBkRpUmCl2FhRnWdQ5CbBA==}
+ '@oxc-parser/binding-linux-ppc64-gnu@0.154.0':
+ resolution: {integrity: sha512-LICfN0Xs4Zdko+bJy6eOAEQojDuIR26suF2JtOsMaXjgbCrpRSH7/NCvJhY13YvYBx12V6hnwrL8n0lk0rbNJQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ppc64]
os: [linux]
libc: [glibc]
- '@oxc-parser/binding-linux-riscv64-gnu@0.153.0':
- resolution: {integrity: sha512-sD0K11GQTLWylln54nPMMTtgmBbQrR5It/vMpZpy/fogiw8O2AvIE+9LuWUXddrWk9zvFIHGRcSgFn4IHOfoYg==}
+ '@oxc-parser/binding-linux-riscv64-gnu@0.154.0':
+ resolution: {integrity: sha512-gbbSYxLF8ssRbQ2qQPy+2EhGNwNH1bAoRdkk6cnWaKHqmCikpSIPtpXjFbCCtjTi0uojqOM3ghFQwQPbDQsU0Q==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64]
os: [linux]
libc: [glibc]
- '@oxc-parser/binding-linux-riscv64-musl@0.153.0':
- resolution: {integrity: sha512-7L66uql2BhvSz51LwfExjOdn6et/ydTiQxl23VApdKzJhTc3TczA1Qt6VR/UcvlQrL2ZbytIJb447vh7p5wmUw==}
+ '@oxc-parser/binding-linux-riscv64-musl@0.154.0':
+ resolution: {integrity: sha512-nSnRYYDLCcRVjSQzF3g6rKqCNYwo5o+aQgnn8BBXfe+ofCgMGlGqkfRyvXm6ptZvoxNkkWtLlqM8W7Xc3j6ZnQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64]
os: [linux]
libc: [musl]
- '@oxc-parser/binding-linux-s390x-gnu@0.153.0':
- resolution: {integrity: sha512-hXV3T7mNyrPR19rbPYkglkQJtoM/UNo/xwbZeeqdAxEg8PXgb4LXXuxPpGgI4bzRRCWwLUxdDSS58xIyC2u1TA==}
+ '@oxc-parser/binding-linux-s390x-gnu@0.154.0':
+ resolution: {integrity: sha512-BxBQoJKtzRQgZEKQIt6CDUm8RGKC5T8Qo4576yDa5/xgc10X3fBDItMbRabzLtbUBfTqKLl+8AVr/H6CF7W22g==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [s390x]
os: [linux]
libc: [glibc]
- '@oxc-parser/binding-linux-x64-gnu@0.153.0':
- resolution: {integrity: sha512-Da8Vqs1xdtoDYtEjmozD7wGgJeLBQkMbR0WUBECOSxodyX5DXy8ySlvJWbukyO2Q0+TM9EK+4LT6tbq0jCg4hQ==}
+ '@oxc-parser/binding-linux-x64-gnu@0.154.0':
+ resolution: {integrity: sha512-/whkust2vYy+GjRUVL5cWaJmEu6jkdFfo5mkxgckyeOX61eMwo4iBoiwzeJZeMWAdzb/XOtQyLApHhFht3sOWA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
libc: [glibc]
- '@oxc-parser/binding-linux-x64-musl@0.153.0':
- resolution: {integrity: sha512-zGAPxNTIIw6X5WyTRscIFE/oDjpdNtrrl32ing6NOXdGjzRucadnxBilexLdeYQ9YxixF93GujpXyQ0jw7ddSg==}
+ '@oxc-parser/binding-linux-x64-musl@0.154.0':
+ resolution: {integrity: sha512-EXURTyW9riw4B/kZnnE+58emAtw6+3VEszQfXUZkRqGaKIcmWDYkZtKB+xY/blHvuZ+Qy/fDclc31nmUCgtkSA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
libc: [musl]
- '@oxc-parser/binding-openharmony-arm64@0.153.0':
- resolution: {integrity: sha512-GoHzpqP5XyPIp9DHokoEdCp+K4UPl/h1neFj1uXnUB3pJYyOQ7NOhFVOttNUgCGcj2eywAvu5cRivTOSq4S10g==}
+ '@oxc-parser/binding-openharmony-arm64@0.154.0':
+ resolution: {integrity: sha512-ZRFooyH3qsR6vuR4jFGlG3XM36490SvvXtNaUahBK4zHpooMdTHNaOMtGGJI0EW38m5hi4rOco9kw7ZwCIp28w==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [openharmony]
- '@oxc-parser/binding-win32-arm64-msvc@0.153.0':
- resolution: {integrity: sha512-xGcy12tO9k7zFbeyQzEuilfWfQpyRq23/fLPfN3wjSWuWv58k46fQT1hsO1KFNykZuVGW9xSJE/z592TmAoSDA==}
+ '@oxc-parser/binding-win32-arm64-msvc@0.154.0':
+ resolution: {integrity: sha512-U0Vp+4lvwUa/PnOCJTZOjydj1rX2+VLHz4Y2vSFqlN8/7LTiURgD7z4uQ9yNv9O/NlU3mELBnPDlu7aaSYG1zQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [win32]
- '@oxc-parser/binding-win32-ia32-msvc@0.153.0':
- resolution: {integrity: sha512-o1ykUjWncvXX6N5a4KebgLjtD8zRui+f1llMhSGoSC9oP2KOqapRpdwmZ3NcNG0axFouwVKmhGBjd+IhA8BksA==}
+ '@oxc-parser/binding-win32-ia32-msvc@0.154.0':
+ resolution: {integrity: sha512-Hc8QgsFY5eUUP25we8TISUruibG2cDt0H4IcPG9RKdabb6odkCzIqjV6Gk9beGWGuOwMVCr81H/Su1q363LCCg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ia32]
os: [win32]
- '@oxc-parser/binding-win32-x64-msvc@0.153.0':
- resolution: {integrity: sha512-gxQz7G96Up136fd+2zWrP+o6FYGs9NO4Dyv55IoeJFJUDwLFHcLYY11hhA5wQKs0HoM57Q8esQ3nEVhnCdsjAQ==}
+ '@oxc-parser/binding-win32-x64-msvc@0.154.0':
+ resolution: {integrity: sha512-hD7judkUMA/hZPoamvKADs6+an1smp8UTK0aMYRijkvi00K/1vl7vEtmyn2JyQ9S+vibtnfcNzxqTLGyJUZCRQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [win32]
- '@oxc-project/types@0.151.0':
- resolution: {integrity: sha512-J1yXrIlNDZVzE3ada310xeAw7nH8yCAyLPuUIsjKatFPmfn5bS1oW+cM+QsGOtVWd5nhSpbwZWx/rue+r5Z+PA==}
-
'@oxc-project/types@0.152.0':
resolution: {integrity: sha512-oM/5rLBm2tPkg0iBgkH/FOeR3PCDpY19GTgAZjMFM8h9WI9VW7cLgzp6nwtarYKmovavIQZ+Fe/RKX/8C8O/Rw==}
- '@oxc-project/types@0.153.0':
- resolution: {integrity: sha512-jSNrRIyvPVLL5E1z/tS5zLAprosGz/FuI1PWwEOz59j3E4TTTzSpqKb/RDGqJhhW0QHYISGXxq582wGx6T11Tw==}
+ '@oxc-project/types@0.154.0':
+ resolution: {integrity: sha512-KYOUGQFlLWR+s4QMV2Q9ko38TZm7EdO87Qm7rvZLqk/webse/cDjtyxKhg/47l0byCbs/k46LT8qc4PKjAikzA==}
'@parcel/watcher-android-arm64@2.6.0':
resolution: {integrity: sha512-trgpLSCKRC/huFjXX/Smh+0sWe4+YtKfktIToiMl59ghz7z+qkH6kMvNnUbLyRs9N11t8l4svSCs1+5B3rOAhA==}
@@ -3320,8 +3262,8 @@ packages:
'@protobufjs/utf8@1.1.2':
resolution: {integrity: sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==}
- '@puppeteer/browsers@3.2.3':
- resolution: {integrity: sha512-2Bt3m6dDAJqmZehn0wiXSYyQmuhyiHHZ7FjvrVaS1W2RoFGV6eCK71UvKYkNJjkwC1Q9nobjhvTMhLQztFVINA==}
+ '@puppeteer/browsers@3.2.5':
+ resolution: {integrity: sha512-UoCo3Pynbm37aLEEoydSiG+t24ui7sLD40+07CKxzxNy4PpSowJMkvlLIiV67XjP1lMVynhQVnuwlTABqBH8LQ==}
engines: {node: '>=22.12.0'}
hasBin: true
peerDependencies:
@@ -3333,22 +3275,16 @@ packages:
yauzl:
optional: true
- '@rolldown/binding-android-arm-eabi@1.2.11':
- resolution: {integrity: sha512-A5kXfGKvKWWZE0TtPrfsvT+q4Y5d1QG8gGUzpYjGydM+fARM9MuX90PrXYXe0XbsDVgyxxNzHo6giCj90bsFNw==}
- engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [arm]
- os: [android]
-
'@rolldown/binding-android-arm-eabi@1.2.12':
resolution: {integrity: sha512-dB/a1214qKfHMXCpgqR4OZT+jS4kTyEXbQGJPqzobt5EwH5rX080pxE37alt3RzvR1bf1Yz/yGqRfrYAxuPw0A==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [android]
- '@rolldown/binding-android-arm64@1.2.11':
- resolution: {integrity: sha512-z6cTycz+iJ4PVkuL4HHW4DfTfoeU/2nqYYuSOrTmH7yHK5Y0LCOnA03V4ZNxavyVaU1oOqUgIg2klN/s+USGOA==}
+ '@rolldown/binding-android-arm-eabi@1.2.14':
+ resolution: {integrity: sha512-aWR+XKH9+rW7m5fWq/5360J3mHycrx/o6xZM2DQFdJnTMdyP7/WzxPjhtLbVWdKo2y612/4U1bWqb3HQhiF7vg==}
engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [arm64]
+ cpu: [arm]
os: [android]
'@rolldown/binding-android-arm64@1.2.12':
@@ -3357,11 +3293,11 @@ packages:
cpu: [arm64]
os: [android]
- '@rolldown/binding-darwin-arm64@1.2.11':
- resolution: {integrity: sha512-jShvqNtP6vDC6/A5JOAzbVV+DkgHqhl/ScVCJEbt+TUY6QYz7YnXcrg3sLtFBniro0f/Ld50ZwCWA6f7KYD1nQ==}
+ '@rolldown/binding-android-arm64@1.2.14':
+ resolution: {integrity: sha512-QiVxHofl6A8lQU7WAtOUY4QMVZXohxwz7WJJoeh8NBEUyKfIkMRKhYyq8az/1RypNiIXzNTtiS6KwHz0erxYRQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
- os: [darwin]
+ os: [android]
'@rolldown/binding-darwin-arm64@1.2.12':
resolution: {integrity: sha512-3YIhqHD96nA5SaYNRBR16HnGv4oavZvXfD/ayHM+oYZ0WD/8lBAtf6zQua4kEyAvpqrluKXl0lnOBoiNby7x9w==}
@@ -3369,10 +3305,10 @@ packages:
cpu: [arm64]
os: [darwin]
- '@rolldown/binding-darwin-x64@1.2.11':
- resolution: {integrity: sha512-f2i2xiNWq1Z1l2++q2fuhZRdLAT3aqxD6vRNm1RAxpUoBcdqNB3C0s1Bt+K+PbEx2F5F4gQp6hqKkphCY/xF9w==}
+ '@rolldown/binding-darwin-arm64@1.2.14':
+ resolution: {integrity: sha512-lTQOzHuBIooh3jIr5XINQkjPGEuGy+Dsy0meXDr6Sjty0b99kYgGh4uBC/8mJX1T0kC8d6S0aPP1Y+bHkh6aBw==}
engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [x64]
+ cpu: [arm64]
os: [darwin]
'@rolldown/binding-darwin-x64@1.2.12':
@@ -3381,11 +3317,11 @@ packages:
cpu: [x64]
os: [darwin]
- '@rolldown/binding-freebsd-x64@1.2.11':
- resolution: {integrity: sha512-4Ir5FSOKIAMr4r0kExpt1s3bMgzJU3rA45AYOHtQpls0oNeqcYBKrWMlckrYH4KCfGLfkfn1tN1dmZPMVsdXow==}
+ '@rolldown/binding-darwin-x64@1.2.14':
+ resolution: {integrity: sha512-hyMKEGatjmBYCs/Q4sbIcL/GqpFEqsX3wc+HYVQ/85A4rxc1o7rPm4DUI4GV4k/h0ITddwFSGpqQunI14GXjTA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
- os: [freebsd]
+ os: [darwin]
'@rolldown/binding-freebsd-x64@1.2.12':
resolution: {integrity: sha512-uMvssit0a4W+/7D8CbHUvG719mH3R2jwXAlh/XcPvuHTE0g++LymF88DCGNX0HM2rBOn0xrzgXktIB6fLSJBTQ==}
@@ -3393,11 +3329,11 @@ packages:
cpu: [x64]
os: [freebsd]
- '@rolldown/binding-linux-arm-gnueabihf@1.2.11':
- resolution: {integrity: sha512-/gnRDM+39BROzAN/k1OZjDPnDMcZxB/0EUxKjONO5yVkNEvlsoMDrxGNKgZi/ttFriS2gwlDNzB65pvNbFOXIQ==}
+ '@rolldown/binding-freebsd-x64@1.2.14':
+ resolution: {integrity: sha512-u371GbXoVXrEgP20PwzoGNOdAOqAMhzo19JzzY+V4YmmnC+DTOoqdbMu+O+54emM59Mik/UdrtWgcuEDKWRPKA==}
engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [arm]
- os: [linux]
+ cpu: [x64]
+ os: [freebsd]
'@rolldown/binding-linux-arm-gnueabihf@1.2.12':
resolution: {integrity: sha512-XcFu0R0xWnwzSf4IQgFH1rJIckPN1pLy2R+4r9IDB7Yfu/ys9cVqfa4pBrMHj7a3gl8mIR4nRNPg0e5IvEVs6g==}
@@ -3405,12 +3341,11 @@ packages:
cpu: [arm]
os: [linux]
- '@rolldown/binding-linux-arm64-gnu@1.2.11':
- resolution: {integrity: sha512-PFaK8HwvAHbaKbBcDNQihjMKYvFnA5hiENx/l5tphTDz1E0WFp32l0A7aq7lyUwGsRw/xSrNIy/gIK4thrSCrw==}
+ '@rolldown/binding-linux-arm-gnueabihf@1.2.14':
+ resolution: {integrity: sha512-BqwKsdZQf6EqVWr8fv2MrDYzAvOZ7+NYFSJESRGs87fkseEhs0TU9TXgRJTkZoRRkxTizyEg1LKUXfU3/78uqg==}
engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [arm64]
+ cpu: [arm]
os: [linux]
- libc: [glibc]
'@rolldown/binding-linux-arm64-gnu@1.2.12':
resolution: {integrity: sha512-260UrKgn8tz39ak+SMDOirKzr7V04M9dWPw5llW00SwBivCZoWcRBKV1d8cXnRkUmSZA3BdiUmBHWk7734Ulpw==}
@@ -3419,12 +3354,12 @@ packages:
os: [linux]
libc: [glibc]
- '@rolldown/binding-linux-arm64-musl@1.2.11':
- resolution: {integrity: sha512-AskzJUIKRLPxkruR1wLKewGbOw+EYfU/9lOrBFj4AFrEA8hPpKFnODWNu2WLaNs0QNkEb9QIJufmVZZIL/bJlg==}
+ '@rolldown/binding-linux-arm64-gnu@1.2.14':
+ resolution: {integrity: sha512-SD9kY8M009x/7s57Z1dgUVlP5+uYBgKQK0Tkr1WIWngrtUJmRCW1RJFMY7QDla2khXhmg2i5Io7MUjcmZNZ/KQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
- libc: [musl]
+ libc: [glibc]
'@rolldown/binding-linux-arm64-musl@1.2.12':
resolution: {integrity: sha512-5YK1I9SqDkbPgc1IA8BgDl34suqUS2q0KWnBrirm0E51YjOs6eo6dV6jbQfNE/argHRSvd0QUGgtpIoYx+WWpw==}
@@ -3433,12 +3368,12 @@ packages:
os: [linux]
libc: [musl]
- '@rolldown/binding-linux-ppc64-gnu@1.2.11':
- resolution: {integrity: sha512-qlUGAheh2yh8afH7QBgx0PrRHN85hKnNd78x8MeMhXivuevgd8vgf6/CstOzmNKY/lLTHvNTrPy98cLnAugzJw==}
+ '@rolldown/binding-linux-arm64-musl@1.2.14':
+ resolution: {integrity: sha512-BJ2CL19M6uuWesMgnqJzgxoI+N+eV7b0A9O9vLV42y+gitC41fNa8KElau1tHVzuLWX5GzEuxMPhAO0tQXQMkg==}
engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [ppc64]
+ cpu: [arm64]
os: [linux]
- libc: [glibc]
+ libc: [musl]
'@rolldown/binding-linux-ppc64-gnu@1.2.12':
resolution: {integrity: sha512-Rkcrmp7eFRg74yL5fXEU91JEWbdEPLevWwGtXpmhbjlD1StScbWTmO94Bhly+Mo+ketKYkdmM1vNUKeWSlx8cQ==}
@@ -3447,10 +3382,10 @@ packages:
os: [linux]
libc: [glibc]
- '@rolldown/binding-linux-s390x-gnu@1.2.11':
- resolution: {integrity: sha512-secpEad+0vCbSfn8upFySkDskv+bGPk3THSDS9Y89yc4rb4kzqHp8Dmyd9BkQW4SnhNXBZCl/6CrO//hZahNJQ==}
+ '@rolldown/binding-linux-ppc64-gnu@1.2.14':
+ resolution: {integrity: sha512-4+Kl8daPV8NDHaD7mfCcc1pRM+Qg7ab8DyMm5FG5WoZgv4h2i3KFN1CybYBNbQqmuYm7ftJLvmMI1eHYJ22S/Q==}
engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [s390x]
+ cpu: [ppc64]
os: [linux]
libc: [glibc]
@@ -3461,10 +3396,10 @@ packages:
os: [linux]
libc: [glibc]
- '@rolldown/binding-linux-x64-gnu@1.2.11':
- resolution: {integrity: sha512-mOVBT3dPpkWm8XBWPmU4bf+U6dYDLeMo/9ojUmis4N0L5uu10qra5vOyngZ7/PSdoE4G9KvRt4bloRxNjLas7A==}
+ '@rolldown/binding-linux-s390x-gnu@1.2.14':
+ resolution: {integrity: sha512-V/h8ePq1fKDrmtFMz6xcCN3DKvuvMRrwwD1q0PkBeeo4DpK64biaKvqWGVxqCeYKqeRk7gE7/iKPxLCn08O97A==}
engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [x64]
+ cpu: [s390x]
os: [linux]
libc: [glibc]
@@ -3475,12 +3410,12 @@ packages:
os: [linux]
libc: [glibc]
- '@rolldown/binding-linux-x64-musl@1.2.11':
- resolution: {integrity: sha512-Is78i9A8Ui4SqcxUwFJ9uMmjDn58IbVTjFWYdQestFEgeuEmHMLGNriXnVJKkwG2YiZjw8cP0zCTyDMdDGtOOg==}
+ '@rolldown/binding-linux-x64-gnu@1.2.14':
+ resolution: {integrity: sha512-WxalXzgrLVpKC93xfpaJ3gCXUWzeCr+FRCbDVD2mUAy4L6Vo3lNVz0epUEUpxPWJkLNYUwM4OSIikv36OJ9mLg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
- libc: [musl]
+ libc: [glibc]
'@rolldown/binding-linux-x64-musl@1.2.12':
resolution: {integrity: sha512-3IBxWFMjbOZskDPKv8Lf9BCnahlKuHthWkYnyIxOH/QcJrFcS4EmcenthApkwr/5+nEqZlLzeYbxeMaX7A5u4g==}
@@ -3489,11 +3424,12 @@ packages:
os: [linux]
libc: [musl]
- '@rolldown/binding-openharmony-arm64@1.2.11':
- resolution: {integrity: sha512-dUCXneZ87INUMyQ0D+C0HrEBNUPNXHaPmU5GTjyKTJEiussw9Kaj5Ln8UztPe4epV/ffvgNBEadksdYhmW6xJA==}
+ '@rolldown/binding-linux-x64-musl@1.2.14':
+ resolution: {integrity: sha512-3G3tnAmTpdk9jO3GQtyHXqeFD2SlecfTws/Y3M2mmj9nMBwwuLT4kur8sZKeu7ENUHSpVO3cIsm5A52LEWWwlg==}
engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [arm64]
- os: [openharmony]
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
'@rolldown/binding-openharmony-arm64@1.2.12':
resolution: {integrity: sha512-xtX61xg4LKPkPWilZU1ynKClz5Gj4bf74LML4r3eVLWumKnGjoEr1OSHQhMdbBDoYTi+yjrujvpZe2pUnqCrrA==}
@@ -3501,11 +3437,11 @@ packages:
cpu: [arm64]
os: [openharmony]
- '@rolldown/binding-win32-arm64-msvc@1.2.11':
- resolution: {integrity: sha512-jByxb6qfd+bH1xUd0qnfFnb17i9sWBPY2tOavJ0l3tdr3OTu+Kvtm8cd/JV5nFt657b1VqGltxg9olOEfofXWw==}
+ '@rolldown/binding-openharmony-arm64@1.2.14':
+ resolution: {integrity: sha512-qyr5XiNGxm2ytx17vvtcJ9nXn6v1gENETi503bJx3OGwZ1tSonj7BosxbMa/xeAfSl5iS9X6KjEWYXLu6v1L7Q==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
- os: [win32]
+ os: [openharmony]
'@rolldown/binding-win32-arm64-msvc@1.2.12':
resolution: {integrity: sha512-At7fPB6PCaIjzgIhEZFxuT+BBFqiQibJDT4d3PhiR3f4E7bbMZF4aKblbFfEM3sETRDd1YiQx/+U/g/B/ou5Ew==}
@@ -3513,10 +3449,10 @@ packages:
cpu: [arm64]
os: [win32]
- '@rolldown/binding-win32-x64-msvc@1.2.11':
- resolution: {integrity: sha512-/PzKqzAJ03i19oy2ItPvyvaVjOjBCNnfaJs8yvUdGBKmiESgnrJSQ2awd81QzFbbnAmu7YO9ZnJrDCb9VSJPRA==}
+ '@rolldown/binding-win32-arm64-msvc@1.2.14':
+ resolution: {integrity: sha512-oA4o5o0S2yB199YyYXDzKUv1Z56Rc+mgOjwm7Z/vJ9Z8igiDPYvoOuDyo6g7AK/ZaF09nPhDKVnGBcYHO11GXA==}
engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [x64]
+ cpu: [arm64]
os: [win32]
'@rolldown/binding-win32-x64-msvc@1.2.12':
@@ -3525,6 +3461,12 @@ packages:
cpu: [x64]
os: [win32]
+ '@rolldown/binding-win32-x64-msvc@1.2.14':
+ resolution: {integrity: sha512-9mE94bf2GZUaR/fUSXCMpBoWkctu421Mi0ORpm4zqfbkjKep7RxzPFa5etcGs5h+2KApoWBOA/hAJa/7saGgEQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [win32]
+
'@rolldown/pluginutils@1.0.1':
resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==}
@@ -3564,146 +3506,146 @@ packages:
rollup:
optional: true
- '@rollup/rollup-android-arm-eabi@4.64.1':
- resolution: {integrity: sha512-QRU7UpoS9hd8Ij5I6fCVBxZ0UpdfAbZ5y7BWG5STFGMoM9jGzUP464yYAa3CzZxvG+jBwq1kI8L07xx0ReAdGA==}
+ '@rollup/rollup-android-arm-eabi@4.64.6':
+ resolution: {integrity: sha512-FkO19Fowv/OQeJZPVfdetJaI3/VpbZmBsnmAlR/rQ+b3QwfiGQiOpVegpSRH331kelvHTVw9hXYG3DwjAaRzyQ==}
cpu: [arm]
os: [android]
- '@rollup/rollup-android-arm64@4.64.1':
- resolution: {integrity: sha512-ttQF6Rp4MrNy9/2AOPmHmMXbNE8kIlNPYoGC3ksid9tonleMQALfrhTFJiQxobBvXYKG5Wcc8VGcHWTHR0ik8w==}
+ '@rollup/rollup-android-arm64@4.64.6':
+ resolution: {integrity: sha512-si5/Etm6MphPc2xYHnk455Shls/hoMjTy3mhXge4OPmvCw7TwC4KP4fKokAlKLV4XaQvLvgSHfafPcblLMYYdQ==}
cpu: [arm64]
os: [android]
- '@rollup/rollup-darwin-arm64@4.64.1':
- resolution: {integrity: sha512-MvzZ+qbBi5jrafURHsASUF1qW/58tOJFt/gFVJo2znQWrKX4CSf/Lt/qGONtoA4yHsNL5QzgdXMuITZxAs62Vg==}
+ '@rollup/rollup-darwin-arm64@4.64.6':
+ resolution: {integrity: sha512-PQCl3q7b0BgvVt72i2xrWM6I5KliwwVe4GpWW5QDGyUQawDS9aPZss/aGyFqBmxdRxlE8wDc9CaxiQ5DHRSp/Q==}
cpu: [arm64]
os: [darwin]
- '@rollup/rollup-darwin-x64@4.64.1':
- resolution: {integrity: sha512-9uj1VBuiPK5ij/+g0mCK17X+V/4SbErvRQMXIQjZAtbl4VcUhv63RhPZsFSWHrCRkTd3FKDtaVTrtT0+8bIhhQ==}
+ '@rollup/rollup-darwin-x64@4.64.6':
+ resolution: {integrity: sha512-l9DFl1Itb1YYdSrP1K3U8ih44AOHa/p+Q4WMMDfGvH5qVWp+ajfgS1DlYo4yCRh8wJ2ZJv0Fqccf+ULAmMFjmg==}
cpu: [x64]
os: [darwin]
- '@rollup/rollup-freebsd-arm64@4.64.1':
- resolution: {integrity: sha512-FCoXm836IqcXWhWPRkqlLx3Hjnv9S7c8tg5MFwsgHB3aFCz1JjUy6b1ssrxEjEbqaHpnvRmNjUUHxsXuU85NYA==}
+ '@rollup/rollup-freebsd-arm64@4.64.6':
+ resolution: {integrity: sha512-bR4GR3205N9+od0+l5Dd9/iZTDpJkIe6d6Ydp2qbcQZJLmKBdYQQRp8gbWpbMt92twKJY66o1vK4NkoKQODIrA==}
cpu: [arm64]
os: [freebsd]
- '@rollup/rollup-freebsd-x64@4.64.1':
- resolution: {integrity: sha512-Xa6Oxo86Ilx1hq1vNb69541NOuUyhGEH3Sc0g7eGkfsfRblWh4hAa4Lj2GWwZyfUVYL+Z4xK3TxhwIuZ3fNPLg==}
+ '@rollup/rollup-freebsd-x64@4.64.6':
+ resolution: {integrity: sha512-XTVNaDzcFl2TeBglvxdGgsCv9JGtAGRAoJENmGBR/XvDH2mA2K0IXc2aMfP0dR8mexSXSKifJ85FixoXX1wfTw==}
cpu: [x64]
os: [freebsd]
- '@rollup/rollup-linux-arm-gnueabihf@4.64.1':
- resolution: {integrity: sha512-Nkw7cVMu1yrczpzr42Mh1BZ5Ai5A4Fsz2Je/frbwHmazpQTJzP+qo7pNjdxHrxVj56ivKTJihNoN90OD1hGxBA==}
+ '@rollup/rollup-linux-arm-gnueabihf@4.64.6':
+ resolution: {integrity: sha512-qWc6qbc+25ugG9vqPR9P422KJBbVfZ05mjcMggoq8tsfWP+eRfC+/tiDdIlRF5VL2pDVZWN9zAhWsmu7R1+7Dw==}
cpu: [arm]
os: [linux]
libc: [glibc]
- '@rollup/rollup-linux-arm-musleabihf@4.64.1':
- resolution: {integrity: sha512-JONaLM9mZPXbSetxMzYG3496qoJuWvG2ERCTrrVptfw/Fwe4UzrQoEx/mYEeZCRv/Xz0RldOLFeqDfqmH75/Zg==}
+ '@rollup/rollup-linux-arm-musleabihf@4.64.6':
+ resolution: {integrity: sha512-V4Nwkp8844X/Xnww3PI1LYS0YPei8XQEVG70R+5MPZGO7AhYoun4hCN7Svs4U3wbQLZbwiz+9xRFhUZZdRl8Ww==}
cpu: [arm]
os: [linux]
libc: [musl]
- '@rollup/rollup-linux-arm64-gnu@4.64.1':
- resolution: {integrity: sha512-OfimHma+prmdoobHI3tfYud2enQ2LXYaMu+iMUQH7IjJkykJ6qUmAs1M/scdQaEKRWysiKwTctsDa2LXvaO0xw==}
+ '@rollup/rollup-linux-arm64-gnu@4.64.6':
+ resolution: {integrity: sha512-xb72A1aPaaIsp+a88VtRae/ovIEXislbUMyp7b9AQQU7ZkP2m/+ik6DW9TQcJyw5R8/RIailF9zExYwkjR++UA==}
cpu: [arm64]
os: [linux]
libc: [glibc]
- '@rollup/rollup-linux-arm64-musl@4.64.1':
- resolution: {integrity: sha512-X5fwh2HM8EHbgfFwpf4m2x2pG/AHdQ2aPDPk+JCDwV4DPeM8yxYmKG1vvm123JSc9gBSu8tu9NECA99wHPztsw==}
+ '@rollup/rollup-linux-arm64-musl@4.64.6':
+ resolution: {integrity: sha512-pbcs1BVBwC43hZkjhjlF8Rx8m5G0KnhLZs9Azy/gqccP6UsNSzJr0hKGIAVPqzAH1O/NdPxxC9GVGb4msQg/aw==}
cpu: [arm64]
os: [linux]
libc: [musl]
- '@rollup/rollup-linux-loong64-gnu@4.64.1':
- resolution: {integrity: sha512-8dp2TxKdjiX/4f7Da9gF7BR29hygxOQlHxKNa8qxJHoqZ13ytrogFTpMPhtVEFrgFu9MSOabAn006PeoygavjA==}
+ '@rollup/rollup-linux-loong64-gnu@4.64.6':
+ resolution: {integrity: sha512-EKOC8os6Vsg487ZLKUqzLF99Jsmnq6tu7O7mAELakNpcA+8KadktFf/JYdRuHe/DzCUXmN38pUKu4XBcKlqGbQ==}
cpu: [loong64]
os: [linux]
libc: [glibc]
- '@rollup/rollup-linux-loong64-musl@4.64.1':
- resolution: {integrity: sha512-YuYDpRSZnU9qLf6sqyhiBdMRCw5ImECGLNqRjM2hZrJIEwAckameWkRJ3SUnn0oxSewZIib/4iLwyEXj40QqQQ==}
+ '@rollup/rollup-linux-loong64-musl@4.64.6':
+ resolution: {integrity: sha512-v/SQ68GnSlr/HyjB79sNXesGDwkOPu9JjbHfmWaymCiM+nZsQ9TstG1KfA4MuEvTr2d3PoY8PhFxj9bt0e32JA==}
cpu: [loong64]
os: [linux]
libc: [musl]
- '@rollup/rollup-linux-ppc64-gnu@4.64.1':
- resolution: {integrity: sha512-gGj3v7YYkysy7IbfclMI4PDtHaa6YX4nU1D5NR1fyvXAGqM4TDk28ZWvrpOkkK92eoQRryAludWz6jNjsm77Qg==}
+ '@rollup/rollup-linux-ppc64-gnu@4.64.6':
+ resolution: {integrity: sha512-G3pmliMQ7r15zFFNwBlaT/xTdSLi4lfgI7CUrQueyKYheNVhrd8JrWCE6Ll8xf4AA1RZFqq+mNJYntiElsVOyA==}
cpu: [ppc64]
os: [linux]
libc: [glibc]
- '@rollup/rollup-linux-ppc64-musl@4.64.1':
- resolution: {integrity: sha512-DTZVwvS94FUYpP0CjCfz2iT0XTmBfQGc/arx9IdwUbDImpe9h8dWuMT/oPUvcGiwLKMQoNmuFBx3AVajm+FNjA==}
+ '@rollup/rollup-linux-ppc64-musl@4.64.6':
+ resolution: {integrity: sha512-XQTB/IPoB/wG6x/wu9uomAt8YH61IAr5iZTubMiad/lu88sotq2ocz9hJd556+Jz2kIkF7ZQZIsUuWE3OWqtcA==}
cpu: [ppc64]
os: [linux]
libc: [musl]
- '@rollup/rollup-linux-riscv64-gnu@4.64.1':
- resolution: {integrity: sha512-NWnyiq2moc8iEHGyTjIFadJTy8VCvCU/rUBfor+3l30JOQKAifpmKdxX4ZxRRPSPE/rLhFpLADdzNjS3Ldctdw==}
+ '@rollup/rollup-linux-riscv64-gnu@4.64.6':
+ resolution: {integrity: sha512-O5mpokth6+ydMuwiGtY8fIjvOBfH7u6SzmDNmZ3k6GK5C6iEAC2q2ZN/T5L9jYILx0IcCT0KnfMDihQ5yQFSBw==}
cpu: [riscv64]
os: [linux]
libc: [glibc]
- '@rollup/rollup-linux-riscv64-musl@4.64.1':
- resolution: {integrity: sha512-yIz+7L37g7bVOGLaUQmGqiYADH262krL4dtf5zU6QGldPgOairLEgW1FTs5pP0UFkHq5uf2qxDttOFsVAX6kxg==}
+ '@rollup/rollup-linux-riscv64-musl@4.64.6':
+ resolution: {integrity: sha512-aIFxbAD9v3TvIaEDsKmukjcDg1JS4/tFXw8SHyQQgzOwzWCQ4cyDK7Ju1pQKqUXDFkEu/BZCFDCDATsKhQcB/Q==}
cpu: [riscv64]
os: [linux]
libc: [musl]
- '@rollup/rollup-linux-s390x-gnu@4.64.1':
- resolution: {integrity: sha512-sRK+GWovJZV6ijyV/k1Ft3FL5+4DscF5OYsJolTbhVTTLFxKOPVjS0wxUUHakvL0vRw/cbFxZNeZLfM/EzuQhA==}
+ '@rollup/rollup-linux-s390x-gnu@4.64.6':
+ resolution: {integrity: sha512-fuNo1UwBc6BxnHDOxxguQL/InhheMN3RJcJMb0b4xP8r5Q3CNCrJbVg0eCIFuJ4e/zAfjR2gYbOfbzO/G7CIyw==}
cpu: [s390x]
os: [linux]
libc: [glibc]
- '@rollup/rollup-linux-x64-gnu@4.64.1':
- resolution: {integrity: sha512-T2C0NXqqD063yJdm8UGdcoudBATDODdphEXWS7rEoh0jOITfoEBv7LHfRBYVsy+pI7wwxgScoZpkFiQOf40ryQ==}
+ '@rollup/rollup-linux-x64-gnu@4.64.6':
+ resolution: {integrity: sha512-05v6wFKDKJPZs9xlytVrrRu6IbRuoSvlH9xNwEOafXsKyjBFZPvAcZz2VIAB/M+lblYeKa9iOYC4RDVdfcAAaw==}
cpu: [x64]
os: [linux]
libc: [glibc]
- '@rollup/rollup-linux-x64-musl@4.64.1':
- resolution: {integrity: sha512-05wl8uRZMkcobB6YZrzskr2SiM0VOdzlFw3bAxOjKKTt3M6o3O0X/hE/8xk15u8oQY17xUCdTKcNMMg45ZAFog==}
+ '@rollup/rollup-linux-x64-musl@4.64.6':
+ resolution: {integrity: sha512-wJXKcdMjvkc/FaavZXNP1yW4i0pfOmhZAIWRSLG2yJ0PB0TWi7dkLErhX0u0vptDcXKKO/m1Y/YTeuyvb2MXwg==}
cpu: [x64]
os: [linux]
libc: [musl]
- '@rollup/rollup-openbsd-x64@4.64.1':
- resolution: {integrity: sha512-NoRZK1VclOgn9x3b9vPJ3sTxwvQ/F+Hf93xurRKSFJKiwNZyQZnLxVpqlCejhDvesMLMF8VNN+Y4jHTFddV/Xg==}
+ '@rollup/rollup-openbsd-x64@4.64.6':
+ resolution: {integrity: sha512-cwg7/h0ThvJwy8CBkmACdiHAxRWpbsCmIsjOt+Zzx0hTnIcSUmKYEV03bGg+hD827OnwUsbKh1ZZDW754xWyBA==}
cpu: [x64]
os: [openbsd]
- '@rollup/rollup-openharmony-arm64@4.64.1':
- resolution: {integrity: sha512-SDkX4OkZBePUPf0/XsXVJLwS+O61CmkDKuIyk5CeWddK3vkE8AZjmWK+p1ILRez4wnbS5rTK+U9YmcbRyx2dHw==}
+ '@rollup/rollup-openharmony-arm64@4.64.6':
+ resolution: {integrity: sha512-T0RkYIJbdYXJEQFw+tMBO09KDFdgmNxkHsof3wWAABrvnx15Yh8RytmrgYy9+q9cBeBNZF66MMQZC+5nzEz6vg==}
cpu: [arm64]
os: [openharmony]
- '@rollup/rollup-win32-arm64-msvc@4.64.1':
- resolution: {integrity: sha512-JQ7el/Plr3juYFxIVu9YXDPNl57XR2L8WIc87JX9wj0L3goV8fXQPQXb3DaHVXq61X/WCGWsTCQsQHo6/Mz5UQ==}
+ '@rollup/rollup-win32-arm64-msvc@4.64.6':
+ resolution: {integrity: sha512-KlfpmF1AAIdAWxt8QQNClbpLFlAUfYOzqIuJ7IXEStMHpFRuH78RG6FjqPb3Rqhh0K89F5npvG+/i3Fjl6IveQ==}
cpu: [arm64]
os: [win32]
- '@rollup/rollup-win32-ia32-msvc@4.64.1':
- resolution: {integrity: sha512-oZSlQ2H3ZDOz3ce1jEyuOZKuD0tPY/D2cKGMcMl0jhHQauBvkHHKAGR1OeRiMluvu3itzLRU2xCTUZptLayObA==}
+ '@rollup/rollup-win32-ia32-msvc@4.64.6':
+ resolution: {integrity: sha512-MrTLjd7Jlt9/ZavJZYG61KQv9Iy9bzbY+yXy73Xvwoa2uP66wvDShkyBr5Chz/yrE6lbD/zHMuTmKQVNQqBApg==}
cpu: [ia32]
os: [win32]
- '@rollup/rollup-win32-x64-gnu@4.64.1':
- resolution: {integrity: sha512-Do2m3jUeVAvUDpee/yVZYRqhO8Ecx4x5sX3EVGalqLx+OxecLDGx3sIwPEm1Nq+MFK2FV3pgdpwWP4624b85Og==}
+ '@rollup/rollup-win32-x64-gnu@4.64.6':
+ resolution: {integrity: sha512-8fWDH1CkPI8GdBKAxzHDza7UmgficsKo2+MVbvUgOGhB0629w5sHMg3Qu5y7TZsrYKHHWpz8fla4KvoT7WsO3Q==}
cpu: [x64]
os: [win32]
- '@rollup/rollup-win32-x64-msvc@4.64.1':
- resolution: {integrity: sha512-KpxCwRn1Qh3tmBHAqIAF4HtUCVKqZd0w57TsItWblx3QVeJLtXaSgeBFAj1WAvBSpBo+Mh9iZCjj6YW/HaBVMw==}
+ '@rollup/rollup-win32-x64-msvc@4.64.6':
+ resolution: {integrity: sha512-9/c9PWdr5GCIHkkxiHM1HjNBQMVdftP4O8QTcoUAaRza2FSqJ4axbf8QAnBuE6BIGQDl71SaRPeDdDYid5ecTw==}
cpu: [x64]
os: [win32]
- '@rollup/wasm-node@4.64.1':
- resolution: {integrity: sha512-NX7sXK/FT9RBgFxkMKB3jFcc3LCcUL/44PMJ8BBE0t0ljgXih0tZrUPUdZEN/JnN1N7i5axbGQtt5iPwlFJDQw==}
+ '@rollup/wasm-node@4.64.6':
+ resolution: {integrity: sha512-ufelhiGxNl8RuflC/Tie5ZVcI3MJUtd27nJ0jC2I4LroyZb7n4iwmajEmXXeTLxJtDiiWUwU8v2UjkACBHqQvw==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
@@ -3781,6 +3723,9 @@ packages:
'@types/cors@2.8.19':
resolution: {integrity: sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==}
+ '@types/debug@4.1.13':
+ resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==}
+
'@types/deep-eql@4.0.2':
resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
@@ -3844,17 +3789,20 @@ packages:
'@types/loader-utils@3.0.0':
resolution: {integrity: sha512-oOi4OGpiLUbb+Q/cN9FIkkDFgOpOGZ2cUAzb5i03wrGstnG6Syx1WDMhSiB5rcP10XX7cw7Uev8mv++/aplnNg==}
- '@types/lodash@4.17.25':
- resolution: {integrity: sha512-+K1NIO8I+F9/wNulfVvu23QYd0Pe9/OCqRrim4NoYIf1VoEDL90Ve4ClzpyqBLc7NpGGWRvYNCKZ1BE/Jpf8dQ==}
+ '@types/lodash@4.17.26':
+ resolution: {integrity: sha512-48NWfiY6oNcKOh47Z4h+sIvwcQR91h6KPhaYKgeMIrkT2jV82Gy90SErj60vW8jQbeMSOSbhIv3bZ7JoqPPVhA==}
'@types/micromatch@2.3.35':
resolution: {integrity: sha512-J749bHo/Zu56w0G0NI/IGHLQPiSsjx//0zJhfEVAN95K/xM5C8ZDmhkXtU3qns0sBOao7HuQzr8XV1/2o5LbXA==}
+ '@types/ms@2.1.0':
+ resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
+
'@types/node@22.20.5':
resolution: {integrity: sha512-U2+DNr+wSjpsTS/wZGYHq7GcwfuSmKiKvoPvK22zwTlRhU91yOniN4qRR5KhIjvif7ysw/dz/hKmfDH0Ris4aA==}
- '@types/node@24.19.0':
- resolution: {integrity: sha512-zY+5tKxXdhGh1PYI0ac+7juvEu4OI6vWtVVoj5i2m42jxAY1U+zHGt6QCyOFwykdP62sM3MJ9stoYYUw5aCWew==}
+ '@types/node@24.19.2':
+ resolution: {integrity: sha512-93d49wCWJkCyN87MxLpNN6KXPCwFw7bVUg79mGUV1OS40JGWwVCr8n61DXCSqz7CV6/VfPkb7xec7uP2M+QHWQ==}
'@types/npm-package-arg@6.1.4':
resolution: {integrity: sha512-vDgdbMy2QXHnAruzlv68pUtXCjmqUk3WrBAsRboRovsOmxbfn/WiYCjmecyKjGztnMps5dWp4Uq2prp+Ilo17Q==}
@@ -3922,67 +3870,67 @@ packages:
'@types/yarnpkg__lockfile@1.1.9':
resolution: {integrity: sha512-GD4Fk15UoP5NLCNor51YdfL9MSdldKCqOC9EssrRw3HVfar9wUZ5y8Lfnp+qVD6hIinLr8ygklDYnmlnlQo12Q==}
- '@typescript-eslint/eslint-plugin@8.71.1':
- resolution: {integrity: sha512-nNlBf6HuotqMgZvSkWD5hNdemiBIxQ2NmrlgfcUIeZRs+BbakjscCQRq/Hb74EFVnFiSWWdL12JruqwBy3ERDw==}
+ '@typescript-eslint/eslint-plugin@8.71.2':
+ resolution: {integrity: sha512-K72/pvT7qpm8q3k8G5u93NCSN1RcLxX5h7Gw0bQpbMXviBHeY6Nx1WEwmk9wP+eKTSQ8ecxvcgt/ZX/rB938xQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
- '@typescript-eslint/parser': ^8.71.1
+ '@typescript-eslint/parser': ^8.71.2
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0'
- '@typescript-eslint/parser@8.71.1':
- resolution: {integrity: sha512-oM/5sAqz/l1v/zYK1qTOPrn2+JIrBGC1V6uNYucRO5gh6eT9vWJ/RhPbGE59byvZEUQ4VP6XkLBaS5Jti5jpvw==}
+ '@typescript-eslint/parser@8.71.2':
+ resolution: {integrity: sha512-aTtmZjp/x3gsGHkDs04/1I8kNogBJkpQaeGaN0PfiG43NzDEmW2n+OP5im9wfsvyX0yP1UZWBrAGtDBfH9jEVw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0'
- '@typescript-eslint/project-service@8.71.1':
- resolution: {integrity: sha512-Oijc9RUsohHjncg6iGi7gCtjnEjYt9FWv9u6ygK8uKcHK5eLjLAkqERQ9BaytbpceOFdk6kifPCS/zAZE+A99g==}
+ '@typescript-eslint/project-service@8.71.2':
+ resolution: {integrity: sha512-Pd68GsLVh5ZXlcEccFPdhSOvtHZ/2WU0XsA8zmXOS3F158lVlcTLhfQ6qvtL1RzbMie0Kp8xtbVwAg4nejKPHw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.1.0'
- '@typescript-eslint/scope-manager@8.71.1':
- resolution: {integrity: sha512-1YUDZXdTnXLlob03SFHBipdyMBsDVm7zoSz0ytTJ39dk5J1TgsTK03VlR/dLXG/RLLUrPcYbD4rp23BmHxHP0w==}
+ '@typescript-eslint/scope-manager@8.71.2':
+ resolution: {integrity: sha512-YF4wgg5iUX5Obywoac27B56FhozMNFhdJSbh11H5GBAwmBtfyRhmgTQqW9tRNNmHDvsZ2CX6UGzoz+YfYn2Leg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@typescript-eslint/tsconfig-utils@8.71.1':
- resolution: {integrity: sha512-oTvkml5SxXhgg+WWKhod5qWQICDXtOB+/Hi9VdPKFAANJ2b7YOgMffgvzXuqog7R6A/JtrzRf128dsxummyWhg==}
+ '@typescript-eslint/tsconfig-utils@8.71.2':
+ resolution: {integrity: sha512-jz49TAWokm/7yWD9/o837nYax9DyALxIPOImdImvVzo6canBCZYzin8zJyqNR5k1j9K1DE0bVvr0XYB+99uAdg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.1.0'
- '@typescript-eslint/type-utils@8.71.1':
- resolution: {integrity: sha512-kH3t3jZCYv2PZSBEWPKTariLrCaoF1CLoPitYFBJOhAGEwWnSRAtGEifrfrpBa4K9JlwWNZotgA5w3/wLSk/FQ==}
+ '@typescript-eslint/type-utils@8.71.2':
+ resolution: {integrity: sha512-cC8UaalCViJkb3rH/xLIvidEwoFRtMZMUqDjjJMGEKaTFwYRHYBcoczlEGHuvkHEO8svRDrgZ0yQgOArFmwang==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0'
- '@typescript-eslint/types@8.71.0':
- resolution: {integrity: sha512-cJ4OoxPGWvFnBTnSZyaU+qJzGTqPTGJY+gDchj6cRyLRdmIdt4rcsE4twj+zPfrNiWuVi38wijHzShL++Z9atQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
'@typescript-eslint/types@8.71.1':
resolution: {integrity: sha512-ybYnPTUwg3VQQOFEiBPLs8Jxl1ry2vXdn1kVKguomBbvxpetdu3MKTNDqFNUrlG8ylP9MpZosmXMFYlGQHk1oQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@typescript-eslint/typescript-estree@8.71.1':
- resolution: {integrity: sha512-pSKSEK1JJpHs6KiKVtABCE4iJK5d7FLFzDXQNBQ2oRY7LEd3UwOt3TZemTgu9syTIf56dJWlTn/pdmrO9oKUXQ==}
+ '@typescript-eslint/types@8.71.2':
+ resolution: {integrity: sha512-y5Ukl3oVp7e/VGxqIoEXoeb/Roj71PAJ4WG/N/RGj+eeDvKRLM15kGr9MijLbN0i03S52zxu31Z98E5gWChJKw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@typescript-eslint/typescript-estree@8.71.2':
+ resolution: {integrity: sha512-DgNOEsl4pdYzwSL+N/Cl33tX1Hlw3FvId73LnKXfq7jnrF2viOEn7X+P7RBkkSWCVm92gnWd28GIC5vJuLREeA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.1.0'
- '@typescript-eslint/utils@8.71.1':
- resolution: {integrity: sha512-CBjT6gfAz3DW2j9Q4moFnqt208Aq+506sVGXfpRcyAeqn0EpayL0mjdWoCO2t3RC7GewNrFxdeehuEaPg6DMzQ==}
+ '@typescript-eslint/utils@8.71.2':
+ resolution: {integrity: sha512-RyKa1G1M9rKHDhrk+HJtiF1MvLD5Ux2JW3TSkzw+02pRALdpJb+QzG1Y5em+LvCgzGwgg8H7mBRFKljNz7ImPw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0'
- '@typescript-eslint/visitor-keys@8.71.1':
- resolution: {integrity: sha512-0GxiUGqMU0qXJt58cBsiG3DP8lUmBaFo2vChtUX+CT7PnR3v/VGLLrzVP4K9r1lNiZXjHYefMBbPunplr09v6w==}
+ '@typescript-eslint/visitor-keys@8.71.2':
+ resolution: {integrity: sha512-zozlN0UA32bSG2zkKAgQyRYSbEISVoyU6vvkKYo2aSny74D8Jh4e+POkJ6Lk0dlezZi5x7TtD+88Xb06IB8nhg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@verdaccio/auth@8.1.5':
@@ -3997,6 +3945,10 @@ packages:
resolution: {integrity: sha512-KRYepjgpSgrYYNHjmg77F9Mp7FMzQ0f9dcNc2AP3fmCmQMx0IWH6TYe4okvqkASoYhLnil5NRWqjO4Z4qSOHVg==}
engines: {node: '>=22'}
+ '@verdaccio/core@8.3.3':
+ resolution: {integrity: sha512-Vhfpo9MIwUOIsNQCGmTKqYn2l73261YQ6NCmRS47NbpXi5YWuSGf7I6i4dIVMZVG7UUtz9633754WtzFFAgFvg==}
+ engines: {node: '>=22'}
+
'@verdaccio/file-locking@13.1.0':
resolution: {integrity: sha512-rGFfdyCZdgpbkROJJfjOA01R5BFtzrnDAhNIkxxc/yWZ6Cir+MRHpEbN2weOEPAwYDke9Wms4JKhpsStu+iV8Q==}
engines: {node: '>=22'}
@@ -4062,11 +4014,11 @@ packages:
peerDependencies:
vite: ^6.0.0 || ^7.0.0 || ^8.0.0
- '@vitest/coverage-v8@5.0.3':
- resolution: {integrity: sha512-+klsyz7BvT1vCU28Zkfzms1Ia78XD0V41U3FUtRaa3S+vOr/EXvK1O6BvVD7l1RzEjm6SONR2aybOvDDf9u0mQ==}
+ '@vitest/coverage-v8@5.0.4':
+ resolution: {integrity: sha512-P5YcQY8Y6RmoE9xRXI38rT8pssbcubEzqtYTM2XQoxOXMDn04nRaTI1SM8qCl9/NfW3ag9GlzdSXu7IwO5Ft8A==}
peerDependencies:
- '@vitest/browser': 5.0.3
- vitest: 5.0.3
+ '@vitest/browser': 5.0.4
+ vitest: 5.0.4
peerDependenciesMeta:
'@vitest/browser':
optional: true
@@ -4079,10 +4031,10 @@ packages:
resolution: {integrity: sha512-gUsfXZJbzPamoIY5TvHFiMMoXESBrUMo+xqaj+rYrWI69+EnvRlYBlP96ZnHPY4vX8kyUpgAnFUCg5wZG/HkDQ==}
engines: {node: '>=22'}
- '@vitest/mocker@5.0.3':
- resolution: {integrity: sha512-T8sWAIbkSyAjkwTcaEc3Iu0o9A27X1/kdXrizhZkGuSKScRQtRzclfAMpOTcGdXCsqxeWlpGy3XjqaW8CpLORg==}
+ '@vitest/mocker@5.0.4':
+ resolution: {integrity: sha512-tqAlrYWce4iUxhr3ncNohejtCTOcHeE8XWrSNZY3OhPoDn01yeGv+gnaBy64ATp7o6pb03eIbBAjzmibpc9vIQ==}
peerDependencies:
- msw: ^2.4.9
+ msw: ^2.4.9 || ^3.0.0
vite: ^6.0.0 || ^7.0.0 || ^8.0.0
peerDependenciesMeta:
msw:
@@ -4090,8 +4042,8 @@ packages:
vite:
optional: true
- '@vitest/spy@5.0.3':
- resolution: {integrity: sha512-XhFysQTB8AZ+P4gMi+Lpo99vg2AZi0qKpaB9yXQl37+CaMEAPO3iH/wGVnSyL5MPERiLezpqTVtrR6UZH5GCXg==}
+ '@vitest/spy@5.0.4':
+ resolution: {integrity: sha512-MZKk/gSkm2q+ICobMxCpH1mA+cCAWm8WV7UhxlqGjq/sJ3AGc1BqFOs5CRVXxH78wQtme9q/NAAgBquj4AcyMw==}
'@webassemblyjs/ast@1.14.1':
resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==}
@@ -4229,6 +4181,72 @@ packages:
os: [win32]
deprecated: yuku-codegen is pure JavaScript since 0.14
+ '@yuku-core/binding-android-arm64@0.19.0':
+ resolution: {integrity: sha512-wdL2XmTiZixAOaHk9Z0JJZ8u9Qm8d333Zjpc6gaxXFX+UR5BlsfxZ7a2+2Rm71pamppsPYGUGFq2oVLbh6DISw==}
+ cpu: [arm64]
+ os: [android]
+
+ '@yuku-core/binding-darwin-arm64@0.19.0':
+ resolution: {integrity: sha512-7sNJa6XJhyetnTy64jw3NEi4YgUcezHk1G5GH9FSvXAuC8wIlbaOwT9lgq5qo5sspjrZJQlBR1TWflP49uRpMw==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@yuku-core/binding-darwin-x64@0.19.0':
+ resolution: {integrity: sha512-pTC7dYEc59isdyizc3nsuyFNBu2LU5wMYZ1be6UMr59PY/AJNtO1aBLWV0MgL/z7C1nv/2sX4TNjGgKLoeevJw==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@yuku-core/binding-freebsd-x64@0.19.0':
+ resolution: {integrity: sha512-xrZjF6XOEwyLOiDIfrwDdRCS6ghxcJeirNC1KivQhVcUwlRonaU79S3/Uiyx3lBylPnT8qKJ3/aMT+H52nGTJQ==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@yuku-core/binding-linux-arm-gnu@0.19.0':
+ resolution: {integrity: sha512-0OyIH53C0I1CbADHn9FSdCfX5qbpeLwJhmOVhonFJNYheybOnkSJ50qGMfTJIb8y5zrwqvLs7FVBvz6Fk8maZg==}
+ cpu: [arm]
+ os: [linux]
+ libc: [glibc]
+
+ '@yuku-core/binding-linux-arm-musl@0.19.0':
+ resolution: {integrity: sha512-z/iPfkCOCSXE34VXNt0uP1ORSW+4mEa9b5CiJcWZeqZH08g49bFU/jRM2T04f+Wpw5mJ6HIzNBiojxeAbrHjeg==}
+ cpu: [arm]
+ os: [linux]
+ libc: [musl]
+
+ '@yuku-core/binding-linux-arm64-gnu@0.19.0':
+ resolution: {integrity: sha512-jLNTi+gzaRwBJ+gwhCJ+rDb5dmx/8hEBx93UWd7hjMSqPTL1D1wvVSvXVAldV5kALvju7b0/m51EHEhs4+I1fA==}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ '@yuku-core/binding-linux-arm64-musl@0.19.0':
+ resolution: {integrity: sha512-YwyPIdW/rN2Fmv0MTFWi47FaB3F9g+2b+sJISyAw83Yd60RWH4T3Nx6XkAHHVN+uKJNBAd6So7/BVihSiFYvuQ==}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ '@yuku-core/binding-linux-x64-gnu@0.19.0':
+ resolution: {integrity: sha512-/vskaAXVX3ESR43FiTdfiYS7z1b9uoQJwVQ/0RgUHgN2sWoAyCZs+aX4CgU7eKGIHTVfp9VFwv+c+2XchYiEtQ==}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ '@yuku-core/binding-linux-x64-musl@0.19.0':
+ resolution: {integrity: sha512-FuXL5igeSKib9Rye02TdH+D6SQezTyGxIATMu1Qsn/QywrzwpGl35OLpS2C1x5vpGLeVE2XgiLd5mVPFHmIglQ==}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ '@yuku-core/binding-win32-arm64@0.19.0':
+ resolution: {integrity: sha512-YuJAe7zEKT1Xa7LuHlhGJpPnYQeVtvo0rZvNjJRqkH0hQGOw4C8QeP30Tg5VKGzZfo2x8CjhjEhKt4TmLwfmdg==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@yuku-core/binding-win32-x64@0.19.0':
+ resolution: {integrity: sha512-o8iY/mXwlRkedp0LNTr4+TEfXTPQwoNZmv6k+1WIAd1ZXEn8xJJTBCtB0osaVvdZo/x/cNmV16UrWrrGpM5Mvw==}
+ cpu: [x64]
+ os: [win32]
+
'@yuku-parser/binding-android-arm64@0.10.2':
resolution: {integrity: sha512-2VPBU9fRGRAQ2xPAvghnec3oou5Nrxm2Bezhf+13UMspAxQSkF/32r+ySKXSwIPA5/RivumDJDxAxc301Sgicw==}
cpu: [arm64]
@@ -4310,6 +4328,9 @@ packages:
'@yuku-toolchain/types@0.10.2':
resolution: {integrity: sha512-sSeo4SSSToiS+sSD+bwn/s94EEcaLJ7tG5LCp8gFYC1G5VzxzX7fqB6m9RU1yMD8KTpu6zdU/I1NlQf8hVBJ9Q==}
+ '@yuku-toolchain/types@0.19.0':
+ resolution: {integrity: sha512-tFkNbsP4WXX9UMUC5syJGdK9dPMLK0PPaIuXCcCYH75sZ8MrebfBZ2XvCILRTw8AgLivSSCfDa4R67iYBDa4Kg==}
+
JSONStream@1.3.5:
resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==}
hasBin: true
@@ -4331,8 +4352,8 @@ packages:
peerDependencies:
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
- acorn@8.18.0:
- resolution: {integrity: sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==}
+ acorn@8.19.0:
+ resolution: {integrity: sha512-oJlA3XiRm7Cyk6qFD2Jn8ak9B7jSy0qy00ADO3+8dpT0LSjFihQYv4C02LFCSYJV3Q37xYwwRy5m+IpIiUzqWw==}
engines: {node: '>=0.4.0'}
hasBin: true
@@ -4555,8 +4576,8 @@ packages:
bare-abort-controller:
optional: true
- bare-fs@4.8.2:
- resolution: {integrity: sha512-+ZI68KHMUvosXfKbg/UOHK0tbCdRnegbvPEdEcZ3Nd6TetieQsJPRXBRXPdLyy8+3VSEbPXtsumTpEtt78xv9w==}
+ bare-fs@4.8.4:
+ resolution: {integrity: sha512-MPC2eyrpbk3A873sK4y6rk+Iv4o2enxTjHZ8zH3HO0mjrpm5XjnguY2XmfidIsDV6vnjpbMBKUAJpV0ISD2SsQ==}
engines: {bare: '>=1.28.0'}
peerDependencies:
bare-buffer: '*'
@@ -4587,8 +4608,8 @@ packages:
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
- baseline-browser-mapping@2.11.27:
- resolution: {integrity: sha512-ElY12DaROGuan+lMmZ8Cvo/ZUbXPe7Enc/9VU/b1T3Kp4dwytRcNdR8DoSJN5SNJT/CuvcCA0DHDVmMOCePdRQ==}
+ baseline-browser-mapping@2.11.28:
+ resolution: {integrity: sha512-br0LOmjJqr6Rt4AEkadbcNf67Zpo7EPwKsWbjnRrJIa1QYFHQBqM4C7F2WTbV8ahTEcg1Eo+Y0aWjjORInYFyA==}
engines: {node: '>=6.0.0'}
hasBin: true
@@ -4601,8 +4622,8 @@ packages:
bcryptjs@2.4.3:
resolution: {integrity: sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==}
- beasties@0.5.4:
- resolution: {integrity: sha512-8/lOOjT+PElYCnaUbmhgd3Uad5R1VTQ4Wg0k4rK8bX04m5WEqHNmnlLy3Q/lJ7dk25XA+72gayzc/skTfKKpcA==}
+ beasties@0.5.5:
+ resolution: {integrity: sha512-4mUqdlIqPmHlX5qwkGmunWnhi406XcT5AfmwltoiDCToyGP2pSxS9ClfURL14IRwPYHq/JAIrtjNptbpSvUTPA==}
engines: {node: '>=20.19.0'}
before-after-hook@4.0.0:
@@ -4735,8 +4756,8 @@ packages:
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
engines: {node: '>=6'}
- caniuse-lite@1.0.30001814:
- resolution: {integrity: sha512-/Uaf1lAzr59XcMpW0o96WoEfr+VXK2OX4U9AgFoiSHsVJ4HppnIFUjtYzsyDH2+tgANaQb2/oxYGwCPapN1FpA==}
+ caniuse-lite@1.0.30001815:
+ resolution: {integrity: sha512-uDybUEyfgbyJJ93J1vikTylBX31AkdVYeVPeffMQpf8XN7hSfr0oZOn4VFOIMNvtU5+rHvC5Udg2TgtJKHm23Q==}
caseless@0.12.0:
resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==}
@@ -4771,8 +4792,8 @@ packages:
resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==}
engines: {node: '>=6.0'}
- chromium-bidi@17.0.2:
- resolution: {integrity: sha512-5v9GQFhTktFvotn/OFNJBmKLKRAb6n9r0bVCwf7sHgWc3/JryK0bj1nn93L3pHFrfgcsu6Be6EWsDi+1XHTGDg==}
+ chromium-bidi@157.0.8090-0:
+ resolution: {integrity: sha512-KJw7IQgqXwxpJgJlEIPg5mr2ZoqA+jkTRtc5EABI7sUJ3bu3cpI7NuEBoj4Gn1AsF78CaT9So5WQWspK3/wYag==}
engines: {node: '>=20.19.0 <22.0.0 || >=22.12.0'}
peerDependencies:
devtools-protocol: '*'
@@ -4895,6 +4916,10 @@ packages:
resolution: {integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==}
engines: {node: '>=18'}
+ content-disposition@2.0.1:
+ resolution: {integrity: sha512-e+H0ZXHSWYrENhQzw1LPuP4oF5MzVKmDU6d3hxlvaPEYLLg62MxtQNPRx4SYSuYJSBUgnQIG4HIN2tEtNv7Dog==}
+ engines: {node: '>=18'}
+
content-type@1.0.5:
resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
engines: {node: '>= 0.6'}
@@ -4911,8 +4936,8 @@ packages:
resolution: {integrity: sha512-cs+LadpH7Kpw0M3k8wurk+sOVVDAENA0iK4OBOrkL94j5lEVYRJ4j3zd2bhY9qgzyrPqthdcYT3axzRN7AliMg==}
engines: {node: '>=22'}
- conventional-commits-parser@7.1.2:
- resolution: {integrity: sha512-O+x4N2yH+ijvqWlIyTHsXTAP+algNWgGbjY2duCe8w2vUMvUB95cLRslCPfTMQyLAKlet3bhZTdu6ozn4M+QJQ==}
+ conventional-commits-parser@7.1.3:
+ resolution: {integrity: sha512-Q9oWm1o9uy/oEsZQIraoFMZ4RuPD+79KgwWj6mJVP356tazolCB0piRLZ5Kz9te9p027uSEcUW+Gu44Eh+X79g==}
engines: {node: '>=22'}
hasBin: true
@@ -5049,15 +5074,6 @@ packages:
supports-color:
optional: true
- debug@4.4.0:
- resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
- engines: {node: '>=6.0'}
- peerDependencies:
- supports-color: '*'
- peerDependenciesMeta:
- supports-color:
- optional: true
-
debug@4.4.3:
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
engines: {node: '>=6.0'}
@@ -5130,8 +5146,8 @@ packages:
engines: {node: '>= 0.8.0'}
hasBin: true
- devtools-protocol@0.0.1687809:
- resolution: {integrity: sha512-t7kSb+UKYdyxcmqy98U2P86ne6rCve3DIJ4+lp54i/hhClgFuG35JrLj23rO14Jw3sWDsp7i+22QhNU0+/qk8g==}
+ devtools-protocol@0.0.1696802:
+ resolution: {integrity: sha512-FO5/SENfvc2K8wRnWQflKcwuoTH4dBkXCWTQ9ebIWtuX8JM5+ZvCotaEmkfh21pO7TvIKGTM3hG4xFiq9WTwmg==}
di@0.0.1:
resolution: {integrity: sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==}
@@ -5211,8 +5227,8 @@ packages:
engines: {node: '>=0.12.18'}
hasBin: true
- electron-to-chromium@1.5.444:
- resolution: {integrity: sha512-5ss/uJfoDYDHT0lfJzT6FbcskIzROIOPf0BbbFkGcvDzoJU7i//9GDrwwIHQVmIsrAGiF3ihpADBRIsrEFt1rQ==}
+ electron-to-chromium@1.5.452:
+ resolution: {integrity: sha512-cVvk1YBSj6571VmV6hdJTqj94Y79xSu8cj6Y9t6ae4Y4431z8/7EJFvu3rVp90xhfuv9BpPKUmaLfTo4+FOGBg==}
emoji-regex@10.6.0:
resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==}
@@ -5476,6 +5492,10 @@ packages:
resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==}
engines: {node: '>= 18'}
+ express@5.3.0:
+ resolution: {integrity: sha512-qCqy1xSoaugxOD4IVHb1ZWdkvCF2W3aE2okKouWj8VwJ+ztskSiXoBnCSJqfKT+cVPJhuJqe9YLbY425+Zh00g==}
+ engines: {node: '>= 18'}
+
extend@3.0.2:
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
@@ -5565,8 +5585,8 @@ packages:
resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
engines: {node: '>=10'}
- firebase@12.19.0:
- resolution: {integrity: sha512-kwXCLcI0ly2lkwygkbuRx6SsX3DSO96355YrWh9SWZ5ncsxK/y5cirn3sY6nZVSiBVE++2nL6Hchzu1EB8uohQ==}
+ firebase@13.0.0:
+ resolution: {integrity: sha512-4cChZajVtuOijT/t7Vw1GZRTuohCxw+aoc8DAwhF+CSbS+zhqHE+i5PzEVttIySw7oKerBDRZRyDt4FynrWecg==}
flat-cache@6.1.23:
resolution: {integrity: sha512-f++BY9pTk+983xK1FLzlLpmM0i0z+jHmx3QESGkURMXujQZz1k5wzwX6hjnQ8goaD0B+sYnDK1yZ6MTyZfUaqA==}
@@ -5582,8 +5602,8 @@ packages:
resolution: {integrity: sha512-kWyh8ADvHBFz6ua5xYOPnUroZTT/bwWfrCeL0Wj1dzG4/YOmOcfJ99W8dOVyyynJN35rZ9aCOtHChqQovV7yog==}
engines: {node: '>=6'}
- folder-hash@4.1.3:
- resolution: {integrity: sha512-94fj+fXj1XHT8zGumUy/VlyFARc/yrslKJ2+vjrP/U6ftTdL7u68+gQhvSBjz9wrwTuty6BpZ7JsbEK5OU9RNw==}
+ folder-hash@4.1.4:
+ resolution: {integrity: sha512-BhHpJCYoTej4YH0C3HY4X49C2uOcWntjSD24T1GBYlfWcW/7mkHZov9HbvzCHQO+ZLbJ3VRE+cL1uEiaQvacLw==}
engines: {node: '>=10.10.0'}
hasBin: true
@@ -6408,8 +6428,8 @@ packages:
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
engines: {node: '>=0.10.0'}
- launch-editor@2.14.1:
- resolution: {integrity: sha512-QWBrQsMpH7gPr965dsKD/3cKWiNoTjpATQf++Xq63N6sKRGMwlVXz41O1IZTMfZQgBctD/K5Zt06+/I6pP6+HA==}
+ launch-editor@2.14.2:
+ resolution: {integrity: sha512-NHJEb30MGBCkmZXLZwz25t37QR4aY03ZzPYUJXOJaOa92uWwExI9SBQUuIznBYc1xkD7cJNGX7oc3Nl3sq2kQQ==}
less-loader@13.0.0:
resolution: {integrity: sha512-TIa8d6znKH634Mg+7OU3jevZT6KeOhh0amW+YeMPD0GM9buUn5Y7HvtyCR5pUDdLaFfqLA8AX5PTSIHMNSexEA==}
@@ -6525,8 +6545,8 @@ packages:
lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
- listr2@11.1.1:
- resolution: {integrity: sha512-zArGFXg2/nhA1vYBz789VpwzMQQXkGZiRxeguxFCsDrg4S+LOR22v4oQlSdTN7dR14XgOW+pW33UfvKf+i8nrQ==}
+ listr2@11.2.0:
+ resolution: {integrity: sha512-+H/hEo9EA7tyLY0ZihpDg76jHWolc0nCjbjnXFguSm4Epk+WYtL1w1tYs1kjEo229NmhgLmUrncyn81K1vBoRw==}
engines: {node: '>=22.13.0'}
lmdb@3.5.7:
@@ -6631,9 +6651,6 @@ packages:
magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
- magic-string@1.4.2:
- resolution: {integrity: sha512-vG+rjFRj1PqdIBozIxAGMjPlOhaVe+GXpbttY/iSK7rGcJRMlwNJO7dcUwmUqkymsFLJiNGI06t4D7Fr7yRC9g==}
-
magic-string@1.4.3:
resolution: {integrity: sha512-z12OxmaPGE0F4xlpGdjuAUckipLpQlTAuAmyGhNoD7ODpYUzvDfvtxUbjM/jwznyP178oju/KDdyi220wNJ0RQ==}
@@ -6858,8 +6875,8 @@ packages:
resolution: {integrity: sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==}
engines: {node: ^20.17.0 || >=22.9.0}
- nanoid@3.3.19:
- resolution: {integrity: sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==}
+ nanoid@3.3.20:
+ resolution: {integrity: sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
@@ -6904,9 +6921,9 @@ packages:
tailwindcss:
optional: true
- nock@14.0.17:
- resolution: {integrity: sha512-EjRr1weMa4ALQX35AgZTEnP+weJJjlW1KGDiNM2IQC2069YDHas4f4B4UUYR+TTLyKWxJvOz2wObDKQs/LNreA==}
- engines: {node: '>=18.20.0 <20 || >=20.12.1'}
+ nock@15.0.1:
+ resolution: {integrity: sha512-Mjx5Xl4t9vP13eUZPWqwwpjjXNjvhUTo1qTdryVM3+7t6Z2w6WHZ9GVZk/zQ8Ym1vbmloWaglye3cloyHAJ8FA==}
+ engines: {node: '>=20.12.1'}
node-addon-api@6.1.0:
resolution: {integrity: sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==}
@@ -6944,8 +6961,8 @@ packages:
resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==}
hasBin: true
- node-releases@2.0.57:
- resolution: {integrity: sha512-kQK9LGGFiHtrWiNhZtA7Qbw17AQz+dmsEKODRIVTXA9+e5MS/2gZEBhYJt13GrAz5/IOZKddH/0Z3TP/Zgo+yw==}
+ node-releases@2.0.58:
+ resolution: {integrity: sha512-BdiKAgbfRlvfMq/XzO/AF9NPmaA8a+YpLAyAFTVFBj3gARrAIfWvNq7Q7NE4se3KgFu0KkrvQMxTS0XVnsGzHg==}
engines: {node: '>=18'}
normalize-path@3.0.0:
@@ -7000,10 +7017,6 @@ packages:
resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
engines: {node: '>= 0.4'}
- obug@2.2.1:
- resolution: {integrity: sha512-XrsrhT5sybtKI6wakr2SPOlGZWWYbUXZ7a0jT8/QOeAPau+1X/bSegNe5YR75oJmEZQbKningirmGOEJCIk61Q==}
- engines: {node: '>=12.20.0'}
-
obug@3.0.0:
resolution: {integrity: sha512-5vvB5+W7ePv+p3uqxi+RcW1XAzLW0/hxt3/4X4Lc4qHudzOhmBiBwOY6DRob4WnanAEGvNcLjF+KNOufrUoEQw==}
engines: {node: '>=12.20.0'}
@@ -7057,8 +7070,8 @@ packages:
resolution: {integrity: sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg==}
engines: {node: '>= 0.4'}
- oxc-parser@0.153.0:
- resolution: {integrity: sha512-cEnpyyV1OJRXv++SFNw0z8i+2o/cr88rVLaOYJafELDoHM5yHvCAbwGRLvxuany6SNLcbblSMUyZaGzH+quSYg==}
+ oxc-parser@0.154.0:
+ resolution: {integrity: sha512-Gr/6fkjZwi937c4Tsz8y0iO4U0FLPkZI6JSVucLAIvQyqh379px7RS8ORIc0HOORbFjXZ6zyqWLl53qxhSeofw==}
engines: {node: ^20.19.0 || >=22.12.0}
p-finally@1.0.0:
@@ -7264,14 +7277,14 @@ packages:
postcss-value-parser@4.2.0:
resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
- postcss@8.5.28:
- resolution: {integrity: sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==}
- engines: {node: ^10 || ^12 || >=14}
-
postcss@8.5.29:
resolution: {integrity: sha512-49cGhUbXj8Qenv0iTMxA1cFBzxXoctpC9Ujd77t1WcbJIr6nF/eI7g/8MgxrYldFRuAXvja7xQRwavoW7kgrxQ==}
engines: {node: ^10 || ^12 || >=14}
+ postcss@8.5.30:
+ resolution: {integrity: sha512-zkd+e9S1AQHhmaBKye9zlFHWjOwVgqXl1q3ECYy8561K7qxR2cREf/STLskulBFd78k6AOFeA+ff1TtEzk9bAA==}
+ engines: {node: ^10 || ^12 || >=14}
+
powershell-utils@0.2.1:
resolution: {integrity: sha512-C+y9x90UElAddDZmV4qOx9W53B61PO7cIqWz2dQsWlwswuq4mr8NEwytdGKboYbQlGZ3awrkTeNvcZiZNHnQ8A==}
engines: {node: '>=20'}
@@ -7280,8 +7293,8 @@ packages:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
- prettier@3.9.9:
- resolution: {integrity: sha512-Z/CJHIkdujO/OtN7nXUii0Rf3VT5SRuhjBA82Xvu2XhBUgX3nhP67T0LHceBdQLex7OOFGTox+Q5Yg8Jk2Qivg==}
+ prettier@3.9.10:
+ resolution: {integrity: sha512-skGHTH1Yb9QvaTC4hWnRTzEYtCpApF0UMBPz+t/0ZPzP8ihefo/btKd+QA7pUE0fEwA1SbS/NmhyEcstdXOIdA==}
engines: {node: '>=14'}
hasBin: true
@@ -7298,17 +7311,13 @@ packages:
process-warning@1.0.0:
resolution: {integrity: sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==}
- process-warning@5.1.0:
- resolution: {integrity: sha512-jQSaVHsPgtyw60e1rQ/A+/ArPEj/S8pS/vFnyGa/gYFXrKk/6RuDkoqVDQ5NI5MmS01698ltlAk0NoDBNLujRw==}
+ process-warning@5.1.1:
+ resolution: {integrity: sha512-oCkNVj4OKnKEcocVBcDfiIugN1/cE6rgfT3nCtzeqZPA8+rIxMaQ0xXzIkGP8Gj2qUaP1UR7uhJ1VD8lUCpzCg==}
process@0.11.10:
resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==}
engines: {node: '>= 0.6.0'}
- propagate@2.0.1:
- resolution: {integrity: sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==}
- engines: {node: '>= 8'}
-
proto3-json-serializer@3.0.4:
resolution: {integrity: sha512-E1sbAYg3aEbXrq0n1ojJkRHQJGE1kaE/O6GLA94y8rnJBfgvOPTOd1b9hOceQK1FFZI9qMh1vBERCyO2ifubcw==}
engines: {node: '>=18'}
@@ -7346,12 +7355,12 @@ packages:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
- puppeteer-core@25.12.0:
- resolution: {integrity: sha512-z6LQUt5SH7jwGtGA+nMtJuEjZIsqPiwQ+EFHCYuVDQrJpvifNmmGuyDvTzAKPyFzihxgHc5f3aMzu2kn8Ps37A==}
+ puppeteer-core@25.14.0:
+ resolution: {integrity: sha512-LQitnes3tBeVbdZ7V/4iwJPLZGgkl9uBVK0W7YYMh68j/3Y9eNuvj4yl+Fdo7zN0SuajOMrhd7aPj3DifK8k6A==}
engines: {node: '>=22.12.0'}
- puppeteer@25.12.0:
- resolution: {integrity: sha512-agM9cYcxbvmU17w9qtF17s7/Vv7Dhbyig6AWwIgvQQLR2dKZdPqNvRPanac7xH4iMPcNYOCfyCkwqCnR4nVOcA==}
+ puppeteer@25.14.0:
+ resolution: {integrity: sha512-+s1Iqbl9DsGLOaQdgCQyhtgHZsF9hi4Iu8iuBqxzraxUXoRG1QkYQI0CA1/VsNK1gZWJfs50BL/oOb1L+Yz8Yg==}
engines: {node: '>=22.12.0'}
hasBin: true
@@ -7419,8 +7428,8 @@ packages:
resolution: {integrity: sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- readable-stream@4.7.0:
- resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==}
+ readable-stream@4.8.0:
+ resolution: {integrity: sha512-2jhTTU3Eilp/2DMT71gbcoqC35eQHasMJH0RHkYxwlxIv3+FR6Y5xAFZIwEGLxKkjZYEFlsiMNIdwUqjK2lLHQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
readdirp@3.6.0:
@@ -7456,15 +7465,15 @@ packages:
resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
engines: {node: '>= 0.4'}
- regexpu-core@6.5.2:
- resolution: {integrity: sha512-zkmVH92DlzjSFc4xKGZp/2BXIFrDIdBQBC8gUXKCsMgKYb1bkCkxfSuoW1werDjaTEMTbULkHtKFHe1L+Abnaw==}
+ regexpu-core@6.5.3:
+ resolution: {integrity: sha512-E8VgUoSK+LMQrLboDxavm76MTBGrQhx9RiNuomRmYnZ10Uw12HrI8fkxOOncktb2hBpzIZ9SV/347euQHG5z+g==}
engines: {node: '>=4'}
regjsgen@0.8.0:
resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==}
- regjsparser@0.13.3:
- resolution: {integrity: sha512-ycwFAS14Jw4mppvmK4GR/J6u3WpWpjkEApehuHtLc/8VpPNpDMbQ4WjqwplXifGeyKOzHSFLmSPqzksDQE2Sfg==}
+ regjsparser@0.13.4:
+ resolution: {integrity: sha512-EWV80YgFaVgFrjGCAsV7oybp4GOxbls5RzBg8OB0nKEVXsBJR1JlV8Di1JhCROg3MzTfe1RI8yitIm1eOs68iA==}
hasBin: true
require-directory@2.1.1:
@@ -7492,8 +7501,8 @@ packages:
resolution: {integrity: sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==}
engines: {node: '>=12'}
- resolve@1.22.12:
- resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==}
+ resolve@1.22.13:
+ resolution: {integrity: sha512-Dj/cW9zBV2aRj6XzCxuGIs3ESZKv02jixne3q6jFZYZ3/Tg09gHHviSMDL4kObh9pqSahdRHEnDoaP2gn8YLhA==}
engines: {node: '>= 0.4'}
hasBin: true
@@ -7522,6 +7531,9 @@ packages:
resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==}
engines: {node: '>= 4'}
+ rettime@0.11.12:
+ resolution: {integrity: sha512-5ExtR1ppiDBQkVoPw5NAqdbfH4Iq2VOmQKHMtUoaFxA9bo2krzFYBtyq6K40xxbYp+2w/YOr6D+1ToF6tTN53A==}
+
reusify@1.1.0:
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
@@ -7560,16 +7572,38 @@ packages:
vue-tsc:
optional: true
- rolldown@1.2.11:
- resolution: {integrity: sha512-qpSwIyz0jHQq5qXBTNxFmE6664rJ7O+4TvPFOiOaBSrz8IOHc1koKKSqTM2H6u1UG1+TveuC6vaDHKXFOvb1Kw==}
- engines: {node: ^20.19.0 || >=22.12.0}
- hasBin: true
+ rolldown-plugin-dts@0.28.8:
+ resolution: {integrity: sha512-FVhfqxorCWcc20BVT5eVRfRjzLLl6mgzjcMR4gSBf0K4oQMXT0qoHhhzfXy0L7y83fQy7Ug5ZDNk90xM3/LiCQ==}
+ engines: {node: ^22.18.0 || ^24.11.0 || >=26.0.0}
+ peerDependencies:
+ '@typescript/native-preview': '*'
+ '@volar/typescript': ~2.4.0
+ '@vue/language-core': ~3.2.0 || ~3.3.0
+ rolldown: ^1.2.0
+ typescript: ^5.0.0 || ^6.0.0 || ~7.0.0
+ vue-tsc: ~3.2.0 || ~3.3.0
+ peerDependenciesMeta:
+ '@typescript/native-preview':
+ optional: true
+ '@volar/typescript':
+ optional: true
+ '@vue/language-core':
+ optional: true
+ typescript:
+ optional: true
+ vue-tsc:
+ optional: true
rolldown@1.2.12:
resolution: {integrity: sha512-8wafseiaG80xmXSfqidUNqZcylTlhmPZZt+za2m+js2sFZ8dTNlhIOV2WcbIPx2hgwPBJpEUGFAMZ9bgBBLTSQ==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
+ rolldown@1.2.14:
+ resolution: {integrity: sha512-eTBTTqMR6uHKLgcUqpJP8ntzDI6V4LYA8negAMBEI7gkgVvOdrx6VsvS2Ym+83KhOPdLCHWJu0w7UQFJZhHKNw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ hasBin: true
+
rollup-plugin-dts@6.5.1:
resolution: {integrity: sha512-jODTXp3H7MK/Ur/ErtsrQ0G1GvaCmc3du+y5pNrdBMf6d7HlL2Nd/N6TkEr+f75CkUj01zEoEd7y2elH0eHi1Q==}
engines: {node: '>=20'}
@@ -7591,8 +7625,8 @@ packages:
'@types/node':
optional: true
- rollup@4.64.1:
- resolution: {integrity: sha512-7s4V+3J8ux75WNj9qwSJnrWmlCmZ2YHr2fojtHy5RiIMvhJv6DGe7HKKz7L6G1sq1Eg1fLC8SjYtAtDis1F4CQ==}
+ rollup@4.64.6:
+ resolution: {integrity: sha512-fX1Vy+UNKdXn+xKDnu/HBXbHVr1AY8cSdQj9BU4kLv5aFCMqGpvrVbyUMmjN3DdzWhSAuTbcX8PCNEVaumthYA==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
@@ -8002,9 +8036,6 @@ packages:
streamx@2.28.1:
resolution: {integrity: sha512-zEzXb0s5Cds7tqMH6rhZ05lcJydCWiQPEwiNngVqzsxCc962vLY4Uw+mW7od8kDH258k2Uz/JrOkdIAAhSh9VA==}
- strict-event-emitter@0.5.1:
- resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==}
-
string-width@4.2.3:
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
engines: {node: '>=8'}
@@ -8135,8 +8166,8 @@ packages:
tiny-inflate@1.0.3:
resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==}
- tinybench@6.2.0:
- resolution: {integrity: sha512-78U2TlB2CnVenajOFzf3BKSm0J6oz5L0NV7g32LCPccvYc0lbWvys4d3uUUCS2B1N8PAf2+aekR8i1KbC3HO7Q==}
+ tinybench@6.2.2:
+ resolution: {integrity: sha512-nIZ2N2dFpjBsg2hgitKu7mA+FvsIJuGJOwysRngmVRRmWgR/UyPjwJj8c/fT/dhm8EkHnF5EOogRf+0Z2qrimA==}
engines: {node: '>=20.0.0'}
tinyexec@1.3.1:
@@ -8154,15 +8185,15 @@ packages:
tldts-core@6.1.86:
resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==}
- tldts-core@7.4.16:
- resolution: {integrity: sha512-MDolfaSJtlSK5Y0A1xl3277ekubZwobpBjugknDizI9O5Rm60a1m8k4ICK+MRsCDzPygT81mp3BBf5RKDlFRfA==}
+ tldts-core@7.4.18:
+ resolution: {integrity: sha512-KI2PKvCmvQI/xD6ypPqkU0i7oxNXR/O58RLRaHR4svsgVUQ2JE/XC8BtMbG6PSehD27I8sZJRcC1ASnCy6lp3g==}
tldts@6.1.86:
resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==}
hasBin: true
- tldts@7.4.16:
- resolution: {integrity: sha512-QwBER5KMR86IIjpIiO7H/Z3IMJPsZ1A6RKPAqzTTgOyUQUSt9FdnKcqhTaJmkY6HVrgouZHZR0ncK5QxvmnQeg==}
+ tldts@7.4.18:
+ resolution: {integrity: sha512-somxA8xKAUzlAxl0TX/jMSYIbRNFIVGnI96pVGJPeMc5BsHmfVXn6mOJT6U++ELnl04eGfzpfcEuZe8WiASkXg==}
hasBin: true
tmp@0.2.7:
@@ -8323,6 +8354,10 @@ packages:
resolution: {integrity: sha512-u4UB2/IrKdU6lFxumHmmo1a3fCQO5tzQllRorfoRS63txhrB7xTpSn1PftwC4qEHkOaqP95fCWW4lJzwErwzhQ==}
engines: {node: '>=22.19.0'}
+ undici@8.12.1:
+ resolution: {integrity: sha512-usz3OVQBeh1LxNn0DzU0voLXMgn5CU/WUdpBsY6Ti5afNao+vTkmn4H/NxoXolc10cOqe2+YIG0Hspq2rsl64w==}
+ engines: {node: '>=22.19.0'}
+
unicode-canonical-property-names-ecmascript@2.0.1:
resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==}
engines: {node: '>=4'}
@@ -8362,8 +8397,8 @@ packages:
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
engines: {node: '>= 0.8'}
- update-browserslist-db@1.3.3:
- resolution: {integrity: sha512-pJ2sYawQS0R/WI928Gj5GlPhTGzbMelq0+4INtSYNDV9ErKJcX6xjGWkoG/VnB3dpUm00zALaqkrUD77pO5TDQ==}
+ update-browserslist-db@1.3.4:
+ resolution: {integrity: sha512-t8wonIOdQyOjtPd2VktlBu6QjTVTks6v8bSi7kd0r2Vll8TK1JYDZtRRdbmCHOAMphkZgrzK+L+vXK4pyZ8t4A==}
hasBin: true
peerDependencies:
browserslist: '>= 4.21.0'
@@ -8407,8 +8442,8 @@ packages:
resolution: {integrity: sha512-Q5dkR66lSUpzoR2xKWFiFCYXlvC8hJqV+ZMMLgt9/vm9355VnH25ueIJzrpunO/QjhhgcT5yBlR6wGQjPHeHkA==}
engines: {node: '>=22'}
- verdaccio-auth-memory@13.1.5:
- resolution: {integrity: sha512-rfKDhm1DzZoFdHUjiSwpe8hlXkiKB4brtzagaZcBnZXyBEASwW6SK/mdr4yU4asMcf+Zc8MjUJYnjlI7ji1yaw==}
+ verdaccio-auth-memory@13.1.6:
+ resolution: {integrity: sha512-L9LNz1q/JW1I9mPLch+8LUGnma/amo4EpS/+hZA6ZJJRIN7G5QAOKU9hLLPV6WqxO/I8T0KPtwNhyav9Aopqtg==}
engines: {node: '>=22'}
verdaccio-htpasswd@13.1.5:
@@ -8420,10 +8455,6 @@ packages:
engines: {node: '>=22'}
hasBin: true
- verkit@0.3.2:
- resolution: {integrity: sha512-zj/ob3UsvJGN0whEAKFp53REA5X66hvffVqoCtVQAakJKnKlH+/PcOfMoFwIG/o4rElqLv/ycAFlx8ZlXUorCg==}
- engines: {node: '>=18.12.0'}
-
verkit@0.5.0:
resolution: {integrity: sha512-u4J1hr6Y+C/hit34GwL3eIcUf3wngT8TlYUjK7tk0jxydKLAq3sYvifjdTDA6U3KCKRcQCQDGf/srjxfZF3l7g==}
engines: {node: '>=18.12.0'}
@@ -8431,8 +8462,8 @@ packages:
verror@1.10.0:
resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==}
- vite@8.3.3:
- resolution: {integrity: sha512-cTAldKPImjg6c+gk48U19POPn3GCBzZwpdsN8ZMEEcbpes+6/wvfqUd0C2y3qYY4wsj8PwgFwrZ/1jBPVttMSg==}
+ vite@8.3.4:
+ resolution: {integrity: sha512-IftLE8phJhdNRIGNEV4JCCvfNScoZQVfcXaN8TQropWGJtOHcu+iAB9pHcuGvmEb/kddw0LBe/jS8ztdC6xdiQ==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
peerDependencies:
@@ -8474,20 +8505,20 @@ packages:
yaml:
optional: true
- vitest@5.0.3:
- resolution: {integrity: sha512-xMw97S3rjdtj5dkVat7jCsqWBpvchs3RlpQctUqwJD0KkERk40vz2fJ77lDwW/Vzh/pk18eItYAzkodhSes3jQ==}
+ vitest@5.0.4:
+ resolution: {integrity: sha512-z0WxZRV2Sg48wF0FSgMq3TFG8JS38/Qr96vZVZdX6+Em9raQTvnXQvdTFJe2m3rfyJnEHeHQ/snceIdi8D1pVg==}
engines: {node: ^22.12.0 || ^24.0.0 || >=26.0.0}
hasBin: true
peerDependencies:
'@edge-runtime/vm': '*'
'@opentelemetry/api': ^1.9.0
'@types/node': ^22.0.0 || >=24.0.0
- '@vitest/browser-playwright': 5.0.3
- '@vitest/browser-preview': 5.0.3
+ '@vitest/browser-playwright': 5.0.4
+ '@vitest/browser-preview': 5.0.4
'@vitest/browser-webdriverio': ^5.0.0-beta.5 || >=5.0.0
- '@vitest/coverage-istanbul': 5.0.3
- '@vitest/coverage-v8': 5.0.3
- '@vitest/ui': 5.0.3
+ '@vitest/coverage-istanbul': 5.0.4
+ '@vitest/coverage-v8': 5.0.4
+ '@vitest/ui': 5.0.4
happy-dom: '*'
jsdom: '*'
vite: ^6.4.0 || ^7.0.0 || ^8.0.0
@@ -8537,8 +8568,8 @@ packages:
web-vitals@4.2.4:
resolution: {integrity: sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==}
- webdriver-bidi-protocol@0.4.3:
- resolution: {integrity: sha512-uuN0goWfxP22B7J/uAgBpOYNPttC+XVseYE+rSY5+rQ+YBeVz/VORw8WbmLVcqW78zNg5A4qnjNXYUWR3il2ig==}
+ webdriver-bidi-protocol@1.0.1:
+ resolution: {integrity: sha512-WXWs/aXF2a6Al1Z2/V/7Gp2oPZOAAmHjJOTmv4KCXRJ122IMj3tSSMc6a4q3K4QOmhQbse/Ahr+oTVJOU2dUiw==}
webidl-conversions@3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
@@ -8777,18 +8808,34 @@ packages:
yuku-ast@0.10.2:
resolution: {integrity: sha512-UnG9mA6giglCvSErft2/40TVFX750Sj1xgwddPLpG7J7rlr/P1wPADg9G2RK+d/1tNLtRVoLdMMOMVBB9561TQ==}
+ yuku-ast@0.19.0:
+ resolution: {integrity: sha512-PyCsiScaelhxBGzL8dyeJkLqvRZycoh78R31Vrt/WqYrm0hMFoKwIw/X7Dx5mBKLWAMlV9I9HEyBOHnj2gZVyw==}
+ engines: {node: '>=14.18.0'}
+
yuku-codegen@0.10.2:
resolution: {integrity: sha512-hentl2dtrF6cPjiAirtkfxfFZBA6Hdm61UqRJ7cA0qrlDNMk9PZGOjw5w1mx3E0hu/6pHcJF4dJW+D0SXHPZOA==}
+ yuku-codegen@0.19.0:
+ resolution: {integrity: sha512-uymAKHjDuaP4BEpkXC/BSLz4DUEF5oArZ5AuD3888nb2miChjWSgpPdojEJxm3pjpXkgUaCRJQyNAbnMN33wHg==}
+ engines: {node: '>=14.18.0'}
+
+ yuku-core@0.19.0:
+ resolution: {integrity: sha512-kYK9e1XdfirNhkipzW0wmMcSWcVF/CWnuugodfVYRCUwvoBefweL9HzB96OiKEhsx78V5WbUxbJqlizMX869Qg==}
+ engines: {node: '>=14.18.0'}
+
yuku-parser@0.10.2:
resolution: {integrity: sha512-CgaU0/PPjCAIEZ3WQroosOxTY3eeKldAN3h+vk8pMNz4+jl1CZzBR4pW+K/rRPF112VooCL5FdjJoiMNjDrL2A==}
- zod@3.25.76:
- resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
+ yuku-parser@0.19.0:
+ resolution: {integrity: sha512-XrBh9ZiQK5mJVRxZBAvD6LwRyAYrK3MFtH3+onyuxFL5hFD44EC3QOmIC1FjTj6H2MMwq46/NAI+NZxLZPZgxg==}
+ engines: {node: '>=14.18.0'}
zod@4.6.5:
resolution: {integrity: sha512-v5l/aFXZQeai4awLbOpSoHecE9UiMrnfx75tEXLjNonXVARxQ5mOeipTjROUchszUNCqnE+hqAMujRsRHsut2Q==}
+ zod@4.6.7:
+ resolution: {integrity: sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg==}
+
zone.js@0.16.3:
resolution: {integrity: sha512-ihXL9+vhYyEhXz4TDNpHeAOZN9FVrbog0Il64OIEI28UP/n5AaI6gsccRuOHBfx+206agzyoK527bYIO0Foy6A==}
@@ -8815,31 +8862,31 @@ snapshots:
'@jridgewell/gen-mapping': 0.3.13
'@jridgewell/trace-mapping': 0.3.31
- '@angular/animations@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))':
+ '@angular/animations@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))':
dependencies:
- '@angular/core': 22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)
+ '@angular/core': 22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)
tslib: 2.8.1
- '@angular/cdk@22.3.0-next.1(1e228ab395252fe57958c1335d3a301f)':
+ '@angular/cdk@22.3.0-next.2(e02572097466d520d7eb144e95d6bbd2)':
dependencies:
- '@angular/common': 22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2)
- '@angular/core': 22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)
- '@angular/forms': 22.3.0-next.1(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(@angular/platform-browser@22.3.0-next.1(@angular/animations@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(rxjs@7.8.2)
- '@angular/platform-browser': 22.3.0-next.1(@angular/animations@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))
+ '@angular/common': 22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2)
+ '@angular/core': 22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)
+ '@angular/forms': 22.3.0-next.2(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(@angular/platform-browser@22.3.0-next.2(@angular/animations@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(rxjs@7.8.2)
+ '@angular/platform-browser': 22.3.0-next.2(@angular/animations@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))
parse5: 8.0.1
rxjs: 7.8.2
tslib: 2.8.1
- '@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2)':
+ '@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2)':
dependencies:
- '@angular/core': 22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)
+ '@angular/core': 22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)
rxjs: 7.8.2
tslib: 2.8.1
- '@angular/compiler-cli@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(typescript@6.0.3)':
+ '@angular/compiler-cli@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(typescript@6.0.3)':
dependencies:
- '@angular/compiler': 22.3.0-next.1
- '@babel/core': 8.0.6
+ '@angular/compiler': 22.3.0-next.2
+ '@babel/core': 8.0.7
'@jridgewell/sourcemap-codec': 1.6.0
chokidar: 5.0.0
convert-source-map: 1.9.0
@@ -8850,70 +8897,68 @@ snapshots:
optionalDependencies:
typescript: 6.0.3
- '@angular/compiler@22.3.0-next.1':
+ '@angular/compiler@22.3.0-next.2':
dependencies:
tslib: 2.8.1
- '@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)':
+ '@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)':
dependencies:
rxjs: 7.8.2
tslib: 2.8.1
optionalDependencies:
- '@angular/compiler': 22.3.0-next.1
+ '@angular/compiler': 22.3.0-next.2
zone.js: 0.16.3
- '@angular/forms@22.3.0-next.1(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(@angular/platform-browser@22.3.0-next.1(@angular/animations@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(rxjs@7.8.2)':
+ '@angular/forms@22.3.0-next.2(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(@angular/platform-browser@22.3.0-next.2(@angular/animations@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(rxjs@7.8.2)':
dependencies:
- '@angular/common': 22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2)
- '@angular/core': 22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)
- '@angular/platform-browser': 22.3.0-next.1(@angular/animations@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))
+ '@angular/common': 22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2)
+ '@angular/core': 22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)
+ '@angular/platform-browser': 22.3.0-next.2(@angular/animations@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))
'@standard-schema/spec': 1.1.0
rxjs: 7.8.2
tslib: 2.8.1
- zod: 4.6.5
+ zod: 4.6.7
- '@angular/localize@22.3.0-next.1(@angular/compiler-cli@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(typescript@6.0.3))(@angular/compiler@22.3.0-next.1)':
+ '@angular/localize@22.3.0-next.2(@angular/compiler-cli@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(typescript@6.0.3))(@angular/compiler@22.3.0-next.2)':
dependencies:
- '@angular/compiler': 22.3.0-next.1
- '@angular/compiler-cli': 22.3.0-next.1(@angular/compiler@22.3.0-next.1)(typescript@6.0.3)
- '@babel/core': 8.0.6
+ '@angular/compiler': 22.3.0-next.2
+ '@angular/compiler-cli': 22.3.0-next.2(@angular/compiler@22.3.0-next.2)(typescript@6.0.3)
+ '@babel/core': 8.0.7
tinyglobby: 0.2.17
yargs: 18.2.0
- '@angular/material@22.3.0-next.1(837417520965053888cf2615dc986a27)':
+ '@angular/material@22.3.0-next.2(4016851894464b4783f4f873310c276b)':
dependencies:
- '@angular/cdk': 22.3.0-next.1(1e228ab395252fe57958c1335d3a301f)
- '@angular/common': 22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2)
- '@angular/core': 22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)
- '@angular/forms': 22.3.0-next.1(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(@angular/platform-browser@22.3.0-next.1(@angular/animations@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(rxjs@7.8.2)
- '@angular/platform-browser': 22.3.0-next.1(@angular/animations@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))
+ '@angular/cdk': 22.3.0-next.2(e02572097466d520d7eb144e95d6bbd2)
+ '@angular/common': 22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2)
+ '@angular/core': 22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)
+ '@angular/forms': 22.3.0-next.2(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(@angular/platform-browser@22.3.0-next.2(@angular/animations@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(rxjs@7.8.2)
+ '@angular/platform-browser': 22.3.0-next.2(@angular/animations@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))
rxjs: 7.8.2
tslib: 2.8.1
- '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/89b8c002e5d47ba1cbc4483d3ec06b0ae0aaccb7':
+ '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/940c0beef0de4cb128e90962d47ff80e352a1cd8':
dependencies:
'@actions/core': 3.0.1
- '@conventional-changelog/git-client': 3.1.2(conventional-commits-filter@6.0.1)(conventional-commits-parser@7.1.2)
+ '@conventional-changelog/git-client': 3.2.0(conventional-commits-filter@6.0.1)(conventional-commits-parser@7.1.3)
'@google-cloud/spanner': 8.0.0(supports-color@11.0.0)
- '@google/genai': 2.25.0(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6)
- '@inquirer/prompts': 8.7.2(@types/node@24.19.0)
- '@inquirer/type': 4.1.1(@types/node@24.19.0)
+ '@google/genai': 2.29.1(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6)
+ '@inquirer/prompts': 8.7.3(@types/node@24.19.2)
+ '@inquirer/type': 4.2.0(@types/node@24.19.2)
'@octokit/auth-app': 8.3.1
'@octokit/core': 7.0.8
'@octokit/graphql': 9.0.5
'@octokit/graphql-schema': 15.26.1
- '@octokit/openapi-types': 28.0.0
- '@octokit/plugin-paginate-rest': 15.0.0(@octokit/core@7.0.8)
'@octokit/plugin-rest-endpoint-methods': 18.0.0(@octokit/core@7.0.8)
'@octokit/request-error': 7.1.2
'@octokit/rest': 22.0.1
- '@octokit/types': 17.0.0
+ '@octokit/types': 18.0.0
'@types/cli-progress': 3.11.6
'@types/ejs': 3.1.5
'@types/events': 3.0.3
'@types/folder-hash': 4.0.4
'@types/jasmine': 6.0.0
- '@types/node': 24.19.0
+ '@types/node': 24.19.2
'@types/semver': 7.8.0
'@types/which': 3.0.4
'@types/yargs': 17.0.35
@@ -8922,19 +8967,19 @@ snapshots:
bufferutil: 4.1.0
cli-progress: 3.12.0
conventional-commits-filter: 6.0.1
- conventional-commits-parser: 7.1.2
+ conventional-commits-parser: 7.1.3
ejs: 7.0.1
encoding: 0.1.13
fast-glob: 3.3.3
- firebase: 12.19.0
- folder-hash: 4.1.3(supports-color@11.0.0)
+ firebase: 13.0.0
+ folder-hash: 4.1.4(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.6
multimatch: 8.0.0
- nock: 14.0.17
+ nock: 15.0.1(supports-color@11.0.0)
semver: 7.8.5
supports-color: 11.0.0
tsx: 4.23.15
@@ -8944,44 +8989,44 @@ snapshots:
which: 7.0.0
yaml: 2.9.1
yargs: 18.2.0
- zod: 4.6.5
+ zod: 4.6.7
transitivePeerDependencies:
- '@modelcontextprotocol/sdk'
- '@react-native-async-storage/async-storage'
- '@angular/platform-browser@22.3.0-next.1(@angular/animations@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))':
+ '@angular/platform-browser@22.3.0-next.2(@angular/animations@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))':
dependencies:
- '@angular/common': 22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2)
- '@angular/core': 22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)
+ '@angular/common': 22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2)
+ '@angular/core': 22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)
tslib: 2.8.1
optionalDependencies:
- '@angular/animations': 22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))
+ '@angular/animations': 22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))
- '@angular/platform-server@22.3.0-next.1(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/compiler@22.3.0-next.1)(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(@angular/platform-browser@22.3.0-next.1(@angular/animations@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(rxjs@7.8.2)':
+ '@angular/platform-server@22.3.0-next.2(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/compiler@22.3.0-next.2)(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(@angular/platform-browser@22.3.0-next.2(@angular/animations@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(rxjs@7.8.2)':
dependencies:
- '@angular/common': 22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2)
- '@angular/compiler': 22.3.0-next.1
- '@angular/core': 22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)
- '@angular/platform-browser': 22.3.0-next.1(@angular/animations@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))
+ '@angular/common': 22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2)
+ '@angular/compiler': 22.3.0-next.2
+ '@angular/core': 22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)
+ '@angular/platform-browser': 22.3.0-next.2(@angular/animations@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))
rxjs: 7.8.2
tslib: 2.8.1
xhr2: 0.2.1
- '@angular/router@22.3.0-next.1(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(@angular/platform-browser@22.3.0-next.1(@angular/animations@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(rxjs@7.8.2)':
+ '@angular/router@22.3.0-next.2(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(@angular/platform-browser@22.3.0-next.2(@angular/animations@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(rxjs@7.8.2)':
dependencies:
- '@angular/common': 22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2)
- '@angular/core': 22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)
- '@angular/platform-browser': 22.3.0-next.1(@angular/animations@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))
+ '@angular/common': 22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2)
+ '@angular/core': 22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)
+ '@angular/platform-browser': 22.3.0-next.2(@angular/animations@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)))(@angular/common@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2))(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))
rxjs: 7.8.2
tslib: 2.8.1
- '@angular/service-worker@22.3.0-next.1(@angular/core@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2)':
+ '@angular/service-worker@22.3.0-next.2(@angular/core@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3))(rxjs@7.8.2)':
dependencies:
- '@angular/core': 22.3.0-next.1(@angular/compiler@22.3.0-next.1)(rxjs@7.8.2)(zone.js@0.16.3)
+ '@angular/core': 22.3.0-next.2(@angular/compiler@22.3.0-next.2)(rxjs@7.8.2)(zone.js@0.16.3)
rxjs: 7.8.2
tslib: 2.8.1
- '@asamuzakjp/css-color@7.1.3':
+ '@asamuzakjp/css-color@7.1.5':
dependencies:
'@csstools/css-calc': 3.4.3(@csstools/css-parser-algorithms@4.0.2(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2)
'@csstools/css-color-parser': 4.2.6(@csstools/css-parser-algorithms@4.0.2(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2)
@@ -9017,10 +9062,10 @@ snapshots:
'@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@11.0.0))(supports-color@11.0.0)
- '@babel/helpers': 7.29.7
+ '@babel/helpers': 7.29.10
'@babel/parser': 7.29.9
'@babel/template': 7.29.7
- '@babel/traverse': 7.29.8(supports-color@11.0.0)
+ '@babel/traverse': 7.29.10(supports-color@11.0.0)
'@babel/types': 7.29.8
'@jridgewell/remapping': 2.3.5
convert-source-map: 2.0.0
@@ -9031,25 +9076,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@babel/core@8.0.6':
- dependencies:
- '@babel/code-frame': 8.0.6
- '@babel/generator': 8.0.6
- '@babel/helper-compilation-targets': 8.0.7
- '@babel/helpers': 8.0.7
- '@babel/parser': 8.0.7
- '@babel/template': 8.0.0
- '@babel/traverse': 8.0.7
- '@babel/types': 8.0.6
- '@types/gensync': 1.0.5
- convert-source-map: 2.0.0
- empathic: 2.1.0
- gensync: 1.0.0-beta.2
- import-meta-resolve: 4.2.0
- json5: 2.2.3
- obug: 2.2.1
- verkit: 0.3.2
-
'@babel/core@8.0.7':
dependencies:
'@babel/code-frame': 8.0.6
@@ -9079,7 +9105,7 @@ snapshots:
'@babel/generator@8.0.6':
dependencies:
- '@babel/parser': 8.0.6
+ '@babel/parser': 8.0.7
'@babel/types': 8.0.6
'@jridgewell/gen-mapping': 0.4.0-beta.0
'@jridgewell/trace-mapping': 0.3.31
@@ -9098,14 +9124,6 @@ snapshots:
lru-cache: 5.1.1
semver: 6.3.1
- '@babel/helper-compilation-targets@8.0.6':
- dependencies:
- '@babel/compat-data': 8.0.5
- '@babel/helper-validator-option': 8.0.0
- browserslist: 4.29.3
- flru: 1.0.2
- verkit: 0.3.2
-
'@babel/helper-compilation-targets@8.0.7':
dependencies:
'@babel/compat-data': 8.0.5
@@ -9114,7 +9132,7 @@ snapshots:
flru: 1.0.2
verkit: 0.5.0
- '@babel/helper-create-class-features-plugin@8.0.6(@babel/core@8.0.7)':
+ '@babel/helper-create-class-features-plugin@8.0.7(@babel/core@8.0.7)':
dependencies:
'@babel/core': 8.0.7
'@babel/helper-annotate-as-pure': 8.0.0
@@ -9122,20 +9140,20 @@ snapshots:
'@babel/helper-optimise-call-expression': 8.0.0
'@babel/helper-replace-supers': 8.0.1(@babel/core@8.0.7)
'@babel/helper-skip-transparent-expression-wrappers': 8.0.0
- '@babel/traverse': 8.0.6
- verkit: 0.3.2
+ '@babel/traverse': 8.0.7
+ verkit: 0.5.0
- '@babel/helper-create-regexp-features-plugin@8.0.5(@babel/core@8.0.7)':
+ '@babel/helper-create-regexp-features-plugin@8.0.7(@babel/core@8.0.7)':
dependencies:
'@babel/core': 8.0.7
'@babel/helper-annotate-as-pure': 8.0.0
- regexpu-core: 6.5.2
- verkit: 0.3.2
+ regexpu-core: 6.5.3
+ verkit: 0.5.0
'@babel/helper-define-polyfill-provider@1.0.0(@babel/core@8.0.7)':
dependencies:
'@babel/core': 8.0.7
- '@babel/helper-compilation-targets': 8.0.6
+ '@babel/helper-compilation-targets': 8.0.7
'@babel/helper-plugin-utils': 8.0.1(@babel/core@8.0.7)
lodash.debounce: 4.0.8
@@ -9145,19 +9163,19 @@ snapshots:
'@babel/helper-member-expression-to-functions@8.0.5':
dependencies:
- '@babel/traverse': 8.0.6
+ '@babel/traverse': 8.0.7
'@babel/types': 8.0.6
'@babel/helper-module-imports@7.29.7(supports-color@11.0.0)':
dependencies:
- '@babel/traverse': 7.29.8(supports-color@11.0.0)
+ '@babel/traverse': 7.29.10(supports-color@11.0.0)
'@babel/types': 7.29.8
transitivePeerDependencies:
- supports-color
'@babel/helper-module-imports@8.0.0':
dependencies:
- '@babel/traverse': 8.0.6
+ '@babel/traverse': 8.0.7
'@babel/types': 8.0.6
'@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7(supports-color@11.0.0))(supports-color@11.0.0)':
@@ -9165,7 +9183,7 @@ snapshots:
'@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.8(supports-color@11.0.0)
+ '@babel/traverse': 7.29.10(supports-color@11.0.0)
transitivePeerDependencies:
- supports-color
@@ -9174,7 +9192,7 @@ snapshots:
'@babel/core': 8.0.7
'@babel/helper-module-imports': 8.0.0
'@babel/helper-validator-identifier': 8.0.6
- '@babel/traverse': 8.0.6
+ '@babel/traverse': 8.0.7
'@babel/helper-optimise-call-expression@8.0.0':
dependencies:
@@ -9189,18 +9207,18 @@ snapshots:
'@babel/core': 8.0.7
'@babel/helper-annotate-as-pure': 8.0.0
'@babel/helper-wrap-function': 8.0.0
- '@babel/traverse': 8.0.6
+ '@babel/traverse': 8.0.7
'@babel/helper-replace-supers@8.0.1(@babel/core@8.0.7)':
dependencies:
'@babel/core': 8.0.7
'@babel/helper-member-expression-to-functions': 8.0.5
'@babel/helper-optimise-call-expression': 8.0.0
- '@babel/traverse': 8.0.6
+ '@babel/traverse': 8.0.7
'@babel/helper-skip-transparent-expression-wrappers@8.0.0':
dependencies:
- '@babel/traverse': 8.0.6
+ '@babel/traverse': 8.0.7
'@babel/types': 8.0.6
'@babel/helper-split-export-declaration@7.24.7':
@@ -9222,10 +9240,10 @@ snapshots:
'@babel/helper-wrap-function@8.0.0':
dependencies:
'@babel/template': 8.0.0
- '@babel/traverse': 8.0.6
+ '@babel/traverse': 8.0.7
'@babel/types': 8.0.6
- '@babel/helpers@7.29.7':
+ '@babel/helpers@7.29.10':
dependencies:
'@babel/template': 7.29.7
'@babel/types': 7.29.8
@@ -9239,10 +9257,6 @@ snapshots:
dependencies:
'@babel/types': 7.29.8
- '@babel/parser@8.0.6':
- dependencies:
- '@babel/types': 8.0.6
-
'@babel/parser@8.0.7':
dependencies:
'@babel/types': 8.0.6
@@ -9290,7 +9304,7 @@ snapshots:
'@babel/core': 8.0.7
'@babel/helper-plugin-utils': 8.0.1(@babel/core@8.0.7)
'@babel/helper-remap-async-to-generator': 8.0.1(@babel/core@8.0.7)
- '@babel/traverse': 8.0.6
+ '@babel/traverse': 8.0.7
'@babel/plugin-transform-async-to-generator@8.0.1(@babel/core@8.0.7)':
dependencies:
@@ -9312,24 +9326,24 @@ snapshots:
'@babel/plugin-transform-class-properties@8.0.1(@babel/core@8.0.7)':
dependencies:
'@babel/core': 8.0.7
- '@babel/helper-create-class-features-plugin': 8.0.6(@babel/core@8.0.7)
+ '@babel/helper-create-class-features-plugin': 8.0.7(@babel/core@8.0.7)
'@babel/helper-plugin-utils': 8.0.1(@babel/core@8.0.7)
'@babel/plugin-transform-class-static-block@8.0.5(@babel/core@8.0.7)':
dependencies:
'@babel/core': 8.0.7
- '@babel/helper-create-class-features-plugin': 8.0.6(@babel/core@8.0.7)
+ '@babel/helper-create-class-features-plugin': 8.0.7(@babel/core@8.0.7)
'@babel/helper-plugin-utils': 8.0.1(@babel/core@8.0.7)
'@babel/plugin-transform-classes@8.0.5(@babel/core@8.0.7)':
dependencies:
'@babel/core': 8.0.7
'@babel/helper-annotate-as-pure': 8.0.0
- '@babel/helper-compilation-targets': 8.0.6
+ '@babel/helper-compilation-targets': 8.0.7
'@babel/helper-globals': 8.0.6
'@babel/helper-plugin-utils': 8.0.1(@babel/core@8.0.7)
'@babel/helper-replace-supers': 8.0.1(@babel/core@8.0.7)
- '@babel/traverse': 8.0.6
+ '@babel/traverse': 8.0.7
'@babel/plugin-transform-computed-properties@8.0.1(@babel/core@8.0.7)':
dependencies:
@@ -9344,7 +9358,7 @@ snapshots:
'@babel/plugin-transform-dotall-regex@8.0.1(@babel/core@8.0.7)':
dependencies:
'@babel/core': 8.0.7
- '@babel/helper-create-regexp-features-plugin': 8.0.5(@babel/core@8.0.7)
+ '@babel/helper-create-regexp-features-plugin': 8.0.7(@babel/core@8.0.7)
'@babel/helper-plugin-utils': 8.0.1(@babel/core@8.0.7)
'@babel/plugin-transform-duplicate-keys@8.0.1(@babel/core@8.0.7)':
@@ -9355,7 +9369,7 @@ snapshots:
'@babel/plugin-transform-duplicate-named-capturing-groups-regex@8.0.1(@babel/core@8.0.7)':
dependencies:
'@babel/core': 8.0.7
- '@babel/helper-create-regexp-features-plugin': 8.0.5(@babel/core@8.0.7)
+ '@babel/helper-create-regexp-features-plugin': 8.0.7(@babel/core@8.0.7)
'@babel/helper-plugin-utils': 8.0.1(@babel/core@8.0.7)
'@babel/plugin-transform-dynamic-import@8.0.1(@babel/core@8.0.7)':
@@ -9388,7 +9402,7 @@ snapshots:
'@babel/plugin-transform-function-name@8.0.1(@babel/core@8.0.7)':
dependencies:
'@babel/core': 8.0.7
- '@babel/helper-compilation-targets': 8.0.6
+ '@babel/helper-compilation-targets': 8.0.7
'@babel/helper-plugin-utils': 8.0.1(@babel/core@8.0.7)
'@babel/plugin-transform-json-strings@8.0.1(@babel/core@8.0.7)':
@@ -9439,7 +9453,7 @@ snapshots:
'@babel/plugin-transform-named-capturing-groups-regex@8.0.1(@babel/core@8.0.7)':
dependencies:
'@babel/core': 8.0.7
- '@babel/helper-create-regexp-features-plugin': 8.0.5(@babel/core@8.0.7)
+ '@babel/helper-create-regexp-features-plugin': 8.0.7(@babel/core@8.0.7)
'@babel/helper-plugin-utils': 8.0.1(@babel/core@8.0.7)
'@babel/plugin-transform-new-target@8.0.1(@babel/core@8.0.7)':
@@ -9460,7 +9474,7 @@ snapshots:
'@babel/plugin-transform-object-rest-spread@8.0.1(@babel/core@8.0.7)':
dependencies:
'@babel/core': 8.0.7
- '@babel/helper-compilation-targets': 8.0.6
+ '@babel/helper-compilation-targets': 8.0.7
'@babel/helper-plugin-utils': 8.0.1(@babel/core@8.0.7)
'@babel/plugin-transform-destructuring': 8.0.5(@babel/core@8.0.7)
'@babel/plugin-transform-parameters': 8.0.5(@babel/core@8.0.7)
@@ -9490,14 +9504,14 @@ snapshots:
'@babel/plugin-transform-private-methods@8.0.1(@babel/core@8.0.7)':
dependencies:
'@babel/core': 8.0.7
- '@babel/helper-create-class-features-plugin': 8.0.6(@babel/core@8.0.7)
+ '@babel/helper-create-class-features-plugin': 8.0.7(@babel/core@8.0.7)
'@babel/helper-plugin-utils': 8.0.1(@babel/core@8.0.7)
'@babel/plugin-transform-private-property-in-object@8.0.5(@babel/core@8.0.7)':
dependencies:
'@babel/core': 8.0.7
'@babel/helper-annotate-as-pure': 8.0.0
- '@babel/helper-create-class-features-plugin': 8.0.6(@babel/core@8.0.7)
+ '@babel/helper-create-class-features-plugin': 8.0.7(@babel/core@8.0.7)
'@babel/helper-plugin-utils': 8.0.1(@babel/core@8.0.7)
'@babel/plugin-transform-property-literals@8.0.1(@babel/core@8.0.7)':
@@ -9513,7 +9527,7 @@ snapshots:
'@babel/plugin-transform-regexp-modifiers@8.0.1(@babel/core@8.0.7)':
dependencies:
'@babel/core': 8.0.7
- '@babel/helper-create-regexp-features-plugin': 8.0.5(@babel/core@8.0.7)
+ '@babel/helper-create-regexp-features-plugin': 8.0.7(@babel/core@8.0.7)
'@babel/helper-plugin-utils': 8.0.1(@babel/core@8.0.7)
'@babel/plugin-transform-reserved-words@8.0.1(@babel/core@8.0.7)':
@@ -9561,19 +9575,19 @@ snapshots:
'@babel/plugin-transform-unicode-property-regex@8.0.1(@babel/core@8.0.7)':
dependencies:
'@babel/core': 8.0.7
- '@babel/helper-create-regexp-features-plugin': 8.0.5(@babel/core@8.0.7)
+ '@babel/helper-create-regexp-features-plugin': 8.0.7(@babel/core@8.0.7)
'@babel/helper-plugin-utils': 8.0.1(@babel/core@8.0.7)
'@babel/plugin-transform-unicode-regex@8.0.1(@babel/core@8.0.7)':
dependencies:
'@babel/core': 8.0.7
- '@babel/helper-create-regexp-features-plugin': 8.0.5(@babel/core@8.0.7)
+ '@babel/helper-create-regexp-features-plugin': 8.0.7(@babel/core@8.0.7)
'@babel/helper-plugin-utils': 8.0.1(@babel/core@8.0.7)
'@babel/plugin-transform-unicode-sets-regex@8.0.1(@babel/core@8.0.7)':
dependencies:
'@babel/core': 8.0.7
- '@babel/helper-create-regexp-features-plugin': 8.0.5(@babel/core@8.0.7)
+ '@babel/helper-create-regexp-features-plugin': 8.0.7(@babel/core@8.0.7)
'@babel/helper-plugin-utils': 8.0.1(@babel/core@8.0.7)
'@babel/preset-env@8.0.7(@babel/core@8.0.7)':
@@ -9665,10 +9679,10 @@ snapshots:
'@babel/template@8.0.0':
dependencies:
'@babel/code-frame': 8.0.6
- '@babel/parser': 8.0.6
+ '@babel/parser': 8.0.7
'@babel/types': 8.0.6
- '@babel/traverse@7.29.8(supports-color@11.0.0)':
+ '@babel/traverse@7.29.10(supports-color@11.0.0)':
dependencies:
'@babel/code-frame': 7.29.7
'@babel/generator': 7.29.8
@@ -9680,16 +9694,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@babel/traverse@8.0.6':
- dependencies:
- '@babel/code-frame': 8.0.6
- '@babel/generator': 8.0.6
- '@babel/helper-globals': 8.0.6
- '@babel/parser': 8.0.6
- '@babel/template': 8.0.0
- '@babel/types': 8.0.6
- obug: 2.2.1
-
'@babel/traverse@8.0.7':
dependencies:
'@babel/code-frame': 8.0.6
@@ -9718,7 +9722,7 @@ snapshots:
'@bcoe/v8-coverage@1.0.2': {}
- '@bramus/specificity@2.4.2':
+ '@bramus/specificity@2.4.3':
dependencies:
css-tree: 3.2.1
@@ -9738,14 +9742,14 @@ snapshots:
'@colors/colors@1.5.0': {}
- '@conventional-changelog/git-client@3.1.2(conventional-commits-filter@6.0.1)(conventional-commits-parser@7.1.2)':
+ '@conventional-changelog/git-client@3.2.0(conventional-commits-filter@6.0.1)(conventional-commits-parser@7.1.3)':
dependencies:
'@simple-libs/child-process-utils': 2.0.0
'@simple-libs/stream-utils': 2.0.0
- semver: 7.8.5
+ verkit: 0.5.0
optionalDependencies:
conventional-commits-filter: 6.0.1
- conventional-commits-parser: 7.1.2
+ conventional-commits-parser: 7.1.3
'@csstools/color-helpers@6.1.2': {}
@@ -9929,9 +9933,9 @@ snapshots:
optionalDependencies:
'@noble/hashes': 1.8.0
- '@firebase/ai@2.16.0(@firebase/app-types@0.9.6)(@firebase/app@0.16.2)':
+ '@firebase/ai@3.0.0(@firebase/app-types@0.9.6)(@firebase/app@0.16.3)':
dependencies:
- '@firebase/app': 0.16.2
+ '@firebase/app': 0.16.3
'@firebase/app-check-interop-types': 0.3.5
'@firebase/app-types': 0.9.6
'@firebase/component': 0.7.5
@@ -9939,33 +9943,33 @@ snapshots:
'@firebase/util': 1.15.3
tslib: 2.8.1
- '@firebase/analytics-compat@0.2.31(@firebase/app-compat@0.5.18)(@firebase/app@0.16.2)':
+ '@firebase/analytics-compat@0.2.31(@firebase/app-compat@0.5.19)(@firebase/app@0.16.3)':
dependencies:
- '@firebase/analytics': 0.10.25(@firebase/app@0.16.2)
+ '@firebase/analytics': 0.10.25(@firebase/app@0.16.3)
'@firebase/analytics-types': 0.8.5
- '@firebase/app': 0.16.2
- '@firebase/app-compat': 0.5.18
+ '@firebase/app': 0.16.3
+ '@firebase/app-compat': 0.5.19
'@firebase/component': 0.7.5
'@firebase/util': 1.15.3
tslib: 2.8.1
'@firebase/analytics-types@0.8.5': {}
- '@firebase/analytics@0.10.25(@firebase/app@0.16.2)':
+ '@firebase/analytics@0.10.25(@firebase/app@0.16.3)':
dependencies:
- '@firebase/app': 0.16.2
+ '@firebase/app': 0.16.3
'@firebase/component': 0.7.5
- '@firebase/installations': 0.6.24(@firebase/app@0.16.2)
+ '@firebase/installations': 0.6.24(@firebase/app@0.16.3)
'@firebase/logger': 0.5.2
'@firebase/util': 1.15.3
tslib: 2.8.1
- '@firebase/app-check-compat@0.4.7(@firebase/app-compat@0.5.18)(@firebase/app@0.16.2)':
+ '@firebase/app-check-compat@0.4.7(@firebase/app-compat@0.5.19)(@firebase/app@0.16.3)':
dependencies:
- '@firebase/app': 0.16.2
- '@firebase/app-check': 0.13.1(@firebase/app@0.16.2)
+ '@firebase/app': 0.16.3
+ '@firebase/app-check': 0.13.1(@firebase/app@0.16.3)
'@firebase/app-check-types': 0.5.5
- '@firebase/app-compat': 0.5.18
+ '@firebase/app-compat': 0.5.19
'@firebase/component': 0.7.5
'@firebase/logger': 0.5.2
'@firebase/util': 1.15.3
@@ -9975,17 +9979,17 @@ snapshots:
'@firebase/app-check-types@0.5.5': {}
- '@firebase/app-check@0.13.1(@firebase/app@0.16.2)':
+ '@firebase/app-check@0.13.1(@firebase/app@0.16.3)':
dependencies:
- '@firebase/app': 0.16.2
+ '@firebase/app': 0.16.3
'@firebase/component': 0.7.5
'@firebase/logger': 0.5.2
'@firebase/util': 1.15.3
tslib: 2.8.1
- '@firebase/app-compat@0.5.18':
+ '@firebase/app-compat@0.5.19':
dependencies:
- '@firebase/app': 0.16.2
+ '@firebase/app': 0.16.3
'@firebase/component': 0.7.5
'@firebase/logger': 0.5.2
'@firebase/util': 1.15.3
@@ -9995,7 +9999,7 @@ snapshots:
dependencies:
'@firebase/logger': 0.5.2
- '@firebase/app@0.16.2':
+ '@firebase/app@0.16.3':
dependencies:
'@firebase/component': 0.7.5
'@firebase/logger': 0.5.2
@@ -10003,11 +10007,11 @@ snapshots:
idb: 7.1.1
tslib: 2.8.1
- '@firebase/auth-compat@0.6.11(@firebase/app-compat@0.5.18)(@firebase/app-types@0.9.6)(@firebase/app@0.16.2)':
+ '@firebase/auth-compat@0.6.12(@firebase/app-compat@0.5.19)(@firebase/app-types@0.9.6)(@firebase/app@0.16.3)':
dependencies:
- '@firebase/app': 0.16.2
- '@firebase/app-compat': 0.5.18
- '@firebase/auth': 1.13.6(@firebase/app@0.16.2)
+ '@firebase/app': 0.16.3
+ '@firebase/app-compat': 0.5.19
+ '@firebase/auth': 1.13.7(@firebase/app@0.16.3)
'@firebase/auth-types': 0.13.2(@firebase/app-types@0.9.6)(@firebase/util@1.15.3)
'@firebase/component': 0.7.5
'@firebase/util': 1.15.3
@@ -10023,9 +10027,9 @@ snapshots:
'@firebase/app-types': 0.9.6
'@firebase/util': 1.15.3
- '@firebase/auth@1.13.6(@firebase/app@0.16.2)':
+ '@firebase/auth@1.13.7(@firebase/app@0.16.3)':
dependencies:
- '@firebase/app': 0.16.2
+ '@firebase/app': 0.16.3
'@firebase/component': 0.7.5
'@firebase/logger': 0.5.2
'@firebase/util': 1.15.3
@@ -10036,16 +10040,16 @@ snapshots:
'@firebase/util': 1.15.3
tslib: 2.8.1
- '@firebase/data-connect@0.7.4(@firebase/app@0.16.2)':
+ '@firebase/data-connect@0.7.4(@firebase/app@0.16.3)':
dependencies:
- '@firebase/app': 0.16.2
+ '@firebase/app': 0.16.3
'@firebase/auth-interop-types': 0.2.6
'@firebase/component': 0.7.5
'@firebase/logger': 0.5.2
'@firebase/util': 1.15.3
tslib: 2.8.1
- '@firebase/database-compat@2.1.7(@firebase/app-compat@0.5.18)(@firebase/app@0.16.2)':
+ '@firebase/database-compat@2.1.7(@firebase/app-compat@0.5.19)(@firebase/app@0.16.3)':
dependencies:
'@firebase/component': 0.7.5
'@firebase/database': 1.1.5
@@ -10054,8 +10058,8 @@ snapshots:
'@firebase/util': 1.15.3
tslib: 2.8.1
optionalDependencies:
- '@firebase/app': 0.16.2
- '@firebase/app-compat': 0.5.18
+ '@firebase/app': 0.16.3
+ '@firebase/app-compat': 0.5.19
'@firebase/database-types@1.0.22':
dependencies:
@@ -10072,12 +10076,12 @@ snapshots:
faye-websocket: 0.11.4
tslib: 2.8.1
- '@firebase/firestore-compat@0.4.14(@firebase/app-compat@0.5.18)(@firebase/app-types@0.9.6)(@firebase/app@0.16.2)':
+ '@firebase/firestore-compat@0.4.15(@firebase/app-compat@0.5.19)(@firebase/app-types@0.9.6)(@firebase/app@0.16.3)':
dependencies:
- '@firebase/app': 0.16.2
- '@firebase/app-compat': 0.5.18
+ '@firebase/app': 0.16.3
+ '@firebase/app-compat': 0.5.19
'@firebase/component': 0.7.5
- '@firebase/firestore': 4.17.2(@firebase/app@0.16.2)
+ '@firebase/firestore': 4.18.0(@firebase/app@0.16.3)
'@firebase/firestore-types': 3.0.5(@firebase/app-types@0.9.6)(@firebase/util@1.15.3)
'@firebase/util': 1.15.3
tslib: 2.8.1
@@ -10089,9 +10093,9 @@ snapshots:
'@firebase/app-types': 0.9.6
'@firebase/util': 1.15.3
- '@firebase/firestore@4.17.2(@firebase/app@0.16.2)':
+ '@firebase/firestore@4.18.0(@firebase/app@0.16.3)':
dependencies:
- '@firebase/app': 0.16.2
+ '@firebase/app': 0.16.3
'@firebase/component': 0.7.5
'@firebase/logger': 0.5.2
'@firebase/util': 1.15.3
@@ -10101,21 +10105,21 @@ snapshots:
re2js: 2.8.6
tslib: 2.8.1
- '@firebase/functions-compat@0.5.0(@firebase/app-compat@0.5.18)(@firebase/app@0.16.2)':
+ '@firebase/functions-compat@0.5.0(@firebase/app-compat@0.5.19)(@firebase/app@0.16.3)':
dependencies:
- '@firebase/app': 0.16.2
- '@firebase/app-compat': 0.5.18
+ '@firebase/app': 0.16.3
+ '@firebase/app-compat': 0.5.19
'@firebase/component': 0.7.5
- '@firebase/functions': 0.14.0(@firebase/app@0.16.2)
+ '@firebase/functions': 0.14.0(@firebase/app@0.16.3)
'@firebase/functions-types': 0.6.5
'@firebase/util': 1.15.3
tslib: 2.8.1
'@firebase/functions-types@0.6.5': {}
- '@firebase/functions@0.14.0(@firebase/app@0.16.2)':
+ '@firebase/functions@0.14.0(@firebase/app@0.16.3)':
dependencies:
- '@firebase/app': 0.16.2
+ '@firebase/app': 0.16.3
'@firebase/app-check-interop-types': 0.3.5
'@firebase/auth-interop-types': 0.2.6
'@firebase/component': 0.7.5
@@ -10123,12 +10127,12 @@ snapshots:
'@firebase/util': 1.15.3
tslib: 2.8.1
- '@firebase/installations-compat@0.2.24(@firebase/app-compat@0.5.18)(@firebase/app-types@0.9.6)(@firebase/app@0.16.2)':
+ '@firebase/installations-compat@0.2.24(@firebase/app-compat@0.5.19)(@firebase/app-types@0.9.6)(@firebase/app@0.16.3)':
dependencies:
- '@firebase/app': 0.16.2
- '@firebase/app-compat': 0.5.18
+ '@firebase/app': 0.16.3
+ '@firebase/app-compat': 0.5.19
'@firebase/component': 0.7.5
- '@firebase/installations': 0.6.24(@firebase/app@0.16.2)
+ '@firebase/installations': 0.6.24(@firebase/app@0.16.3)
'@firebase/installations-types': 0.5.5(@firebase/app-types@0.9.6)
'@firebase/util': 1.15.3
tslib: 2.8.1
@@ -10139,9 +10143,9 @@ snapshots:
dependencies:
'@firebase/app-types': 0.9.6
- '@firebase/installations@0.6.24(@firebase/app@0.16.2)':
+ '@firebase/installations@0.6.24(@firebase/app@0.16.3)':
dependencies:
- '@firebase/app': 0.16.2
+ '@firebase/app': 0.16.3
'@firebase/component': 0.7.5
'@firebase/util': 1.15.3
idb: 7.1.1
@@ -10151,78 +10155,78 @@ snapshots:
dependencies:
tslib: 2.8.1
- '@firebase/messaging-compat@0.2.30(@firebase/app-compat@0.5.18)(@firebase/app@0.16.2)':
+ '@firebase/messaging-compat@0.2.30(@firebase/app-compat@0.5.19)(@firebase/app@0.16.3)':
dependencies:
- '@firebase/app': 0.16.2
- '@firebase/app-compat': 0.5.18
+ '@firebase/app': 0.16.3
+ '@firebase/app-compat': 0.5.19
'@firebase/component': 0.7.5
- '@firebase/messaging': 0.13.3(@firebase/app@0.16.2)
+ '@firebase/messaging': 0.13.3(@firebase/app@0.16.3)
'@firebase/util': 1.15.3
tslib: 2.8.1
'@firebase/messaging-interop-types@0.2.6': {}
- '@firebase/messaging@0.13.3(@firebase/app@0.16.2)':
+ '@firebase/messaging@0.13.3(@firebase/app@0.16.3)':
dependencies:
- '@firebase/app': 0.16.2
+ '@firebase/app': 0.16.3
'@firebase/component': 0.7.5
- '@firebase/installations': 0.6.24(@firebase/app@0.16.2)
+ '@firebase/installations': 0.6.24(@firebase/app@0.16.3)
'@firebase/messaging-interop-types': 0.2.6
'@firebase/util': 1.15.3
idb: 7.1.1
tslib: 2.8.1
- '@firebase/performance-compat@0.2.27(@firebase/app-compat@0.5.18)(@firebase/app@0.16.2)':
+ '@firebase/performance-compat@0.2.27(@firebase/app-compat@0.5.19)(@firebase/app@0.16.3)':
dependencies:
- '@firebase/app': 0.16.2
- '@firebase/app-compat': 0.5.18
+ '@firebase/app': 0.16.3
+ '@firebase/app-compat': 0.5.19
'@firebase/component': 0.7.5
'@firebase/logger': 0.5.2
- '@firebase/performance': 0.7.14(@firebase/app@0.16.2)
+ '@firebase/performance': 0.7.14(@firebase/app@0.16.3)
'@firebase/performance-types': 0.2.5
'@firebase/util': 1.15.3
tslib: 2.8.1
'@firebase/performance-types@0.2.5': {}
- '@firebase/performance@0.7.14(@firebase/app@0.16.2)':
+ '@firebase/performance@0.7.14(@firebase/app@0.16.3)':
dependencies:
- '@firebase/app': 0.16.2
+ '@firebase/app': 0.16.3
'@firebase/component': 0.7.5
- '@firebase/installations': 0.6.24(@firebase/app@0.16.2)
+ '@firebase/installations': 0.6.24(@firebase/app@0.16.3)
'@firebase/logger': 0.5.2
'@firebase/util': 1.15.3
tslib: 2.8.1
web-vitals: 4.2.4
- '@firebase/remote-config-compat@0.2.29(@firebase/app-compat@0.5.18)(@firebase/app@0.16.2)':
+ '@firebase/remote-config-compat@0.2.30(@firebase/app-compat@0.5.19)(@firebase/app@0.16.3)':
dependencies:
- '@firebase/app': 0.16.2
- '@firebase/app-compat': 0.5.18
+ '@firebase/app': 0.16.3
+ '@firebase/app-compat': 0.5.19
'@firebase/component': 0.7.5
'@firebase/logger': 0.5.2
- '@firebase/remote-config': 0.9.2(@firebase/app@0.16.2)
+ '@firebase/remote-config': 0.9.3(@firebase/app@0.16.3)
'@firebase/remote-config-types': 0.5.2
'@firebase/util': 1.15.3
tslib: 2.8.1
'@firebase/remote-config-types@0.5.2': {}
- '@firebase/remote-config@0.9.2(@firebase/app@0.16.2)':
+ '@firebase/remote-config@0.9.3(@firebase/app@0.16.3)':
dependencies:
- '@firebase/app': 0.16.2
+ '@firebase/app': 0.16.3
'@firebase/component': 0.7.5
- '@firebase/installations': 0.6.24(@firebase/app@0.16.2)
+ '@firebase/installations': 0.6.24(@firebase/app@0.16.3)
'@firebase/logger': 0.5.2
'@firebase/util': 1.15.3
tslib: 2.8.1
- '@firebase/storage-compat@0.4.5(@firebase/app-compat@0.5.18)(@firebase/app-types@0.9.6)(@firebase/app@0.16.2)':
+ '@firebase/storage-compat@0.4.6(@firebase/app-compat@0.5.19)(@firebase/app-types@0.9.6)(@firebase/app@0.16.3)':
dependencies:
- '@firebase/app': 0.16.2
- '@firebase/app-compat': 0.5.18
+ '@firebase/app': 0.16.3
+ '@firebase/app-compat': 0.5.19
'@firebase/component': 0.7.5
- '@firebase/storage': 0.14.5(@firebase/app@0.16.2)
+ '@firebase/storage': 0.14.6(@firebase/app@0.16.3)
'@firebase/storage-types': 0.8.5(@firebase/app-types@0.9.6)(@firebase/util@1.15.3)
'@firebase/util': 1.15.3
tslib: 2.8.1
@@ -10234,9 +10238,9 @@ snapshots:
'@firebase/app-types': 0.9.6
'@firebase/util': 1.15.3
- '@firebase/storage@0.14.5(@firebase/app@0.16.2)':
+ '@firebase/storage@0.14.6(@firebase/app@0.16.3)':
dependencies:
- '@firebase/app': 0.16.2
+ '@firebase/app': 0.16.3
'@firebase/component': 0.7.5
'@firebase/util': 1.15.3
tslib: 2.8.1
@@ -10281,8 +10285,8 @@ snapshots:
'@google-cloud/promisify': 5.1.0
'@grpc/proto-loader': 0.7.15
'@opentelemetry/api': 1.9.1
- '@opentelemetry/context-async-hooks': 2.11.0(@opentelemetry/api@1.9.1)
- '@opentelemetry/core': 2.11.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/context-async-hooks': 2.12.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/core': 2.12.0(@opentelemetry/api@1.9.1)
'@opentelemetry/semantic-conventions': 1.43.0
'@types/big.js': 6.2.2
'@types/stack-trace': 0.0.33
@@ -10308,7 +10312,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@google/genai@2.25.0(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6)':
+ '@google/genai@2.29.1(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6)':
dependencies:
google-auth-library: 10.9.1(supports-color@11.0.0)
p-retry: 4.6.2
@@ -10319,7 +10323,7 @@ snapshots:
- supports-color
- utf-8-validate
- '@grpc/grpc-js@1.14.5':
+ '@grpc/grpc-js@1.14.6':
dependencies:
'@grpc/proto-loader': 0.8.1
'@js-sdsl/ordered-map': 4.4.2
@@ -10373,21 +10377,14 @@ snapshots:
optionalDependencies:
'@types/node': 22.20.5
- '@inquirer/checkbox@5.2.6(@types/node@24.19.0)':
+ '@inquirer/checkbox@5.2.6(@types/node@24.19.2)':
dependencies:
'@inquirer/ansi': 2.0.9
- '@inquirer/core': 12.0.4(@types/node@24.19.0)
+ '@inquirer/core': 12.0.4(@types/node@24.19.2)
'@inquirer/figures': 2.0.9
- '@inquirer/type': 4.2.0(@types/node@24.19.0)
+ '@inquirer/type': 4.2.0(@types/node@24.19.2)
optionalDependencies:
- '@types/node': 24.19.0
-
- '@inquirer/confirm@6.3.2(@types/node@24.19.0)':
- dependencies:
- '@inquirer/core': 12.0.4(@types/node@24.19.0)
- '@inquirer/type': 4.1.1(@types/node@24.19.0)
- optionalDependencies:
- '@types/node': 24.19.0
+ '@types/node': 24.19.2
'@inquirer/confirm@6.3.3(@types/node@22.20.5)':
dependencies:
@@ -10396,6 +10393,13 @@ snapshots:
optionalDependencies:
'@types/node': 22.20.5
+ '@inquirer/confirm@6.3.3(@types/node@24.19.2)':
+ dependencies:
+ '@inquirer/core': 12.0.4(@types/node@24.19.2)
+ '@inquirer/type': 4.2.0(@types/node@24.19.2)
+ optionalDependencies:
+ '@types/node': 24.19.2
+
'@inquirer/core@12.0.4(@types/node@22.20.5)':
dependencies:
'@inquirer/ansi': 2.0.9
@@ -10408,17 +10412,17 @@ snapshots:
optionalDependencies:
'@types/node': 22.20.5
- '@inquirer/core@12.0.4(@types/node@24.19.0)':
+ '@inquirer/core@12.0.4(@types/node@24.19.2)':
dependencies:
'@inquirer/ansi': 2.0.9
'@inquirer/figures': 2.0.9
- '@inquirer/type': 4.2.0(@types/node@24.19.0)
+ '@inquirer/type': 4.2.0(@types/node@24.19.2)
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.19.0
+ '@types/node': 24.19.2
'@inquirer/editor@5.3.4(@types/node@22.20.5)':
dependencies:
@@ -10428,13 +10432,13 @@ snapshots:
optionalDependencies:
'@types/node': 22.20.5
- '@inquirer/editor@5.3.4(@types/node@24.19.0)':
+ '@inquirer/editor@5.3.4(@types/node@24.19.2)':
dependencies:
- '@inquirer/core': 12.0.4(@types/node@24.19.0)
- '@inquirer/external-editor': 3.0.6(@types/node@24.19.0)
- '@inquirer/type': 4.2.0(@types/node@24.19.0)
+ '@inquirer/core': 12.0.4(@types/node@24.19.2)
+ '@inquirer/external-editor': 3.0.6(@types/node@24.19.2)
+ '@inquirer/type': 4.2.0(@types/node@24.19.2)
optionalDependencies:
- '@types/node': 24.19.0
+ '@types/node': 24.19.2
'@inquirer/expand@5.1.6(@types/node@22.20.5)':
dependencies:
@@ -10443,12 +10447,12 @@ snapshots:
optionalDependencies:
'@types/node': 22.20.5
- '@inquirer/expand@5.1.6(@types/node@24.19.0)':
+ '@inquirer/expand@5.1.6(@types/node@24.19.2)':
dependencies:
- '@inquirer/core': 12.0.4(@types/node@24.19.0)
- '@inquirer/type': 4.2.0(@types/node@24.19.0)
+ '@inquirer/core': 12.0.4(@types/node@24.19.2)
+ '@inquirer/type': 4.2.0(@types/node@24.19.2)
optionalDependencies:
- '@types/node': 24.19.0
+ '@types/node': 24.19.2
'@inquirer/external-editor@3.0.6(@types/node@22.20.5)':
dependencies:
@@ -10457,12 +10461,12 @@ snapshots:
optionalDependencies:
'@types/node': 22.20.5
- '@inquirer/external-editor@3.0.6(@types/node@24.19.0)':
+ '@inquirer/external-editor@3.0.6(@types/node@24.19.2)':
dependencies:
chardet: 2.2.0
iconv-lite: 0.7.3
optionalDependencies:
- '@types/node': 24.19.0
+ '@types/node': 24.19.2
'@inquirer/figures@2.0.9': {}
@@ -10473,12 +10477,12 @@ snapshots:
optionalDependencies:
'@types/node': 22.20.5
- '@inquirer/input@5.1.7(@types/node@24.19.0)':
+ '@inquirer/input@5.1.7(@types/node@24.19.2)':
dependencies:
- '@inquirer/core': 12.0.4(@types/node@24.19.0)
- '@inquirer/type': 4.2.0(@types/node@24.19.0)
+ '@inquirer/core': 12.0.4(@types/node@24.19.2)
+ '@inquirer/type': 4.2.0(@types/node@24.19.2)
optionalDependencies:
- '@types/node': 24.19.0
+ '@types/node': 24.19.2
'@inquirer/number@4.2.4(@types/node@22.20.5)':
dependencies:
@@ -10487,12 +10491,12 @@ snapshots:
optionalDependencies:
'@types/node': 22.20.5
- '@inquirer/number@4.2.4(@types/node@24.19.0)':
+ '@inquirer/number@4.2.4(@types/node@24.19.2)':
dependencies:
- '@inquirer/core': 12.0.4(@types/node@24.19.0)
- '@inquirer/type': 4.2.0(@types/node@24.19.0)
+ '@inquirer/core': 12.0.4(@types/node@24.19.2)
+ '@inquirer/type': 4.2.0(@types/node@24.19.2)
optionalDependencies:
- '@types/node': 24.19.0
+ '@types/node': 24.19.2
'@inquirer/password@5.2.3(@types/node@22.20.5)':
dependencies:
@@ -10502,28 +10506,13 @@ snapshots:
optionalDependencies:
'@types/node': 22.20.5
- '@inquirer/password@5.2.3(@types/node@24.19.0)':
+ '@inquirer/password@5.2.3(@types/node@24.19.2)':
dependencies:
'@inquirer/ansi': 2.0.9
- '@inquirer/core': 12.0.4(@types/node@24.19.0)
- '@inquirer/type': 4.2.0(@types/node@24.19.0)
+ '@inquirer/core': 12.0.4(@types/node@24.19.2)
+ '@inquirer/type': 4.2.0(@types/node@24.19.2)
optionalDependencies:
- '@types/node': 24.19.0
-
- '@inquirer/prompts@8.7.2(@types/node@24.19.0)':
- dependencies:
- '@inquirer/checkbox': 5.2.6(@types/node@24.19.0)
- '@inquirer/confirm': 6.3.2(@types/node@24.19.0)
- '@inquirer/editor': 5.3.4(@types/node@24.19.0)
- '@inquirer/expand': 5.1.6(@types/node@24.19.0)
- '@inquirer/input': 5.1.7(@types/node@24.19.0)
- '@inquirer/number': 4.2.4(@types/node@24.19.0)
- '@inquirer/password': 5.2.3(@types/node@24.19.0)
- '@inquirer/rawlist': 5.3.6(@types/node@24.19.0)
- '@inquirer/search': 4.3.4(@types/node@24.19.0)
- '@inquirer/select': 5.2.6(@types/node@24.19.0)
- optionalDependencies:
- '@types/node': 24.19.0
+ '@types/node': 24.19.2
'@inquirer/prompts@8.7.3(@types/node@22.20.5)':
dependencies:
@@ -10540,6 +10529,21 @@ snapshots:
optionalDependencies:
'@types/node': 22.20.5
+ '@inquirer/prompts@8.7.3(@types/node@24.19.2)':
+ dependencies:
+ '@inquirer/checkbox': 5.2.6(@types/node@24.19.2)
+ '@inquirer/confirm': 6.3.3(@types/node@24.19.2)
+ '@inquirer/editor': 5.3.4(@types/node@24.19.2)
+ '@inquirer/expand': 5.1.6(@types/node@24.19.2)
+ '@inquirer/input': 5.1.7(@types/node@24.19.2)
+ '@inquirer/number': 4.2.4(@types/node@24.19.2)
+ '@inquirer/password': 5.2.3(@types/node@24.19.2)
+ '@inquirer/rawlist': 5.3.6(@types/node@24.19.2)
+ '@inquirer/search': 4.3.4(@types/node@24.19.2)
+ '@inquirer/select': 5.2.6(@types/node@24.19.2)
+ optionalDependencies:
+ '@types/node': 24.19.2
+
'@inquirer/rawlist@5.3.6(@types/node@22.20.5)':
dependencies:
'@inquirer/core': 12.0.4(@types/node@22.20.5)
@@ -10547,12 +10551,12 @@ snapshots:
optionalDependencies:
'@types/node': 22.20.5
- '@inquirer/rawlist@5.3.6(@types/node@24.19.0)':
+ '@inquirer/rawlist@5.3.6(@types/node@24.19.2)':
dependencies:
- '@inquirer/core': 12.0.4(@types/node@24.19.0)
- '@inquirer/type': 4.2.0(@types/node@24.19.0)
+ '@inquirer/core': 12.0.4(@types/node@24.19.2)
+ '@inquirer/type': 4.2.0(@types/node@24.19.2)
optionalDependencies:
- '@types/node': 24.19.0
+ '@types/node': 24.19.2
'@inquirer/search@4.3.4(@types/node@22.20.5)':
dependencies:
@@ -10562,13 +10566,13 @@ snapshots:
optionalDependencies:
'@types/node': 22.20.5
- '@inquirer/search@4.3.4(@types/node@24.19.0)':
+ '@inquirer/search@4.3.4(@types/node@24.19.2)':
dependencies:
- '@inquirer/core': 12.0.4(@types/node@24.19.0)
+ '@inquirer/core': 12.0.4(@types/node@24.19.2)
'@inquirer/figures': 2.0.9
- '@inquirer/type': 4.2.0(@types/node@24.19.0)
+ '@inquirer/type': 4.2.0(@types/node@24.19.2)
optionalDependencies:
- '@types/node': 24.19.0
+ '@types/node': 24.19.2
'@inquirer/select@5.2.6(@types/node@22.20.5)':
dependencies:
@@ -10579,26 +10583,22 @@ snapshots:
optionalDependencies:
'@types/node': 22.20.5
- '@inquirer/select@5.2.6(@types/node@24.19.0)':
+ '@inquirer/select@5.2.6(@types/node@24.19.2)':
dependencies:
'@inquirer/ansi': 2.0.9
- '@inquirer/core': 12.0.4(@types/node@24.19.0)
+ '@inquirer/core': 12.0.4(@types/node@24.19.2)
'@inquirer/figures': 2.0.9
- '@inquirer/type': 4.2.0(@types/node@24.19.0)
- optionalDependencies:
- '@types/node': 24.19.0
-
- '@inquirer/type@4.1.1(@types/node@24.19.0)':
+ '@inquirer/type': 4.2.0(@types/node@24.19.2)
optionalDependencies:
- '@types/node': 24.19.0
+ '@types/node': 24.19.2
'@inquirer/type@4.2.0(@types/node@22.20.5)':
optionalDependencies:
'@types/node': 22.20.5
- '@inquirer/type@4.2.0(@types/node@24.19.0)':
+ '@inquirer/type@4.2.0(@types/node@24.19.2)':
optionalDependencies:
- '@types/node': 24.19.0
+ '@types/node': 24.19.2
'@isaacs/cliui@8.0.2':
dependencies:
@@ -10782,11 +10782,11 @@ snapshots:
'@leichtgewicht/ip-codec@2.0.5': {}
- '@listr2/prompt-adapter-inquirer@4.2.7(@inquirer/prompts@8.7.3(@types/node@22.20.5))(@types/node@22.20.5)(listr2@11.1.1)':
+ '@listr2/prompt-adapter-inquirer@4.3.1(@inquirer/prompts@8.7.3(@types/node@22.20.5))(@types/node@22.20.5)(listr2@11.2.0)':
dependencies:
'@inquirer/prompts': 8.7.3(@types/node@22.20.5)
'@inquirer/type': 4.2.0(@types/node@22.20.5)
- listr2: 11.1.1
+ listr2: 11.2.0
transitivePeerDependencies:
- '@types/node'
@@ -10813,12 +10813,12 @@ snapshots:
'@modelcontextprotocol/core@2.3.1':
dependencies:
- zod: 4.6.5
+ zod: 4.6.7
'@modelcontextprotocol/server@2.3.1':
dependencies:
'@modelcontextprotocol/core': 2.3.1
- zod: 4.6.5
+ zod: 4.6.7
'@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4':
optional: true
@@ -10838,14 +10838,16 @@ snapshots:
'@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4':
optional: true
- '@mswjs/interceptors@0.41.9':
+ '@mswjs/interceptors@0.44.0(supports-color@11.0.0)':
dependencies:
- '@open-draft/deferred-promise': 2.2.0
- '@open-draft/logger': 0.3.0
- '@open-draft/until': 2.1.0
+ '@open-draft/until': 3.0.1
+ '@types/debug': 4.1.13
+ debug: 4.4.3(supports-color@11.0.0)
is-node-process: 1.2.0
outvariant: 1.4.3
- strict-event-emitter: 0.5.1
+ rettime: 0.11.12
+ transitivePeerDependencies:
+ - supports-color
'@napi-rs/lzma-linux-x64-gnu@1.5.1':
optional: true
@@ -11018,11 +11020,6 @@ snapshots:
'@octokit/core': 7.0.8
'@octokit/types': 16.0.0
- '@octokit/plugin-paginate-rest@15.0.0(@octokit/core@7.0.8)':
- dependencies:
- '@octokit/core': 7.0.8
- '@octokit/types': 17.0.0
-
'@octokit/plugin-request-log@6.0.0(@octokit/core@7.0.8)':
dependencies:
'@octokit/core': 7.0.8
@@ -11069,90 +11066,81 @@ snapshots:
dependencies:
'@octokit/openapi-types': 29.0.1
- '@open-draft/deferred-promise@2.2.0': {}
-
- '@open-draft/logger@0.3.0':
- dependencies:
- is-node-process: 1.2.0
- outvariant: 1.4.3
-
- '@open-draft/until@2.1.0': {}
+ '@open-draft/until@3.0.1': {}
'@opentelemetry/api@1.9.1': {}
- '@opentelemetry/context-async-hooks@2.11.0(@opentelemetry/api@1.9.1)':
+ '@opentelemetry/context-async-hooks@2.12.0(@opentelemetry/api@1.9.1)':
dependencies:
'@opentelemetry/api': 1.9.1
- '@opentelemetry/core@2.11.0(@opentelemetry/api@1.9.1)':
+ '@opentelemetry/core@2.12.0(@opentelemetry/api@1.9.1)':
dependencies:
'@opentelemetry/api': 1.9.1
'@opentelemetry/semantic-conventions': 1.43.0
'@opentelemetry/semantic-conventions@1.43.0': {}
- '@oxc-parser/binding-android-arm-eabi@0.153.0':
+ '@oxc-parser/binding-android-arm-eabi@0.154.0':
optional: true
- '@oxc-parser/binding-android-arm64@0.153.0':
+ '@oxc-parser/binding-android-arm64@0.154.0':
optional: true
- '@oxc-parser/binding-darwin-arm64@0.153.0':
+ '@oxc-parser/binding-darwin-arm64@0.154.0':
optional: true
- '@oxc-parser/binding-darwin-x64@0.153.0':
+ '@oxc-parser/binding-darwin-x64@0.154.0':
optional: true
- '@oxc-parser/binding-freebsd-x64@0.153.0':
+ '@oxc-parser/binding-freebsd-x64@0.154.0':
optional: true
- '@oxc-parser/binding-linux-arm-gnueabihf@0.153.0':
+ '@oxc-parser/binding-linux-arm-gnueabihf@0.154.0':
optional: true
- '@oxc-parser/binding-linux-arm-musleabihf@0.153.0':
+ '@oxc-parser/binding-linux-arm-musleabihf@0.154.0':
optional: true
- '@oxc-parser/binding-linux-arm64-gnu@0.153.0':
+ '@oxc-parser/binding-linux-arm64-gnu@0.154.0':
optional: true
- '@oxc-parser/binding-linux-arm64-musl@0.153.0':
+ '@oxc-parser/binding-linux-arm64-musl@0.154.0':
optional: true
- '@oxc-parser/binding-linux-ppc64-gnu@0.153.0':
+ '@oxc-parser/binding-linux-ppc64-gnu@0.154.0':
optional: true
- '@oxc-parser/binding-linux-riscv64-gnu@0.153.0':
+ '@oxc-parser/binding-linux-riscv64-gnu@0.154.0':
optional: true
- '@oxc-parser/binding-linux-riscv64-musl@0.153.0':
+ '@oxc-parser/binding-linux-riscv64-musl@0.154.0':
optional: true
- '@oxc-parser/binding-linux-s390x-gnu@0.153.0':
+ '@oxc-parser/binding-linux-s390x-gnu@0.154.0':
optional: true
- '@oxc-parser/binding-linux-x64-gnu@0.153.0':
+ '@oxc-parser/binding-linux-x64-gnu@0.154.0':
optional: true
- '@oxc-parser/binding-linux-x64-musl@0.153.0':
+ '@oxc-parser/binding-linux-x64-musl@0.154.0':
optional: true
- '@oxc-parser/binding-openharmony-arm64@0.153.0':
+ '@oxc-parser/binding-openharmony-arm64@0.154.0':
optional: true
- '@oxc-parser/binding-win32-arm64-msvc@0.153.0':
+ '@oxc-parser/binding-win32-arm64-msvc@0.154.0':
optional: true
- '@oxc-parser/binding-win32-ia32-msvc@0.153.0':
+ '@oxc-parser/binding-win32-ia32-msvc@0.154.0':
optional: true
- '@oxc-parser/binding-win32-x64-msvc@0.153.0':
+ '@oxc-parser/binding-win32-x64-msvc@0.154.0':
optional: true
- '@oxc-project/types@0.151.0': {}
-
'@oxc-project/types@0.152.0': {}
- '@oxc-project/types@0.153.0': {}
+ '@oxc-project/types@0.154.0': {}
'@parcel/watcher-android-arm64@2.6.0':
optional: true
@@ -11329,106 +11317,106 @@ snapshots:
'@protobufjs/utf8@1.1.2': {}
- '@puppeteer/browsers@3.2.3':
+ '@puppeteer/browsers@3.2.5':
dependencies:
modern-tar: 0.8.5
yargs: 18.2.0
- '@rolldown/binding-android-arm-eabi@1.2.11':
- optional: true
-
'@rolldown/binding-android-arm-eabi@1.2.12':
optional: true
- '@rolldown/binding-android-arm64@1.2.11':
+ '@rolldown/binding-android-arm-eabi@1.2.14':
optional: true
'@rolldown/binding-android-arm64@1.2.12':
optional: true
- '@rolldown/binding-darwin-arm64@1.2.11':
+ '@rolldown/binding-android-arm64@1.2.14':
optional: true
'@rolldown/binding-darwin-arm64@1.2.12':
optional: true
- '@rolldown/binding-darwin-x64@1.2.11':
+ '@rolldown/binding-darwin-arm64@1.2.14':
optional: true
'@rolldown/binding-darwin-x64@1.2.12':
optional: true
- '@rolldown/binding-freebsd-x64@1.2.11':
+ '@rolldown/binding-darwin-x64@1.2.14':
optional: true
'@rolldown/binding-freebsd-x64@1.2.12':
optional: true
- '@rolldown/binding-linux-arm-gnueabihf@1.2.11':
+ '@rolldown/binding-freebsd-x64@1.2.14':
optional: true
'@rolldown/binding-linux-arm-gnueabihf@1.2.12':
optional: true
- '@rolldown/binding-linux-arm64-gnu@1.2.11':
+ '@rolldown/binding-linux-arm-gnueabihf@1.2.14':
optional: true
'@rolldown/binding-linux-arm64-gnu@1.2.12':
optional: true
- '@rolldown/binding-linux-arm64-musl@1.2.11':
+ '@rolldown/binding-linux-arm64-gnu@1.2.14':
optional: true
'@rolldown/binding-linux-arm64-musl@1.2.12':
optional: true
- '@rolldown/binding-linux-ppc64-gnu@1.2.11':
+ '@rolldown/binding-linux-arm64-musl@1.2.14':
optional: true
'@rolldown/binding-linux-ppc64-gnu@1.2.12':
optional: true
- '@rolldown/binding-linux-s390x-gnu@1.2.11':
+ '@rolldown/binding-linux-ppc64-gnu@1.2.14':
optional: true
'@rolldown/binding-linux-s390x-gnu@1.2.12':
optional: true
- '@rolldown/binding-linux-x64-gnu@1.2.11':
+ '@rolldown/binding-linux-s390x-gnu@1.2.14':
optional: true
'@rolldown/binding-linux-x64-gnu@1.2.12':
optional: true
- '@rolldown/binding-linux-x64-musl@1.2.11':
+ '@rolldown/binding-linux-x64-gnu@1.2.14':
optional: true
'@rolldown/binding-linux-x64-musl@1.2.12':
optional: true
- '@rolldown/binding-openharmony-arm64@1.2.11':
+ '@rolldown/binding-linux-x64-musl@1.2.14':
optional: true
'@rolldown/binding-openharmony-arm64@1.2.12':
optional: true
- '@rolldown/binding-win32-arm64-msvc@1.2.11':
+ '@rolldown/binding-openharmony-arm64@1.2.14':
optional: true
'@rolldown/binding-win32-arm64-msvc@1.2.12':
optional: true
- '@rolldown/binding-win32-x64-msvc@1.2.11':
+ '@rolldown/binding-win32-arm64-msvc@1.2.14':
optional: true
'@rolldown/binding-win32-x64-msvc@1.2.12':
optional: true
+ '@rolldown/binding-win32-x64-msvc@1.2.14':
+ optional: true
+
'@rolldown/pluginutils@1.0.1': {}
- '@rollup/plugin-commonjs@29.0.3(rollup@4.64.1)':
+ '@rollup/plugin-commonjs@29.0.3(rollup@4.64.6)':
dependencies:
- '@rollup/pluginutils': 5.4.0(rollup@4.64.1)
+ '@rollup/pluginutils': 5.4.0(rollup@4.64.6)
commondir: 1.0.1
estree-walker: 2.0.2
fdir: 6.5.0(picomatch@4.0.7)
@@ -11436,108 +11424,108 @@ snapshots:
magic-string: 0.30.21
picomatch: 4.0.7
optionalDependencies:
- rollup: 4.64.1
+ rollup: 4.64.6
- '@rollup/plugin-json@6.1.0(rollup@4.64.1)':
+ '@rollup/plugin-json@6.1.0(rollup@4.64.6)':
dependencies:
- '@rollup/pluginutils': 5.4.0(rollup@4.64.1)
+ '@rollup/pluginutils': 5.4.0(rollup@4.64.6)
optionalDependencies:
- rollup: 4.64.1
+ rollup: 4.64.6
- '@rollup/plugin-node-resolve@16.0.3(rollup@4.64.1)':
+ '@rollup/plugin-node-resolve@16.0.3(rollup@4.64.6)':
dependencies:
- '@rollup/pluginutils': 5.4.0(rollup@4.64.1)
+ '@rollup/pluginutils': 5.4.0(rollup@4.64.6)
'@types/resolve': 1.20.2
deepmerge: 4.3.1
is-module: 1.0.0
- resolve: 1.22.12
+ resolve: 1.22.13
optionalDependencies:
- rollup: 4.64.1
+ rollup: 4.64.6
- '@rollup/pluginutils@5.4.0(rollup@4.64.1)':
+ '@rollup/pluginutils@5.4.0(rollup@4.64.6)':
dependencies:
'@types/estree': 1.0.9
estree-walker: 2.0.2
picomatch: 4.0.7
optionalDependencies:
- rollup: 4.64.1
+ rollup: 4.64.6
- '@rollup/rollup-android-arm-eabi@4.64.1':
+ '@rollup/rollup-android-arm-eabi@4.64.6':
optional: true
- '@rollup/rollup-android-arm64@4.64.1':
+ '@rollup/rollup-android-arm64@4.64.6':
optional: true
- '@rollup/rollup-darwin-arm64@4.64.1':
+ '@rollup/rollup-darwin-arm64@4.64.6':
optional: true
- '@rollup/rollup-darwin-x64@4.64.1':
+ '@rollup/rollup-darwin-x64@4.64.6':
optional: true
- '@rollup/rollup-freebsd-arm64@4.64.1':
+ '@rollup/rollup-freebsd-arm64@4.64.6':
optional: true
- '@rollup/rollup-freebsd-x64@4.64.1':
+ '@rollup/rollup-freebsd-x64@4.64.6':
optional: true
- '@rollup/rollup-linux-arm-gnueabihf@4.64.1':
+ '@rollup/rollup-linux-arm-gnueabihf@4.64.6':
optional: true
- '@rollup/rollup-linux-arm-musleabihf@4.64.1':
+ '@rollup/rollup-linux-arm-musleabihf@4.64.6':
optional: true
- '@rollup/rollup-linux-arm64-gnu@4.64.1':
+ '@rollup/rollup-linux-arm64-gnu@4.64.6':
optional: true
- '@rollup/rollup-linux-arm64-musl@4.64.1':
+ '@rollup/rollup-linux-arm64-musl@4.64.6':
optional: true
- '@rollup/rollup-linux-loong64-gnu@4.64.1':
+ '@rollup/rollup-linux-loong64-gnu@4.64.6':
optional: true
- '@rollup/rollup-linux-loong64-musl@4.64.1':
+ '@rollup/rollup-linux-loong64-musl@4.64.6':
optional: true
- '@rollup/rollup-linux-ppc64-gnu@4.64.1':
+ '@rollup/rollup-linux-ppc64-gnu@4.64.6':
optional: true
- '@rollup/rollup-linux-ppc64-musl@4.64.1':
+ '@rollup/rollup-linux-ppc64-musl@4.64.6':
optional: true
- '@rollup/rollup-linux-riscv64-gnu@4.64.1':
+ '@rollup/rollup-linux-riscv64-gnu@4.64.6':
optional: true
- '@rollup/rollup-linux-riscv64-musl@4.64.1':
+ '@rollup/rollup-linux-riscv64-musl@4.64.6':
optional: true
- '@rollup/rollup-linux-s390x-gnu@4.64.1':
+ '@rollup/rollup-linux-s390x-gnu@4.64.6':
optional: true
- '@rollup/rollup-linux-x64-gnu@4.64.1':
+ '@rollup/rollup-linux-x64-gnu@4.64.6':
optional: true
- '@rollup/rollup-linux-x64-musl@4.64.1':
+ '@rollup/rollup-linux-x64-musl@4.64.6':
optional: true
- '@rollup/rollup-openbsd-x64@4.64.1':
+ '@rollup/rollup-openbsd-x64@4.64.6':
optional: true
- '@rollup/rollup-openharmony-arm64@4.64.1':
+ '@rollup/rollup-openharmony-arm64@4.64.6':
optional: true
- '@rollup/rollup-win32-arm64-msvc@4.64.1':
+ '@rollup/rollup-win32-arm64-msvc@4.64.6':
optional: true
- '@rollup/rollup-win32-ia32-msvc@4.64.1':
+ '@rollup/rollup-win32-ia32-msvc@4.64.6':
optional: true
- '@rollup/rollup-win32-x64-gnu@4.64.1':
+ '@rollup/rollup-win32-x64-gnu@4.64.6':
optional: true
- '@rollup/rollup-win32-x64-msvc@4.64.1':
+ '@rollup/rollup-win32-x64-msvc@4.64.6':
optional: true
- '@rollup/wasm-node@4.64.1':
+ '@rollup/wasm-node@4.64.6':
dependencies:
'@types/estree': 1.0.9
optionalDependencies:
@@ -11563,7 +11551,7 @@ snapshots:
'@stylistic/eslint-plugin@5.10.0(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))':
dependencies:
'@eslint-community/eslint-utils': 4.10.1(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))
- '@typescript-eslint/types': 8.71.0
+ '@typescript-eslint/types': 8.71.1
eslint: 10.12.0(jiti@2.7.0)(supports-color@11.0.0)
eslint-visitor-keys: 4.2.1
espree: 10.4.0
@@ -11635,6 +11623,10 @@ snapshots:
dependencies:
'@types/node': 22.20.5
+ '@types/debug@4.1.13':
+ dependencies:
+ '@types/ms': 2.1.0
+
'@types/deep-eql@4.0.2': {}
'@types/duplexify@3.6.5':
@@ -11698,7 +11690,7 @@ snapshots:
'@types/loader-utils@3.0.0(esbuild@0.28.2)(lightningcss@1.33.0)(uglify-js@3.19.3)':
dependencies:
'@types/node': 22.20.5
- webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)
+ webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)
transitivePeerDependencies:
- '@minify-html/node'
- '@napi-rs/image'
@@ -11718,17 +11710,19 @@ snapshots:
- uglify-js
- webpack-cli
- '@types/lodash@4.17.25': {}
+ '@types/lodash@4.17.26': {}
'@types/micromatch@2.3.35':
dependencies:
'@types/parse-glob': 3.0.32
+ '@types/ms@2.1.0': {}
+
'@types/node@22.20.5':
dependencies:
undici-types: 6.21.0
- '@types/node@24.19.0':
+ '@types/node@24.19.2':
dependencies:
undici-types: 7.24.6
@@ -11797,14 +11791,14 @@ snapshots:
'@types/yarnpkg__lockfile@1.1.9': {}
- '@typescript-eslint/eslint-plugin@8.71.1(@typescript-eslint/parser@8.71.1(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3)':
+ '@typescript-eslint/eslint-plugin@8.71.2(@typescript-eslint/parser@8.71.2(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3))(eslint@10.12.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.71.1(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3)
- '@typescript-eslint/scope-manager': 8.71.1
- '@typescript-eslint/type-utils': 8.71.1(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3)
- '@typescript-eslint/utils': 8.71.1(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3)
- '@typescript-eslint/visitor-keys': 8.71.1
+ '@typescript-eslint/parser': 8.71.2(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3)
+ '@typescript-eslint/scope-manager': 8.71.2
+ '@typescript-eslint/type-utils': 8.71.2(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3)
+ '@typescript-eslint/utils': 8.71.2(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3)
+ '@typescript-eslint/visitor-keys': 8.71.2
eslint: 10.12.0(jiti@2.7.0)(supports-color@11.0.0)
ignore: 7.0.12
natural-compare: 1.4.0
@@ -11813,41 +11807,41 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@8.71.1(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3)':
+ '@typescript-eslint/parser@8.71.2(eslint@10.12.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.71.1
- '@typescript-eslint/types': 8.71.1
- '@typescript-eslint/typescript-estree': 8.71.1(supports-color@11.0.0)(typescript@6.0.3)
- '@typescript-eslint/visitor-keys': 8.71.1
+ '@typescript-eslint/scope-manager': 8.71.2
+ '@typescript-eslint/types': 8.71.2
+ '@typescript-eslint/typescript-estree': 8.71.2(supports-color@11.0.0)(typescript@6.0.3)
+ '@typescript-eslint/visitor-keys': 8.71.2
debug: 4.4.3(supports-color@11.0.0)
eslint: 10.12.0(jiti@2.7.0)(supports-color@11.0.0)
typescript: 6.0.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/project-service@8.71.1(supports-color@11.0.0)(typescript@6.0.3)':
+ '@typescript-eslint/project-service@8.71.2(supports-color@11.0.0)(typescript@6.0.3)':
dependencies:
- '@typescript-eslint/tsconfig-utils': 8.71.1(typescript@6.0.3)
- '@typescript-eslint/types': 8.71.1
+ '@typescript-eslint/tsconfig-utils': 8.71.2(typescript@6.0.3)
+ '@typescript-eslint/types': 8.71.2
debug: 4.4.3(supports-color@11.0.0)
typescript: 6.0.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/scope-manager@8.71.1':
+ '@typescript-eslint/scope-manager@8.71.2':
dependencies:
- '@typescript-eslint/types': 8.71.1
- '@typescript-eslint/visitor-keys': 8.71.1
+ '@typescript-eslint/types': 8.71.2
+ '@typescript-eslint/visitor-keys': 8.71.2
- '@typescript-eslint/tsconfig-utils@8.71.1(typescript@6.0.3)':
+ '@typescript-eslint/tsconfig-utils@8.71.2(typescript@6.0.3)':
dependencies:
typescript: 6.0.3
- '@typescript-eslint/type-utils@8.71.1(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3)':
+ '@typescript-eslint/type-utils@8.71.2(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3)':
dependencies:
- '@typescript-eslint/types': 8.71.1
- '@typescript-eslint/typescript-estree': 8.71.1(supports-color@11.0.0)(typescript@6.0.3)
- '@typescript-eslint/utils': 8.71.1(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3)
+ '@typescript-eslint/types': 8.71.2
+ '@typescript-eslint/typescript-estree': 8.71.2(supports-color@11.0.0)(typescript@6.0.3)
+ '@typescript-eslint/utils': 8.71.2(eslint@10.12.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.12.0(jiti@2.7.0)(supports-color@11.0.0)
ts-api-utils: 2.5.0(typescript@6.0.3)
@@ -11855,16 +11849,16 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/types@8.71.0': {}
-
'@typescript-eslint/types@8.71.1': {}
- '@typescript-eslint/typescript-estree@8.71.1(supports-color@11.0.0)(typescript@6.0.3)':
+ '@typescript-eslint/types@8.71.2': {}
+
+ '@typescript-eslint/typescript-estree@8.71.2(supports-color@11.0.0)(typescript@6.0.3)':
dependencies:
- '@typescript-eslint/project-service': 8.71.1(supports-color@11.0.0)(typescript@6.0.3)
- '@typescript-eslint/tsconfig-utils': 8.71.1(typescript@6.0.3)
- '@typescript-eslint/types': 8.71.1
- '@typescript-eslint/visitor-keys': 8.71.1
+ '@typescript-eslint/project-service': 8.71.2(supports-color@11.0.0)(typescript@6.0.3)
+ '@typescript-eslint/tsconfig-utils': 8.71.2(typescript@6.0.3)
+ '@typescript-eslint/types': 8.71.2
+ '@typescript-eslint/visitor-keys': 8.71.2
debug: 4.4.3(supports-color@11.0.0)
minimatch: 10.2.6
semver: 7.8.5
@@ -11874,20 +11868,20 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@8.71.1(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3)':
+ '@typescript-eslint/utils@8.71.2(eslint@10.12.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.12.0(jiti@2.7.0)(supports-color@11.0.0))
- '@typescript-eslint/scope-manager': 8.71.1
- '@typescript-eslint/types': 8.71.1
- '@typescript-eslint/typescript-estree': 8.71.1(supports-color@11.0.0)(typescript@6.0.3)
+ '@typescript-eslint/scope-manager': 8.71.2
+ '@typescript-eslint/types': 8.71.2
+ '@typescript-eslint/typescript-estree': 8.71.2(supports-color@11.0.0)(typescript@6.0.3)
eslint: 10.12.0(jiti@2.7.0)(supports-color@11.0.0)
typescript: 6.0.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/visitor-keys@8.71.1':
+ '@typescript-eslint/visitor-keys@8.71.2':
dependencies:
- '@typescript-eslint/types': 8.71.1
+ '@typescript-eslint/types': 8.71.2
eslint-visitor-keys: 5.0.1
'@verdaccio/auth@8.1.5(supports-color@11.0.0)':
@@ -11921,6 +11915,16 @@ snapshots:
process-warning: 1.0.0
semver: 7.8.5
+ '@verdaccio/core@8.3.3':
+ dependencies:
+ ajv: 8.20.0
+ http-errors: 2.0.1
+ http-status-codes: 2.3.0
+ lodash: 4.18.1
+ minimatch: 10.2.6
+ process-warning: 1.0.0
+ semver: 7.8.5
+
'@verdaccio/file-locking@13.1.0':
dependencies:
lockfile: 1.0.4
@@ -12048,21 +12052,21 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@vitejs/plugin-basic-ssl@2.3.0(vite@8.3.3(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1))':
+ '@vitejs/plugin-basic-ssl@2.3.0(vite@8.3.4(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1))':
dependencies:
- vite: 8.3.3(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1)
+ vite: 8.3.4(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1)
- '@vitest/coverage-v8@5.0.3(vitest@5.0.3)':
+ '@vitest/coverage-v8@5.0.4(vitest@5.0.4)':
dependencies:
'@bcoe/v8-coverage': 1.0.2
'@vitest/istanbul-lib-coverage': 1.0.2
'@vitest/istanbul-lib-report': 1.0.2
ast-v8-to-istanbul: 1.0.7
magicast: 0.5.5
- obug: 2.2.1
+ obug: 3.0.0
std-env: 4.3.0
tinyrainbow: 3.2.0
- vitest: 5.0.3(@opentelemetry/api@1.9.1)(@types/node@22.20.5)(@vitest/coverage-v8@5.0.3)(jsdom@30.1.2(@noble/hashes@1.8.0))(vite@8.3.3(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1))
+ vitest: 5.0.4(@opentelemetry/api@1.9.1)(@types/node@22.20.5)(@vitest/coverage-v8@5.0.4)(jsdom@30.1.2(@noble/hashes@1.8.0))(vite@8.3.4(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1))
'@vitest/istanbul-lib-coverage@1.0.2': {}
@@ -12070,16 +12074,16 @@ snapshots:
dependencies:
'@vitest/istanbul-lib-coverage': 1.0.2
- '@vitest/mocker@5.0.3(vite@8.3.3(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1))':
+ '@vitest/mocker@5.0.4(vite@8.3.4(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1))':
dependencies:
'@jridgewell/trace-mapping': 0.3.31
- '@vitest/spy': 5.0.3
+ '@vitest/spy': 5.0.4
estree-walker: 3.0.3
- magic-string: 1.4.2
+ magic-string: 1.4.3
optionalDependencies:
- vite: 8.3.3(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1)
+ vite: 8.3.4(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1)
- '@vitest/spy@5.0.3': {}
+ '@vitest/spy@5.0.4': {}
'@webassemblyjs/ast@1.14.1':
dependencies:
@@ -12201,6 +12205,42 @@ snapshots:
'@yuku-codegen/binding-win32-x64@0.10.2':
optional: true
+ '@yuku-core/binding-android-arm64@0.19.0':
+ optional: true
+
+ '@yuku-core/binding-darwin-arm64@0.19.0':
+ optional: true
+
+ '@yuku-core/binding-darwin-x64@0.19.0':
+ optional: true
+
+ '@yuku-core/binding-freebsd-x64@0.19.0':
+ optional: true
+
+ '@yuku-core/binding-linux-arm-gnu@0.19.0':
+ optional: true
+
+ '@yuku-core/binding-linux-arm-musl@0.19.0':
+ optional: true
+
+ '@yuku-core/binding-linux-arm64-gnu@0.19.0':
+ optional: true
+
+ '@yuku-core/binding-linux-arm64-musl@0.19.0':
+ optional: true
+
+ '@yuku-core/binding-linux-x64-gnu@0.19.0':
+ optional: true
+
+ '@yuku-core/binding-linux-x64-musl@0.19.0':
+ optional: true
+
+ '@yuku-core/binding-win32-arm64@0.19.0':
+ optional: true
+
+ '@yuku-core/binding-win32-x64@0.19.0':
+ optional: true
+
'@yuku-parser/binding-android-arm64@0.10.2':
optional: true
@@ -12239,6 +12279,8 @@ snapshots:
'@yuku-toolchain/types@0.10.2': {}
+ '@yuku-toolchain/types@0.19.0': {}
+
JSONStream@1.3.5:
dependencies:
jsonparse: 1.3.1
@@ -12258,11 +12300,11 @@ snapshots:
mime-types: 3.0.2
negotiator: 1.1.0
- acorn-jsx@5.3.2(acorn@8.18.0):
+ acorn-jsx@5.3.2(acorn@8.19.0):
dependencies:
- acorn: 8.18.0
+ acorn: 8.19.0
- acorn@8.18.0: {}
+ acorn@8.19.0: {}
adjust-sourcemap-loader@4.0.0:
dependencies:
@@ -12425,13 +12467,13 @@ snapshots:
atomic-sleep@1.0.0: {}
- autoprefixer@10.6.1(postcss@8.5.29):
+ autoprefixer@10.6.1(postcss@8.5.30):
dependencies:
browserslist: 4.29.3
- caniuse-lite: 1.0.30001814
+ caniuse-lite: 1.0.30001815
fraction.js: 5.3.4
picocolors: 1.1.1
- postcss: 8.5.29
+ postcss: 8.5.30
postcss-value-parser: 4.2.0
available-typed-arrays@1.0.7:
@@ -12444,12 +12486,12 @@ snapshots:
b4a@1.9.0: {}
- babel-loader@10.1.1(@babel/core@8.0.7)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)):
+ babel-loader@10.1.1(@babel/core@8.0.7)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)):
dependencies:
'@babel/core': 8.0.7
find-up: 5.0.0
optionalDependencies:
- webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)
+ webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)
babel-plugin-polyfill-corejs3@1.0.0(@babel/core@8.0.7):
dependencies:
@@ -12463,7 +12505,7 @@ snapshots:
bare-events@2.9.2: {}
- bare-fs@4.8.2:
+ bare-fs@4.8.4:
dependencies:
bare-events: 2.9.2
bare-path: 3.1.2
@@ -12492,7 +12534,7 @@ snapshots:
base64-js@1.5.1: {}
- baseline-browser-mapping@2.11.27: {}
+ baseline-browser-mapping@2.11.28: {}
batch@0.6.1: {}
@@ -12502,7 +12544,7 @@ snapshots:
bcryptjs@2.4.3: {}
- beasties@0.5.4:
+ beasties@0.5.5:
dependencies:
css-select: 7.0.0
css-what: 8.0.0
@@ -12510,9 +12552,9 @@ snapshots:
domhandler: 6.0.1
htmlparser2: 12.0.0
picocolors: 1.1.1
- postcss: 8.5.29
+ postcss: 8.5.30
postcss-media-query-parser: 0.2.3
- postcss-safe-parser: 7.1.0(postcss@8.5.29)
+ postcss-safe-parser: 7.1.0(postcss@8.5.30)
before-after-hook@4.0.0: {}
@@ -12647,11 +12689,11 @@ snapshots:
browserslist@4.29.3:
dependencies:
- baseline-browser-mapping: 2.11.27
- caniuse-lite: 1.0.30001814
- electron-to-chromium: 1.5.444
- node-releases: 2.0.57
- update-browserslist-db: 1.3.3(browserslist@4.29.3)
+ baseline-browser-mapping: 2.11.28
+ caniuse-lite: 1.0.30001815
+ electron-to-chromium: 1.5.452
+ node-releases: 2.0.58
+ update-browserslist-db: 1.3.4(browserslist@4.29.3)
bs-recipes@1.3.4: {}
@@ -12717,7 +12759,7 @@ snapshots:
callsites@3.1.0: {}
- caniuse-lite@1.0.30001814: {}
+ caniuse-lite@1.0.30001815: {}
caseless@0.12.0: {}
@@ -12758,11 +12800,11 @@ snapshots:
chrome-trace-event@1.0.4: {}
- chromium-bidi@17.0.2(devtools-protocol@0.0.1687809):
+ chromium-bidi@157.0.8090-0(devtools-protocol@0.0.1696802):
dependencies:
- devtools-protocol: 0.0.1687809
+ devtools-protocol: 0.0.1696802
mitt: 3.0.1
- zod: 3.25.76
+ zod: 4.6.7
chunk-data@0.1.0: {}
@@ -12896,6 +12938,8 @@ snapshots:
content-disposition@1.1.0: {}
+ content-disposition@2.0.1: {}
+
content-type@1.0.5: {}
content-type@2.1.0: {}
@@ -12904,7 +12948,7 @@ snapshots:
conventional-commits-filter@6.0.1: {}
- conventional-commits-parser@7.1.2:
+ conventional-commits-parser@7.1.3:
dependencies:
'@simple-libs/stream-utils': 2.0.0
argue-cli: 3.2.0
@@ -12923,14 +12967,14 @@ snapshots:
dependencies:
is-what: 4.1.16
- copy-webpack-plugin@14.0.0(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)):
+ copy-webpack-plugin@14.0.0(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)):
dependencies:
glob-parent: 6.0.2
normalize-path: 3.0.0
schema-utils: 4.5.0
serialize-javascript: 7.1.2
tinyglobby: 0.2.17
- webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)
+ webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)
core-js-compat@3.50.0:
dependencies:
@@ -12960,18 +13004,18 @@ snapshots:
shebang-command: 2.0.0
which: 2.0.2
- css-loader@7.1.5(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)):
+ css-loader@7.1.5(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)):
dependencies:
- icss-utils: 5.1.0(postcss@8.5.29)
- postcss: 8.5.29
- postcss-modules-extract-imports: 3.1.0(postcss@8.5.29)
- postcss-modules-local-by-default: 4.2.0(postcss@8.5.29)
- postcss-modules-scope: 3.2.1(postcss@8.5.29)
- postcss-modules-values: 4.0.0(postcss@8.5.29)
+ icss-utils: 5.1.0(postcss@8.5.30)
+ postcss: 8.5.30
+ postcss-modules-extract-imports: 3.1.0(postcss@8.5.30)
+ postcss-modules-local-by-default: 4.2.0(postcss@8.5.30)
+ postcss-modules-scope: 3.2.1(postcss@8.5.30)
+ postcss-modules-values: 4.0.0(postcss@8.5.30)
postcss-value-parser: 4.2.0
semver: 7.8.5
optionalDependencies:
- webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)
+ webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)
css-select@7.0.0:
dependencies:
@@ -13039,12 +13083,6 @@ snapshots:
optionalDependencies:
supports-color: 11.0.0
- debug@4.4.0(supports-color@11.0.0):
- dependencies:
- ms: 2.1.3
- optionalDependencies:
- supports-color: 11.0.0
-
debug@4.4.3(supports-color@11.0.0):
dependencies:
ms: 2.1.3
@@ -13096,7 +13134,7 @@ snapshots:
dev-ip@1.0.1: {}
- devtools-protocol@0.0.1687809: {}
+ devtools-protocol@0.0.1696802: {}
di@0.0.1: {}
@@ -13182,7 +13220,7 @@ snapshots:
ejs@7.0.1: {}
- electron-to-chromium@1.5.444: {}
+ electron-to-chromium@1.5.452: {}
emoji-regex@10.6.0: {}
@@ -13408,17 +13446,17 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.14.0(@typescript-eslint/parser@8.71.1(eslint@10.12.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.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0):
+ eslint-module-utils@2.14.0(@typescript-eslint/parser@8.71.2(eslint@10.12.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.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0):
dependencies:
debug: 3.2.7(supports-color@11.0.0)
optionalDependencies:
- '@typescript-eslint/parser': 8.71.1(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3)
+ '@typescript-eslint/parser': 8.71.2(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3)
eslint: 10.12.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.71.1(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0):
+ eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.71.2(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.2.0
@@ -13429,7 +13467,7 @@ snapshots:
doctrine: 2.1.0
eslint: 10.12.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.71.1(eslint@10.12.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.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)
+ eslint-module-utils: 2.14.0(@typescript-eslint/parser@8.71.2(eslint@10.12.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.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)
hasown: 2.0.4
is-core-module: 2.17.0
is-glob: 4.0.3
@@ -13441,7 +13479,7 @@ snapshots:
string.prototype.trimend: 1.0.10
tsconfig-paths: 3.15.0
optionalDependencies:
- '@typescript-eslint/parser': 8.71.1(eslint@10.12.0(jiti@2.7.0)(supports-color@11.0.0))(supports-color@11.0.0)(typescript@6.0.3)
+ '@typescript-eslint/parser': 8.71.2(eslint@10.12.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
@@ -13499,14 +13537,14 @@ snapshots:
espree@10.4.0:
dependencies:
- acorn: 8.18.0
- acorn-jsx: 5.3.2(acorn@8.18.0)
+ acorn: 8.19.0
+ acorn-jsx: 5.3.2(acorn@8.19.0)
eslint-visitor-keys: 4.2.1
espree@11.2.0:
dependencies:
- acorn: 8.18.0
- acorn-jsx: 5.3.2(acorn@8.18.0)
+ acorn: 8.19.0
+ acorn-jsx: 5.3.2(acorn@8.19.0)
eslint-visitor-keys: 5.0.1
esquery@1.7.0:
@@ -13616,6 +13654,39 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ express@5.3.0(supports-color@11.0.0):
+ dependencies:
+ accepts: 2.0.0
+ body-parser: 2.3.0(supports-color@11.0.0)
+ content-disposition: 2.0.1
+ content-type: 2.1.0
+ cookie: 0.7.2
+ cookie-signature: 1.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@11.0.0)
+ fresh: 2.0.0
+ http-errors: 2.0.1
+ merge-descriptors: 2.0.0
+ mime-types: 3.0.2
+ on-finished: 2.4.1
+ once: 1.4.0
+ parseurl: 1.3.3
+ proxy-addr: 2.0.8
+ qs: 6.16.0
+ range-parser: 1.3.0
+ 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
+ transitivePeerDependencies:
+ - supports-color
+
extend@3.0.2: {}
extsprintf@1.3.0: {}
@@ -13732,35 +13803,35 @@ snapshots:
locate-path: 6.0.0
path-exists: 4.0.0
- firebase@12.19.0:
+ firebase@13.0.0:
dependencies:
- '@firebase/ai': 2.16.0(@firebase/app-types@0.9.6)(@firebase/app@0.16.2)
- '@firebase/analytics': 0.10.25(@firebase/app@0.16.2)
- '@firebase/analytics-compat': 0.2.31(@firebase/app-compat@0.5.18)(@firebase/app@0.16.2)
- '@firebase/app': 0.16.2
- '@firebase/app-check': 0.13.1(@firebase/app@0.16.2)
- '@firebase/app-check-compat': 0.4.7(@firebase/app-compat@0.5.18)(@firebase/app@0.16.2)
- '@firebase/app-compat': 0.5.18
+ '@firebase/ai': 3.0.0(@firebase/app-types@0.9.6)(@firebase/app@0.16.3)
+ '@firebase/analytics': 0.10.25(@firebase/app@0.16.3)
+ '@firebase/analytics-compat': 0.2.31(@firebase/app-compat@0.5.19)(@firebase/app@0.16.3)
+ '@firebase/app': 0.16.3
+ '@firebase/app-check': 0.13.1(@firebase/app@0.16.3)
+ '@firebase/app-check-compat': 0.4.7(@firebase/app-compat@0.5.19)(@firebase/app@0.16.3)
+ '@firebase/app-compat': 0.5.19
'@firebase/app-types': 0.9.6
- '@firebase/auth': 1.13.6(@firebase/app@0.16.2)
- '@firebase/auth-compat': 0.6.11(@firebase/app-compat@0.5.18)(@firebase/app-types@0.9.6)(@firebase/app@0.16.2)
- '@firebase/data-connect': 0.7.4(@firebase/app@0.16.2)
+ '@firebase/auth': 1.13.7(@firebase/app@0.16.3)
+ '@firebase/auth-compat': 0.6.12(@firebase/app-compat@0.5.19)(@firebase/app-types@0.9.6)(@firebase/app@0.16.3)
+ '@firebase/data-connect': 0.7.4(@firebase/app@0.16.3)
'@firebase/database': 1.1.5
- '@firebase/database-compat': 2.1.7(@firebase/app-compat@0.5.18)(@firebase/app@0.16.2)
- '@firebase/firestore': 4.17.2(@firebase/app@0.16.2)
- '@firebase/firestore-compat': 0.4.14(@firebase/app-compat@0.5.18)(@firebase/app-types@0.9.6)(@firebase/app@0.16.2)
- '@firebase/functions': 0.14.0(@firebase/app@0.16.2)
- '@firebase/functions-compat': 0.5.0(@firebase/app-compat@0.5.18)(@firebase/app@0.16.2)
- '@firebase/installations': 0.6.24(@firebase/app@0.16.2)
- '@firebase/installations-compat': 0.2.24(@firebase/app-compat@0.5.18)(@firebase/app-types@0.9.6)(@firebase/app@0.16.2)
- '@firebase/messaging': 0.13.3(@firebase/app@0.16.2)
- '@firebase/messaging-compat': 0.2.30(@firebase/app-compat@0.5.18)(@firebase/app@0.16.2)
- '@firebase/performance': 0.7.14(@firebase/app@0.16.2)
- '@firebase/performance-compat': 0.2.27(@firebase/app-compat@0.5.18)(@firebase/app@0.16.2)
- '@firebase/remote-config': 0.9.2(@firebase/app@0.16.2)
- '@firebase/remote-config-compat': 0.2.29(@firebase/app-compat@0.5.18)(@firebase/app@0.16.2)
- '@firebase/storage': 0.14.5(@firebase/app@0.16.2)
- '@firebase/storage-compat': 0.4.5(@firebase/app-compat@0.5.18)(@firebase/app-types@0.9.6)(@firebase/app@0.16.2)
+ '@firebase/database-compat': 2.1.7(@firebase/app-compat@0.5.19)(@firebase/app@0.16.3)
+ '@firebase/firestore': 4.18.0(@firebase/app@0.16.3)
+ '@firebase/firestore-compat': 0.4.15(@firebase/app-compat@0.5.19)(@firebase/app-types@0.9.6)(@firebase/app@0.16.3)
+ '@firebase/functions': 0.14.0(@firebase/app@0.16.3)
+ '@firebase/functions-compat': 0.5.0(@firebase/app-compat@0.5.19)(@firebase/app@0.16.3)
+ '@firebase/installations': 0.6.24(@firebase/app@0.16.3)
+ '@firebase/installations-compat': 0.2.24(@firebase/app-compat@0.5.19)(@firebase/app-types@0.9.6)(@firebase/app@0.16.3)
+ '@firebase/messaging': 0.13.3(@firebase/app@0.16.3)
+ '@firebase/messaging-compat': 0.2.30(@firebase/app-compat@0.5.19)(@firebase/app@0.16.3)
+ '@firebase/performance': 0.7.14(@firebase/app@0.16.3)
+ '@firebase/performance-compat': 0.2.27(@firebase/app-compat@0.5.19)(@firebase/app@0.16.3)
+ '@firebase/remote-config': 0.9.3(@firebase/app@0.16.3)
+ '@firebase/remote-config-compat': 0.2.30(@firebase/app-compat@0.5.19)(@firebase/app@0.16.3)
+ '@firebase/storage': 0.14.6(@firebase/app@0.16.3)
+ '@firebase/storage-compat': 0.4.6(@firebase/app-compat@0.5.19)(@firebase/app-types@0.9.6)(@firebase/app@0.16.3)
'@firebase/util': 1.15.3
transitivePeerDependencies:
- '@react-native-async-storage/async-storage'
@@ -13777,9 +13848,9 @@ snapshots:
flru@1.0.2: {}
- folder-hash@4.1.3(supports-color@11.0.0):
+ folder-hash@4.1.4(supports-color@11.0.0):
dependencies:
- debug: 4.4.0(supports-color@11.0.0)
+ debug: 4.4.3(supports-color@11.0.0)
minimatch: 7.4.9
transitivePeerDependencies:
- supports-color
@@ -14011,7 +14082,7 @@ snapshots:
google-gax@5.0.8(supports-color@11.0.0):
dependencies:
- '@grpc/grpc-js': 1.14.5
+ '@grpc/grpc-js': 1.14.6
'@grpc/proto-loader': 0.8.1
duplexify: 4.1.3
google-auth-library: 10.5.0(supports-color@11.0.0)
@@ -14055,7 +14126,7 @@ snapshots:
grpc-gcp@1.1.1:
dependencies:
- '@grpc/grpc-js': 1.14.5
+ '@grpc/grpc-js': 1.14.6
protobufjs: 7.6.6
gtoken@8.0.0(supports-color@11.0.0):
@@ -14233,9 +14304,9 @@ snapshots:
dependencies:
safer-buffer: 2.1.2
- icss-utils@5.1.0(postcss@8.5.29):
+ icss-utils@5.1.0(postcss@8.5.30):
dependencies:
- postcss: 8.5.29
+ postcss: 8.5.30
idb@7.1.1: {}
@@ -14567,9 +14638,9 @@ snapshots:
jsdom@30.1.2(@noble/hashes@1.8.0):
dependencies:
- '@asamuzakjp/css-color': 7.1.3
+ '@asamuzakjp/css-color': 7.1.5
'@asamuzakjp/dom-selector': 9.2.4
- '@bramus/specificity': 2.4.2
+ '@bramus/specificity': 2.4.3
'@csstools/css-syntax-patches-for-csstree': 1.1.15(css-tree@3.2.1)
'@exodus/bytes': 1.16.0(@noble/hashes@1.8.0)
css-tree: 3.2.1
@@ -14727,17 +14798,17 @@ snapshots:
kind-of@6.0.3: {}
- launch-editor@2.14.1:
+ launch-editor@2.14.2:
dependencies:
picocolors: 1.1.1
shell-quote: 1.12.0
- less-loader@13.0.0(less@4.9.1(supports-color@11.0.0))(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)):
+ less-loader@13.0.0(less@4.9.1(supports-color@11.0.0))(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)):
dependencies:
'@types/less': 3.0.8
less: 4.9.1(supports-color@11.0.0)
optionalDependencies:
- webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)
+ webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)
less@4.9.1(supports-color@11.0.0):
dependencies:
@@ -14759,11 +14830,11 @@ snapshots:
prelude-ls: 1.2.1
type-check: 0.4.0
- license-webpack-plugin@4.0.2(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)):
+ license-webpack-plugin@4.0.2(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)):
dependencies:
webpack-sources: 3.6.0
optionalDependencies:
- webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)
+ webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)
lightningcss-android-arm64@1.33.0:
optional: true
@@ -14820,7 +14891,7 @@ snapshots:
lines-and-columns@1.2.4: {}
- listr2@11.1.1:
+ listr2@11.2.0:
dependencies:
cli-truncate: 6.1.1
log-update: 8.0.0
@@ -14939,10 +15010,6 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.6.0
- magic-string@1.4.2:
- dependencies:
- '@jridgewell/sourcemap-codec': 1.6.0
-
magic-string@1.4.3:
dependencies:
'@jridgewell/sourcemap-codec': 1.6.0
@@ -15022,11 +15089,11 @@ snapshots:
mimic-response@4.0.0: {}
- mini-css-extract-plugin@2.10.2(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)):
+ mini-css-extract-plugin@2.10.2(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)):
dependencies:
schema-utils: 4.5.0
tapable: 2.3.3
- webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)
+ webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)
minimatch@10.2.6:
dependencies:
@@ -15046,30 +15113,30 @@ snapshots:
minimist@1.2.8: {}
- minimizer-webpack-plugin@5.13.0(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.28)(uglify-js@3.19.3)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.28)(uglify-js@3.19.3)):
+ minimizer-webpack-plugin@5.13.0(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)):
dependencies:
'@jridgewell/trace-mapping': 0.3.31
jest-worker: 27.5.1
schema-utils: 4.5.0
terser: 5.51.2
- webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.28)(uglify-js@3.19.3)
+ webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)
optionalDependencies:
esbuild: 0.28.2
lightningcss: 1.33.0
- postcss: 8.5.28
+ postcss: 8.5.29
uglify-js: 3.19.3
- minimizer-webpack-plugin@5.13.0(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)):
+ minimizer-webpack-plugin@5.13.0(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)):
dependencies:
'@jridgewell/trace-mapping': 0.3.31
jest-worker: 27.5.1
schema-utils: 4.5.0
terser: 5.51.2
- webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)
+ webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)
optionalDependencies:
esbuild: 0.28.2
lightningcss: 1.33.0
- postcss: 8.5.29
+ postcss: 8.5.30
uglify-js: 3.19.3
minipass@7.1.3: {}
@@ -15122,7 +15189,7 @@ snapshots:
mute-stream@3.0.0: {}
- nanoid@3.3.19: {}
+ nanoid@3.3.20: {}
natural-compare@1.4.0: {}
@@ -15151,10 +15218,10 @@ snapshots:
neo-async@2.6.2: {}
- ng-packagr@22.3.0-next.2(@angular/compiler-cli@22.3.0-next.1(@angular/compiler@22.3.0-next.1)(typescript@6.0.3))(supports-color@11.0.0)(tslib@2.8.1)(typescript@6.0.3):
+ ng-packagr@22.3.0-next.2(@angular/compiler-cli@22.3.0-next.2(@angular/compiler@22.3.0-next.2)(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.3.0-next.1(@angular/compiler@22.3.0-next.1)(typescript@6.0.3)
+ '@angular/compiler-cli': 22.3.0-next.2(@angular/compiler@22.3.0-next.2)(typescript@6.0.3)
ajv: 8.20.0
browserslist: 4.29.3
chokidar: 5.0.0
@@ -15166,9 +15233,9 @@ snapshots:
jsonc-parser: 3.3.1
less: 4.9.1(supports-color@11.0.0)
ora: 9.4.1
- postcss: 8.5.28
- rolldown: 1.2.11
- rolldown-plugin-dts: 0.28.6(rolldown@1.2.11)(typescript@6.0.3)
+ postcss: 8.5.29
+ rolldown: 1.2.12
+ rolldown-plugin-dts: 0.28.6(rolldown@1.2.12)(typescript@6.0.3)
rxjs: 7.8.2
sass: 1.105.1
sass-embedded: 1.105.1
@@ -15183,11 +15250,11 @@ snapshots:
- supports-color
- vue-tsc
- nock@14.0.17:
+ nock@15.0.1(supports-color@11.0.0):
dependencies:
- '@mswjs/interceptors': 0.41.9
- json-stringify-safe: 5.0.1
- propagate: 2.0.1
+ '@mswjs/interceptors': 0.44.0(supports-color@11.0.0)
+ transitivePeerDependencies:
+ - supports-color
node-addon-api@6.1.0:
optional: true
@@ -15222,7 +15289,7 @@ snapshots:
node-gyp-build@4.8.4: {}
- node-releases@2.0.57: {}
+ node-releases@2.0.58: {}
normalize-path@3.0.0: {}
@@ -15283,8 +15350,6 @@ snapshots:
define-properties: 1.2.1
es-object-atoms: 1.1.2
- obug@2.2.1: {}
-
obug@3.0.0: {}
on-exit-leak-free@2.1.2: {}
@@ -15352,29 +15417,29 @@ snapshots:
object-keys: 1.1.1
safe-push-apply: 1.0.0
- oxc-parser@0.153.0:
+ oxc-parser@0.154.0:
dependencies:
- '@oxc-project/types': 0.153.0
+ '@oxc-project/types': 0.154.0
optionalDependencies:
- '@oxc-parser/binding-android-arm-eabi': 0.153.0
- '@oxc-parser/binding-android-arm64': 0.153.0
- '@oxc-parser/binding-darwin-arm64': 0.153.0
- '@oxc-parser/binding-darwin-x64': 0.153.0
- '@oxc-parser/binding-freebsd-x64': 0.153.0
- '@oxc-parser/binding-linux-arm-gnueabihf': 0.153.0
- '@oxc-parser/binding-linux-arm-musleabihf': 0.153.0
- '@oxc-parser/binding-linux-arm64-gnu': 0.153.0
- '@oxc-parser/binding-linux-arm64-musl': 0.153.0
- '@oxc-parser/binding-linux-ppc64-gnu': 0.153.0
- '@oxc-parser/binding-linux-riscv64-gnu': 0.153.0
- '@oxc-parser/binding-linux-riscv64-musl': 0.153.0
- '@oxc-parser/binding-linux-s390x-gnu': 0.153.0
- '@oxc-parser/binding-linux-x64-gnu': 0.153.0
- '@oxc-parser/binding-linux-x64-musl': 0.153.0
- '@oxc-parser/binding-openharmony-arm64': 0.153.0
- '@oxc-parser/binding-win32-arm64-msvc': 0.153.0
- '@oxc-parser/binding-win32-ia32-msvc': 0.153.0
- '@oxc-parser/binding-win32-x64-msvc': 0.153.0
+ '@oxc-parser/binding-android-arm-eabi': 0.154.0
+ '@oxc-parser/binding-android-arm64': 0.154.0
+ '@oxc-parser/binding-darwin-arm64': 0.154.0
+ '@oxc-parser/binding-darwin-x64': 0.154.0
+ '@oxc-parser/binding-freebsd-x64': 0.154.0
+ '@oxc-parser/binding-linux-arm-gnueabihf': 0.154.0
+ '@oxc-parser/binding-linux-arm-musleabihf': 0.154.0
+ '@oxc-parser/binding-linux-arm64-gnu': 0.154.0
+ '@oxc-parser/binding-linux-arm64-musl': 0.154.0
+ '@oxc-parser/binding-linux-ppc64-gnu': 0.154.0
+ '@oxc-parser/binding-linux-riscv64-gnu': 0.154.0
+ '@oxc-parser/binding-linux-riscv64-musl': 0.154.0
+ '@oxc-parser/binding-linux-s390x-gnu': 0.154.0
+ '@oxc-parser/binding-linux-x64-gnu': 0.154.0
+ '@oxc-parser/binding-linux-x64-musl': 0.154.0
+ '@oxc-parser/binding-openharmony-arm64': 0.154.0
+ '@oxc-parser/binding-win32-arm64-msvc': 0.154.0
+ '@oxc-parser/binding-win32-ia32-msvc': 0.154.0
+ '@oxc-parser/binding-win32-x64-msvc': 0.154.0
p-finally@1.0.0: {}
@@ -15479,7 +15544,7 @@ snapshots:
pino-abstract-transport@1.2.0:
dependencies:
- readable-stream: 4.7.0
+ readable-stream: 4.8.0
split2: 4.2.0
pino-abstract-transport@2.0.0:
@@ -15495,7 +15560,7 @@ snapshots:
on-exit-leak-free: 2.1.2
pino-abstract-transport: 2.0.0
pino-std-serializers: 7.1.0
- process-warning: 5.1.0
+ process-warning: 5.1.1
quick-format-unescaped: 4.0.4
real-require: 0.2.0
safe-stable-stringify: 2.5.0
@@ -15528,43 +15593,43 @@ snapshots:
possible-typed-array-names@1.1.0: {}
- postcss-loader@8.2.1(postcss@8.5.29)(typescript@6.0.3)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)):
+ postcss-loader@8.2.1(postcss@8.5.30)(typescript@6.0.3)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)):
dependencies:
cosmiconfig: 9.0.2(typescript@6.0.3)
jiti: 2.7.0
- postcss: 8.5.29
+ postcss: 8.5.30
semver: 7.8.5
optionalDependencies:
- webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)
+ webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)
transitivePeerDependencies:
- typescript
postcss-media-query-parser@0.2.3: {}
- postcss-modules-extract-imports@3.1.0(postcss@8.5.29):
+ postcss-modules-extract-imports@3.1.0(postcss@8.5.30):
dependencies:
- postcss: 8.5.29
+ postcss: 8.5.30
- postcss-modules-local-by-default@4.2.0(postcss@8.5.29):
+ postcss-modules-local-by-default@4.2.0(postcss@8.5.30):
dependencies:
- icss-utils: 5.1.0(postcss@8.5.29)
- postcss: 8.5.29
+ icss-utils: 5.1.0(postcss@8.5.30)
+ postcss: 8.5.30
postcss-selector-parser: 7.1.6
postcss-value-parser: 4.2.0
- postcss-modules-scope@3.2.1(postcss@8.5.29):
+ postcss-modules-scope@3.2.1(postcss@8.5.30):
dependencies:
- postcss: 8.5.29
+ postcss: 8.5.30
postcss-selector-parser: 7.1.6
- postcss-modules-values@4.0.0(postcss@8.5.29):
+ postcss-modules-values@4.0.0(postcss@8.5.30):
dependencies:
- icss-utils: 5.1.0(postcss@8.5.29)
- postcss: 8.5.29
+ icss-utils: 5.1.0(postcss@8.5.30)
+ postcss: 8.5.30
- postcss-safe-parser@7.1.0(postcss@8.5.29):
+ postcss-safe-parser@7.1.0(postcss@8.5.30):
dependencies:
- postcss: 8.5.29
+ postcss: 8.5.30
postcss-selector-parser@7.1.6:
dependencies:
@@ -15573,15 +15638,15 @@ snapshots:
postcss-value-parser@4.2.0: {}
- postcss@8.5.28:
+ postcss@8.5.29:
dependencies:
- nanoid: 3.3.19
+ nanoid: 3.3.20
picocolors: 1.1.1
source-map-js: 1.2.2
- postcss@8.5.29:
+ postcss@8.5.30:
dependencies:
- nanoid: 3.3.19
+ nanoid: 3.3.20
picocolors: 1.1.1
source-map-js: 1.2.2
@@ -15589,7 +15654,7 @@ snapshots:
prelude-ls@1.2.1: {}
- prettier@3.9.9: {}
+ prettier@3.9.10: {}
probe-image-size@7.4.0(supports-color@11.0.0):
dependencies:
@@ -15606,12 +15671,10 @@ snapshots:
process-warning@1.0.0: {}
- process-warning@5.1.0: {}
+ process-warning@5.1.1: {}
process@0.11.10: {}
- propagate@2.0.1: {}
-
proto3-json-serializer@3.0.4:
dependencies:
protobufjs: 7.6.6
@@ -15655,13 +15718,13 @@ snapshots:
punycode@2.3.1: {}
- puppeteer-core@25.12.0(bufferutil@4.1.0)(utf-8-validate@6.0.6):
+ puppeteer-core@25.14.0(bufferutil@4.1.0)(utf-8-validate@6.0.6):
dependencies:
- '@puppeteer/browsers': 3.2.3
- chromium-bidi: 17.0.2(devtools-protocol@0.0.1687809)
- devtools-protocol: 0.0.1687809
+ '@puppeteer/browsers': 3.2.5
+ chromium-bidi: 157.0.8090-0(devtools-protocol@0.0.1696802)
+ devtools-protocol: 0.0.1696802
typed-query-selector: 2.12.3
- webdriver-bidi-protocol: 0.4.3
+ webdriver-bidi-protocol: 1.0.1
ws: 8.22.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)
transitivePeerDependencies:
- bufferutil
@@ -15669,13 +15732,13 @@ snapshots:
- utf-8-validate
- yauzl
- puppeteer@25.12.0(bufferutil@4.1.0)(utf-8-validate@6.0.6):
+ puppeteer@25.14.0(bufferutil@4.1.0)(utf-8-validate@6.0.6):
dependencies:
- '@puppeteer/browsers': 3.2.3
- chromium-bidi: 17.0.2(devtools-protocol@0.0.1687809)
- devtools-protocol: 0.0.1687809
+ '@puppeteer/browsers': 3.2.5
+ chromium-bidi: 157.0.8090-0(devtools-protocol@0.0.1696802)
+ devtools-protocol: 0.0.1696802
lilconfig: 3.1.3
- puppeteer-core: 25.12.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)
+ puppeteer-core: 25.14.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)
typed-query-selector: 2.12.3
transitivePeerDependencies:
- bufferutil
@@ -15766,7 +15829,7 @@ snapshots:
process: 0.11.10
string_decoder: 1.3.0
- readable-stream@4.7.0:
+ readable-stream@4.8.0:
dependencies:
abort-controller: 3.0.0
buffer: 6.0.3
@@ -15812,18 +15875,18 @@ snapshots:
gopd: 1.2.0
set-function-name: 2.0.2
- regexpu-core@6.5.2:
+ regexpu-core@6.5.3:
dependencies:
regenerate: 1.5.0
regenerate-unicode-properties: 10.3.0
regjsgen: 0.8.0
- regjsparser: 0.13.3
+ regjsparser: 0.13.4
unicode-match-property-ecmascript: 2.0.0
unicode-match-property-value-ecmascript: 2.2.1
regjsgen@0.8.0: {}
- regjsparser@0.13.3:
+ regjsparser@0.13.4:
dependencies:
jsesc: 3.1.0
@@ -15844,10 +15907,10 @@ snapshots:
adjust-sourcemap-loader: 4.0.0
convert-source-map: 1.9.0
loader-utils: 2.0.4
- postcss: 8.5.29
+ postcss: 8.5.30
source-map: 0.6.1
- resolve@1.22.12:
+ resolve@1.22.13:
dependencies:
es-errors: 1.3.0
is-core-module: 2.17.0
@@ -15888,6 +15951,8 @@ snapshots:
retry@0.13.1: {}
+ rettime@0.11.12: {}
+
reusify@1.1.0: {}
rfdc@1.4.1: {}
@@ -15900,12 +15965,12 @@ snapshots:
dependencies:
glob: 10.5.0
- rolldown-plugin-dts@0.28.6(rolldown@1.2.11)(typescript@6.0.3):
+ rolldown-plugin-dts@0.28.6(rolldown@1.2.12)(typescript@6.0.3):
dependencies:
dts-resolver: 3.0.0
get-tsconfig: 5.0.0-beta.6
obug: 3.0.0
- rolldown: 1.2.11
+ rolldown: 1.2.12
yuku-ast: 0.10.2
yuku-codegen: 0.10.2
yuku-parser: 0.10.2
@@ -15914,41 +15979,20 @@ snapshots:
transitivePeerDependencies:
- oxc-resolver
- rolldown-plugin-dts@0.28.6(rolldown@1.2.12)(typescript@6.0.3):
+ rolldown-plugin-dts@0.28.8(rolldown@1.2.14)(typescript@6.0.3):
dependencies:
dts-resolver: 3.0.0
get-tsconfig: 5.0.0-beta.6
obug: 3.0.0
- rolldown: 1.2.12
- yuku-ast: 0.10.2
- yuku-codegen: 0.10.2
- yuku-parser: 0.10.2
+ rolldown: 1.2.14
+ yuku-ast: 0.19.0
+ yuku-codegen: 0.19.0
+ yuku-parser: 0.19.0
optionalDependencies:
typescript: 6.0.3
transitivePeerDependencies:
- oxc-resolver
- rolldown@1.2.11:
- dependencies:
- '@oxc-project/types': 0.151.0
- '@rolldown/pluginutils': 1.0.1
- optionalDependencies:
- '@rolldown/binding-android-arm-eabi': 1.2.11
- '@rolldown/binding-android-arm64': 1.2.11
- '@rolldown/binding-darwin-arm64': 1.2.11
- '@rolldown/binding-darwin-x64': 1.2.11
- '@rolldown/binding-freebsd-x64': 1.2.11
- '@rolldown/binding-linux-arm-gnueabihf': 1.2.11
- '@rolldown/binding-linux-arm64-gnu': 1.2.11
- '@rolldown/binding-linux-arm64-musl': 1.2.11
- '@rolldown/binding-linux-ppc64-gnu': 1.2.11
- '@rolldown/binding-linux-s390x-gnu': 1.2.11
- '@rolldown/binding-linux-x64-gnu': 1.2.11
- '@rolldown/binding-linux-x64-musl': 1.2.11
- '@rolldown/binding-openharmony-arm64': 1.2.11
- '@rolldown/binding-win32-arm64-msvc': 1.2.11
- '@rolldown/binding-win32-x64-msvc': 1.2.11
-
rolldown@1.2.12:
dependencies:
'@oxc-project/types': 0.152.0
@@ -15970,54 +16014,75 @@ snapshots:
'@rolldown/binding-win32-arm64-msvc': 1.2.12
'@rolldown/binding-win32-x64-msvc': 1.2.12
- rollup-plugin-dts@6.5.1(rollup@4.64.1)(typescript@6.0.3):
+ rolldown@1.2.14:
+ dependencies:
+ '@oxc-project/types': 0.154.0
+ '@rolldown/pluginutils': 1.0.1
+ optionalDependencies:
+ '@rolldown/binding-android-arm-eabi': 1.2.14
+ '@rolldown/binding-android-arm64': 1.2.14
+ '@rolldown/binding-darwin-arm64': 1.2.14
+ '@rolldown/binding-darwin-x64': 1.2.14
+ '@rolldown/binding-freebsd-x64': 1.2.14
+ '@rolldown/binding-linux-arm-gnueabihf': 1.2.14
+ '@rolldown/binding-linux-arm64-gnu': 1.2.14
+ '@rolldown/binding-linux-arm64-musl': 1.2.14
+ '@rolldown/binding-linux-ppc64-gnu': 1.2.14
+ '@rolldown/binding-linux-s390x-gnu': 1.2.14
+ '@rolldown/binding-linux-x64-gnu': 1.2.14
+ '@rolldown/binding-linux-x64-musl': 1.2.14
+ '@rolldown/binding-openharmony-arm64': 1.2.14
+ '@rolldown/binding-win32-arm64-msvc': 1.2.14
+ '@rolldown/binding-win32-x64-msvc': 1.2.14
+
+ rollup-plugin-dts@6.5.1(rollup@4.64.6)(typescript@6.0.3):
dependencies:
'@jridgewell/remapping': 2.3.5
'@jridgewell/sourcemap-codec': 1.6.0
convert-source-map: 2.0.0
magic-string: 0.30.21
- rollup: 4.64.1
+ rollup: 4.64.6
typescript: 6.0.3
optionalDependencies:
'@babel/code-frame': 8.0.6
- rollup-plugin-sourcemaps2@0.5.9(@types/node@22.20.5)(rollup@4.64.1):
+ rollup-plugin-sourcemaps2@0.5.9(@types/node@22.20.5)(rollup@4.64.6):
dependencies:
- '@rollup/pluginutils': 5.4.0(rollup@4.64.1)
- rollup: 4.64.1
+ '@rollup/pluginutils': 5.4.0(rollup@4.64.6)
+ rollup: 4.64.6
optionalDependencies:
'@types/node': 22.20.5
- rollup@4.64.1:
+ rollup@4.64.6:
dependencies:
'@types/estree': 1.0.9
optionalDependencies:
'@napi-rs/lzma-linux-x64-gnu': 1.5.1
- '@rollup/rollup-android-arm-eabi': 4.64.1
- '@rollup/rollup-android-arm64': 4.64.1
- '@rollup/rollup-darwin-arm64': 4.64.1
- '@rollup/rollup-darwin-x64': 4.64.1
- '@rollup/rollup-freebsd-arm64': 4.64.1
- '@rollup/rollup-freebsd-x64': 4.64.1
- '@rollup/rollup-linux-arm-gnueabihf': 4.64.1
- '@rollup/rollup-linux-arm-musleabihf': 4.64.1
- '@rollup/rollup-linux-arm64-gnu': 4.64.1
- '@rollup/rollup-linux-arm64-musl': 4.64.1
- '@rollup/rollup-linux-loong64-gnu': 4.64.1
- '@rollup/rollup-linux-loong64-musl': 4.64.1
- '@rollup/rollup-linux-ppc64-gnu': 4.64.1
- '@rollup/rollup-linux-ppc64-musl': 4.64.1
- '@rollup/rollup-linux-riscv64-gnu': 4.64.1
- '@rollup/rollup-linux-riscv64-musl': 4.64.1
- '@rollup/rollup-linux-s390x-gnu': 4.64.1
- '@rollup/rollup-linux-x64-gnu': 4.64.1
- '@rollup/rollup-linux-x64-musl': 4.64.1
- '@rollup/rollup-openbsd-x64': 4.64.1
- '@rollup/rollup-openharmony-arm64': 4.64.1
- '@rollup/rollup-win32-arm64-msvc': 4.64.1
- '@rollup/rollup-win32-ia32-msvc': 4.64.1
- '@rollup/rollup-win32-x64-gnu': 4.64.1
- '@rollup/rollup-win32-x64-msvc': 4.64.1
+ '@rollup/rollup-android-arm-eabi': 4.64.6
+ '@rollup/rollup-android-arm64': 4.64.6
+ '@rollup/rollup-darwin-arm64': 4.64.6
+ '@rollup/rollup-darwin-x64': 4.64.6
+ '@rollup/rollup-freebsd-arm64': 4.64.6
+ '@rollup/rollup-freebsd-x64': 4.64.6
+ '@rollup/rollup-linux-arm-gnueabihf': 4.64.6
+ '@rollup/rollup-linux-arm-musleabihf': 4.64.6
+ '@rollup/rollup-linux-arm64-gnu': 4.64.6
+ '@rollup/rollup-linux-arm64-musl': 4.64.6
+ '@rollup/rollup-linux-loong64-gnu': 4.64.6
+ '@rollup/rollup-linux-loong64-musl': 4.64.6
+ '@rollup/rollup-linux-ppc64-gnu': 4.64.6
+ '@rollup/rollup-linux-ppc64-musl': 4.64.6
+ '@rollup/rollup-linux-riscv64-gnu': 4.64.6
+ '@rollup/rollup-linux-riscv64-musl': 4.64.6
+ '@rollup/rollup-linux-s390x-gnu': 4.64.6
+ '@rollup/rollup-linux-x64-gnu': 4.64.6
+ '@rollup/rollup-linux-x64-musl': 4.64.6
+ '@rollup/rollup-openbsd-x64': 4.64.6
+ '@rollup/rollup-openharmony-arm64': 4.64.6
+ '@rollup/rollup-win32-arm64-msvc': 4.64.6
+ '@rollup/rollup-win32-ia32-msvc': 4.64.6
+ '@rollup/rollup-win32-x64-gnu': 4.64.6
+ '@rollup/rollup-win32-x64-msvc': 4.64.6
fsevents: 2.3.3
router@2.2.0(supports-color@11.0.0):
@@ -16160,11 +16225,11 @@ snapshots:
sass-embedded-win32-arm64: 1.105.1
sass-embedded-win32-x64: 1.105.1
- sass-loader@17.0.1(sass-embedded@1.105.1)(sass@1.105.1)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)):
+ sass-loader@17.0.1(sass-embedded@1.105.1)(sass@1.105.1)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)):
optionalDependencies:
sass: 1.105.1
sass-embedded: 1.105.1
- webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)
+ webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)
sass@1.105.1:
dependencies:
@@ -16390,11 +16455,11 @@ snapshots:
source-map-js@1.2.2: {}
- source-map-loader@5.0.0(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)):
+ source-map-loader@5.0.0(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)):
dependencies:
iconv-lite: 0.6.3
source-map-js: 1.2.2
- webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)
+ webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)
source-map-support@0.5.21:
dependencies:
@@ -16484,8 +16549,6 @@ snapshots:
- bare-abort-controller
- react-native-b4a
- strict-event-emitter@0.5.1: {}
-
string-width@4.2.3:
dependencies:
emoji-regex: 8.0.0
@@ -16580,7 +16643,7 @@ snapshots:
tar-stream@3.2.0:
dependencies:
b4a: 1.9.0
- bare-fs: 4.8.2
+ bare-fs: 4.8.4
fast-fifo: 1.3.2
streamx: 2.28.1
transitivePeerDependencies:
@@ -16591,7 +16654,7 @@ snapshots:
tar-stream@3.2.2:
dependencies:
b4a: 1.9.0
- bare-fs: 4.8.2
+ bare-fs: 4.8.4
fast-fifo: 1.3.2
streamx: 2.28.1
transitivePeerDependencies:
@@ -16618,7 +16681,7 @@ snapshots:
terser@5.51.2:
dependencies:
'@jridgewell/source-map': 0.3.11
- acorn: 8.18.0
+ acorn: 8.19.0
commander: 2.20.3
source-map-support: 0.5.21
@@ -16651,7 +16714,7 @@ snapshots:
tiny-inflate@1.0.3: {}
- tinybench@6.2.0: {}
+ tinybench@6.2.2: {}
tinyexec@1.3.1: {}
@@ -16664,15 +16727,15 @@ snapshots:
tldts-core@6.1.86: {}
- tldts-core@7.4.16: {}
+ tldts-core@7.4.18: {}
tldts@6.1.86:
dependencies:
tldts-core: 6.1.86
- tldts@7.4.16:
+ tldts@7.4.18:
dependencies:
- tldts-core: 7.4.16
+ tldts-core: 7.4.18
tmp@0.2.7: {}
@@ -16690,7 +16753,7 @@ snapshots:
tough-cookie@6.0.2:
dependencies:
- tldts: 7.4.16
+ tldts: 7.4.18
tr46@0.0.3: {}
@@ -16824,6 +16887,8 @@ snapshots:
undici@8.11.2: {}
+ undici@8.12.1: {}
+
unicode-canonical-property-names-ecmascript@2.0.1: {}
unicode-match-property-ecmascript@2.0.0:
@@ -16855,7 +16920,7 @@ snapshots:
unpipe@1.0.0: {}
- update-browserslist-db@1.3.3(browserslist@4.29.3):
+ update-browserslist-db@1.3.4(browserslist@4.29.3):
dependencies:
browserslist: 4.29.3
escalade: 3.2.0
@@ -16896,9 +16961,9 @@ snapshots:
- encoding
- supports-color
- verdaccio-auth-memory@13.1.5(supports-color@11.0.0):
+ verdaccio-auth-memory@13.1.6(supports-color@11.0.0):
dependencies:
- '@verdaccio/core': 8.3.2
+ '@verdaccio/core': 8.3.3
debug: 4.4.3(supports-color@11.0.0)
transitivePeerDependencies:
- supports-color
@@ -16954,8 +17019,6 @@ snapshots:
- react-native-b4a
- supports-color
- verkit@0.3.2: {}
-
verkit@0.5.0: {}
verror@1.10.0:
@@ -16964,12 +17027,12 @@ snapshots:
core-util-is: 1.0.2
extsprintf: 1.3.0
- vite@8.3.3(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1):
+ vite@8.3.4(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1):
dependencies:
lightningcss: 1.33.0
picomatch: 4.0.7
- postcss: 8.5.28
- rolldown: 1.2.11
+ postcss: 8.5.30
+ rolldown: 1.2.14
tinyglobby: 0.2.17
optionalDependencies:
'@types/node': 22.20.5
@@ -16983,26 +17046,26 @@ snapshots:
tsx: 4.23.15
yaml: 2.9.1
- vitest@5.0.3(@opentelemetry/api@1.9.1)(@types/node@22.20.5)(@vitest/coverage-v8@5.0.3)(jsdom@30.1.2(@noble/hashes@1.8.0))(vite@8.3.3(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1)):
+ vitest@5.0.4(@opentelemetry/api@1.9.1)(@types/node@22.20.5)(@vitest/coverage-v8@5.0.4)(jsdom@30.1.2(@noble/hashes@1.8.0))(vite@8.3.4(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1)):
dependencies:
'@types/chai': 5.2.3
- '@vitest/mocker': 5.0.3(vite@8.3.3(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1))
+ '@vitest/mocker': 5.0.4(vite@8.3.4(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1))
chai: 6.3.0
es-module-lexer: 2.3.2
expect-type: 1.4.0
- magic-string: 1.4.2
- obug: 2.2.1
+ magic-string: 1.4.3
+ obug: 3.0.0
picomatch: 4.0.7
std-env: 4.3.0
- tinybench: 6.2.0
+ tinybench: 6.2.2
tinyexec: 1.3.1
tinyglobby: 0.2.17
- vite: 8.3.3(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1)
+ vite: 8.3.4(@types/node@22.20.5)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@11.0.0))(sass-embedded@1.105.1)(sass@1.105.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.1)
why-is-node-running: 3.2.1
optionalDependencies:
'@opentelemetry/api': 1.9.1
'@types/node': 22.20.5
- '@vitest/coverage-v8': 5.0.3(vitest@5.0.3)
+ '@vitest/coverage-v8': 5.0.4(vitest@5.0.4)
jsdom: 30.1.2(@noble/hashes@1.8.0)
transitivePeerDependencies:
- msw
@@ -17024,13 +17087,13 @@ snapshots:
web-vitals@4.2.4: {}
- webdriver-bidi-protocol@0.4.3: {}
+ webdriver-bidi-protocol@1.0.1: {}
webidl-conversions@3.0.1: {}
webidl-conversions@8.0.1: {}
- webpack-dev-middleware@8.3.0(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.28)(uglify-js@3.19.3)):
+ webpack-dev-middleware@8.3.0(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)):
dependencies:
ansi-html-community: 0.0.8
memfs: 4.80.0
@@ -17038,9 +17101,9 @@ snapshots:
range-parser: 1.3.0
schema-utils: 4.5.0
optionalDependencies:
- webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.28)(uglify-js@3.19.3)
+ webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)
- webpack-dev-middleware@8.3.0(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)):
+ webpack-dev-middleware@8.3.0(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)):
dependencies:
ansi-html-community: 0.0.8
memfs: 4.80.0
@@ -17048,9 +17111,9 @@ snapshots:
range-parser: 1.3.0
schema-utils: 4.5.0
optionalDependencies:
- webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)
+ webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)
- webpack-dev-server@6.0.0(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.28)(uglify-js@3.19.3)):
+ webpack-dev-server@6.0.0(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)):
dependencies:
'@types/bonjour': 3.5.13
'@types/connect-history-api-fallback': 1.5.4
@@ -17068,23 +17131,23 @@ snapshots:
graceful-fs: 4.2.11
http-proxy-middleware: 4.2.0(supports-color@11.0.0)
ipaddr.js: 2.5.0
- launch-editor: 2.14.1
+ launch-editor: 2.14.2
open: 11.0.4
p-retry: 8.0.1
schema-utils: 4.5.0
selfsigned: 5.5.0
serve-index: 1.9.2(supports-color@11.0.0)
tinyglobby: 0.2.17
- webpack-dev-middleware: 8.3.0(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.28)(uglify-js@3.19.3))
+ webpack-dev-middleware: 8.3.0(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3))
ws: 8.22.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)
optionalDependencies:
- webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.28)(uglify-js@3.19.3)
+ webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)
transitivePeerDependencies:
- bufferutil
- supports-color
- utf-8-validate
- webpack-dev-server@6.0.0(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)):
+ webpack-dev-server@6.0.0(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)):
dependencies:
'@types/bonjour': 3.5.13
'@types/connect-history-api-fallback': 1.5.4
@@ -17102,17 +17165,17 @@ snapshots:
graceful-fs: 4.2.11
http-proxy-middleware: 4.2.0(supports-color@11.0.0)
ipaddr.js: 2.5.0
- launch-editor: 2.14.1
+ launch-editor: 2.14.2
open: 11.0.4
p-retry: 8.0.1
schema-utils: 4.5.0
selfsigned: 5.5.0
serve-index: 1.9.2(supports-color@11.0.0)
tinyglobby: 0.2.17
- webpack-dev-middleware: 8.3.0(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3))
+ webpack-dev-middleware: 8.3.0(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3))
ws: 8.22.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)
optionalDependencies:
- webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)
+ webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)
transitivePeerDependencies:
- bufferutil
- supports-color
@@ -17126,12 +17189,12 @@ snapshots:
webpack-sources@3.6.0: {}
- webpack-subresource-integrity@5.1.0(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)):
+ webpack-subresource-integrity@5.1.0(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)):
dependencies:
typed-assert: 1.0.9
- webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)
+ webpack: 5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)
- webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.28)(uglify-js@3.19.3):
+ webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3):
dependencies:
'@types/estree': 1.0.9
'@types/json-schema': 7.0.15
@@ -17145,7 +17208,7 @@ snapshots:
events: 3.3.0
graceful-fs: 4.2.11
mime-db: 1.54.0
- minimizer-webpack-plugin: 5.13.0(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.28)(uglify-js@3.19.3)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.28)(uglify-js@3.19.3))
+ minimizer-webpack-plugin: 5.13.0(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3))
schema-utils: 4.5.0
tapable: 2.3.3
watchpack: 2.5.2
@@ -17168,7 +17231,7 @@ snapshots:
- svgo
- uglify-js
- webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3):
+ webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3):
dependencies:
'@types/estree': 1.0.9
'@types/json-schema': 7.0.15
@@ -17182,7 +17245,7 @@ snapshots:
events: 3.3.0
graceful-fs: 4.2.11
mime-db: 1.54.0
- minimizer-webpack-plugin: 5.13.0(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.29)(uglify-js@3.19.3))
+ minimizer-webpack-plugin: 5.13.0(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3)(webpack@5.111.1(esbuild@0.28.2)(lightningcss@1.33.0)(postcss@8.5.30)(uglify-js@3.19.3))
schema-utils: 4.5.0
tapable: 2.3.3
watchpack: 2.5.2
@@ -17390,6 +17453,10 @@ snapshots:
dependencies:
'@yuku-toolchain/types': 0.10.2
+ yuku-ast@0.19.0:
+ dependencies:
+ '@yuku-toolchain/types': 0.19.0
+
yuku-codegen@0.10.2:
dependencies:
'@yuku-toolchain/types': 0.10.2
@@ -17407,6 +17474,27 @@ snapshots:
'@yuku-codegen/binding-win32-arm64': 0.10.2
'@yuku-codegen/binding-win32-x64': 0.10.2
+ yuku-codegen@0.19.0:
+ dependencies:
+ '@yuku-toolchain/types': 0.19.0
+
+ yuku-core@0.19.0:
+ dependencies:
+ '@yuku-toolchain/types': 0.19.0
+ optionalDependencies:
+ '@yuku-core/binding-android-arm64': 0.19.0
+ '@yuku-core/binding-darwin-arm64': 0.19.0
+ '@yuku-core/binding-darwin-x64': 0.19.0
+ '@yuku-core/binding-freebsd-x64': 0.19.0
+ '@yuku-core/binding-linux-arm-gnu': 0.19.0
+ '@yuku-core/binding-linux-arm-musl': 0.19.0
+ '@yuku-core/binding-linux-arm64-gnu': 0.19.0
+ '@yuku-core/binding-linux-arm64-musl': 0.19.0
+ '@yuku-core/binding-linux-x64-gnu': 0.19.0
+ '@yuku-core/binding-linux-x64-musl': 0.19.0
+ '@yuku-core/binding-win32-arm64': 0.19.0
+ '@yuku-core/binding-win32-x64': 0.19.0
+
yuku-parser@0.10.2:
dependencies:
'@yuku-toolchain/types': 0.10.2
@@ -17425,8 +17513,13 @@ snapshots:
'@yuku-parser/binding-win32-arm64': 0.10.2
'@yuku-parser/binding-win32-x64': 0.10.2
- zod@3.25.76: {}
+ yuku-parser@0.19.0:
+ dependencies:
+ '@yuku-toolchain/types': 0.19.0
+ yuku-core: 0.19.0
zod@4.6.5: {}
+ zod@4.6.7: {}
+
zone.js@0.16.3: {}
diff --git a/tests/e2e/ng-snapshot/package.json b/tests/e2e/ng-snapshot/package.json
index a3e554ca1640..e02c1dcd10e4 100644
--- a/tests/e2e/ng-snapshot/package.json
+++ b/tests/e2e/ng-snapshot/package.json
@@ -2,21 +2,21 @@
"description": "snapshot versions of Angular for e2e testing",
"private": true,
"dependencies": {
- "@angular/animations": "github:angular/animations-builds#3ec405d1cb11a6f18eacdd7e09378cd097a9a427",
- "@angular/cdk": "github:angular/cdk-builds#8eedcdb798ec78b2c0191953b46804f54296ed4f",
- "@angular/common": "github:angular/common-builds#bae1a4226a83f02bcb77b6ef447e039d8b5081f3",
- "@angular/compiler": "github:angular/compiler-builds#fc8fced0b21574f7846b999a751511f9a453e0cd",
- "@angular/compiler-cli": "github:angular/compiler-cli-builds#20b42c8d2e12f28eea2376ff0b0f1f5ec59cac63",
- "@angular/core": "github:angular/core-builds#080d86fc456c2029952d72e43ae5e019374a3546",
- "@angular/forms": "github:angular/forms-builds#b8ff96856639a22bb3dec5c8bebb562c5395c638",
- "@angular/language-service": "github:angular/language-service-builds#9e0a5e50a0f37d5671fc2478ebf2626399fb23f4",
- "@angular/localize": "github:angular/localize-builds#fec5dc5c69698fbf47aa794ac8fd80a2baa9b1d5",
- "@angular/material": "github:angular/material-builds#72d50c0fd59ea4d1f7fc2053d74d4f2610503730",
- "@angular/material-moment-adapter": "github:angular/material-moment-adapter-builds#30012ad773e0536aa4e5ff009c1b65ec8bb1e5f2",
- "@angular/platform-browser": "github:angular/platform-browser-builds#ca08a1a24ac892344fb1f69c6f5ac15eb504370b",
- "@angular/platform-browser-dynamic": "github:angular/platform-browser-dynamic-builds#163f8f1af3365efeab12b2656ad229a8d76e39b9",
- "@angular/platform-server": "github:angular/platform-server-builds#fe61afa721e53041b0bac92f0241a82326d72a47",
- "@angular/router": "github:angular/router-builds#7df611a733d4a35d41fd4b5596e0a9800cc67e8e",
- "@angular/service-worker": "github:angular/service-worker-builds#3ef11b4fbbd965535f0f45de2ba41a4e3886b918"
+ "@angular/animations": "github:angular/animations-builds#43efef5cbf38f5261191e5c11d7f49c276428137",
+ "@angular/cdk": "github:angular/cdk-builds#43c02174c1dc0f4b74a85342bbd9f43d040bf1ae",
+ "@angular/common": "github:angular/common-builds#89d9b5d43c81051c59a33d24ccccd75b51f6dc48",
+ "@angular/compiler": "github:angular/compiler-builds#e91181d83e7086debe8f32f21bfa434c4bd94afd",
+ "@angular/compiler-cli": "github:angular/compiler-cli-builds#bfd2191e1955c38a1ce52aa467508702d132e7ba",
+ "@angular/core": "github:angular/core-builds#31cf6f74f000a8499b3ce204ad9b339e830dcc39",
+ "@angular/forms": "github:angular/forms-builds#1dbb38cca305af00e3362cb59c5293b44a7ae7f1",
+ "@angular/language-service": "github:angular/language-service-builds#54ce2dee3572da8657674dc965d010fd37b6d15b",
+ "@angular/localize": "github:angular/localize-builds#bcdfcaf668fd983db3496cdb696ca8b3aa2f68aa",
+ "@angular/material": "github:angular/material-builds#2c82c94514f7cb2bc3dafd3b5db2160aa9c01517",
+ "@angular/material-moment-adapter": "github:angular/material-moment-adapter-builds#728a7be6d90391791e0967357a07959d2a4fa3d3",
+ "@angular/platform-browser": "github:angular/platform-browser-builds#a1b99915c2e91ab779ee0443904bd0194b8e2fb0",
+ "@angular/platform-browser-dynamic": "github:angular/platform-browser-dynamic-builds#cdfb691b31a234662977f12f0982b880035bb72e",
+ "@angular/platform-server": "github:angular/platform-server-builds#9e3f315c175ed493a83d91b2d1743582e4934ab3",
+ "@angular/router": "github:angular/router-builds#972a0d117fd048a478e2cb035ef5b442e8cc5ceb",
+ "@angular/service-worker": "github:angular/service-worker-builds#f3e0f7d39cadb10a0257cf826cc0519e7809e8e2"
}
}
diff --git a/tests/e2e/tests/i18n/extract-ivy.ts b/tests/e2e/tests/i18n/extract-ivy.ts
index 382051e83cce..cf0d23da08e3 100644
--- a/tests/e2e/tests/i18n/extract-ivy.ts
+++ b/tests/e2e/tests/i18n/extract-ivy.ts
@@ -1,8 +1,9 @@
import { join } from 'node:path';
import { getGlobalVariable } from '../../utils/env';
-import { expectFileToMatch, writeFile } from '../../utils/fs';
+import { deleteFile, expectFileToMatch, writeFile } from '../../utils/fs';
import { uninstallPackage } from '../../utils/packages';
import { ng } from '../../utils/process';
+import { updateJsonFile } from '../../utils/project';
import { expectToFail } from '../../utils/utils';
import { readNgVersion } from '../../utils/version';
@@ -52,5 +53,13 @@ export default async function () {
await expectFileToMatch('messages.xlf', 'Hello world');
+ // Template messages should also be extracted when the build target disables AOT
+ await updateJsonFile('angular.json', (workspaceJson) => {
+ workspaceJson.projects['test-project'].architect.build.options.aot = false;
+ });
+ await deleteFile('messages.xlf');
+ await ng('extract-i18n');
+ await expectFileToMatch('messages.xlf', 'Hello world');
+
await uninstallPackage('@angular/localize');
}