diff --git a/.bazelrc b/.bazelrc index d736ebd75612..00d2d33dfc37 100644 --- a/.bazelrc +++ b/.bazelrc @@ -4,6 +4,8 @@ build --action_env=NG_FORCE_TTY=false # Required by `rules_ts`. common --@aspect_rules_ts//ts:skipLibCheck=always common --@aspect_rules_ts//ts:default_to_tsc_transpiler +# TODO: remove this flag once we get to bazel version >7. +common --incompatible_merge_fixed_and_default_shell_env # Make TypeScript compilation fast, by keeping a few copies of the compiler # running as daemons, and cache SourceFile AST's to reduce parse time. @@ -135,6 +137,7 @@ build:remote --platforms=@devinfra//bazel/remote-execution:platform_with_network # Set remote caching settings build:remote --remote_accept_cached=true +build:remote --remote_upload_local_results=false # Force remote executions to consider the entire run as linux. # This is required for OSX cross-platform RBE. @@ -147,9 +150,12 @@ build:remote --google_default_credentials # Use HTTP remote cache build:remote-cache --remote_cache=https://storage.googleapis.com/angular-team-cache build:remote-cache --remote_accept_cached=true -build:remote-cache --remote_upload_local_results=true +build:remote-cache --remote_upload_local_results=false build:remote-cache --google_default_credentials +# Additional flags added when running a "trusted build" with additional access +build:trusted-build --remote_upload_local_results=true + ############################### # NodeJS rules settings # These settings are required for rules_nodejs diff --git a/.github/shared-actions/windows-bazel-test/action.yml b/.github/shared-actions/windows-bazel-test/action.yml index 7bdf488fc62c..b66f6d955889 100644 --- a/.github/shared-actions/windows-bazel-test/action.yml +++ b/.github/shared-actions/windows-bazel-test/action.yml @@ -16,11 +16,6 @@ inputs: runs: using: composite steps: - - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@2667d139a421977a40c3ea7ec768609fb19a8b9d - with: - allow_windows_rbe: true - - name: Initialize WSL id: init_wsl uses: angular/dev-infra/github-actions/setup-wsl@9a3e28a515bf51cd2ecfd5f4d5b17613845e6f44 diff --git a/.github/workflows/assistant-to-the-branch-manager.yml b/.github/workflows/assistant-to-the-branch-manager.yml index 1f3261e0e854..2199c1f3be6d 100644 --- a/.github/workflows/assistant-to-the-branch-manager.yml +++ b/.github/workflows/assistant-to-the-branch-manager.yml @@ -16,6 +16,6 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: angular/dev-infra/github-actions/branch-manager@47572aba6019f368057c00966ac7ce354b1d65bc + - uses: angular/dev-infra/github-actions/branch-manager@64d0e9da9c4309a5a05f6c0a05383203a46a700d with: angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f02abd9d59ae..703dd732beaf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Install node modules run: pnpm install --frozen-lockfile - name: Generate JSON schema types @@ -42,11 +42,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/setup@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/configure-remote@64d0e9da9c4309a5a05f6c0a05383203a46a700d + with: + google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Install node modules run: pnpm install --frozen-lockfile - name: Build release targets @@ -57,11 +59,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/setup@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/configure-remote@64d0e9da9c4309a5a05f6c0a05383203a46a700d + with: + google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Install node modules run: pnpm install --frozen-lockfile - name: Run module and package tests @@ -81,13 +85,15 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/setup@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/configure-remote@64d0e9da9c4309a5a05f6c0a05383203a46a700d + with: + google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Run CLI E2E tests run: pnpm bazel test --test_env=E2E_SHARD_TOTAL=6 --test_env=E2E_SHARD_INDEX=${{ matrix.shard }} --config=e2e //tests/legacy-cli:e2e.${{ matrix.subset }}_node${{ matrix.node }} @@ -102,7 +108,12 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@64d0e9da9c4309a5a05f6c0a05383203a46a700d + - name: Setup Bazel RBE + uses: angular/dev-infra/github-actions/bazel/configure-remote@64d0e9da9c4309a5a05f6c0a05383203a46a700d + with: + allow_windows_rbe: true + google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Run CLI E2E tests uses: ./.github/shared-actions/windows-bazel-test with: @@ -123,13 +134,15 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/setup@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/configure-remote@64d0e9da9c4309a5a05f6c0a05383203a46a700d + with: + google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Run CLI E2E tests run: pnpm bazel test --test_env=E2E_SHARD_TOTAL=3 --test_env=E2E_SHARD_INDEX=${{ matrix.shard }} --config=e2e //tests/legacy-cli:e2e.${{ matrix.subset }}_node${{ matrix.node }} @@ -145,13 +158,15 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/setup@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/configure-remote@64d0e9da9c4309a5a05f6c0a05383203a46a700d + with: + google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Run CLI E2E tests run: pnpm bazel test --test_env=E2E_SHARD_TOTAL=6 --test_env=E2E_SHARD_INDEX=${{ matrix.shard }} --config=e2e //tests/legacy-cli:e2e.snapshots.${{ matrix.subset }}_node${{ matrix.node }} @@ -163,13 +178,15 @@ 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@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/setup@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/configure-remote@64d0e9da9c4309a5a05f6c0a05383203a46a700d + with: + google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Run E2E Browser tests env: SAUCE_USERNAME: ${{ vars.SAUCE_USERNAME }} @@ -184,7 +201,7 @@ jobs: ./scripts/saucelabs/wait-for-tunnel.sh pnpm bazel test --config=saucelabs //tests/legacy-cli:e2e.saucelabs ./scripts/saucelabs/stop-tunnel.sh - - uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 if: ${{ failure() }} with: name: sauce-connect-log @@ -197,11 +214,11 @@ jobs: CIRCLE_BRANCH: ${{ github.ref_name }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/setup@64d0e9da9c4309a5a05f6c0a05383203a46a700d - run: pnpm admin snapshots --verbose env: SNAPSHOT_BUILDS_GITHUB_TOKEN: ${{ secrets.SNAPSHOT_BUILDS_GITHUB_TOKEN }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e6a99a028cdc..899774b4290a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -23,12 +23,12 @@ jobs: with: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 + uses: github/codeql-action/init@45775bd8235c68ba998cffa5171334d58593da47 # v3.28.15 with: languages: javascript-typescript build-mode: none config-file: .github/codeql/config.yml - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 + uses: github/codeql-action/analyze@45775bd8235c68ba998cffa5171334d58593da47 # v3.28.15 with: category: '/language:javascript-typescript' diff --git a/.github/workflows/dev-infra.yml b/.github/workflows/dev-infra.yml index b4ab1d44985b..dc61ccd50d57 100644 --- a/.github/workflows/dev-infra.yml +++ b/.github/workflows/dev-infra.yml @@ -13,13 +13,13 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: angular/dev-infra/github-actions/commit-message-based-labels@47572aba6019f368057c00966ac7ce354b1d65bc + - uses: angular/dev-infra/github-actions/commit-message-based-labels@64d0e9da9c4309a5a05f6c0a05383203a46a700d with: angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} post_approval_changes: runs-on: ubuntu-latest steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: angular/dev-infra/github-actions/post-approval-changes@47572aba6019f368057c00966ac7ce354b1d65bc + - uses: angular/dev-infra/github-actions/post-approval-changes@64d0e9da9c4309a5a05f6c0a05383203a46a700d with: angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} diff --git a/.github/workflows/feature-requests.yml b/.github/workflows/feature-requests.yml index 5e922d9c70f0..bdcc271996d3 100644 --- a/.github/workflows/feature-requests.yml +++ b/.github/workflows/feature-requests.yml @@ -16,6 +16,6 @@ jobs: if: github.repository == 'angular/angular-cli' runs-on: ubuntu-latest steps: - - uses: angular/dev-infra/github-actions/feature-request@47572aba6019f368057c00966ac7ce354b1d65bc + - uses: angular/dev-infra/github-actions/feature-request@64d0e9da9c4309a5a05f6c0a05383203a46a700d with: angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} diff --git a/.github/workflows/perf.yml b/.github/workflows/perf.yml index de3d47cc389e..8a91163ab591 100644 --- a/.github/workflows/perf.yml +++ b/.github/workflows/perf.yml @@ -23,7 +23,7 @@ jobs: workflows: ${{ steps.workflows.outputs.workflows }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Install node modules run: pnpm install --frozen-lockfile - id: workflows @@ -38,9 +38,9 @@ jobs: workflow: ${{ fromJSON(needs.list.outputs.workflows) }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/setup@64d0e9da9c4309a5a05f6c0a05383203a46a700d - 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 5e2afb76122a..0ef8c04cc910 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@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Setup ESLint Caching - uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4.2.2 + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 with: path: .eslintcache key: ${{ runner.os }}-${{ hashFiles('.eslintrc.json') }} @@ -54,7 +54,7 @@ jobs: - name: Run Validation run: pnpm admin validate - name: Check Package Licenses - uses: angular/dev-infra/github-actions/linting/licenses@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/linting/licenses@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Check tooling setup run: pnpm check-tooling-setup - name: Check commit message @@ -70,17 +70,17 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/setup@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/configure-remote@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Install node modules run: pnpm install --frozen-lockfile - name: Build release targets run: pnpm ng-dev release build - name: Store PR release packages - uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: packages path: dist/releases/*.tgz @@ -91,11 +91,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/setup@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/configure-remote@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Install node modules run: pnpm install --frozen-lockfile - name: Run module and package tests @@ -115,13 +115,13 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/setup@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/configure-remote@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Run CLI E2E tests run: pnpm bazel test --test_env=E2E_SHARD_TOTAL=6 --test_env=E2E_SHARD_INDEX=${{ matrix.shard }} --config=e2e //tests/legacy-cli:e2e.${{ matrix.subset }}_node${{ matrix.node }} @@ -130,7 +130,11 @@ jobs: runs-on: windows-2025 steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@64d0e9da9c4309a5a05f6c0a05383203a46a700d + - name: Setup Bazel RBE + uses: angular/dev-infra/github-actions/bazel/configure-remote@64d0e9da9c4309a5a05f6c0a05383203a46a700d + with: + allow_windows_rbe: true - name: Run CLI E2E tests uses: ./.github/shared-actions/windows-bazel-test with: @@ -149,13 +153,13 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/setup@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/configure-remote@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Run CLI E2E tests run: pnpm bazel test --test_env=E2E_SHARD_TOTAL=3 --test_env=E2E_SHARD_INDEX=${{ matrix.shard }} --config=e2e //tests/legacy-cli:e2e.${{ matrix.subset }}_node${{ matrix.node }} @@ -172,12 +176,12 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/setup@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@47572aba6019f368057c00966ac7ce354b1d65bc + uses: angular/dev-infra/github-actions/bazel/configure-remote@64d0e9da9c4309a5a05f6c0a05383203a46a700d - name: Run CLI E2E tests run: pnpm bazel test --test_env=E2E_SHARD_TOTAL=6 --test_env=E2E_SHARD_INDEX=${{ matrix.shard }} --config=e2e //tests/legacy-cli:e2e.snapshots.${{ matrix.subset }}_node${{ matrix.node }} diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 1d7ff690a396..62c593627fad 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -38,7 +38,7 @@ jobs: # Upload the results as artifacts. - name: 'Upload artifact' - uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: SARIF file path: results.sarif @@ -46,6 +46,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: 'Upload to code-scanning' - uses: github/codeql-action/upload-sarif@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 + uses: github/codeql-action/upload-sarif@45775bd8235c68ba998cffa5171334d58593da47 # v3.28.15 with: sarif_file: results.sarif diff --git a/.nvmrc b/.nvmrc index d4b7699d36ca..7d41c735d712 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -20.18.1 +22.14.0 diff --git a/BUILD.bazel b/BUILD.bazel index e428d013ef93..33ef92b85fd3 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -1,7 +1,7 @@ load("@aspect_rules_ts//ts:defs.bzl", rules_js_tsconfig = "ts_config") load("@bazel_skylib//rules:common_settings.bzl", "bool_flag") load("@npm2//:defs.bzl", "npm_link_all_packages") -load("//tools:defaults2.bzl", "copy_to_bin") +load("//tools:defaults.bzl", "copy_to_bin") package(default_visibility = ["//visibility:public"]) diff --git a/CHANGELOG.md b/CHANGELOG.md index baa3eef1ae64..e45afe7be65f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,372 @@ + + +# 20.0.0-next.6 (2025-04-16) + +### @schematics/angular + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | -------------------------------------------------------------- | +| [d6f594fe0](https://github.com/angular/angular-cli/commit/d6f594fe0f8f21d9c0e2abedb5c8433a1aa5c157) | feat | generate applications using TypeScript project references | +| [8654b3fea](https://github.com/angular/angular-cli/commit/8654b3fea4e2ba5af651e6c2a4afddaf6fc42802) | fix | application migration should migrate karma builder package | +| [be6f13ec1](https://github.com/angular/angular-cli/commit/be6f13ec16f01851d38b900dbfc4df7ccfb94d16) | fix | remove setting files tsconfig field with SSR/Server generation | + +### @angular/build + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | -------------------------------------------------------------------- | +| [d5a409a79](https://github.com/angular/angular-cli/commit/d5a409a79da16d368a6c0c588f9c987355ead529) | fix | include `module` value check when adding custom conditions | +| [95d16dc52](https://github.com/angular/angular-cli/commit/95d16dc52113a1d5f67c95a5f6d82e5e937f299c) | fix | pass `preserveSymlinks` option to Karma esbuild builder | +| [3d997feb6](https://github.com/angular/angular-cli/commit/3d997feb689b838a9777b7727bf937098c7d5e83) | fix | prevent nested CSS in components | +| [6e6315d72](https://github.com/angular/angular-cli/commit/6e6315d72686a88f29ec9e7565b463e302fdbed8) | fix | properly resolve transitive external dependencies in vite-dev-server | + + + + + +# 19.2.8 (2025-04-16) + +### @angular/build + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | -------------------------------------------------------------------- | +| [4a8a4a083](https://github.com/angular/angular-cli/commit/4a8a4a0837af6a095a1e4ad6ae07436073324a7a) | fix | include `module` value check when adding custom conditions | +| [00cd0d123](https://github.com/angular/angular-cli/commit/00cd0d1235ed13781689ae4c4636371dab46b493) | fix | prevent nested CSS in components | +| [a297c4153](https://github.com/angular/angular-cli/commit/a297c4153fd72581cbcf8136c9524c415c561f53) | fix | properly resolve transitive external dependencies in vite-dev-server | +| [8ab033e8e](https://github.com/angular/angular-cli/commit/8ab033e8e56d26c75d8871f81291e702b8985adc) | fix | update vite to 6.2.6 | + + + + + +# 20.0.0-next.5 (2025-04-09) + +### @schematics/angular + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | --------------------------------------------------------------------- | +| [fdc6291dd](https://github.com/angular/angular-cli/commit/fdc6291dda4903f418667d415b05367390cf829d) | feat | add update migration to keep previous style guide generation behavior | +| [90615a88b](https://github.com/angular/angular-cli/commit/90615a88b10535d7f0197008b9d48ceac4409c23) | fix | default component templates to not use `.ng.html` extension | +| [5fc595144](https://github.com/angular/angular-cli/commit/5fc5951440c9306c4349fa3f8dbcb1b584441fe8) | fix | generate guards with a dash type separator | +| [040282d8f](https://github.com/angular/angular-cli/commit/040282d8fd5838266785997442c4f5a269666cf3) | fix | generate interceptors with a dash type separator | +| [070d60fb3](https://github.com/angular/angular-cli/commit/070d60fb383bb14d39f969942641253e54980fcf) | fix | generate modules with a dash type separator | +| [e6083b57b](https://github.com/angular/angular-cli/commit/e6083b57bb5b38db14264253095a9729738d22f2) | fix | generate pipes with a dash type separator | +| [92e193c0b](https://github.com/angular/angular-cli/commit/92e193c0b9a2b85b68d83c5f378d30fc8d10f13e) | fix | generate resolvers with a dash type separator | +| [ea1143ddd](https://github.com/angular/angular-cli/commit/ea1143ddd801b775828f0b62788f4cce0dd7e9ce) | fix | infer app component name and path in server schematic | +| [661609e3e](https://github.com/angular/angular-cli/commit/661609e3e583198828baf236338db17b6222f4d8) | fix | set explicit type in library schematic | + +### @angular/build + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ----------------------------------------------------------- | +| [3e24a59a9](https://github.com/angular/angular-cli/commit/3e24a59a9db9f11a80fa616c68be4380c4816ed5) | fix | disable TypeScript `composite` option with Angular compiler | +| [6f913ad5e](https://github.com/angular/angular-cli/commit/6f913ad5e4d8ad9932ef2607851e3b8776e1af3a) | fix | include component test metadata in development builds | +| [fc0e05fea](https://github.com/angular/angular-cli/commit/fc0e05fea89598204a7e5de494da897c396c4e52) | fix | skip normalization of relative externals | + +### @angular/ssr + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------ | +| [319b8e0c2](https://github.com/angular/angular-cli/commit/319b8e0c2a0cd30ab96576464b4172a1f76a97a6) | fix | manage unhandled errors in zoneless applications | + +### @ngtools/webpack + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | --------------------------------------------------------- | +| [427bd846f](https://github.com/angular/angular-cli/commit/427bd846f552b393cb969472a05488ac11d47e9f) | fix | disable TypeScript composite option with Angular compiler | + + + + + +# 19.2.7 (2025-04-09) + +### @angular/build + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ----------------------------------------------------- | +| [7f1e8c677](https://github.com/angular/angular-cli/commit/7f1e8c6777dbf60e2a3864774a8c4140bb76f640) | fix | include component test metadata in development builds | +| [74cd4edd5](https://github.com/angular/angular-cli/commit/74cd4edd5bbf5ae03a910be036f6e7fa7db35642) | fix | skip normalization of relative externals | + + + + + +# 18.2.18 (2025-04-09) + +### @angular/build + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | --------------------- | +| [4245ca7b4](https://github.com/angular/angular-cli/commit/4245ca7b434e0aa859c805c459ce50238601b940) | fix | update vite to 5.4.17 | + + + + + +# 17.3.16 (2025-04-09) + +### @angular-devkit/build-angular + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------- | +| [5aa53b40c](https://github.com/angular/angular-cli/commit/5aa53b40c34e1555548d201f840a5ffc01f14601) | fix | remove undici from dependencies | +| [fce61564d](https://github.com/angular/angular-cli/commit/fce61564ded8c476ef1c257d2844b1a1560af732) | fix | update vite to 5.4.17 | + + + + + +# 20.0.0-next.4 (2025-04-02) + +### @schematics/angular + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------- | +| [1e137ca84](https://github.com/angular/angular-cli/commit/1e137ca848839402bc214fbccdc04243862d01d0) | feat | add migration to update `moduleResolution` to `bundler` | + +### @angular-devkit/schematics + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | -------------------------------------------------------------------------- | +| [4955ee0aa](https://github.com/angular/angular-cli/commit/4955ee0aa31c1021b6369c29a250dd5a9a3f11cd) | fix | properly resolve relative schematics when executed from a nested directory | + +### @angular/build + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------ | +| [d067cedf0](https://github.com/angular/angular-cli/commit/d067cedf05051e3a0f237d50306e1e4c881a0328) | feat | support custom resolution conditions with applications | +| [8a89438be](https://github.com/angular/angular-cli/commit/8a89438bef66e00d9795a5684c2b91dfdc102b3f) | fix | correctly handle `false` value in server option | +| [52fbffcd7](https://github.com/angular/angular-cli/commit/52fbffcd7bb129720a10e6bf865e4e3a01f939d6) | fix | warn and remove jsdom launcher when used with karma | + + + + + +# 19.2.6 (2025-04-02) + +### @angular-devkit/schematics + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | -------------------------------------------------------------------------- | +| [e5aec562f](https://github.com/angular/angular-cli/commit/e5aec562feb0d293e88d560ea4ec0720e90dbc11) | fix | properly resolve relative schematics when executed from a nested directory | + +### @angular/build + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ----------------------------------------------- | +| [76cfd364a](https://github.com/angular/angular-cli/commit/76cfd364a8b398153c09ce29c5672272ac0bce23) | fix | correctly handle `false` value in server option | +| [d69188c6b](https://github.com/angular/angular-cli/commit/d69188c6be2b851e3dfb84e2bd8d209062d7a283) | fix | update vite to 6.2.4 due to a security issues | + + + + + +# 18.2.17 (2025-04-02) + +### @angular/build + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ---------------------------------------------- | +| [247ceff7f](https://github.com/angular/angular-cli/commit/247ceff7f7d71901f51dbab1c1a5235d59e45847) | fix | update vite to 5.4.16 due to a security issues | + + + + + +# 17.3.15 (2025-04-02) + +### @angular-devkit/build-angular + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ---------------------------------------------- | +| [0525fec61](https://github.com/angular/angular-cli/commit/0525fec6183c2972b97a6ad4d57e89aaa478a2de) | fix | update vite to 5.4.16 due to a security issues | + + + + + +# 20.0.0-next.3 (2025-03-26) + +## Breaking Changes + +### @angular/cli + +- Node.js versions from 22.0 to 22.10 are no longer supported + +### @schematics/angular + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | --------------------------------------------------------------------- | +| [9e6b9b537](https://github.com/angular/angular-cli/commit/9e6b9b5379d0448578b3bfb6100852dea7febe75) | fix | add type checking of host bindings to strict config | +| [381d35fe4](https://github.com/angular/angular-cli/commit/381d35fe40f062713eac550a12b58c30c1ec33a9) | fix | remove empty `scripts` option value from new applications | +| [a910fe9ae](https://github.com/angular/angular-cli/commit/a910fe9ae0423146f6509c5b9c45c88415365c9f) | fix | remove explicit `outputPath` option value from generated applications | + +### @angular/cli + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------ | +| [64732534e](https://github.com/angular/angular-cli/commit/64732534ecb84d702bde2469466a05e765879f9a) | fix | update minimum supported Node.js 22 version to 22.11.0 | + +### @angular/build + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ----------------------------------------------------------------------- | +| [c1de63300](https://github.com/angular/angular-cli/commit/c1de633007c423cfd9113cc781b5647e59306146) | feat | allow control of source map sources content for application builds | +| [9b682e625](https://github.com/angular/angular-cli/commit/9b682e62519e761477e6266650239bf58026a9f4) | feat | support a default outputPath option for applications | +| [156a14e38](https://github.com/angular/angular-cli/commit/156a14e387d83002fa01b33d574a6fbc078dad84) | fix | correct handling of response/request errors | +| [a8817a3b2](https://github.com/angular/angular-cli/commit/a8817a3b2a9a94bdfcba4bf690e217e7d2d4686c) | fix | handle undefined `getOrCreateAngularServerApp` during error compilation | +| [bd917d92a](https://github.com/angular/angular-cli/commit/bd917d92a653b1a5ece7ab96adfde8f8d282c34a) | fix | normalize karma asset paths before lookup | + +### @angular/ssr + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ----------------------------------------------- | +| [63428f3f1](https://github.com/angular/angular-cli/commit/63428f3f1e2ffd427011ea8a17b70f8829ae0bdf) | perf | flush headers prior to start rendering the HTML | +| [6bd7b9b4a](https://github.com/angular/angular-cli/commit/6bd7b9b4a59240caa4f19185570aec8263d8a0a7) | perf | optimized request handling performance | + + + + + +# 19.2.5 (2025-03-26) + +### @angular/build + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ----------------------------------------------------------------------- | +| [20455e2a6](https://github.com/angular/angular-cli/commit/20455e2a64558fcbb11906cb414a99d3976645d6) | fix | correct handling of response/request errors | +| [32b1dcd91](https://github.com/angular/angular-cli/commit/32b1dcd91b9f351bb6baa54f52c81c465185e01b) | fix | handle undefined `getOrCreateAngularServerApp` during error compilation | +| [7552a9fec](https://github.com/angular/angular-cli/commit/7552a9fec971f64ff27d78754ed13654e9a56b43) | fix | normalize karma asset paths before lookup | +| [1eb5b4357](https://github.com/angular/angular-cli/commit/1eb5b43575ab9908122606b94c0aaa53718678aa) | fix | update vite to 6.2.3 | + + + + + +# 18.2.16 (2025-03-26) + +### @angular-devkit/build-angular + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | --------------------------------------------------- | +| [4267a80c5](https://github.com/angular/angular-cli/commit/4267a80c5cd1e9e6aaae0f9090e21c2d71a6887f) | fix | remove `@vitejs/plugin-basic-ssl` from dependencies | + +### @angular/build + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | --------------------- | +| [9c2904d0d](https://github.com/angular/angular-cli/commit/9c2904d0d3a7b2790b27d21c1ff23e6d8a01c4f0) | fix | update vite to 5.4.15 | + + + + + +# 17.3.14 (2025-03-26) + +### @angular-devkit/build-angular + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | --------------------- | +| [cb8f859f1](https://github.com/angular/angular-cli/commit/cb8f859f181a325c15b91791c78f5326f22bb7f5) | fix | update vite to 5.4.15 | + + + + + +# 20.0.0-next.2 (2025-03-19) + +## Breaking Changes + +### @schematics/angular + +- `--server-routing` option has been removed from several schematics. Server routing will be used when using the application builder. + +### @schematics/angular + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ---------------------------------------------------------------------------------------- | +| [26fd4ea73](https://github.com/angular/angular-cli/commit/26fd4ea73ad2a0148ae587d582134c68a0bf4b86) | feat | add migrations for server rendering updates | +| [18e13e2ce](https://github.com/angular/angular-cli/commit/18e13e2ceed931d29aa5582980c7d6d1f66c9787) | feat | remove `--server-routing` option | +| [86d241629](https://github.com/angular/angular-cli/commit/86d241629ff51f0bb5988e81cac8658b01704d49) | fix | add `@angular/ssr` dependency only when `provideServerRendering` import has been updated | +| [da6ef626f](https://github.com/angular/angular-cli/commit/da6ef626f960b187a7862f0caa3d8aed38224ac2) | fix | ensure app-shell schematic consistently uses `withAppShell` | +| [f126f8d34](https://github.com/angular/angular-cli/commit/f126f8d34b087dd3a916dfb93cd255aac4d6c309) | fix | ensure module discovery checks for an NgModule decorator | +| [23fc8e1e1](https://github.com/angular/angular-cli/commit/23fc8e1e176f23442876b086bff52dd5f35abbc0) | fix | generate components without a `.component` extension/type | +| [8d715fa94](https://github.com/angular/angular-cli/commit/8d715fa948d432b18d06bcf42eed3a7681383523) | fix | generate directives without a .directive extension/type | +| [bc0f07b48](https://github.com/angular/angular-cli/commit/bc0f07b484300848ee81c5719c58909b40f99deb) | fix | generate services without a .service extension/type | +| [c0de72317](https://github.com/angular/angular-cli/commit/c0de723173549f62a524b6e6c58c6d80c8054581) | fix | replace `@angular/platform-browser-dynamic` with `@angular/platform-browser` | + +### @angular/build + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ---------------------------------------------------- | +| [f4be83119](https://github.com/angular/angular-cli/commit/f4be831197010a17394264bc74b1eb385ba95028) | feat | Support Sass package importers | +| [cb2ab43ab](https://github.com/angular/angular-cli/commit/cb2ab43abcf0e3c1a2cc584a326e1eea5eede7a8) | fix | ensure errors for missing component resources | +| [f780e8beb](https://github.com/angular/angular-cli/commit/f780e8beb3ccea27ef0442d1d3814ec2a668057d) | fix | ensure relative karma stack traces for test failures | + +### @angular/ssr + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------------------------------- | +| [33b9de3eb](https://github.com/angular/angular-cli/commit/33b9de3eb1fa596a4d5a975d05275739f2f7b8ae) | feat | expose `provideServerRendering` and remove `provideServerRouting` | +| [cdfc50c29](https://github.com/angular/angular-cli/commit/cdfc50c29a2aa6f32d172b505a0ef09e563dfc59) | feat | stabilize `AngularNodeAppEngine`, `AngularAppEngine`, and `provideServerRouting` APIs | + + + + + +# 19.2.4 (2025-03-19) + +### @schematics/angular + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ---------------------------------------------------------------------------- | +| [0a4e96bda](https://github.com/angular/angular-cli/commit/0a4e96bda054876332c5603a3bc972c3ec1eb0bf) | fix | replace `@angular/platform-browser-dynamic` with `@angular/platform-browser` | + +### @angular/build + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ---------------------------------------------------- | +| [b0b643e46](https://github.com/angular/angular-cli/commit/b0b643e46f1009be66423fdff568d042717c5e2b) | fix | ensure errors for missing component resources | +| [2cd763e89](https://github.com/angular/angular-cli/commit/2cd763e893788cfb38260d48eef40afa574a6a70) | fix | ensure relative karma stack traces for test failures | + + + + + +# 17.3.13 (2025-03-13) + +### @angular-devkit/build-angular + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | --------------------- | +| [22901df02](https://github.com/angular/angular-cli/commit/22901df0261812a3408ff9d7a7690bf6b87ec2a3) | fix | update babel packages | + + + + + +# 19.2.3 (2025-03-13) + +### @angular/build + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | --------------------- | +| [5a739820b](https://github.com/angular/angular-cli/commit/5a739820be5cc7cb25e159a1f2283db92e741f78) | fix | update babel packages | + + + + + +# 18.2.15 (2025-03-13) + +### @angular-devkit/build-angular + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | --------------------- | +| [255c8a50d](https://github.com/angular/angular-cli/commit/255c8a50d2214747c8121e963afcd96cbff39293) | fix | update babel packages | + + + # 20.0.0-next.1 (2025-03-13) diff --git a/WORKSPACE b/WORKSPACE index 9ea78d517bf9..09a28c7b4da2 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -31,9 +31,9 @@ build_bazel_rules_nodejs_dependencies() http_archive( name = "aspect_rules_js", - sha256 = "d66f8abf914a0454a69181b7b17acaae56d7b0e2784cb26b40cb3273c4d836d1", - strip_prefix = "rules_js-2.2.0", - url = "https://github.com/aspect-build/rules_js/releases/download/v2.2.0/rules_js-v2.2.0.tar.gz", + sha256 = "1be1a3ec3d3baec4a71bc09ce446eb59bb48ae31af63016481df1532a0d81aee", + strip_prefix = "rules_js-2.3.5", + url = "https://github.com/aspect-build/rules_js/releases/download/v2.3.5/rules_js-v2.3.5.tar.gz", ) load("@aspect_rules_js//js:repositories.bzl", "rules_js_dependencies") @@ -90,15 +90,15 @@ nodejs_register_toolchains( name = "node22", # The below can be removed once @rules_nodejs/nodejs is updated to latest which contains https://github.com/bazelbuild/rules_nodejs/pull/3701 node_repositories = { - "22.0.0-darwin_arm64": ("node-v22.0.0-darwin-arm64.tar.gz", "node-v22.0.0-darwin-arm64", "ea96d349cfaa67aa87ceeaa3e5b52c9167f7ac302fd8d1ff162d0785e9dc0785"), - "22.0.0-darwin_amd64": ("node-v22.0.0-darwin-x64.tar.gz", "node-v22.0.0-darwin-x64", "422a3887ff5418f0a4552d89cf99346ab8ab51bb5d384660baa88b8444d2c111"), - "22.0.0-linux_arm64": ("node-v22.0.0-linux-arm64.tar.xz", "node-v22.0.0-linux-arm64", "83711d29cbe46375bdffab5419f3d831892e24294169272f6c39edc364556241"), - "22.0.0-linux_ppc64le": ("node-v22.0.0-linux-ppc64le.tar.xz", "node-v22.0.0-linux-ppc64le", "2b3fb8707a79243bfb3131312b86716ddc3855bce21bb168095b6b916798e5e9"), - "22.0.0-linux_s390x": ("node-v22.0.0-linux-s390x.tar.xz", "node-v22.0.0-linux-s390x", "89a8efeeb9f94ce9ea251b8109e079c14919f4c0dc2cbc9f545ec47ef0886737"), - "22.0.0-linux_amd64": ("node-v22.0.0-linux-x64.tar.xz", "node-v22.0.0-linux-x64", "9122e50f2642afd5f6078cafd1f52ede60fc464284384f05c18a04d13d07ae5a"), - "22.0.0-windows_amd64": ("node-v22.0.0-win-x64.zip", "node-v22.0.0-win-x64", "32d639b47d4c0a651ff8f8d7d41a454168a3d4045be37985f9a810cf8cef6174"), + "22.11.0-darwin_arm64": ("node-v22.11.0-darwin-arm64.tar.gz", "node-v22.11.0-darwin-arm64", "2e89afe6f4e3aa6c7e21c560d8a0453d84807e97850bbb819b998531a22bdfde"), + "22.11.0-darwin_amd64": ("node-v22.11.0-darwin-x64.tar.gz", "node-v22.11.0-darwin-x64", "668d30b9512137b5f5baeef6c1bb4c46efff9a761ba990a034fb6b28b9da2465"), + "22.11.0-linux_arm64": ("node-v22.11.0-linux-arm64.tar.xz", "node-v22.11.0-linux-arm64", "6031d04b98f59ff0f7cb98566f65b115ecd893d3b7870821171708cdbaf7ae6e"), + "22.11.0-linux_ppc64le": ("node-v22.11.0-linux-ppc64le.tar.xz", "node-v22.11.0-linux-ppc64le", "d1d49d7d611b104b6d616e18ac439479d8296aa20e3741432de0e85f4735a81e"), + "22.11.0-linux_s390x": ("node-v22.11.0-linux-s390x.tar.xz", "node-v22.11.0-linux-s390x", "f474ed77d6b13d66d07589aee1c2b9175be4c1b165483e608ac1674643064a99"), + "22.11.0-linux_amd64": ("node-v22.11.0-linux-x64.tar.xz", "node-v22.11.0-linux-x64", "83bf07dd343002a26211cf1fcd46a9d9534219aad42ee02847816940bf610a72"), + "22.11.0-windows_amd64": ("node-v22.11.0-win-x64.zip", "node-v22.11.0-win-x64", "905373a059aecaf7f48c1ce10ffbd5334457ca00f678747f19db5ea7d256c236"), }, - node_version = "22.0.0", + node_version = "22.11.0", ) load("@aspect_rules_js//js:toolchains.bzl", "rules_js_register_toolchains") @@ -199,9 +199,9 @@ npm_repositories() http_archive( name = "aspect_rules_ts", - sha256 = "4263532b2fb4d16f309d80e3597191a1cb2fb69c19e95d91711bd6b97874705e", - strip_prefix = "rules_ts-3.5.0", - url = "https://github.com/aspect-build/rules_ts/releases/download/v3.5.0/rules_ts-v3.5.0.tar.gz", + sha256 = "fa5659a511f236b1ae6112258bff602fa20a40324b282734c841bc1e857797f3", + strip_prefix = "rules_ts-3.5.2", + url = "https://github.com/aspect-build/rules_ts/releases/download/v3.5.2/rules_ts-v3.5.2.tar.gz", ) load("@aspect_rules_ts//ts:repositories.bzl", "rules_ts_dependencies") @@ -234,7 +234,7 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") git_repository( name = "devinfra", - commit = "47572aba6019f368057c00966ac7ce354b1d65bc", + commit = "64d0e9da9c4309a5a05f6c0a05383203a46a700d", remote = "https://github.com/angular/dev-infra.git", ) @@ -256,3 +256,42 @@ register_toolchains( "@devinfra//bazel/git-toolchain:git_macos_arm64_toolchain", "@devinfra//bazel/git-toolchain:git_windows_toolchain", ) + +http_archive( + name = "aspect_rules_esbuild", + sha256 = "550e33ddeb86a564b22b2c5d3f84748c6639b1b2b71fae66bf362c33392cbed8", + strip_prefix = "rules_esbuild-0.21.0", + url = "https://github.com/aspect-build/rules_esbuild/releases/download/v0.21.0/rules_esbuild-v0.21.0.tar.gz", +) + +load("@aspect_rules_esbuild//esbuild:dependencies.bzl", "rules_esbuild_dependencies") + +rules_esbuild_dependencies() + +load("@aspect_rules_esbuild//esbuild:repositories.bzl", "LATEST_ESBUILD_VERSION", "esbuild_register_toolchains") + +esbuild_register_toolchains( + name = "esbuild", + esbuild_version = LATEST_ESBUILD_VERSION, +) + +git_repository( + name = "rules_angular", + commit = "be32410fcf198d500ace78469de12d5f4db458fd", + remote = "https://github.com/devversion/rules_angular.git", +) + +load("@rules_angular//setup:step_1.bzl", "rules_angular_step1") + +rules_angular_step1() + +load("@rules_angular//setup:step_2.bzl", "rules_angular_step2") + +rules_angular_step2() + +load("@rules_angular//setup:step_3.bzl", "rules_angular_step3") + +rules_angular_step3( + angular_compiler_cli = "//:node_modules/@angular/compiler-cli", + typescript = "//:node_modules/typescript", +) diff --git a/constants.bzl b/constants.bzl index 0521fb762b44..87028bf0a607 100644 --- a/constants.bzl +++ b/constants.bzl @@ -1,5 +1,5 @@ # Engine versions to stamp in a release package.json -RELEASE_ENGINES_NODE = "^20.11.1 || >=22.0.0" +RELEASE_ENGINES_NODE = "^20.11.1 || >=22.11.0" RELEASE_ENGINES_NPM = "^6.11.0 || ^7.5.6 || >=8.0.0" RELEASE_ENGINES_YARN = ">= 1.13.0" diff --git a/docs/DEVELOPER.md b/docs/DEVELOPER.md index 2544e6e2f4b1..36cf7da7fcdf 100644 --- a/docs/DEVELOPER.md +++ b/docs/DEVELOPER.md @@ -89,8 +89,8 @@ You can find more info about debugging [tests with Bazel in the docs.](https://g ### End to end tests - For a complete list of test targets use the following Bazel query: `pnpm bazel query "tests(//tests/...)"` -- Run a subset of the tests: `pnpm bazel test //tests/legacy-cli:e2e_node18 --config=e2e --test_filter="tests/i18n/ivy-localize-*"` -- Use `bazel run` to debug failing tests debugging: `pnpm bazel run //tests/legacy-cli:e2e_node18 --config=e2e --test_arg="--glob=tests/basic/aot.ts"` +- Run a subset of the tests: `pnpm bazel test //tests/legacy-cli:e2e_node22 --config=e2e --test_filter="tests/i18n/ivy-localize-*"` +- Use `bazel run` to debug failing tests debugging: `JS_BINARY__PATCH_NODE_FS=0 pnpm bazel run //tests/legacy-cli:e2e_node22 --config=e2e --test_arg="--glob=tests/basic/aot.ts"` - Provide additional `e2e_runner` options using `--test_arg`: `--test_arg="--package-manager=yarn"` When running the debug commands, Node will stop and wait for a debugger to attach. diff --git a/eslint.config.mjs b/eslint.config.mjs index dd6ed8fbae63..eeb7f6c60cd2 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -121,14 +121,6 @@ export default [ 'import/newline-after-import': 'error', 'import/no-absolute-path': 'error', 'import/no-duplicates': 'error', - - 'import/no-unassigned-import': [ - 'error', - { - allow: ['symbol-observable'], - }, - ], - 'import/order': [ 'error', { diff --git a/goldens/public-api/angular/build/index.api.md b/goldens/public-api/angular/build/index.api.md index 79240b301679..6c0c2f19145b 100644 --- a/goldens/public-api/angular/build/index.api.md +++ b/goldens/public-api/angular/build/index.api.md @@ -28,6 +28,7 @@ export type ApplicationBuilderOptions = { browser: string; budgets?: Budget[]; clearScreen?: boolean; + conditions?: string[]; crossOrigin?: CrossOrigin; define?: { [key: string]: string; @@ -39,7 +40,7 @@ export type ApplicationBuilderOptions = { fileReplacements?: FileReplacement[]; i18nDuplicateTranslation?: I18NTranslation; i18nMissingTranslation?: I18NTranslation; - index: IndexUnion; + index?: IndexUnion; inlineStyleLanguage?: InlineStyleLanguage; loader?: { [key: string]: any; @@ -49,7 +50,7 @@ export type ApplicationBuilderOptions = { optimization?: OptimizationUnion; outputHashing?: OutputHashing; outputMode?: OutputMode; - outputPath: OutputPathUnion; + outputPath?: OutputPathUnion; poll?: number; polyfills?: string[]; prerender?: PrerenderUnion; @@ -57,8 +58,8 @@ export type ApplicationBuilderOptions = { progress?: boolean; scripts?: ScriptElement[]; security?: Security; - server?: string; - serviceWorker?: ServiceWorker_2; + server?: Serv; + serviceWorker?: Serv; sourceMap?: SourceMapUnion; ssr?: SsrUnion; statsJson?: boolean; @@ -165,7 +166,7 @@ export type ExtractI18nBuilderOptions = { // @public export type NgPackagrBuilderOptions = { poll?: number; - project: string; + project?: string; tsConfig?: string; watch?: boolean; }; diff --git a/goldens/public-api/angular/ssr/index.api.md b/goldens/public-api/angular/ssr/index.api.md index f6a0d089b4b4..81764fcc1f62 100644 --- a/goldens/public-api/angular/ssr/index.api.md +++ b/goldens/public-api/angular/ssr/index.api.md @@ -27,7 +27,7 @@ export enum PrerenderFallback { } // @public -export function provideServerRouting(routes: ServerRoute[], ...features: ServerRoutesFeature[]): EnvironmentProviders; +export function provideServerRendering(...features: ServerRenderingFeature[]): EnvironmentProviders; // @public export enum RenderMode { @@ -72,7 +72,10 @@ export interface ServerRouteServer extends ServerRouteCommon { } // @public -export function withAppShell(component: Type | (() => Promise | DefaultExport>>)): ServerRoutesFeature; +export function withAppShell(component: Type | (() => Promise | DefaultExport>>)): ServerRenderingFeature; + +// @public +export function withRoutes(routes: ServerRoute[]): ServerRenderingFeature; // (No @packageDocumentation comment for this package) diff --git a/goldens/public-api/angular/ssr/node/index.api.md b/goldens/public-api/angular/ssr/node/index.api.md index 0bbeb8ae145a..0f30fa7e99c5 100644 --- a/goldens/public-api/angular/ssr/node/index.api.md +++ b/goldens/public-api/angular/ssr/node/index.api.md @@ -5,15 +5,16 @@ ```ts import { ApplicationRef } from '@angular/core'; -import type { Http2ServerRequest } from 'node:http2'; -import type { Http2ServerResponse } from 'node:http2'; -import type { IncomingMessage } from 'node:http'; -import type { ServerResponse } from 'node:http'; +import { Http2ServerRequest } from 'node:http2'; +import { Http2ServerResponse } from 'node:http2'; +import { IncomingMessage } from 'node:http'; +import { ServerResponse } from 'node:http'; import { StaticProvider } from '@angular/core'; import { Type } from '@angular/core'; // @public export class AngularNodeAppEngine { + constructor(); handle(request: IncomingMessage | Http2ServerRequest, requestContext?: unknown): Promise; } diff --git a/goldens/public-api/angular_devkit/core/index.api.md b/goldens/public-api/angular_devkit/core/index.api.md index fe8b609ccf68..802ed4569719 100644 --- a/goldens/public-api/angular_devkit/core/index.api.md +++ b/goldens/public-api/angular_devkit/core/index.api.md @@ -18,6 +18,9 @@ import { ValidateFunction } from 'ajv'; // @public (undocumented) function addUndefinedDefaults(value: JsonValue, _pointer: JsonPointer, schema?: JsonSchema): JsonValue; +// @public (undocumented) +function addUndefinedObjectDefaults(value: JsonValue, _pointer: JsonPointer, schema?: JsonSchema): JsonValue; + // @public class AliasHost extends ResolverHost { // (undocumented) @@ -1297,6 +1300,7 @@ class TransformLogger extends Logger { declare namespace transforms { export { + addUndefinedObjectDefaults, addUndefinedDefaults } } diff --git a/modules/testing/builder/BUILD.bazel b/modules/testing/builder/BUILD.bazel index 6983baca7fda..eeadaca4f839 100644 --- a/modules/testing/builder/BUILD.bazel +++ b/modules/testing/builder/BUILD.bazel @@ -1,5 +1,5 @@ load("@npm2//:defs.bzl", "npm_link_all_packages") -load("//tools:defaults2.bzl", "jasmine_test", "ts_project") +load("//tools:defaults.bzl", "jasmine_test", "ts_project") package(default_visibility = ["//visibility:public"]) @@ -24,8 +24,8 @@ ts_project( deps = [ ":node_modules/@angular-devkit/architect", ":node_modules/@angular-devkit/core", + ":node_modules/rxjs", "//:node_modules/@types/node", - "//:node_modules/rxjs", ], ) diff --git a/modules/testing/builder/package.json b/modules/testing/builder/package.json index d315fc454ede..9e62d668aeee 100644 --- a/modules/testing/builder/package.json +++ b/modules/testing/builder/package.json @@ -3,6 +3,7 @@ "@angular-devkit/core": "workspace:*", "@angular-devkit/architect": "workspace:*", "@angular/ssr": "workspace:*", - "@angular-devkit/build-angular": "workspace:*" + "@angular-devkit/build-angular": "workspace:*", + "rxjs": "7.8.2" } } diff --git a/modules/testing/builder/projects/hello-world-app/src/main.ts b/modules/testing/builder/projects/hello-world-app/src/main.ts index 0b9dfa142956..d975b48d7808 100644 --- a/modules/testing/builder/projects/hello-world-app/src/main.ts +++ b/modules/testing/builder/projects/hello-world-app/src/main.ts @@ -6,10 +6,10 @@ * found in the LICENSE file at https://angular.dev/license */ -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { platformBrowser } from '@angular/platform-browser'; import { AppModule } from './app/app.module'; -platformBrowserDynamic() +platformBrowser() .bootstrapModule(AppModule) .catch(err => console.log(err)); diff --git a/modules/testing/builder/src/builder-harness.ts b/modules/testing/builder/src/builder-harness.ts index 9fdca970a277..ecee882739d8 100644 --- a/modules/testing/builder/src/builder-harness.ts +++ b/modules/testing/builder/src/builder-harness.ts @@ -104,7 +104,11 @@ export class BuilderHarness { ...builderInfo, }; - this.schemaRegistry.addPostTransform(json.schema.transforms.addUndefinedDefaults); + if (builderInfo?.builderName?.startsWith('@angular/build:')) { + this.schemaRegistry.addPostTransform(json.schema.transforms.addUndefinedObjectDefaults); + } else { + this.schemaRegistry.addPostTransform(json.schema.transforms.addUndefinedDefaults); + } } private resolvePath(path: string): string { diff --git a/package.json b/package.json index 135047a4f7e8..eadd413512bb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@angular/devkit-repo", - "version": "20.0.0-next.1", + "version": "20.0.0-next.6", "private": true, "description": "Software Development Kit for Angular", "keywords": [ @@ -34,7 +34,7 @@ }, "packageManager": "pnpm@9.15.6", "engines": { - "node": "^20.11.1 || >=22.0.0", + "node": "^20.11.1 || >=22.11.0", "npm": "Please use pnpm instead of NPM to install dependencies", "yarn": "Please use pnpm instead of Yarn to install dependencies", "pnpm": "^9.15.6" @@ -46,49 +46,34 @@ }, "homepage": "https://github.com/angular/angular-cli", "devDependencies": { - "@ampproject/remapping": "2.3.0", - "@angular/animations": "20.0.0-next.2", - "@angular/cdk": "20.0.0-next.1", - "@angular/common": "20.0.0-next.2", - "@angular/compiler": "20.0.0-next.2", - "@angular/compiler-cli": "20.0.0-next.2", - "@angular/core": "20.0.0-next.2", - "@angular/forms": "20.0.0-next.2", - "@angular/localize": "20.0.0-next.2", - "@angular/material": "20.0.0-next.1", - "@angular/ng-dev": "https://github.com/angular/dev-infra-private-ng-dev-builds.git#9fd3adb2e8b9a0fef1ba5bc905a900e018445e05", - "@angular/platform-browser": "20.0.0-next.2", - "@angular/platform-browser-dynamic": "20.0.0-next.2", - "@angular/platform-server": "20.0.0-next.2", - "@angular/router": "20.0.0-next.2", - "@angular/service-worker": "20.0.0-next.2", - "@babel/core": "7.26.10", - "@babel/generator": "7.26.10", - "@babel/helper-annotate-as-pure": "7.25.9", - "@babel/helper-split-export-declaration": "7.24.7", - "@babel/plugin-syntax-import-attributes": "7.26.0", - "@babel/plugin-transform-async-generator-functions": "7.26.8", - "@babel/plugin-transform-async-to-generator": "7.25.9", - "@babel/plugin-transform-runtime": "7.26.10", - "@babel/preset-env": "7.26.9", - "@babel/runtime": "7.26.10", - "@bazel/bazelisk": "1.25.0", + "@angular/animations": "20.0.0-next.7", + "@angular/cdk": "20.0.0-next.7", + "@angular/common": "20.0.0-next.7", + "@angular/compiler": "20.0.0-next.7", + "@angular/compiler-cli": "20.0.0-next.7", + "@angular/core": "20.0.0-next.7", + "@angular/forms": "20.0.0-next.7", + "@angular/localize": "20.0.0-next.7", + "@angular/material": "20.0.0-next.7", + "@angular/ng-dev": "https://github.com/angular/dev-infra-private-ng-dev-builds.git#94729f43b53fb611c71c695733d2fb3d873cd25d", + "@angular/platform-browser": "20.0.0-next.7", + "@angular/platform-server": "20.0.0-next.7", + "@angular/router": "20.0.0-next.7", + "@angular/service-worker": "20.0.0-next.7", + "@bazel/bazelisk": "1.26.0", "@bazel/buildifier": "8.0.3", - "@discoveryjs/json-ext": "0.6.3", - "@eslint/compat": "1.2.7", - "@eslint/eslintrc": "3.3.0", - "@eslint/js": "9.22.0", - "@inquirer/prompts": "7.3.3", - "@listr2/prompt-adapter-inquirer": "2.0.18", + "@eslint/compat": "1.2.8", + "@eslint/eslintrc": "3.3.1", + "@eslint/js": "9.24.0", "@rollup/plugin-alias": "^5.1.1", "@rollup/plugin-commonjs": "^28.0.0", "@rollup/plugin-json": "^6.1.0", - "@rollup/plugin-node-resolve": "^13.0.5", + "@rollup/plugin-node-resolve": "16.0.1", "@stylistic/eslint-plugin": "^4.0.0", "@types/babel__core": "7.20.5", "@types/babel__generator": "^7.6.8", "@types/browser-sync": "^2.27.0", - "@types/express": "^4.16.0", + "@types/express": "~5.0.1", "@types/http-proxy": "^1.17.4", "@types/ini": "^4.0.0", "@types/jasmine": "~5.1.0", @@ -100,7 +85,7 @@ "@types/node": "^20.17.19", "@types/npm-package-arg": "^6.1.0", "@types/pacote": "^11.1.3", - "@types/picomatch": "^3.0.0", + "@types/picomatch": "^4.0.0", "@types/progress": "^2.0.3", "@types/resolve": "^1.17.1", "@types/semver": "^7.3.12", @@ -109,106 +94,57 @@ "@types/yargs": "^17.0.20", "@types/yargs-parser": "^21.0.0", "@types/yarnpkg__lockfile": "^1.1.5", - "@typescript-eslint/eslint-plugin": "8.26.1", - "@typescript-eslint/parser": "8.26.1", - "@web/test-runner": "^0.20.0", - "@yarnpkg/lockfile": "1.1.0", + "@typescript-eslint/eslint-plugin": "8.30.1", + "@typescript-eslint/parser": "8.30.1", "ajv": "8.17.1", - "ajv-formats": "3.0.1", "ansi-colors": "4.1.3", - "autoprefixer": "10.4.21", - "babel-loader": "10.0.0", - "beasties": "0.2.0", - "browser-sync": "3.0.3", - "browserslist": "^4.21.5", + "beasties": "0.3.2", "buffer": "6.0.3", - "chokidar": "4.0.3", - "copy-webpack-plugin": "13.0.0", - "css-loader": "7.1.2", - "debug": "^4.1.1", - "esbuild": "0.25.1", - "esbuild-wasm": "0.25.1", - "eslint": "9.22.0", - "eslint-config-prettier": "10.1.1", + "esbuild": "0.25.2", + "esbuild-wasm": "0.25.2", + "eslint": "9.24.0", + "eslint-config-prettier": "10.1.2", "eslint-plugin-header": "3.1.1", "eslint-plugin-import": "2.31.0", - "express": "4.21.2", + "express": "5.1.0", "fast-glob": "3.3.3", "globals": "16.0.0", "http-proxy": "^1.18.1", - "http-proxy-middleware": "3.0.3", - "https-proxy-agent": "7.0.6", + "http-proxy-middleware": "3.0.5", "husky": "9.1.7", - "ini": "5.0.0", - "istanbul-lib-instrument": "6.0.3", "jasmine": "~5.6.0", "jasmine-core": "~5.6.0", "jasmine-reporters": "^2.5.2", "jasmine-spec-reporter": "~7.0.0", - "jsonc-parser": "3.3.1", "karma": "~6.4.0", "karma-chrome-launcher": "~3.2.0", "karma-coverage": "~2.2.0", "karma-jasmine": "~5.1.0", "karma-jasmine-html-reporter": "~2.1.0", "karma-source-map-support": "1.4.0", - "less": "4.2.2", - "less-loader": "12.2.0", - "license-webpack-plugin": "4.0.2", - "listr2": "8.2.5", - "lmdb": "3.2.6", - "loader-utils": "3.3.1", + "listr2": "8.3.2", "lodash": "^4.17.21", - "magic-string": "0.30.17", - "mini-css-extract-plugin": "2.9.2", - "mrmime": "2.0.1", - "ng-packagr": "20.0.0-next.1", "npm": "^11.0.0", - "npm-package-arg": "12.0.2", - "npm-pick-manifest": "10.0.0", - "open": "10.1.0", - "ora": "5.4.1", - "pacote": "20.0.0", - "parse5-html-rewriting-stream": "7.0.0", - "picomatch": "4.0.2", - "piscina": "4.8.0", - "postcss": "8.5.3", - "postcss-loader": "8.1.1", + "magic-string": "0.30.17", + "rollup-plugin-dts": "6.2.1", + "rollup-plugin-sourcemaps2": "0.5.0", "prettier": "^3.0.0", "protractor": "~7.0.0", "puppeteer": "18.2.1", "quicktype-core": "23.0.171", - "resolve-url-loader": "5.0.0", - "rollup": "4.35.0", + "rollup": "4.40.0", "rollup-license-plugin": "~3.0.1", - "rollup-plugin-sourcemaps": "^0.6.0", - "rxjs": "7.8.2", - "sass": "1.85.1", - "sass-loader": "16.0.5", "semver": "7.7.1", "shelljs": "^0.9.0", - "source-map": "0.7.4", - "source-map-loader": "5.0.0", "source-map-support": "0.5.21", - "symbol-observable": "4.0.0", "tar": "^7.0.0", - "terser": "5.39.0", - "tinyglobby": "0.2.12", - "tree-kill": "1.2.2", "ts-node": "^10.9.1", "tslib": "2.8.1", - "typescript": "5.8.2", - "undici": "7.5.0", + "typescript": "5.8.3", + "undici": "7.8.0", "unenv": "^1.10.0", - "verdaccio": "6.0.5", + "verdaccio": "6.1.2", "verdaccio-auth-memory": "^10.0.0", - "watchpack": "2.4.2", - "webpack": "5.98.0", - "webpack-dev-middleware": "7.4.2", - "webpack-dev-server": "5.2.0", - "webpack-merge": "6.0.1", - "webpack-subresource-integrity": "5.1.0", - "yargs": "17.7.2", "yargs-parser": "21.1.1", "zone.js": "^0.15.0" }, @@ -233,15 +169,10 @@ "peerDependencies": { "protobufjs": "*" } - }, - "@angular/platform-server": { - "peerDependencies": { - "rxjs": "*" - } } } }, "resolutions": { - "typescript": "5.8.2" + "typescript": "5.8.3" } } diff --git a/packages/angular/build/BUILD.bazel b/packages/angular/build/BUILD.bazel index 98a15eec1458..c842065f865a 100644 --- a/packages/angular/build/BUILD.bazel +++ b/packages/angular/build/BUILD.bazel @@ -1,6 +1,6 @@ load("@devinfra//bazel/api-golden:index_rjs.bzl", "api_golden_test_npm_package") load("@npm2//:defs.bzl", "npm_link_all_packages") -load("//tools:defaults2.bzl", "copy_to_bin", "jasmine_test", "npm_package", "ts_project") +load("//tools:defaults.bzl", "copy_to_bin", "jasmine_test", "npm_package", "ts_project") load("//tools:ts_json_schema.bzl", "ts_json_schema") licenses(["notice"]) @@ -74,13 +74,34 @@ ts_project( data = RUNTIME_ASSETS, module_name = "@angular/build", deps = [ + ":node_modules/@ampproject/remapping", ":node_modules/@angular-devkit/architect", ":node_modules/@angular-devkit/core", ":node_modules/@angular/ssr", + ":node_modules/@babel/core", + ":node_modules/@babel/helper-annotate-as-pure", + ":node_modules/@babel/helper-split-export-declaration", ":node_modules/@inquirer/confirm", ":node_modules/@vitejs/plugin-basic-ssl", + ":node_modules/browserslist", + ":node_modules/https-proxy-agent", + ":node_modules/istanbul-lib-instrument", + ":node_modules/jsonc-parser", + ":node_modules/less", + ":node_modules/listr2", + ":node_modules/lmdb", + ":node_modules/magic-string", + ":node_modules/mrmime", + ":node_modules/ng-packagr", + ":node_modules/parse5-html-rewriting-stream", + ":node_modules/picomatch", + ":node_modules/piscina", + ":node_modules/postcss", + ":node_modules/sass", + ":node_modules/source-map-support", + ":node_modules/tinyglobby", ":node_modules/vite", - "//:node_modules/@ampproject/remapping", + ":node_modules/watchpack", "//:node_modules/@angular/common", "//:node_modules/@angular/compiler", "//:node_modules/@angular/compiler-cli", @@ -88,10 +109,6 @@ ts_project( "//:node_modules/@angular/localize", "//:node_modules/@angular/platform-server", "//:node_modules/@angular/service-worker", - "//:node_modules/@babel/core", - "//:node_modules/@babel/helper-annotate-as-pure", - "//:node_modules/@babel/helper-split-export-declaration", - "//:node_modules/@babel/plugin-syntax-import-attributes", "//:node_modules/@types/babel__core", "//:node_modules/@types/karma", "//:node_modules/@types/less", @@ -100,31 +117,13 @@ ts_project( "//:node_modules/@types/semver", "//:node_modules/@types/watchpack", "//:node_modules/beasties", - "//:node_modules/browserslist", "//:node_modules/esbuild", "//:node_modules/esbuild-wasm", - "//:node_modules/https-proxy-agent", - "//:node_modules/istanbul-lib-instrument", - "//:node_modules/jsonc-parser", "//:node_modules/karma", - "//:node_modules/less", - "//:node_modules/listr2", - "//:node_modules/lmdb", - "//:node_modules/magic-string", - "//:node_modules/mrmime", - "//:node_modules/ng-packagr", - "//:node_modules/parse5-html-rewriting-stream", - "//:node_modules/picomatch", - "//:node_modules/piscina", - "//:node_modules/postcss", "//:node_modules/rollup", - "//:node_modules/sass", "//:node_modules/semver", - "//:node_modules/source-map-support", - "//:node_modules/tinyglobby", "//:node_modules/tslib", "//:node_modules/typescript", - "//:node_modules/watchpack", ], ) @@ -138,8 +137,8 @@ ts_project( deps = [ ":build", ":node_modules/@angular-devkit/core", + ":node_modules/@babel/core", "//:node_modules/@angular/compiler-cli", - "//:node_modules/@babel/core", "//:node_modules/@types/jasmine", "//:node_modules/prettier", "//:node_modules/typescript", @@ -169,9 +168,8 @@ ts_project( "//:node_modules/@angular/compiler-cli", "//:node_modules/@angular/core", "//:node_modules/@angular/platform-browser", - "//:node_modules/@angular/platform-browser-dynamic", "//:node_modules/@angular/router", - "//:node_modules/rxjs", + ":node_modules/rxjs", "//:node_modules/tslib", "//:node_modules/typescript", "//:node_modules/zone.js", @@ -202,10 +200,9 @@ ts_project( "//:node_modules/@angular/compiler-cli", "//:node_modules/@angular/core", "//:node_modules/@angular/platform-browser", - "//:node_modules/@angular/platform-browser-dynamic", "//:node_modules/@angular/router", - "//:node_modules/ng-packagr", - "//:node_modules/rxjs", + ":node_modules/ng-packagr", + ":node_modules/rxjs", "//:node_modules/tslib", "//:node_modules/typescript", "//:node_modules/zone.js", @@ -238,9 +235,8 @@ ts_project( "//:node_modules/@angular/compiler-cli", "//:node_modules/@angular/core", "//:node_modules/@angular/platform-browser", - "//:node_modules/@angular/platform-browser-dynamic", "//:node_modules/@angular/router", - "//:node_modules/rxjs", + ":node_modules/rxjs", "//:node_modules/tslib", "//:node_modules/typescript", "//:node_modules/zone.js", diff --git a/packages/angular/build/package.json b/packages/angular/build/package.json index beab6f8fa95c..5585f1512374 100644 --- a/packages/angular/build/package.json +++ b/packages/angular/build/package.json @@ -23,26 +23,26 @@ "@babel/core": "7.26.10", "@babel/helper-annotate-as-pure": "7.25.9", "@babel/helper-split-export-declaration": "7.24.7", - "@babel/plugin-syntax-import-attributes": "7.26.0", - "@inquirer/confirm": "5.1.7", + "@inquirer/confirm": "5.1.9", "@vitejs/plugin-basic-ssl": "2.0.0", - "beasties": "0.2.0", + "beasties": "0.3.2", "browserslist": "^4.23.0", - "esbuild": "0.25.1", + "esbuild": "0.25.2", "https-proxy-agent": "7.0.6", "istanbul-lib-instrument": "6.0.3", - "listr2": "8.2.5", + "jsonc-parser": "3.3.1", + "listr2": "8.3.2", "magic-string": "0.30.17", "mrmime": "2.0.1", "parse5-html-rewriting-stream": "7.0.0", "picomatch": "4.0.2", - "piscina": "4.8.0", - "rollup": "4.35.0", - "sass": "1.85.1", + "piscina": "4.9.2", + "rollup": "4.40.0", + "sass": "1.86.3", "semver": "7.7.1", "source-map-support": "0.5.21", "tinyglobby": "0.2.12", - "vite": "6.2.1", + "vite": "6.2.6", "watchpack": "2.4.2" }, "optionalDependencies": { @@ -50,12 +50,18 @@ }, "devDependencies": { "@angular/ssr": "workspace:*", - "@angular-devkit/core": "workspace:*" + "@angular-devkit/core": "workspace:*", + "less": "4.3.0", + "ng-packagr": "20.0.0-next.6", + "postcss": "8.5.3", + "rxjs": "7.8.2" }, "peerDependencies": { + "@angular/core": "0.0.0-ANGULAR-FW-PEER-DEP", "@angular/compiler": "0.0.0-ANGULAR-FW-PEER-DEP", "@angular/compiler-cli": "0.0.0-ANGULAR-FW-PEER-DEP", "@angular/localize": "0.0.0-ANGULAR-FW-PEER-DEP", + "@angular/platform-browser": "0.0.0-ANGULAR-FW-PEER-DEP", "@angular/platform-server": "0.0.0-ANGULAR-FW-PEER-DEP", "@angular/service-worker": "0.0.0-ANGULAR-FW-PEER-DEP", "@angular/ssr": "^0.0.0-PLACEHOLDER", @@ -64,12 +70,19 @@ "ng-packagr": "0.0.0-NG-PACKAGR-PEER-DEP", "postcss": "^8.4.0", "tailwindcss": "^2.0.0 || ^3.0.0 || ^4.0.0", + "tslib": "^2.3.0", "typescript": ">=5.8 <5.9" }, "peerDependenciesMeta": { + "@angular/core": { + "optional": true + }, "@angular/localize": { "optional": true }, + "@angular/platform-browser": { + "optional": true + }, "@angular/platform-server": { "optional": true }, diff --git a/packages/angular/build/src/builders/application/index.ts b/packages/angular/build/src/builders/application/index.ts index afe657e59da7..80261c41277f 100644 --- a/packages/angular/build/src/builders/application/index.ts +++ b/packages/angular/build/src/builders/application/index.ts @@ -28,6 +28,8 @@ import { import { Result, ResultKind } from './results'; import { Schema as ApplicationBuilderOptions } from './schema'; +const isNodeV22orHigher = Number(process.versions.node.split('.', 1)[0]) >= 22; + export type { ApplicationBuilderOptions }; export async function* buildApplicationInternal( @@ -211,7 +213,17 @@ export async function* buildApplication( await fs.writeFile(fullFilePath, file.contents); } else { // Copy file contents - await fs.copyFile(file.inputPath, fullFilePath, fs.constants.COPYFILE_FICLONE); + if (isNodeV22orHigher) { + // Use newer `cp` API on Node.js 22+ (minimum v22 for CLI is 22.11) + await fs.cp(file.inputPath, fullFilePath, { + mode: fs.constants.COPYFILE_FICLONE, + preserveTimestamps: true, + }); + } else { + // For Node.js 20 use `copyFile` (`cp` is not stable for v20) + // TODO: Remove when Node.js 20 is no longer supported + await fs.copyFile(file.inputPath, fullFilePath, fs.constants.COPYFILE_FICLONE); + } } }); diff --git a/packages/angular/build/src/builders/application/options.ts b/packages/angular/build/src/builders/application/options.ts index a58c60386c9c..5600c1e633ad 100644 --- a/packages/angular/build/src/builders/application/options.ts +++ b/packages/angular/build/src/builders/application/options.ts @@ -9,7 +9,7 @@ import type { BuilderContext } from '@angular-devkit/architect'; import type { Plugin } from 'esbuild'; import { realpathSync } from 'node:fs'; -import { access, constants } from 'node:fs/promises'; +import { access, constants, readFile } from 'node:fs/promises'; import { createRequire } from 'node:module'; import path from 'node:path'; import { normalizeAssetPatterns, normalizeOptimization, normalizeSourceMaps } from '../../utils'; @@ -259,10 +259,12 @@ export async function normalizeOptions( : await getTailwindConfig(searchDirectories, workspaceRoot, context); let serverEntryPoint: string | undefined; - if (options.server) { + if (typeof options.server === 'string') { + if (options.server === '') { + throw new Error('The "server" option cannot be an empty string.'); + } + serverEntryPoint = path.join(workspaceRoot, options.server); - } else if (options.server === '') { - throw new Error('The "server" option cannot be an empty string.'); } let prerenderOptions; @@ -295,7 +297,7 @@ export async function normalizeOptions( }; } - const outputPath = options.outputPath; + const outputPath = options.outputPath ?? path.join(workspaceRoot, 'dist', projectName); const outputOptions: NormalizedOutputOptions = { browser: 'browser', server: 'server', @@ -330,11 +332,16 @@ export async function normalizeOptions( let indexHtmlOptions; // index can never have a value of `true` but in the schema it's of type `boolean`. if (typeof options.index !== 'boolean') { + let indexInput: string; let indexOutput: string; // The output file will be created within the configured output path if (typeof options.index === 'string') { - indexOutput = options.index; + indexInput = indexOutput = path.join(workspaceRoot, options.index); + } else if (typeof options.index === 'undefined') { + indexInput = path.join(projectSourceRoot, 'index.html'); + indexOutput = 'index.html'; } else { + indexInput = path.join(workspaceRoot, options.index.input); indexOutput = options.index.output || 'index.html'; } @@ -354,10 +361,7 @@ export async function normalizeOptions( : indexBaseName; indexHtmlOptions = { - input: path.join( - workspaceRoot, - typeof options.index === 'string' ? options.index : options.index.input, - ), + input: indexInput, output: indexOutput, insertionOrder: [ ['polyfills', true], @@ -496,6 +500,8 @@ export async function normalizeOptions( security, templateUpdates: !!options.templateUpdates, incrementalResults: !!options.incrementalResults, + customConditions: options.conditions, + frameworkVersion: await findFrameworkVersion(projectRoot), }; } @@ -701,5 +707,31 @@ function normalizeExternals(value: string[] | undefined): string[] | undefined { return undefined; } - return [...new Set(value.map((d) => (d.endsWith('/*') ? d.slice(0, -2) : d)))]; + return [ + ...new Set( + value.map((d) => + // remove "/*" wildcard in the end if provided string is not path-like + d.endsWith('/*') && !/^\.{0,2}\//.test(d) ? d.slice(0, -2) : d, + ), + ), + ]; +} + +async function findFrameworkVersion(projectRoot: string): Promise { + // Create a custom require function for ESM compliance. + // NOTE: The trailing slash is significant. + const projectResolve = createRequire(projectRoot + '/').resolve; + + try { + const manifestPath = projectResolve('@angular/core/package.json'); + const manifestData = await readFile(manifestPath, 'utf-8'); + const manifestObject = JSON.parse(manifestData) as { version: string }; + const version = manifestObject.version; + + return version; + } catch { + throw new Error( + 'Error: It appears that "@angular/core" is missing as a dependency. Please ensure it is included in your project.', + ); + } } diff --git a/packages/angular/build/src/builders/application/schema.json b/packages/angular/build/src/builders/application/schema.json index d990e3a3cff3..934bfe9390f4 100644 --- a/packages/angular/build/src/builders/application/schema.json +++ b/packages/angular/build/src/builders/application/schema.json @@ -17,7 +17,6 @@ "description": "The full path for the browser entry point to the application, relative to the current workspace." }, "server": { - "type": "string", "description": "The full path for the server entry point to the application, relative to the current workspace.", "oneOf": [ { @@ -293,6 +292,13 @@ "type": "string" } }, + "conditions": { + "description": "Custom package resolution conditions used to resolve conditional exports/imports. Defaults to ['module', 'development'/'production']. The following special conditions are always present if the requirements are satisfied: 'default', 'import', 'require', 'browser', 'node'.", + "type": "array", + "items": { + "type": "string" + } + }, "fileReplacements": { "description": "Replace compilation source files with other compilation source files in the build.", "type": "array", @@ -370,6 +376,11 @@ "type": "boolean", "description": "Resolve vendor packages source maps.", "default": false + }, + "sourcesContent": { + "type": "boolean", + "description": "Output original source content for files within the source map.", + "default": true } }, "additionalProperties": false @@ -605,7 +616,7 @@ } }, "additionalProperties": false, - "required": ["outputPath", "index", "browser", "tsConfig"], + "required": ["browser", "tsConfig"], "definitions": { "assetPattern": { "oneOf": [ diff --git a/packages/angular/build/src/builders/application/setup-bundling.ts b/packages/angular/build/src/builders/application/setup-bundling.ts index 413c625eb81c..9b47bc67e49d 100644 --- a/packages/angular/build/src/builders/application/setup-bundling.ts +++ b/packages/angular/build/src/builders/application/setup-bundling.ts @@ -177,6 +177,7 @@ export function createComponentStyleBundler( // the same as being disabled. Disabling has the advantage of avoiding the overhead // of sourcemap processing. sourcemapOptions.styles && !sourcemapOptions.hidden ? 'linked' : false, + sourcesContent: sourcemapOptions.sourcesContent, outputNames, includePaths: stylePreprocessorOptions?.includePaths, // string[] | undefined' is not assignable to type '(Version | DeprecationOrId)[] | undefined'. diff --git a/packages/angular/build/src/builders/application/tests/behavior/component-stylesheets_spec.ts b/packages/angular/build/src/builders/application/tests/behavior/component-stylesheets_spec.ts index 7853c3a920b0..ecc460bcb405 100644 --- a/packages/angular/build/src/builders/application/tests/behavior/component-stylesheets_spec.ts +++ b/packages/angular/build/src/builders/application/tests/behavior/component-stylesheets_spec.ts @@ -44,5 +44,44 @@ describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => { harness.expectFile('dist/browser/main.js').content.not.toContain('variables'); }); + + it('should generate an error for a missing stylesheet with AOT', async () => { + await harness.modifyFile('src/app/app.component.ts', (content) => { + return content.replace('./app.component.css', './not-present.css'); + }); + + 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(`Could not find stylesheet file './not-present.css'`), + }), + ); + }); + + it('should generate an error for a missing stylesheet with JIT', async () => { + await harness.modifyFile('src/app/app.component.ts', (content) => { + return content.replace('./app.component.css', './not-present.css'); + }); + + harness.useTarget('build', { + ...BASE_OPTIONS, + aot: false, + }); + + const { result, logs } = await harness.executeOnce({ outputLogsOnFailure: false }); + expect(result?.success).toBeFalse(); + expect(logs).toContain( + jasmine.objectContaining({ + level: 'error', + message: jasmine.stringContaining('Could not resolve'), + }), + ); + }); }); }); diff --git a/packages/angular/build/src/builders/application/tests/behavior/component-templates_spec.ts b/packages/angular/build/src/builders/application/tests/behavior/component-templates_spec.ts new file mode 100644 index 000000000000..687ed78dc74c --- /dev/null +++ b/packages/angular/build/src/builders/application/tests/behavior/component-templates_spec.ts @@ -0,0 +1,33 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import { buildApplication } from '../../index'; +import { APPLICATION_BUILDER_INFO, BASE_OPTIONS, describeBuilder } from '../setup'; + +describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => { + describe('Behavior: "Component Templates"', () => { + it('should generate an error for a missing template', async () => { + await harness.modifyFile('src/app/app.component.ts', (content) => { + return content.replace('./app.component.html', './not-present.html'); + }); + + 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(`Could not find template file './not-present.html'`), + }), + ); + }); + }); +}); diff --git a/packages/angular/build/src/builders/application/tests/options/app-shell_spec.ts b/packages/angular/build/src/builders/application/tests/options/app-shell_spec.ts index a946357af48c..9c8384b29efc 100644 --- a/packages/angular/build/src/builders/application/tests/options/app-shell_spec.ts +++ b/packages/angular/build/src/builders/application/tests/options/app-shell_spec.ts @@ -69,10 +69,10 @@ const appShellRouteFiles: Record = { export class AppServerModule {} `, 'src/main.ts': ` - import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + import { platformBrowser } from '@angular/platform-browser'; import { AppModule } from './app/app.module'; - platformBrowserDynamic().bootstrapModule(AppModule).catch(err => console.log(err)); + platformBrowser().bootstrapModule(AppModule).catch(err => console.log(err)); `, 'src/app/app-routing.module.ts': ` import { NgModule } from '@angular/core'; diff --git a/packages/angular/build/src/builders/application/tests/options/conditions_spec.ts b/packages/angular/build/src/builders/application/tests/options/conditions_spec.ts new file mode 100644 index 000000000000..11e2cdb62ab0 --- /dev/null +++ b/packages/angular/build/src/builders/application/tests/options/conditions_spec.ts @@ -0,0 +1,162 @@ +/** + * @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 { + setupConditionImport, + setTargetMapping, +} from '../../../../../../../../modules/testing/builder/src/dev_prod_mode'; +import { buildApplication } from '../../index'; +import { APPLICATION_BUILDER_INFO, BASE_OPTIONS, describeBuilder } from '../setup'; + +describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => { + describe('Option: "conditions"', () => { + beforeEach(async () => { + await setupConditionImport(harness); + }); + + interface ImportsTestCase { + name: string; + mapping: unknown; + output?: string; + customConditions?: string[]; + } + + const GOOD_TARGET = './src/good.js'; + const BAD_TARGET = './src/bad.js'; + + const emptyArrayCases: ImportsTestCase[] = [ + { + name: 'default fallback without matching condition', + mapping: { + 'never': BAD_TARGET, + 'default': GOOD_TARGET, + }, + }, + { + name: 'development condition', + mapping: { + 'development': BAD_TARGET, + 'default': GOOD_TARGET, + }, + }, + { + name: 'production condition', + mapping: { + 'production': BAD_TARGET, + 'default': GOOD_TARGET, + }, + }, + { + name: 'browser condition (in browser)', + mapping: { + 'browser': GOOD_TARGET, + 'default': BAD_TARGET, + }, + }, + { + name: 'browser condition (in server)', + output: 'server/main.server.mjs', + mapping: { + 'browser': BAD_TARGET, + 'default': GOOD_TARGET, + }, + }, + ]; + + for (const testCase of emptyArrayCases) { + describe('with empty array ' + testCase.name, () => { + beforeEach(async () => { + await setTargetMapping(harness, testCase.mapping); + }); + + it('resolves to expected target', async () => { + harness.useTarget('build', { + ...BASE_OPTIONS, + optimization: true, + ssr: true, + server: 'src/main.ts', + conditions: [], + }); + + const { result } = await harness.executeOnce(); + + expect(result?.success).toBeTrue(); + const outputFile = `dist/${testCase.output ?? 'browser/main.js'}`; + harness.expectFile(outputFile).content.toContain('"good-value"'); + harness.expectFile(outputFile).content.not.toContain('"bad-value"'); + }); + }); + } + + const customCases: ImportsTestCase[] = [ + { + name: 'default fallback without matching condition', + mapping: { + 'never': BAD_TARGET, + 'default': GOOD_TARGET, + }, + }, + { + name: 'development condition', + mapping: { + 'development': BAD_TARGET, + 'default': GOOD_TARGET, + }, + }, + { + name: 'staging condition', + mapping: { + 'staging': GOOD_TARGET, + 'production': BAD_TARGET, + 'default': BAD_TARGET, + }, + }, + { + name: 'browser condition (in browser)', + mapping: { + 'browser': GOOD_TARGET, + 'staging': BAD_TARGET, + 'default': BAD_TARGET, + }, + }, + { + name: 'browser condition (in server)', + output: 'server/main.server.mjs', + mapping: { + 'browser': BAD_TARGET, + 'default': GOOD_TARGET, + }, + }, + ]; + + for (const testCase of customCases) { + describe('with custom condition ' + testCase.name, () => { + beforeEach(async () => { + await setTargetMapping(harness, testCase.mapping); + }); + + it('resolves to expected target', async () => { + harness.useTarget('build', { + ...BASE_OPTIONS, + optimization: true, + ssr: true, + server: 'src/main.ts', + conditions: ['staging'], + }); + + const { result } = await harness.executeOnce(); + + expect(result?.success).toBeTrue(); + const outputFile = `dist/${testCase.output ?? 'browser/main.js'}`; + harness.expectFile(outputFile).content.toContain('"good-value"'); + harness.expectFile(outputFile).content.not.toContain('"bad-value"'); + }); + }); + } + }); +}); diff --git a/packages/angular/build/src/builders/application/tests/options/index_spec.ts b/packages/angular/build/src/builders/application/tests/options/index_spec.ts index d3a5fe9e57d3..11228658bbce 100644 --- a/packages/angular/build/src/builders/application/tests/options/index_spec.ts +++ b/packages/angular/build/src/builders/application/tests/options/index_spec.ts @@ -62,6 +62,23 @@ describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => { harness.expectFile('dist/browser/index.html').content.toContain('TEST_123'); }); + it('should use the the index.html file within the project source root when not present', async () => { + harness.useTarget('build', { + ...BASE_OPTIONS, + index: undefined, + }); + + await harness.writeFile( + 'src/index.html', + 'TEST_123', + ); + + const { result } = await harness.executeOnce(); + + expect(result?.success).toBe(true); + harness.expectFile('dist/browser/index.html').content.toContain('TEST_123'); + }); + // TODO: Build needs to be fixed to not throw an unhandled exception for this case xit('should fail build when a string path to non-existent file', async () => { harness.useTarget('build', { diff --git a/packages/angular/build/src/builders/application/tests/options/optimization-scripts_spec.ts b/packages/angular/build/src/builders/application/tests/options/optimization-scripts_spec.ts new file mode 100644 index 000000000000..013451467bb0 --- /dev/null +++ b/packages/angular/build/src/builders/application/tests/options/optimization-scripts_spec.ts @@ -0,0 +1,42 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import { buildApplication } from '../../index'; +import { APPLICATION_BUILDER_INFO, BASE_OPTIONS, describeBuilder } from '../setup'; + +describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => { + describe('Option: "optimization.scripts"', () => { + it(`should include 'setClassMetadata' calls when false`, async () => { + harness.useTarget('build', { + ...BASE_OPTIONS, + optimization: { + scripts: false, + }, + }); + + const { result } = await harness.executeOnce(); + expect(result?.success).toBeTrue(); + + harness.expectFile('dist/browser/main.js').content.toContain('setClassMetadata('); + }); + + it(`should not include 'setClassMetadata' calls when true`, async () => { + harness.useTarget('build', { + ...BASE_OPTIONS, + optimization: { + scripts: true, + }, + }); + + const { result } = await harness.executeOnce(); + expect(result?.success).toBeTrue(); + + harness.expectFile('dist/browser/main.js').content.not.toContain('setClassMetadata('); + }); + }); +}); diff --git a/packages/angular/build/src/builders/application/tests/options/sourcemap_spec.ts b/packages/angular/build/src/builders/application/tests/options/sourcemap_spec.ts index 72df6c710f35..c5cb8c321d32 100644 --- a/packages/angular/build/src/builders/application/tests/options/sourcemap_spec.ts +++ b/packages/angular/build/src/builders/application/tests/options/sourcemap_spec.ts @@ -209,6 +209,82 @@ describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => { harness.expectFile('dist/browser/main.js.map').content.toContain('"x_google_ignoreList"'); }); + it(`should not include 'sourcesContent' field when 'sourcesContent' suboption is false`, async () => { + await harness.writeFile('src/styles.css', `div { flex: 1 }`); + + harness.useTarget('build', { + ...BASE_OPTIONS, + styles: ['src/styles.css'], + sourceMap: { scripts: true, styles: true, sourcesContent: false }, + }); + + const { result } = await harness.executeOnce(); + + expect(result?.success).toBeTrue(); + + harness.expectFile('dist/browser/main.js.map').content.not.toContain('"sourcesContent"'); + + harness.expectFile('dist/browser/styles.css.map').toExist(); + harness.expectFile('dist/browser/styles.css.map').content.not.toContain('"sourcesContent"'); + }); + + it(`should include 'sourcesContent' field when 'sourcesContent' suboption is true`, async () => { + await harness.writeFile('src/styles.css', `div { flex: 1 }`); + + harness.useTarget('build', { + ...BASE_OPTIONS, + styles: ['src/styles.css'], + sourceMap: { scripts: true, styles: true, sourcesContent: true }, + }); + + const { result } = await harness.executeOnce(); + + expect(result?.success).toBeTrue(); + + harness.expectFile('dist/browser/main.js.map').content.toContain('"sourcesContent"'); + + harness.expectFile('dist/browser/styles.css.map').toExist(); + harness.expectFile('dist/browser/styles.css.map').content.toContain('"sourcesContent"'); + }); + + it(`should include 'sourcesContent' field when 'sourcesContent' suboption is not present`, async () => { + await harness.writeFile('src/styles.css', `div { flex: 1 }`); + + harness.useTarget('build', { + ...BASE_OPTIONS, + styles: ['src/styles.css'], + sourceMap: { scripts: true, styles: true }, + }); + + const { result } = await harness.executeOnce(); + + expect(result?.success).toBeTrue(); + + harness.expectFile('dist/browser/main.js.map').content.toContain('"sourcesContent"'); + + harness.expectFile('dist/browser/styles.css.map').toExist(); + harness.expectFile('dist/browser/styles.css.map').content.toContain('"sourcesContent"'); + }); + + it(`should include 'sourcesContent' field when 'sourceMap' is true`, async () => { + await harness.writeFile('src/styles.css', `div { flex: 1 }`); + + harness.useTarget('build', { + ...BASE_OPTIONS, + styles: ['src/styles.css'], + sourceMap: true, + }); + + const { result } = await harness.executeOnce(); + + expect(result?.success).toBeTrue(); + + harness.expectFile('dist/browser/main.js.map').content.toContain('"sourcesContent"'); + + harness.expectFile('dist/browser/styles.css.map').toExist(); + harness.expectFile('dist/browser/styles.css.map').content.toContain('"sourcesContent"'); + }); + it('should generate component sourcemaps when sourcemaps when true', async () => { await harness.writeFile('src/app/app.component.css', `* { color: red}`); diff --git a/packages/angular/build/src/builders/application/tests/setup.ts b/packages/angular/build/src/builders/application/tests/setup.ts index 93a5cda2a1df..ca8a54a0bf31 100644 --- a/packages/angular/build/src/builders/application/tests/setup.ts +++ b/packages/angular/build/src/builders/application/tests/setup.ts @@ -13,7 +13,7 @@ import { Schema } from '../schema'; export * from '../../../../../../../modules/testing/builder/src'; export const APPLICATION_BUILDER_INFO = Object.freeze({ - name: '@angular-devkit/build-angular:application', + name: '@angular/build:application', schemaPath: __dirname + '/../schema.json', }); diff --git a/packages/angular/build/src/builders/dev-server/tests/behavior/component-updates_spec.ts b/packages/angular/build/src/builders/dev-server/tests/behavior/component-updates_spec.ts index d471d487c556..742e07ea3b74 100644 --- a/packages/angular/build/src/builders/dev-server/tests/behavior/component-updates_spec.ts +++ b/packages/angular/build/src/builders/dev-server/tests/behavior/component-updates_spec.ts @@ -47,5 +47,39 @@ describeServeBuilder(executeDevServer, DEV_SERVER_BUILDER_INFO, (harness, setupT expect(response?.headers.get('Cache-Control')).toEqual('no-cache'); expect(output).toBe(''); }); + + it('sets ngHmrMode define to true when HMR is enabled', async () => { + harness.useTarget('serve', { + ...BASE_OPTIONS, + hmr: true, + }); + + await harness.writeFile( + 'src/main.ts', + 'declare const ngHmrMode: boolean; console.log(`HMR=${ngHmrMode}`);', + ); + + const { result, content } = await executeOnceAndFetch(harness, 'main.js'); + + expect(result?.success).toBeTrue(); + expect(content).toContain('HMR=${true}'); + }); + + it('sets ngHmrMode define to false when HMR is disabled', async () => { + harness.useTarget('serve', { + ...BASE_OPTIONS, + hmr: false, + }); + + await harness.writeFile( + 'src/main.ts', + 'declare const ngHmrMode: boolean; console.log(`HMR=${ngHmrMode}`);', + ); + + const { result, content } = await executeOnceAndFetch(harness, 'main.js'); + + expect(result?.success).toBeTrue(); + expect(content).toContain('HMR=${false}'); + }); }); }); diff --git a/packages/angular/build/src/builders/dev-server/tests/options/hmr_spec.ts b/packages/angular/build/src/builders/dev-server/tests/options/hmr_spec.ts deleted file mode 100644 index 4b9ba6a4c780..000000000000 --- a/packages/angular/build/src/builders/dev-server/tests/options/hmr_spec.ts +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.dev/license - */ - -import { logging } from '@angular-devkit/core'; -import { executeDevServer } from '../../index'; -import { executeOnceAndFetch } from '../execute-fetch'; -import { describeServeBuilder } from '../jasmine-helpers'; -import { BASE_OPTIONS, DEV_SERVER_BUILDER_INFO } from '../setup'; - -describeServeBuilder(executeDevServer, DEV_SERVER_BUILDER_INFO, (harness, setupTarget) => { - describe('option: "hmr"', () => { - beforeEach(async () => { - setupTarget(harness, {}); - }); - - it('shows message with opt out steps by default', async () => { - harness.useTarget('serve', { - ...BASE_OPTIONS, - }); - - const { result, logs } = await executeOnceAndFetch(harness, '/'); - - expect(result?.success).toBeTrue(); - expect(logs).toContain( - jasmine.objectContaining({ - message: jasmine.stringMatching('Component HMR has been enabled'), - }), - ); - expect(logs).toContain( - jasmine.objectContaining({ - message: jasmine.stringMatching('--no-hmr'), - }), - ); - }); - - it('shows message with opt out steps when explicitly enabled', async () => { - harness.useTarget('serve', { - ...BASE_OPTIONS, - hmr: true, - }); - - const { result, logs } = await executeOnceAndFetch(harness, '/'); - - expect(result?.success).toBeTrue(); - expect(logs).toContain( - jasmine.objectContaining({ - message: jasmine.stringMatching('Component HMR has been enabled'), - }), - ); - expect(logs).toContain( - jasmine.objectContaining({ - message: jasmine.stringMatching('--no-hmr'), - }), - ); - }); - - it('does not show enabled message with opt out steps when explicitly disabled', async () => { - harness.useTarget('serve', { - ...BASE_OPTIONS, - hmr: false, - }); - - const { result, logs } = await executeOnceAndFetch(harness, '/'); - - expect(result?.success).toBeTrue(); - expect(logs).not.toContain( - jasmine.objectContaining({ - message: jasmine.stringMatching('Component HMR has been enabled'), - }), - ); - expect(logs).not.toContain( - jasmine.objectContaining({ - message: jasmine.stringMatching('--no-hmr'), - }), - ); - }); - }); -}); diff --git a/packages/angular/build/src/builders/dev-server/tests/setup.ts b/packages/angular/build/src/builders/dev-server/tests/setup.ts index da9362134b75..2c5906e9644d 100644 --- a/packages/angular/build/src/builders/dev-server/tests/setup.ts +++ b/packages/angular/build/src/builders/dev-server/tests/setup.ts @@ -22,7 +22,7 @@ export * from '../../../../../../../modules/testing/builder/src'; // TODO: Remove and use import after Vite-based dev server is moved to new package export const APPLICATION_BUILDER_INFO = Object.freeze({ - name: '@angular-devkit/build-angular:application', + name: '@angular/build:application', schemaPath: path.join( path.dirname(require.resolve('@angular/build/package.json')), 'src/builders/application/schema.json', @@ -49,7 +49,7 @@ export const APPLICATION_BASE_OPTIONS = Object.freeze({ }); export const DEV_SERVER_BUILDER_INFO = Object.freeze({ - name: '@angular-devkit/build-angular:dev-server', + name: '@angular/build:dev-server', schemaPath: __dirname + '/../schema.json', }); diff --git a/packages/angular/build/src/builders/dev-server/vite-server.ts b/packages/angular/build/src/builders/dev-server/vite-server.ts index f211ae587263..b09775c4a312 100644 --- a/packages/angular/build/src/builders/dev-server/vite-server.ts +++ b/packages/angular/build/src/builders/dev-server/vite-server.ts @@ -166,15 +166,6 @@ export async function* serveWithVite( // This will also replace file-based/inline styles as code if external runtime styles are not enabled. browserOptions.templateUpdates = serverOptions.liveReload && serverOptions.hmr && useComponentTemplateHmr; - if (browserOptions.templateUpdates) { - context.logger.warn( - 'Component HMR has been enabled.\n' + - 'If you encounter application reload issues, you can manually reload the page to bypass HMR and/or disable this feature with the' + - ' `--no-hmr` command line option.\n' + - 'Please consider reporting any issues you encounter here: https://github.com/angular/angular-cli/issues\n', - ); - } - browserOptions.incrementalResults = true; // Setup the prebundling transformer that will be shared across Vite prebundling requests @@ -356,8 +347,9 @@ export async function* serveWithVite( externalMetadata.implicitServer.length = 0; externalMetadata.implicitBrowser.length = 0; - externalMetadata.explicitBrowser.push(...explicit); - externalMetadata.explicitServer.push(...explicit, ...builtinModules); + const externalDeps = browserOptions.externalDependencies ?? []; + externalMetadata.explicitBrowser.push(...explicit, ...externalDeps); + externalMetadata.explicitServer.push(...explicit, ...externalDeps, ...builtinModules); externalMetadata.implicitServer.push(...implicitServerFiltered); externalMetadata.implicitBrowser.push(...implicitBrowserFiltered); @@ -447,7 +439,10 @@ export async function* serveWithVite( componentStyles, templateUpdates, browserOptions.loader as EsbuildLoaderOption | undefined, - browserOptions.define, + { + ...browserOptions.define, + 'ngHmrMode': browserOptions.templateUpdates ? 'true' : 'false', + }, extensions?.middleware, transformers?.indexHtml, thirdPartySourcemaps, diff --git a/packages/angular/build/src/builders/karma/application_builder.ts b/packages/angular/build/src/builders/karma/application_builder.ts index bfe7af7711ca..2c9c86067e6c 100644 --- a/packages/angular/build/src/builders/karma/application_builder.ts +++ b/packages/angular/build/src/builders/karma/application_builder.ts @@ -25,6 +25,7 @@ import { findTests, getTestEntrypoints } from './find-tests'; import { Schema as KarmaBuilderOptions } from './schema'; const localResolve = createRequire(__filename).resolve; +const isWindows = process.platform === 'win32'; interface BuildOptions extends ApplicationBuilderInternalOptions { // We know that it's always a string since we set it. @@ -69,7 +70,14 @@ class AngularAssetsMiddleware { let err = null; try { const url = new URL(`http://${req.headers['host']}${req.url}`); - const file = this.latestBuildFiles.files[url.pathname.slice(1)]; + // Remove the leading slash from the URL path and convert to platform specific. + // The latest build files will use the platform path separator. + let pathname = url.pathname.slice(1); + if (isWindows) { + pathname = pathname.replaceAll(path.posix.sep, path.win32.sep); + } + + const file = this.latestBuildFiles.files[pathname]; if (file?.origin === 'disk') { this.serveFile(file.inputPath, undefined, res); @@ -353,6 +361,7 @@ async function collectEntrypoints( return getTestEntrypoints(testFiles, { projectSourceRoot, workspaceRoot: context.workspaceRoot }); } +// eslint-disable-next-line max-lines-per-function async function initializeApplication( options: KarmaBuilderOptions, context: BuilderContext, @@ -396,6 +405,7 @@ async function initializeApplication( entryPoints, tsConfig: options.tsConfig, outputPath, + preserveSymlinks: options.preserveSymlinks, aot: options.aot, index: false, outputHashing: OutputHashing.None, @@ -438,7 +448,8 @@ async function initializeApplication( await writeTestFiles(buildOutput.files, buildOptions.outputPath); // We need to add this to the beginning *after* the testing framework has - // prepended its files. + // prepended its files. The output path is required for each since they are + // added later in the test process via a plugin. const polyfillsFile: FilePattern = { pattern: `${outputPath}/polyfills.js`, included: true, @@ -454,12 +465,14 @@ async function initializeApplication( watched: false, }; + karmaOptions.basePath = outputPath; + karmaOptions.files ??= []; if (options.scripts?.length) { // This should be more granular to support named bundles. // However, it replicates the behavior of the Karma Webpack-based builder. karmaOptions.files.push({ - pattern: `${outputPath}/scripts.js`, + pattern: `scripts.js`, watched: false, type: 'js', }); @@ -467,18 +480,18 @@ async function initializeApplication( karmaOptions.files.push( // Serve global setup script. - { pattern: `${outputPath}/${mainName}.js`, type: 'module', watched: false }, + { pattern: `${mainName}.js`, type: 'module', watched: false }, // Serve all source maps. - { pattern: `${outputPath}/*.map`, included: false, watched: false }, + { pattern: `*.map`, included: false, watched: false }, // These are the test entrypoints. - { pattern: `${outputPath}/spec-*.js`, type: 'module', watched: false }, + { pattern: `spec-*.js`, type: 'module', watched: false }, ); if (hasChunkOrWorkerFiles(buildOutput.files)) { karmaOptions.files.push( // Allow loading of chunk-* files but don't include them all on load. { - pattern: `${outputPath}/{chunk,worker}-*.js`, + pattern: `{chunk,worker}-*.js`, type: 'module', included: false, watched: false, @@ -488,7 +501,7 @@ async function initializeApplication( if (options.styles?.length) { // Serve CSS outputs on page load, these are the global styles. - karmaOptions.files.push({ pattern: `${outputPath}/*.css`, type: 'css', watched: false }); + karmaOptions.files.push({ pattern: `*.css`, type: 'css', watched: false }); } const parsedKarmaConfig: Config & ConfigOptions = await karma.config.parseConfig( @@ -497,6 +510,17 @@ async function initializeApplication( { promiseConfig: true, throwErrors: true }, ); + // Check for jsdom which does not support executing ESM scripts. + // If present, remove jsdom and issue a warning. + const updatedBrowsers = parsedKarmaConfig.browsers?.filter((browser) => browser !== 'jsdom'); + if (parsedKarmaConfig.browsers?.length !== updatedBrowsers?.length) { + parsedKarmaConfig.browsers = updatedBrowsers; + context.logger.warn( + `'jsdom' does not support ESM code execution and cannot be used for karma testing.` + + ` The 'jsdom' entry has been removed from the 'browsers' option.`, + ); + } + // Remove the webpack plugin/framework: // Alternative would be to make the Karma plugin "smart" but that's a tall order // with managing unneeded imports etc.. diff --git a/packages/angular/build/src/builders/karma/index.ts b/packages/angular/build/src/builders/karma/index.ts index ca7ee3ed827e..1e5f5613e3a3 100644 --- a/packages/angular/build/src/builders/karma/index.ts +++ b/packages/angular/build/src/builders/karma/index.ts @@ -68,7 +68,7 @@ function getBaseKarmaOptions( // Convert browsers from a string to an array if (typeof options.browsers === 'string' && options.browsers) { - karmaOptions.browsers = options.browsers.split(','); + karmaOptions.browsers = options.browsers.split(',').map((browser) => browser.trim()); } else if (options.browsers === false) { karmaOptions.browsers = []; } diff --git a/packages/angular/build/src/builders/karma/polyfills/init_test_bed.js b/packages/angular/build/src/builders/karma/polyfills/init_test_bed.js index 0857396195c8..fdbb476808c3 100644 --- a/packages/angular/build/src/builders/karma/polyfills/init_test_bed.js +++ b/packages/angular/build/src/builders/karma/polyfills/init_test_bed.js @@ -7,13 +7,10 @@ */ import { getTestBed } from '@angular/core/testing'; -import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting, -} from '@angular/platform-browser-dynamic/testing'; +import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing'; // Initialize the Angular testing environment. -getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { +getTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting(), { errorOnUnknownElements: true, errorOnUnknownProperties: true, }); diff --git a/packages/angular/build/src/builders/karma/tests/options/browsers_spec.ts b/packages/angular/build/src/builders/karma/tests/options/browsers_spec.ts new file mode 100644 index 000000000000..d3f774e750c5 --- /dev/null +++ b/packages/angular/build/src/builders/karma/tests/options/browsers_spec.ts @@ -0,0 +1,33 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import { execute } from '../../index'; +import { BASE_OPTIONS, KARMA_BUILDER_INFO, describeKarmaBuilder } from '../setup'; + +describeKarmaBuilder(execute, KARMA_BUILDER_INFO, (harness, setupTarget) => { + describe('Option: "browsers"', () => { + it('should warn if jsdom is used', async () => { + await setupTarget(harness); + + harness.useTarget('test', { + ...BASE_OPTIONS, + browsers: BASE_OPTIONS.browsers + ',jsdom', + }); + + const { result, logs } = await harness.executeOnce(); + expect(result?.success).toBeTrue(); + expect(logs).toContain( + jasmine.objectContaining({ + message: jasmine.stringMatching( + `'jsdom' does not support ESM code execution and cannot be used for karma testing.`, + ), + }), + ); + }); + }); +}); diff --git a/packages/angular/build/src/builders/ng-packagr/builder.ts b/packages/angular/build/src/builders/ng-packagr/builder.ts index f2dc60ebf30c..24b606aeede1 100644 --- a/packages/angular/build/src/builders/ng-packagr/builder.ts +++ b/packages/angular/build/src/builders/ng-packagr/builder.ts @@ -30,7 +30,7 @@ export async function* execute( // Purge old build disk cache. await purgeStaleBuildCache(context); - const root = context.workspaceRoot; + const workspaceRoot = context.workspaceRoot; let packager; try { packager = (await import('ng-packagr')).ngPackagr(); @@ -47,18 +47,22 @@ export async function* execute( throw error; } - packager.forProject(resolve(root, options.project)); - - if (options.tsConfig) { - packager.withTsConfig(resolve(root, options.tsConfig)); - } - const projectName = context.target?.project; if (!projectName) { throw new Error('The builder requires a target.'); } const metadata = await context.getProjectMetadata(projectName); + const ngPackagrConfig = options.project + ? join(workspaceRoot, options.project) + : join(workspaceRoot, (metadata.root as string | undefined) ?? '', 'ng-package.json'); + + packager.forProject(ngPackagrConfig); + + if (options.tsConfig) { + packager.withTsConfig(resolve(workspaceRoot, options.tsConfig)); + } + const { enabled: cacheEnabled, path: cacheDirectory } = normalizeCacheOptions( metadata, context.workspaceRoot, diff --git a/packages/angular/build/src/builders/ng-packagr/schema.json b/packages/angular/build/src/builders/ng-packagr/schema.json index da76255f092a..0aa80ed6fe5f 100644 --- a/packages/angular/build/src/builders/ng-packagr/schema.json +++ b/packages/angular/build/src/builders/ng-packagr/schema.json @@ -22,6 +22,5 @@ "description": "Enable and define the file watching poll time period in milliseconds." } }, - "additionalProperties": false, - "required": ["project"] + "additionalProperties": false } diff --git a/packages/angular/build/src/tools/angular/angular-host.ts b/packages/angular/build/src/tools/angular/angular-host.ts index 103b3e37ac68..38c096f67674 100644 --- a/packages/angular/build/src/tools/angular/angular-host.ts +++ b/packages/angular/build/src/tools/angular/angular-host.ts @@ -208,6 +208,9 @@ export function createAngularCompilerHost( host.resourceNameToFileName = function (resourceName, containingFile) { const resolvedPath = nodePath.join(nodePath.dirname(containingFile), resourceName); + if (!this.fileExists(resolvedPath)) { + return null; + } // All resource names that have template file extensions are assumed to be templates // TODO: Update compiler to provide the resource type to avoid extension matching here. diff --git a/packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts b/packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts index 97444b7b4e66..72131901ae94 100644 --- a/packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts +++ b/packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts @@ -35,6 +35,7 @@ export interface CompilerPluginOptions { sourcemap: boolean | 'external'; tsconfig: string; jit?: boolean; + includeTestMetadata?: boolean; advancedOptimizations?: boolean; thirdPartySourcemaps?: boolean; @@ -292,7 +293,6 @@ export function createCompilerPlugin( pluginOptions, preserveSymlinks, build.initialOptions.conditions, - build.initialOptions.absWorkingDir, ), ); shouldTsIgnoreJs = !initializationResult.compilerOptions.allowJs; @@ -623,7 +623,6 @@ function createCompilerOptionsTransformer( pluginOptions: CompilerPluginOptions, preserveSymlinks: boolean | undefined, customConditions: string[] | undefined, - absWorkingDir: string | undefined, ): Parameters[2] { return (compilerOptions) => { // target of 9 is ES2022 (using the number avoids an expensive import of typescript just for an enum) @@ -699,13 +698,17 @@ function createCompilerOptionsTransformer( // Synchronize custom resolve conditions. // Set if using the supported bundler resolution mode (bundler is the default in new projects) - if (compilerOptions.moduleResolution === 100 /* ModuleResolutionKind.Bundler */) { + if ( + compilerOptions.moduleResolution === 100 /* ModuleResolutionKind.Bundler */ || + compilerOptions.module === 200 /** ModuleKind.Preserve */ + ) { compilerOptions.customConditions = customConditions; } return { ...compilerOptions, noEmitOnError: false, + composite: false, inlineSources: !!pluginOptions.sourcemap, inlineSourceMap: !!pluginOptions.sourcemap, sourceMap: undefined, @@ -714,6 +717,7 @@ function createCompilerOptionsTransformer( preserveSymlinks, externalRuntimeStyles: pluginOptions.externalRuntimeStyles, _enableHmr: !!pluginOptions.templateUpdates, + supportTestBed: !!pluginOptions.includeTestMetadata, }; }; } diff --git a/packages/angular/build/src/tools/esbuild/angular/component-stylesheets.ts b/packages/angular/build/src/tools/esbuild/angular/component-stylesheets.ts index ce9cca6c7529..3b8d12ec1461 100644 --- a/packages/angular/build/src/tools/esbuild/angular/component-stylesheets.ts +++ b/packages/angular/build/src/tools/esbuild/angular/component-stylesheets.ts @@ -74,6 +74,11 @@ export class ComponentStylesheetBundler { buildOptions.entryPoints = [entry]; } + // Angular encapsulation does not support nesting + // See: https://github.com/angular/angular/issues/58996 + buildOptions.supported ??= {}; + buildOptions.supported['nesting'] = false; + return buildOptions; }); }); @@ -124,6 +129,11 @@ export class ComponentStylesheetBundler { buildOptions.entryPoints = [`${namespace};${entry}`]; } + // Angular encapsulation does not support nesting + // See: https://github.com/angular/angular/issues/58996 + buildOptions.supported ??= {}; + buildOptions.supported['nesting'] = false; + buildOptions.plugins.push({ name: 'angular-component-styles', setup(build) { diff --git a/packages/angular/build/src/tools/esbuild/application-code-bundle.ts b/packages/angular/build/src/tools/esbuild/application-code-bundle.ts index 58bdd78c2dcf..45825ee607a0 100644 --- a/packages/angular/build/src/tools/esbuild/application-code-bundle.ts +++ b/packages/angular/build/src/tools/esbuild/application-code-bundle.ts @@ -546,6 +546,8 @@ function getEsBuildCommonOptions(options: NormalizedApplicationBuildOptions): Bu loaderExtensions, jsonLogs, i18nOptions, + customConditions, + frameworkVersion, } = options; // Ensure unique hashes for i18n translation changes when using post-process inlining. @@ -563,18 +565,37 @@ function getEsBuildCommonOptions(options: NormalizedApplicationBuildOptions): Bu footer = { js: `/**i18n:${createHash('sha256').update(i18nHash).digest('hex')}*/` }; } + // Core conditions that are always included + const conditions = [ + // Required to support rxjs 7.x which will use es5 code if this condition is not present + 'es2015', + 'es2020', + ]; + // The pre-linked code is not used with JIT for two reasons: + // 1) The pre-linked code may not have the metadata included that is required for JIT + // 2) The CLI is otherwise setup to use runtime linking for JIT to match the application template compilation + if (!jit) { + // The pre-linked package condition is based on the framework version. + // Currently this is specific to each patch version of the framework. + conditions.push('angular:linked-' + frameworkVersion); + } + + // Append custom conditions if present + if (customConditions) { + conditions.push(...customConditions); + } else { + // Include default conditions + conditions.push('module'); + conditions.push(optimizationOptions.scripts ? 'production' : 'development'); + } + return { absWorkingDir: workspaceRoot, format: 'esm', bundle: true, packages: 'bundle', assetNames: outputNames.media, - conditions: [ - 'es2020', - 'es2015', - 'module', - optimizationOptions.scripts ? 'production' : 'development', - ], + conditions, resolveExtensions: ['.ts', '.tsx', '.mjs', '.js', '.cjs'], metafile: true, legalComments: options.extractLicenses ? 'none' : 'eof', @@ -586,6 +607,7 @@ function getEsBuildCommonOptions(options: NormalizedApplicationBuildOptions): Bu outdir: workspaceRoot, outExtension: outExtension ? { '.js': `.${outExtension}` } : undefined, sourcemap: sourcemapOptions.scripts && (sourcemapOptions.hidden ? 'external' : true), + sourcesContent: sourcemapOptions.sourcesContent, splitting: true, chunkNames: options.namedChunks ? '[name]-[hash]' : 'chunk-[hash]', tsconfig, @@ -600,6 +622,7 @@ function getEsBuildCommonOptions(options: NormalizedApplicationBuildOptions): Bu ...(optimizationOptions.scripts ? { 'ngDevMode': 'false' } : undefined), 'ngJitMode': jit ? 'true' : 'false', 'ngServerMode': 'false', + 'ngHmrMode': options.templateUpdates ? 'true' : 'false', }, loader: loaderExtensions, footer, diff --git a/packages/angular/build/src/tools/esbuild/compiler-plugin-options.ts b/packages/angular/build/src/tools/esbuild/compiler-plugin-options.ts index 355bbad228ff..04ce3ef94f4a 100644 --- a/packages/angular/build/src/tools/esbuild/compiler-plugin-options.ts +++ b/packages/angular/build/src/tools/esbuild/compiler-plugin-options.ts @@ -27,6 +27,7 @@ export function createCompilerPluginOptions( jit, externalRuntimeStyles, instrumentForCoverage, + optimizationOptions, } = options; const incremental = !!options.watch; @@ -43,5 +44,6 @@ export function createCompilerPluginOptions( externalRuntimeStyles, instrumentForCoverage, templateUpdates, + includeTestMetadata: !optimizationOptions.scripts, }; } diff --git a/packages/angular/build/src/tools/esbuild/global-styles.ts b/packages/angular/build/src/tools/esbuild/global-styles.ts index 64f670971c3d..682885c43350 100644 --- a/packages/angular/build/src/tools/esbuild/global-styles.ts +++ b/packages/angular/build/src/tools/esbuild/global-styles.ts @@ -53,6 +53,7 @@ export function createGlobalStylesBundleOptions( optimization: !!optimizationOptions.styles.minify, inlineFonts: !!optimizationOptions.fonts.inline, sourcemap: !!sourcemapOptions.styles && (sourcemapOptions.hidden ? 'external' : true), + sourcesContent: sourcemapOptions.sourcesContent, preserveSymlinks, target, externalDependencies, diff --git a/packages/angular/build/src/tools/esbuild/javascript-transformer-worker.ts b/packages/angular/build/src/tools/esbuild/javascript-transformer-worker.ts index 7bf29fc2e7a8..3d7c8d2ca126 100644 --- a/packages/angular/build/src/tools/esbuild/javascript-transformer-worker.ts +++ b/packages/angular/build/src/tools/esbuild/javascript-transformer-worker.ts @@ -61,9 +61,7 @@ async function transformWithBabel( options.sourcemap && (!!options.thirdPartySourcemaps || !/[\\/]node_modules[\\/]/.test(filename)); - // @ts-expect-error Import attribute syntax plugin does not currently have type definitions - const { default: importAttributePlugin } = await import('@babel/plugin-syntax-import-attributes'); - const plugins: PluginItem[] = [importAttributePlugin]; + const plugins: PluginItem[] = []; if (options.instrumentForCoverage) { const { default: coveragePlugin } = await import('../babel/plugins/add-code-coverage.js'); diff --git a/packages/angular/build/src/tools/esbuild/stylesheets/bundle-options.ts b/packages/angular/build/src/tools/esbuild/stylesheets/bundle-options.ts index 2a6200124ea5..9bbcb7c5ecb8 100644 --- a/packages/angular/build/src/tools/esbuild/stylesheets/bundle-options.ts +++ b/packages/angular/build/src/tools/esbuild/stylesheets/bundle-options.ts @@ -24,6 +24,7 @@ export interface BundleStylesheetOptions { inlineFonts: boolean; preserveSymlinks?: boolean; sourcemap: boolean | 'external' | 'inline' | 'linked'; + sourcesContent?: boolean; outputNames: { bundles: string; media: string }; includePaths?: string[]; sass?: StylesheetPluginsass; @@ -77,6 +78,7 @@ export function createStylesheetBundleOptions( minify: options.optimization, metafile: true, sourcemap: options.sourcemap, + sourcesContent: options.sourcesContent, outdir: options.workspaceRoot, write: false, platform: 'browser', diff --git a/packages/angular/build/src/tools/esbuild/stylesheets/sass-language.ts b/packages/angular/build/src/tools/esbuild/stylesheets/sass-language.ts index b3972ac407f4..4bccfb3adba4 100644 --- a/packages/angular/build/src/tools/esbuild/stylesheets/sass-language.ts +++ b/packages/angular/build/src/tools/esbuild/stylesheets/sass-language.ts @@ -43,7 +43,8 @@ export const SassStylesheetLanguage = Object.freeze({ resolveDir = dirname(fileURLToPath(options.containingUrl)); } - const result = await build.resolve(url, { + const path = url.startsWith('pkg:') ? url.slice(4) : url; + const result = await build.resolve(path, { kind: 'import-rule', resolveDir, }); @@ -56,8 +57,8 @@ export const SassStylesheetLanguage = Object.freeze({ }); function parsePackageName(url: string): { packageName: string; readonly pathSegments: string[] } { - const parts = url.split('/'); - const hasScope = parts.length >= 2 && parts[0].startsWith('@'); + const parts = (url.startsWith('pkg:') ? url.slice(4) : url).split('/'); + const hasScope = parts.length >= 2 && parts[0][0] === '@'; const [nameOrScope, nameOrFirstPath, ...pathPart] = parts; const packageName = hasScope ? `${nameOrScope}/${nameOrFirstPath}` : nameOrScope; diff --git a/packages/angular/build/src/tools/vite/middlewares/ssr-middleware.ts b/packages/angular/build/src/tools/vite/middlewares/ssr-middleware.ts index 36e602491fd4..387a94a2ba53 100644 --- a/packages/angular/build/src/tools/vite/middlewares/ssr-middleware.ts +++ b/packages/angular/build/src/tools/vite/middlewares/ssr-middleware.ts @@ -40,15 +40,16 @@ export function createAngularSsrInternalMiddleware( const { writeResponseToNodeResponse, createWebRequestFromNodeRequest } = await loadEsmModule('@angular/ssr/node'); - // The following is necessary because accessing the module after invalidation may result in an empty module, - // which can trigger a `TypeError: ɵgetOrCreateAngularServerApp is not a function` error. - // TODO: look into why. - await server.ssrLoadModule('/main.server.mjs'); - const { ɵgetOrCreateAngularServerApp } = (await server.ssrLoadModule('/main.server.mjs')) as { ɵgetOrCreateAngularServerApp: typeof getOrCreateAngularServerApp; }; + // `ɵgetOrCreateAngularServerApp` can be undefined right after an error. + // See: https://github.com/angular/angular-cli/issues/29907 + if (!ɵgetOrCreateAngularServerApp) { + return next(); + } + const angularServerApp = ɵgetOrCreateAngularServerApp({ allowStaticRouteRender: true, }); diff --git a/packages/angular/build/src/utils/normalize-source-maps.ts b/packages/angular/build/src/utils/normalize-source-maps.ts index ddeb3e5322d4..cf26ca236bae 100644 --- a/packages/angular/build/src/utils/normalize-source-maps.ts +++ b/packages/angular/build/src/utils/normalize-source-maps.ts @@ -13,11 +13,13 @@ export function normalizeSourceMaps(sourceMap: SourceMapUnion): SourceMapClass { const styles = typeof sourceMap === 'object' ? sourceMap.styles : sourceMap; const hidden = (typeof sourceMap === 'object' && sourceMap.hidden) || false; const vendor = (typeof sourceMap === 'object' && sourceMap.vendor) || false; + const sourcesContent = typeof sourceMap === 'object' ? sourceMap.sourcesContent : sourceMap; return { vendor, hidden, scripts, styles, + sourcesContent, }; } diff --git a/packages/angular/build/src/utils/server-rendering/launch-server.ts b/packages/angular/build/src/utils/server-rendering/launch-server.ts index 4d8f3fbdd259..cfb15b0d979b 100644 --- a/packages/angular/build/src/utils/server-rendering/launch-server.ts +++ b/packages/angular/build/src/utils/server-rendering/launch-server.ts @@ -33,7 +33,7 @@ export async function launchServer(): Promise { // handle request if (isSsrNodeRequestHandler(reqHandler)) { await reqHandler(req, res, (e) => { - throw e; + throw e ?? new Error(`Unable to handle request: '${req.url}'.`); }); } else { const webRes = await reqHandler(createWebRequestFromNodeRequest(req)); diff --git a/packages/angular/build/src/utils/server-rendering/prerender.ts b/packages/angular/build/src/utils/server-rendering/prerender.ts index 76b9de2bc2fe..a8a42c7c941a 100644 --- a/packages/angular/build/src/utils/server-rendering/prerender.ts +++ b/packages/angular/build/src/utils/server-rendering/prerender.ts @@ -113,7 +113,7 @@ export async function prerenderPages( outputMode, ).catch((err) => { return { - errors: [`An error occurred while extracting routes.\n\n${err.stack ?? err.message ?? err}`], + errors: [`An error occurred while extracting routes.\n\n${err.message ?? err.stack ?? err}`], serializedRouteTree: [], appShellRoute: undefined, }; @@ -258,7 +258,7 @@ async function renderPages( }) .catch((err) => { errors.push( - `An error occurred while prerendering route '${route}'.\n\n${err.stack ?? err.message ?? err.code ?? err}`, + `An error occurred while prerendering route '${route}'.\n\n${err.message ?? err.stack ?? err.code ?? err}`, ); void renderWorker.destroy(); }); @@ -359,7 +359,7 @@ async function getAllRoutes( return { errors: [ - `An error occurred while extracting routes.\n\n${err.stack ?? err.message ?? err.code ?? err}`, + `An error occurred while extracting routes.\n\n${err.message ?? err.stack ?? err.code ?? err}`, ], serializedRouteTree: [], }; diff --git a/packages/angular/cli/BUILD.bazel b/packages/angular/cli/BUILD.bazel index 5fce2f4bab5c..de8c7eff0b74 100644 --- a/packages/angular/cli/BUILD.bazel +++ b/packages/angular/cli/BUILD.bazel @@ -4,7 +4,7 @@ # found in the LICENSE file at https://angular.dev/license load("@npm2//:defs.bzl", "npm_link_all_packages") -load("//tools:defaults2.bzl", "jasmine_test", "npm_package", "ts_project") +load("//tools:defaults.bzl", "jasmine_test", "npm_package", "ts_project") load("//tools:ng_cli_schema_generator.bzl", "cli_json_schema") load("//tools:ts_json_schema.bzl", "ts_json_schema") @@ -48,10 +48,17 @@ ts_project( ":node_modules/@angular-devkit/architect", ":node_modules/@angular-devkit/core", ":node_modules/@angular-devkit/schematics", + ":node_modules/@inquirer/prompts", + ":node_modules/@listr2/prompt-adapter-inquirer", + ":node_modules/@yarnpkg/lockfile", + ":node_modules/ini", + ":node_modules/jsonc-parser", + ":node_modules/npm-package-arg", + ":node_modules/npm-pick-manifest", + ":node_modules/pacote", ":node_modules/resolve", + ":node_modules/yargs", "//:node_modules/@angular/core", - "//:node_modules/@inquirer/prompts", - "//:node_modules/@listr2/prompt-adapter-inquirer", "//:node_modules/@types/ini", "//:node_modules/@types/node", "//:node_modules/@types/npm-package-arg", @@ -60,16 +67,8 @@ ts_project( "//:node_modules/@types/semver", "//:node_modules/@types/yargs", "//:node_modules/@types/yarnpkg__lockfile", - "//:node_modules/@yarnpkg/lockfile", - "//:node_modules/ini", - "//:node_modules/jsonc-parser", "//:node_modules/listr2", - "//:node_modules/npm-package-arg", - "//:node_modules/npm-pick-manifest", - "//:node_modules/pacote", "//:node_modules/semver", - "//:node_modules/symbol-observable", - "//:node_modules/yargs", ], ) @@ -111,10 +110,10 @@ ts_project( ":angular-cli", ":node_modules/@angular-devkit/core", ":node_modules/@angular-devkit/schematics", + ":node_modules/yargs", "//:node_modules/@types/semver", "//:node_modules/@types/yargs", "//:node_modules/semver", - "//:node_modules/yargs", ], ) diff --git a/packages/angular/cli/lib/init.ts b/packages/angular/cli/lib/init.ts index 181166d621c4..cd324b6df69b 100644 --- a/packages/angular/cli/lib/init.ts +++ b/packages/angular/cli/lib/init.ts @@ -6,9 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ -import 'symbol-observable'; -// symbol polyfill must go first -import { promises as fs } from 'node:fs'; +import { readFile } from 'node:fs/promises'; import { createRequire } from 'node:module'; import * as path from 'node:path'; import { SemVer, major } from 'semver'; @@ -62,7 +60,7 @@ let forceExit = false; let localVersion = cli.VERSION?.full; if (!localVersion) { try { - const localPackageJson = await fs.readFile( + const localPackageJson = await readFile( path.join(path.dirname(projectLocalCli), '../../package.json'), 'utf-8', ); diff --git a/packages/angular/cli/package.json b/packages/angular/cli/package.json index cebf38c7dc6a..daa734d47ada 100644 --- a/packages/angular/cli/package.json +++ b/packages/angular/cli/package.json @@ -25,19 +25,18 @@ "@angular-devkit/architect": "workspace:0.0.0-EXPERIMENTAL-PLACEHOLDER", "@angular-devkit/core": "workspace:0.0.0-PLACEHOLDER", "@angular-devkit/schematics": "workspace:0.0.0-PLACEHOLDER", - "@inquirer/prompts": "7.3.3", - "@listr2/prompt-adapter-inquirer": "2.0.18", + "@inquirer/prompts": "7.4.1", + "@listr2/prompt-adapter-inquirer": "2.0.21", "@schematics/angular": "workspace:0.0.0-PLACEHOLDER", "@yarnpkg/lockfile": "1.1.0", "ini": "5.0.0", "jsonc-parser": "3.3.1", - "listr2": "8.2.5", + "listr2": "8.3.2", "npm-package-arg": "12.0.2", "npm-pick-manifest": "10.0.0", "pacote": "20.0.0", "resolve": "1.22.10", "semver": "7.7.1", - "symbol-observable": "4.0.0", "yargs": "17.7.2" }, "ng-update": { diff --git a/packages/angular/cli/src/command-builder/architect-base-command-module.ts b/packages/angular/cli/src/command-builder/architect-base-command-module.ts index 9ce2230fd5ee..566e0e62b209 100644 --- a/packages/angular/cli/src/command-builder/architect-base-command-module.ts +++ b/packages/angular/cli/src/command-builder/architect-base-command-module.ts @@ -52,10 +52,16 @@ export abstract class ArchitectBaseCommandModule return this.onMissingTarget(e.message); } + const isAngularBuild = builderName.startsWith('@angular/build:'); + const { logger } = this.context; - const run = await this.getArchitect().scheduleTarget(target, options as json.JsonObject, { - logger, - }); + const run = await this.getArchitect(isAngularBuild).scheduleTarget( + target, + options as json.JsonObject, + { + logger, + }, + ); const analytics = isPackageNameSafeForAnalytics(builderName) ? await this.getAnalytics() @@ -150,13 +156,17 @@ export abstract class ArchitectBaseCommandModule } private _architect: Architect | undefined; - protected getArchitect(): Architect { + protected getArchitect(skipUndefinedArrayTransform: boolean): Architect { if (this._architect) { return this._architect; } const registry = new json.schema.CoreSchemaRegistry(); - registry.addPostTransform(json.schema.transforms.addUndefinedDefaults); + if (skipUndefinedArrayTransform) { + registry.addPostTransform(json.schema.transforms.addUndefinedObjectDefaults); + } else { + registry.addPostTransform(json.schema.transforms.addUndefinedDefaults); + } registry.useXDeprecatedProvider((msg) => this.context.logger.warn(msg)); const architectHost = this.getArchitectHost(); diff --git a/packages/angular/cli/src/commands/cache/clean/cli.ts b/packages/angular/cli/src/commands/cache/clean/cli.ts index e037503846b6..a115b686b7e0 100644 --- a/packages/angular/cli/src/commands/cache/clean/cli.ts +++ b/packages/angular/cli/src/commands/cache/clean/cli.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ -import { promises as fs } from 'node:fs'; +import { rm } from 'node:fs/promises'; import { Argv } from 'yargs'; import { CommandModule, @@ -28,7 +28,7 @@ export class CacheCleanModule extends CommandModule implements CommandModuleImpl run(): Promise { const { path } = getCacheConfig(this.context.workspace); - return fs.rm(path, { + return rm(path, { force: true, recursive: true, maxRetries: 3, diff --git a/packages/angular/cli/src/commands/cache/info/cli.ts b/packages/angular/cli/src/commands/cache/info/cli.ts index 51fd8ca6bc9e..447d92e02c1f 100644 --- a/packages/angular/cli/src/commands/cache/info/cli.ts +++ b/packages/angular/cli/src/commands/cache/info/cli.ts @@ -7,7 +7,7 @@ */ import { tags } from '@angular-devkit/core'; -import { promises as fs } from 'node:fs'; +import * as fs from 'node:fs/promises'; import { join } from 'node:path'; import { Argv } from 'yargs'; import { diff --git a/packages/angular/cli/src/utilities/completion.ts b/packages/angular/cli/src/utilities/completion.ts index 011968b1a660..436680902395 100644 --- a/packages/angular/cli/src/utilities/completion.ts +++ b/packages/angular/cli/src/utilities/completion.ts @@ -8,7 +8,7 @@ import { json, logging } from '@angular-devkit/core'; import { execFile } from 'node:child_process'; -import { promises as fs } from 'node:fs'; +import * as fs from 'node:fs/promises'; import * as path from 'node:path'; import { env } from 'node:process'; import { colors } from '../utilities/color'; diff --git a/packages/angular/create/BUILD.bazel b/packages/angular/create/BUILD.bazel index fe815b0b75dc..fd21c1f70271 100644 --- a/packages/angular/create/BUILD.bazel +++ b/packages/angular/create/BUILD.bazel @@ -3,7 +3,7 @@ # Use of this source code is governed by an MIT-style license that can be # found in the LICENSE file at https://angular.dev/license -load("//tools:defaults2.bzl", "npm_package", "ts_project") +load("//tools:defaults.bzl", "npm_package", "ts_project") licenses(["notice"]) diff --git a/packages/angular/pwa/BUILD.bazel b/packages/angular/pwa/BUILD.bazel index 1e0355fe015c..24325c22040e 100644 --- a/packages/angular/pwa/BUILD.bazel +++ b/packages/angular/pwa/BUILD.bazel @@ -4,7 +4,7 @@ # found in the LICENSE file at https://angular.dev/license load("@npm2//:defs.bzl", "npm_link_all_packages") -load("//tools:defaults2.bzl", "jasmine_test", "npm_package", "ts_project") +load("//tools:defaults.bzl", "jasmine_test", "npm_package", "ts_project") load("//tools:ts_json_schema.bzl", "ts_json_schema") licenses(["notice"]) @@ -36,8 +36,8 @@ ts_project( deps = [ ":node_modules/@angular-devkit/schematics", ":node_modules/@schematics/angular", + ":node_modules/parse5-html-rewriting-stream", "//:node_modules/@types/node", - "//:node_modules/parse5-html-rewriting-stream", ], ) diff --git a/packages/angular/ssr/BUILD.bazel b/packages/angular/ssr/BUILD.bazel index fbe46237d063..0f50ec8b25a6 100644 --- a/packages/angular/ssr/BUILD.bazel +++ b/packages/angular/ssr/BUILD.bazel @@ -1,8 +1,7 @@ -load("@aspect_rules_js//npm:defs.bzl", "npm_package") load("@devinfra//bazel/api-golden:index_rjs.bzl", "api_golden_test_npm_package") load("@npm2//:defs.bzl", "npm_link_all_packages") load("@rules_pkg//:pkg.bzl", "pkg_tar") -load("//tools:defaults2.bzl", "ng_package", "ts_project") +load("//tools:defaults.bzl", "ng_package", "ts_project") package(default_visibility = ["//visibility:public"]) @@ -40,8 +39,7 @@ ts_project( ) ng_package( - name = "angular_package", - package_name = "@angular/ssr", + name = "npm_package", srcs = [ ":package.json", "//packages/angular/ssr/third_party/beasties:beasties_bundled", @@ -53,10 +51,21 @@ ng_package( ], nested_packages = [ "//packages/angular/ssr/schematics:pkg", + # Included directly as the generated types reference the types file in this location. + "//packages/angular/ssr/third_party/beasties:beasties_dts", ], + package = "@angular/ssr", + rollup_runtime_deps = [ + "//:node_modules/@rollup/plugin-commonjs", + "//:node_modules/@rollup/plugin-node-resolve", + "//:node_modules/magic-string", + "//:node_modules/rollup-plugin-dts", + "//:node_modules/rollup-plugin-sourcemaps2", + ], + tags = ["release-package"], deps = [ - ":ssr_legacy", - "//packages/angular/ssr/node:node_legacy", + ":ssr", + "//packages/angular/ssr/node", ], ) @@ -69,16 +78,6 @@ pkg_tar( tags = ["manual"], ) -# TODO: Replace when `ng_package` creates a valid `rules_js`-compliant npm package. -npm_package( - name = "npm_package", - srcs = [":angular_package"], - replace_prefixes = { - "angular_package/": "", - }, - tags = ["release-package"], -) - alias( name = "pkg", actual = ":npm_package", diff --git a/packages/angular/ssr/node/src/app-engine.ts b/packages/angular/ssr/node/src/app-engine.ts index a59502ee47a8..8edac0ef69c6 100644 --- a/packages/angular/ssr/node/src/app-engine.ts +++ b/packages/angular/ssr/node/src/app-engine.ts @@ -9,6 +9,7 @@ import { AngularAppEngine } from '@angular/ssr'; import type { IncomingMessage } from 'node:http'; import type { Http2ServerRequest } from 'node:http2'; +import { attachNodeGlobalErrorHandlers } from './errors'; import { createWebRequestFromNodeRequest } from './request'; /** @@ -18,12 +19,14 @@ import { createWebRequestFromNodeRequest } from './request'; * * @remarks This class should be instantiated once and used as a singleton across the server-side * application to ensure consistent handling of rendering requests and resource management. - * - * @developerPreview */ export class AngularNodeAppEngine { private readonly angularAppEngine = new AngularAppEngine(); + constructor() { + attachNodeGlobalErrorHandlers(); + } + /** * Handles an incoming HTTP request by serving prerendered content, performing server-side rendering, * or delivering a static file for client-side rendered routes based on the `RenderMode` setting. diff --git a/packages/angular/ssr/node/src/common-engine/common-engine.ts b/packages/angular/ssr/node/src/common-engine/common-engine.ts index 828fe17cf2b1..63c3f6075a23 100644 --- a/packages/angular/ssr/node/src/common-engine/common-engine.ts +++ b/packages/angular/ssr/node/src/common-engine/common-engine.ts @@ -11,6 +11,7 @@ import { renderApplication, renderModule, ɵSERVER_CONTEXT } from '@angular/plat import * as fs from 'node:fs'; import { dirname, join, normalize, resolve } from 'node:path'; import { URL } from 'node:url'; +import { attachNodeGlobalErrorHandlers } from '../errors'; import { CommonEngineInlineCriticalCssProcessor } from './inline-css-processor'; import { noopRunMethodAndMeasurePerf, @@ -63,7 +64,9 @@ export class CommonEngine { private readonly inlineCriticalCssProcessor = new CommonEngineInlineCriticalCssProcessor(); private readonly pageIsSSG = new Map(); - constructor(private options?: CommonEngineOptions) {} + constructor(private options?: CommonEngineOptions) { + attachNodeGlobalErrorHandlers(); + } /** * Render an HTML document for a specific URL with specified diff --git a/packages/angular/ssr/node/src/errors.ts b/packages/angular/ssr/node/src/errors.ts new file mode 100644 index 000000000000..f78699dcecc0 --- /dev/null +++ b/packages/angular/ssr/node/src/errors.ts @@ -0,0 +1,40 @@ +/** + * @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 + */ + +/** + * Attaches listeners to the Node.js process to capture and handle unhandled rejections and uncaught exceptions. + * Captured errors are logged to the console. This function logs errors to the console, preventing unhandled errors + * from crashing the server. It is particularly useful for Zoneless apps, ensuring error handling without relying on Zone.js. + * + * @remarks + * This function is a no-op if zone.js is available. + * For Zone-based apps, similar functionality is provided by Zone.js itself. See the Zone.js implementation here: + * https://github.com/angular/angular/blob/4a8d0b79001ec09bcd6f2d6b15117aa6aac1932c/packages/zone.js/lib/node/node.ts#L94%7C + * + * @internal + */ +export function attachNodeGlobalErrorHandlers(): void { + if (typeof Zone !== 'undefined') { + return; + } + + // Ensure that the listeners are registered only once. + // Otherwise, multiple instances may be registered during edit/refresh. + const gThis: typeof globalThis & { ngAttachNodeGlobalErrorHandlersCalled?: boolean } = globalThis; + if (gThis.ngAttachNodeGlobalErrorHandlersCalled) { + return; + } + + gThis.ngAttachNodeGlobalErrorHandlersCalled = true; + + process + // eslint-disable-next-line no-console + .on('unhandledRejection', (error) => console.error('unhandledRejection', error)) + // eslint-disable-next-line no-console + .on('uncaughtException', (error) => console.error('uncaughtException', error)); +} diff --git a/packages/angular/ssr/node/src/globals.d.ts b/packages/angular/ssr/node/src/globals.d.ts new file mode 100644 index 000000000000..596389a8a60d --- /dev/null +++ b/packages/angular/ssr/node/src/globals.d.ts @@ -0,0 +1,9 @@ +/** + * @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 const Zone: unknown | undefined; diff --git a/packages/angular/ssr/node/src/handler.ts b/packages/angular/ssr/node/src/handler.ts index be67c1dcb339..89452b3099b1 100644 --- a/packages/angular/ssr/node/src/handler.ts +++ b/packages/angular/ssr/node/src/handler.ts @@ -16,7 +16,6 @@ import type { IncomingMessage, ServerResponse } from 'node:http'; * @param next - A callback function that signals the completion of the middleware or forwards the error if provided. * * @returns A Promise that resolves to void or simply void. The handler can be asynchronous. - * @developerPreview */ export type NodeRequestHandlerFunction = ( req: IncomingMessage, @@ -66,7 +65,6 @@ export type NodeRequestHandlerFunction = ( * res.send('Hello from Fastify with Node Next Handler!'); * })); * ``` - * @developerPreview */ export function createNodeRequestHandler(handler: T): T { (handler as T & { __ng_node_request_handler__?: boolean })['__ng_node_request_handler__'] = true; diff --git a/packages/angular/ssr/node/src/module.ts b/packages/angular/ssr/node/src/module.ts index f53943a89727..bd52455940a2 100644 --- a/packages/angular/ssr/node/src/module.ts +++ b/packages/angular/ssr/node/src/module.ts @@ -23,7 +23,6 @@ import { fileURLToPath } from 'node:url'; * * @param url The URL of the module to check. This should typically be `import.meta.url`. * @returns `true` if the provided URL represents the main entry point, otherwise `false`. - * @developerPreview */ export function isMainModule(url: string): boolean { return url.startsWith('file:') && argv[1] === fileURLToPath(url); diff --git a/packages/angular/ssr/node/src/request.ts b/packages/angular/ssr/node/src/request.ts index 78ec7f2ef712..51331a18cc35 100644 --- a/packages/angular/ssr/node/src/request.ts +++ b/packages/angular/ssr/node/src/request.ts @@ -27,7 +27,6 @@ const HTTP2_PSEUDO_HEADERS = new Set([':method', ':scheme', ':authority', ':path * * @param nodeRequest - The Node.js request object (`IncomingMessage` or `Http2ServerRequest`) to convert. * @returns A Web Standard `Request` object. - * @developerPreview */ export function createWebRequestFromNodeRequest( nodeRequest: IncomingMessage | Http2ServerRequest, diff --git a/packages/angular/ssr/node/src/response.ts b/packages/angular/ssr/node/src/response.ts index 8f26bc319361..56f091deed5f 100644 --- a/packages/angular/ssr/node/src/response.ts +++ b/packages/angular/ssr/node/src/response.ts @@ -19,7 +19,6 @@ import type { Http2ServerResponse } from 'node:http2'; * @param source - The web-standard `Response` object to stream from. * @param destination - The Node.js response object (`ServerResponse` or `Http2ServerResponse`) to stream into. * @returns A promise that resolves once the streaming operation is complete. - * @developerPreview */ export async function writeResponseToNodeResponse( source: Response, diff --git a/packages/angular/ssr/node/test/BUILD.bazel b/packages/angular/ssr/node/test/BUILD.bazel index 9e5448549fe9..e816a3e022ae 100644 --- a/packages/angular/ssr/node/test/BUILD.bazel +++ b/packages/angular/ssr/node/test/BUILD.bazel @@ -1,5 +1,5 @@ load("@devinfra//bazel/spec-bundling:index_rjs.bzl", "spec_bundle") -load("//tools:defaults2.bzl", "jasmine_test", "ts_project") +load("//tools:defaults.bzl", "jasmine_test", "ts_project") ts_project( name = "unit_test_lib", diff --git a/packages/angular/ssr/package.json b/packages/angular/ssr/package.json index 7f579f5deadd..7d3027932475 100644 --- a/packages/angular/ssr/package.json +++ b/packages/angular/ssr/package.json @@ -29,12 +29,12 @@ }, "devDependencies": { "@angular-devkit/schematics": "workspace:*", - "@angular/common": "20.0.0-next.2", - "@angular/compiler": "20.0.0-next.2", - "@angular/core": "20.0.0-next.2", - "@angular/platform-browser": "20.0.0-next.2", - "@angular/platform-server": "20.0.0-next.2", - "@angular/router": "20.0.0-next.2", + "@angular/common": "20.0.0-next.7", + "@angular/compiler": "20.0.0-next.7", + "@angular/core": "20.0.0-next.7", + "@angular/platform-browser": "20.0.0-next.7", + "@angular/platform-server": "20.0.0-next.7", + "@angular/router": "20.0.0-next.7", "@schematics/angular": "workspace:*" }, "sideEffects": false, diff --git a/packages/angular/ssr/public_api.ts b/packages/angular/ssr/public_api.ts index fbeadeac929f..e685f4ceabe3 100644 --- a/packages/angular/ssr/public_api.ts +++ b/packages/angular/ssr/public_api.ts @@ -14,8 +14,9 @@ export { createRequestHandler, type RequestHandlerFunction } from './src/handler export { PrerenderFallback, type ServerRoute, - provideServerRouting, + provideServerRendering, withAppShell, + withRoutes, RenderMode, type ServerRouteClient, type ServerRoutePrerender, diff --git a/packages/angular/ssr/schematics/BUILD.bazel b/packages/angular/ssr/schematics/BUILD.bazel index 67164e942e43..2b322cdef026 100644 --- a/packages/angular/ssr/schematics/BUILD.bazel +++ b/packages/angular/ssr/schematics/BUILD.bazel @@ -3,8 +3,8 @@ # Use of this source code is governed by an MIT-style license that can be # found in the LICENSE file at https://angular.dev/license -load("@aspect_rules_js//npm:defs.bzl", "npm_package") -load("//tools:defaults2.bzl", "jasmine_test", "ts_project") +load("@aspect_rules_js//js:defs.bzl", "js_library") +load("//tools:defaults.bzl", "jasmine_test", "ts_project") load("//tools:ts_json_schema.bzl", "ts_json_schema") licenses(["notice"]) @@ -91,8 +91,8 @@ jasmine_test( ], ) -# This package is intended to be combined into the main @angular/ssr package as a dep. -npm_package( +# This target is used as nested_package in the main @angular/ssr package as a dep. +js_library( name = "pkg", srcs = [ "package.json", diff --git a/packages/angular/ssr/schematics/ng-add/index_spec.ts b/packages/angular/ssr/schematics/ng-add/index_spec.ts index bdf5474e0d70..b93a509200b1 100644 --- a/packages/angular/ssr/schematics/ng-add/index_spec.ts +++ b/packages/angular/ssr/schematics/ng-add/index_spec.ts @@ -14,7 +14,6 @@ import { join } from 'node:path'; describe('@angular/ssr ng-add schematic', () => { const defaultOptions = { project: 'test-app', - serverRouting: false, }; const schematicRunner = new SchematicTestRunner( diff --git a/packages/angular/ssr/schematics/ng-add/schema.json b/packages/angular/ssr/schematics/ng-add/schema.json index f82d7373620b..2f0df90db22b 100644 --- a/packages/angular/ssr/schematics/ng-add/schema.json +++ b/packages/angular/ssr/schematics/ng-add/schema.json @@ -16,10 +16,6 @@ "description": "Skip the automatic installation of packages. You will need to manually install the dependencies later.", "type": "boolean", "default": false - }, - "serverRouting": { - "description": "Configure the server application to use the Angular Server Routing API and App Engine APIs (currently in Developer Preview).", - "type": "boolean" } }, "required": ["project"], diff --git a/packages/angular/ssr/src/app-engine.ts b/packages/angular/ssr/src/app-engine.ts index c1e2e7fcd5a4..0ce5d23c30d1 100644 --- a/packages/angular/ssr/src/app-engine.ts +++ b/packages/angular/ssr/src/app-engine.ts @@ -19,8 +19,6 @@ import { joinUrlParts } from './utils/url'; * * @remarks This class should be instantiated once and used as a singleton across the server-side * application to ensure consistent handling of rendering requests and resource management. - * - * @developerPreview */ export class AngularAppEngine { /** diff --git a/packages/angular/ssr/src/app.ts b/packages/angular/ssr/src/app.ts index 87710e167a57..a4eb2fbf6098 100644 --- a/packages/angular/ssr/src/app.ts +++ b/packages/angular/ssr/src/app.ts @@ -102,6 +102,14 @@ export class AngularServerApp { constructor(private readonly options: Readonly = {}) { this.allowStaticRouteRender = this.options.allowStaticRouteRender ?? false; this.hooks = options.hooks ?? new Hooks(); + + if (this.manifest.inlineCriticalCss) { + this.inlineCriticalCssProcessor = new InlineCriticalCssProcessor((path: string) => { + const fileName = path.split('/').pop() ?? path; + + return this.assets.getServerAsset(fileName).text(); + }); + } } /** @@ -267,7 +275,7 @@ export class AngularServerApp { const platformProviders: StaticProvider[] = []; const { - manifest: { bootstrap, inlineCriticalCss, locale }, + manifest: { bootstrap, locale }, assets, } = this; @@ -315,7 +323,8 @@ export class AngularServerApp { this.boostrap ??= await bootstrap(); let html = await assets.getIndexServerHtml().text(); html = await this.runTransformsOnHtml(html, url, preload); - html = await renderAngular( + + const { content } = await renderAngular( html, this.boostrap, url, @@ -323,41 +332,38 @@ export class AngularServerApp { SERVER_CONTEXT_VALUE[renderMode], ); - if (!inlineCriticalCss) { - return new Response(html, responseInit); - } - - this.inlineCriticalCssProcessor ??= new InlineCriticalCssProcessor((path: string) => { - const fileName = path.split('/').pop() ?? path; - - return this.assets.getServerAsset(fileName).text(); - }); - const { inlineCriticalCssProcessor, criticalCssLRUCache, textDecoder } = this; - // Use a stream to send the response before inlining critical CSS, improving performance via header flushing. + // Use a stream to send the response before finishing rendering and inling critical CSS, improving performance via header flushing. const stream = new ReadableStream({ async start(controller) { - let htmlWithCriticalCss; + const renderedHtml = await content(); + + if (!inlineCriticalCssProcessor) { + controller.enqueue(textDecoder.encode(renderedHtml)); + controller.close(); + return; + } + + let htmlWithCriticalCss; try { if (renderMode === RenderMode.Server) { - const cacheKey = await sha256(html); + const cacheKey = await sha256(renderedHtml); htmlWithCriticalCss = criticalCssLRUCache.get(cacheKey); if (!htmlWithCriticalCss) { - htmlWithCriticalCss = await inlineCriticalCssProcessor.process(html); + htmlWithCriticalCss = await inlineCriticalCssProcessor.process(renderedHtml); criticalCssLRUCache.put(cacheKey, htmlWithCriticalCss); } } else { - htmlWithCriticalCss = await inlineCriticalCssProcessor.process(html); + htmlWithCriticalCss = await inlineCriticalCssProcessor.process(renderedHtml); } } catch (error) { // eslint-disable-next-line no-console console.error(`An error occurred while inlining critical CSS for: ${url}.`, error); } - controller.enqueue(textDecoder.encode(htmlWithCriticalCss ?? html)); - + controller.enqueue(textDecoder.encode(htmlWithCriticalCss ?? renderedHtml)); controller.close(); }, }); diff --git a/packages/angular/ssr/src/global.d.ts b/packages/angular/ssr/src/globals.d.ts similarity index 100% rename from packages/angular/ssr/src/global.d.ts rename to packages/angular/ssr/src/globals.d.ts diff --git a/packages/angular/ssr/src/handler.ts b/packages/angular/ssr/src/handler.ts index e375b327f829..5969e06907f5 100644 --- a/packages/angular/ssr/src/handler.ts +++ b/packages/angular/ssr/src/handler.ts @@ -12,7 +12,6 @@ * @param request - The incoming HTTP request object. * @returns A Promise resolving to a `Response` object, `null`, or directly a `Response`, * supporting both synchronous and asynchronous handling. - * @developerPreview */ export type RequestHandlerFunction = ( request: Request, @@ -39,7 +38,6 @@ export type RequestHandlerFunction = ( * const handler = toWebHandler(app); * export default createRequestHandler(handler); * ``` - * @developerPreview */ export function createRequestHandler(handler: RequestHandlerFunction): RequestHandlerFunction { (handler as RequestHandlerFunction & { __ng_request_handler__?: boolean })[ diff --git a/packages/angular/ssr/src/routes/route-config.ts b/packages/angular/ssr/src/routes/route-config.ts index 26f115ad6256..a5fb6709e4e5 100644 --- a/packages/angular/ssr/src/routes/route-config.ts +++ b/packages/angular/ssr/src/routes/route-config.ts @@ -11,8 +11,11 @@ import { InjectionToken, Provider, Type, + inject, makeEnvironmentProviders, + provideEnvironmentInitializer, } from '@angular/core'; +import { provideServerRendering as provideServerRenderingPlatformServer } from '@angular/platform-server'; import { type DefaultExport, ROUTES, type Route } from '@angular/router'; /** @@ -22,29 +25,27 @@ import { type DefaultExport, ROUTES, type Route } from '@angular/router'; const APP_SHELL_ROUTE = 'ng-app-shell'; /** - * Identifies a particular kind of `ServerRoutesFeatureKind`. - * @see {@link ServerRoutesFeature} - * @developerPreview + * Identifies a particular kind of `ServerRenderingFeatureKind`. + * @see {@link ServerRenderingFeature} */ -enum ServerRoutesFeatureKind { +enum ServerRenderingFeatureKind { AppShell, + ServerRoutes, } /** * Helper type to represent a server routes feature. - * @see {@link ServerRoutesFeatureKind} - * @developerPreview + * @see {@link ServerRenderingFeatureKind} */ -interface ServerRoutesFeature { +interface ServerRenderingFeature { ɵkind: FeatureKind; - ɵproviders: Provider[]; + ɵproviders: (Provider | EnvironmentProviders)[]; } /** * Different rendering modes for server routes. - * @see {@link provideServerRouting} + * @see {@link withRoutes} * @see {@link ServerRoute} - * @developerPreview */ export enum RenderMode { /** Server-Side Rendering (SSR) mode, where content is rendered on the server for each request. */ @@ -61,7 +62,6 @@ export enum RenderMode { * Defines the fallback strategies for Static Site Generation (SSG) routes when a pre-rendered path is not available. * This is particularly relevant for routes with parameterized URLs where some paths might not be pre-rendered at build time. * @see {@link ServerRoutePrerenderWithParams} - * @developerPreview */ export enum PrerenderFallback { /** @@ -85,7 +85,6 @@ export enum PrerenderFallback { /** * Common interface for server routes, providing shared properties. - * @developerPreview */ export interface ServerRouteCommon { /** The path associated with this route. */ @@ -101,7 +100,6 @@ export interface ServerRouteCommon { /** * A server route that uses Client-Side Rendering (CSR) mode. * @see {@link RenderMode} - * @developerPreview */ export interface ServerRouteClient extends ServerRouteCommon { /** Specifies that the route uses Client-Side Rendering (CSR) mode. */ @@ -111,7 +109,6 @@ export interface ServerRouteClient extends ServerRouteCommon { /** * A server route that uses Static Site Generation (SSG) mode. * @see {@link RenderMode} - * @developerPreview */ export interface ServerRoutePrerender extends Omit { /** Specifies that the route uses Static Site Generation (SSG) mode. */ @@ -126,7 +123,6 @@ export interface ServerRoutePrerender extends Omit * @see {@link RenderMode} * @see {@link ServerRoutePrerender} * @see {@link PrerenderFallback} - * @developerPreview */ export interface ServerRoutePrerenderWithParams extends Omit { /** @@ -171,7 +167,6 @@ export interface ServerRoutePrerenderWithParams extends Omit('SERVER_ROUTES_CONFIG'); /** - * Sets up the necessary providers for configuring server routes. - * This function accepts an array of server routes and optional configuration - * options, returning an `EnvironmentProviders` object that encapsulates - * the server routes and configuration settings. + * Configures server-side routing for the application. * - * @param routes - An array of server routes to be provided. - * @param features - (Optional) server routes features. - * @returns An `EnvironmentProviders` instance with the server routes configuration. + * This function registers an array of `ServerRoute` definitions, enabling server-side rendering + * for specific URL paths. These routes are used to pre-render content on the server, improving + * initial load performance and SEO. * + * @param routes - An array of `ServerRoute` objects, each defining a server-rendered route. + * @returns A `ServerRenderingFeature` object configuring server-side routes. + * + * @example + * ```ts + * import { provideServerRendering, withRoutes, ServerRoute, RenderMode } from '@angular/ssr'; + * + * const serverRoutes: ServerRoute[] = [ + * { + * route: '', // This renders the "/" route on the client (CSR) + * renderMode: RenderMode.Client, + * }, + * { + * route: 'about', // This page is static, so we prerender it (SSG) + * renderMode: RenderMode.Prerender, + * }, + * { + * route: 'profile', // This page requires user-specific data, so we use SSR + * renderMode: RenderMode.Server, + * }, + * { + * route: '**', // All other routes will be rendered on the server (SSR) + * renderMode: RenderMode.Server, + * }, + * ]; + * + * provideServerRendering(withRoutes(serverRoutes)); + * ``` + * + * @see {@link provideServerRendering} * @see {@link ServerRoute} - * @see {@link withAppShell} - * @developerPreview */ -export function provideServerRouting( +export function withRoutes( routes: ServerRoute[], - ...features: ServerRoutesFeature[] -): EnvironmentProviders { +): ServerRenderingFeature { const config: ServerRoutesConfig = { routes }; - const hasAppShell = features.some((f) => f.ɵkind === ServerRoutesFeatureKind.AppShell); - if (hasAppShell) { - config.appShellRoute = APP_SHELL_ROUTE; - } - - const providers: Provider[] = [ - { - provide: SERVER_ROUTES_CONFIG, - useValue: config, - }, - ]; - - for (const feature of features) { - providers.push(...feature.ɵproviders); - } - return makeEnvironmentProviders(providers); + return { + ɵkind: ServerRenderingFeatureKind.ServerRoutes, + ɵproviders: [ + { + provide: SERVER_ROUTES_CONFIG, + useValue: config, + }, + ], + }; } /** - * Configures the app shell route with the provided component. + * Configures the shell of the application. + * + * The app shell is a minimal, static HTML page that is served immediately, while the + * full Angular application loads in the background. This improves perceived performance + * by providing instant feedback to the user. + * + * This function configures the app shell route, which serves the provided component for + * requests that do not match any defined server routes. * - * The app shell serves as the main entry point for the application and is commonly used - * to enable server-side rendering (SSR) of the application shell. It handles requests - * that do not match any specific server route, providing a fallback mechanism and improving - * perceived performance during navigation. + * @param component - The Angular component to render for the app shell. Can be a direct + * component type or a dynamic import function. + * @returns A `ServerRenderingFeature` object configuring the app shell. * - * This configuration is particularly useful in applications leveraging Progressive Web App (PWA) - * patterns, such as service workers, to deliver a seamless user experience. + * @example + * ```ts + * import { provideServerRendering, withAppShell, withRoutes } from '@angular/ssr'; + * import { AppShellComponent } from './app-shell.component'; * - * @param component The Angular component to render for the app shell route. - * @returns A server routes feature configuration for the app shell. + * provideServerRendering( + * withRoutes(serverRoutes), + * withAppShell(AppShellComponent) + * ); + * ``` * - * @see {@link provideServerRouting} - * @see {@link https://angular.dev/ecosystem/service-workers/app-shell | App shell pattern on Angular.dev} + * @example + * ```ts + * import { provideServerRendering, withAppShell, withRoutes } from '@angular/ssr'; + * + * provideServerRendering( + * withRoutes(serverRoutes), + * withAppShell(() => + * import('./app-shell.component').then((m) => m.AppShellComponent) + * ) + * ); + * ``` + * + * @see {@link provideServerRendering} + * @see {@link https://angular.dev/ecosystem/service-workers/app-shell App shell pattern on Angular.dev} */ export function withAppShell( component: Type | (() => Promise | DefaultExport>>), -): ServerRoutesFeature { +): ServerRenderingFeature { const routeConfig: Route = { path: APP_SHELL_ROUTE, }; @@ -278,13 +312,73 @@ export function withAppShell( } return { - ɵkind: ServerRoutesFeatureKind.AppShell, + ɵkind: ServerRenderingFeatureKind.AppShell, ɵproviders: [ { provide: ROUTES, useValue: routeConfig, multi: true, }, + provideEnvironmentInitializer(() => { + const config = inject(SERVER_ROUTES_CONFIG); + config.appShellRoute = APP_SHELL_ROUTE; + }), ], }; } + +/** + * Configures server-side rendering for an Angular application. + * + * This function sets up the necessary providers for server-side rendering, including + * support for server routes and app shell. It combines features configured using + * `withRoutes` and `withAppShell` to provide a comprehensive server-side rendering setup. + * + * @param features - Optional features to configure additional server rendering behaviors. + * @returns An `EnvironmentProviders` instance with the server-side rendering configuration. + * + * @example + * Basic example of how you can enable server-side rendering in your application + * when using the `bootstrapApplication` function: + * + * ```ts + * import { bootstrapApplication } from '@angular/platform-browser'; + * import { provideServerRendering, withRoutes, withAppShell } from '@angular/ssr'; + * import { AppComponent } from './app/app.component'; + * import { SERVER_ROUTES } from './app/app.server.routes'; + * import { AppShellComponent } from './app/app-shell.component'; + * + * bootstrapApplication(AppComponent, { + * providers: [ + * provideServerRendering( + * withRoutes(SERVER_ROUTES), + * withAppShell(AppShellComponent) + * ) + * ] + * }); + * ``` + * @see {@link withRoutes} configures server-side routing + * @see {@link withAppShell} configures the application shell + */ +export function provideServerRendering( + ...features: ServerRenderingFeature[] +): EnvironmentProviders { + let hasAppShell = false; + let hasServerRoutes = false; + const providers: (Provider | EnvironmentProviders)[] = [provideServerRenderingPlatformServer()]; + + for (const { ɵkind, ɵproviders } of features) { + hasAppShell ||= ɵkind === ServerRenderingFeatureKind.AppShell; + hasServerRoutes ||= ɵkind === ServerRenderingFeatureKind.ServerRoutes; + providers.push(...ɵproviders); + } + + if (!hasServerRoutes && hasAppShell) { + throw new Error( + `Configuration error: found 'withAppShell()' without 'withRoutes()' in the same call to 'provideServerRendering()'.` + + `The 'withAppShell()' function requires 'withRoutes()' to be used.`, + ); + } + + return makeEnvironmentProviders(providers); +} diff --git a/packages/angular/ssr/src/utils/ng.ts b/packages/angular/ssr/src/utils/ng.ts index 55faa0adb205..98c0e7be99d2 100644 --- a/packages/angular/ssr/src/utils/ng.ts +++ b/packages/angular/ssr/src/utils/ng.ts @@ -6,12 +6,18 @@ * found in the LICENSE file at https://angular.dev/license */ -import { ɵConsole } from '@angular/core'; -import type { ApplicationRef, StaticProvider, Type } from '@angular/core'; import { + ApplicationRef, + type PlatformRef, + type StaticProvider, + type Type, + ɵConsole, +} from '@angular/core'; +import { + INITIAL_CONFIG, ɵSERVER_CONTEXT as SERVER_CONTEXT, - renderApplication, - renderModule, + platformServer, + ɵrenderInternal as renderInternal, } from '@angular/platform-server'; import { Console } from '../console'; import { stripIndexHtmlFromURL } from './url'; @@ -41,16 +47,26 @@ export type AngularBootstrap = Type | (() => Promise); * rendering process. * @param serverContext - A string representing the server context, used to provide additional * context or metadata during server-side rendering. - * @returns A promise that resolves to a string containing the rendered HTML. + * @returns A promise resolving to an object containing a `content` method, which returns a + * promise that resolves to the rendered HTML string. */ -export function renderAngular( +export async function renderAngular( html: string, bootstrap: AngularBootstrap, url: URL, platformProviders: StaticProvider[], serverContext: string, -): Promise { - const providers = [ +): Promise<{ content: () => Promise }> { + // A request to `http://www.example.com/page/index.html` will render the Angular route corresponding to `http://www.example.com/page`. + const urlToRender = stripIndexHtmlFromURL(url).toString(); + const platformRef = platformServer([ + { + provide: INITIAL_CONFIG, + useValue: { + url: urlToRender, + document: html, + }, + }, { provide: SERVER_CONTEXT, useValue: serverContext, @@ -64,22 +80,37 @@ export function renderAngular( useFactory: () => new Console(), }, ...platformProviders, - ]; + ]); - // A request to `http://www.example.com/page/index.html` will render the Angular route corresponding to `http://www.example.com/page`. - const urlToRender = stripIndexHtmlFromURL(url).toString(); + try { + let applicationRef: ApplicationRef; + if (isNgModule(bootstrap)) { + const moduleRef = await platformRef.bootstrapModule(bootstrap); + applicationRef = moduleRef.injector.get(ApplicationRef); + } else { + applicationRef = await bootstrap(); + } - return isNgModule(bootstrap) - ? renderModule(bootstrap, { - url: urlToRender, - document: html, - extraProviders: providers, - }) - : renderApplication(bootstrap, { - url: urlToRender, - document: html, - platformProviders: providers, - }); + // Block until application is stable. + await applicationRef.whenStable(); + + return { + content: () => + new Promise((resolve, reject) => { + // Defer rendering to the next event loop iteration to avoid blocking, as most operations in `renderInternal` are synchronous. + setTimeout(() => { + renderInternal(platformRef, applicationRef) + .then(resolve) + .catch(reject) + .finally(() => void asyncDestroyPlatform(platformRef)); + }, 0); + }), + }; + } catch (error) { + await asyncDestroyPlatform(platformRef); + + throw error; + } } /** @@ -93,3 +124,18 @@ export function renderAngular( export function isNgModule(value: AngularBootstrap): value is Type { return 'ɵmod' in value; } + +/** + * Gracefully destroys the application in a macrotask, allowing pending promises to resolve + * and surfacing any potential errors to the user. + * + * @param platformRef - The platform reference to be destroyed. + */ +function asyncDestroyPlatform(platformRef: PlatformRef): Promise { + return new Promise((resolve) => { + setTimeout(() => { + platformRef.destroy(); + resolve(); + }, 0); + }); +} diff --git a/packages/angular/ssr/test/BUILD.bazel b/packages/angular/ssr/test/BUILD.bazel index 8fad8bd45ca9..c81599b43a79 100644 --- a/packages/angular/ssr/test/BUILD.bazel +++ b/packages/angular/ssr/test/BUILD.bazel @@ -1,5 +1,5 @@ load("@devinfra//bazel/spec-bundling:index_rjs.bzl", "spec_bundle") -load("//tools:defaults2.bzl", "jasmine_test", "ts_project") +load("//tools:defaults.bzl", "jasmine_test", "ts_project") ts_project( name = "unit_test_lib", @@ -13,7 +13,6 @@ ts_project( "//:node_modules/@angular/compiler", "//:node_modules/@angular/core", "//:node_modules/@angular/platform-browser", - "//:node_modules/@angular/platform-server", "//:node_modules/@angular/router", "//:node_modules/@types/node", "//packages/angular/ssr", diff --git a/packages/angular/ssr/test/npm_package/BUILD.bazel b/packages/angular/ssr/test/npm_package/BUILD.bazel index 9111a91325c0..97331cf8a9e0 100644 --- a/packages/angular/ssr/test/npm_package/BUILD.bazel +++ b/packages/angular/ssr/test/npm_package/BUILD.bazel @@ -1,6 +1,6 @@ load("@bazel_skylib//rules:diff_test.bzl", "diff_test") load("@bazel_skylib//rules:write_file.bzl", "write_file") -load("//tools:defaults2.bzl", "jasmine_test", "ts_project") +load("//tools:defaults.bzl", "jasmine_test", "ts_project") ts_project( name = "unit_test_lib", diff --git a/packages/angular/ssr/test/npm_package/package_spec.ts b/packages/angular/ssr/test/npm_package/package_spec.ts index 2bd37aeabf5b..c519c53f7b92 100644 --- a/packages/angular/ssr/test/npm_package/package_spec.ts +++ b/packages/angular/ssr/test/npm_package/package_spec.ts @@ -24,12 +24,6 @@ const CRITTERS_ACTUAL_LICENSE_FILE_PATH = join( 'third_party/beasties/THIRD_PARTY_LICENSES.txt', ); -/** - * Path to the golden reference license file for the Beasties library. - * This file is used as a reference for comparison and is located in the same directory as this script. - */ -const CRITTERS_GOLDEN_LICENSE_FILE_PATH = join(__dirname, 'THIRD_PARTY_LICENSES.txt.golden'); - describe('NPM Package Tests', () => { it('should not include the contents of third_party/beasties/index.js in the FESM bundle', async () => { const fesmFilePath = join(ANGULAR_SSR_PACKAGE_PATH, 'fesm2022/ssr.mjs'); diff --git a/packages/angular/ssr/test/testing-utils.ts b/packages/angular/ssr/test/testing-utils.ts index b6d01398d7cc..92521972ac58 100644 --- a/packages/angular/ssr/test/testing-utils.ts +++ b/packages/angular/ssr/test/testing-utils.ts @@ -14,11 +14,10 @@ import { provideExperimentalZonelessChangeDetection, } from '@angular/core'; import { bootstrapApplication } from '@angular/platform-browser'; -import { provideServerRendering } from '@angular/platform-server'; import { RouterOutlet, Routes, provideRouter } from '@angular/router'; import { destroyAngularServerApp } from '../src/app'; import { ServerAsset, setAngularAppManifest } from '../src/manifest'; -import { ServerRoute, provideServerRouting } from '../src/routes/route-config'; +import { ServerRoute, provideServerRendering, withRoutes } from '../src/routes/route-config'; @Component({ standalone: true, @@ -94,10 +93,9 @@ export function setAngularAppTestingManifest( bootstrap: async () => () => { return bootstrapApplication(rootComponent, { providers: [ - provideServerRendering(), provideExperimentalZonelessChangeDetection(), provideRouter(routes), - provideServerRouting(serverRoutes), + provideServerRendering(withRoutes(serverRoutes)), ...extraProviders, ], }); diff --git a/packages/angular_devkit/architect/BUILD.bazel b/packages/angular_devkit/architect/BUILD.bazel index 5edb897086a8..83a6bd4bae74 100644 --- a/packages/angular_devkit/architect/BUILD.bazel +++ b/packages/angular_devkit/architect/BUILD.bazel @@ -5,7 +5,7 @@ load("@devinfra//bazel/api-golden:index_rjs.bzl", "api_golden_test_npm_package") load("@npm2//:defs.bzl", "npm_link_all_packages") -load("//tools:defaults2.bzl", "jasmine_test", "npm_package", "ts_project") +load("//tools:defaults.bzl", "jasmine_test", "npm_package", "ts_project") load("//tools:ts_json_schema.bzl", "ts_json_schema") package(default_visibility = ["//visibility:public"]) @@ -69,8 +69,8 @@ ts_project( module_name = "@angular-devkit/architect", deps = [ ":node_modules/@angular-devkit/core", + ":node_modules/rxjs", "//:node_modules/@types/node", - "//:node_modules/rxjs", ], ) @@ -81,9 +81,9 @@ ts_project( deps = [ ":architect", ":node_modules/@angular-devkit/core", + ":node_modules/rxjs", "//:node_modules/@types/jasmine", "//:node_modules/@types/node", - "//:node_modules/rxjs", "//packages/angular_devkit/architect/testing", ], ) diff --git a/packages/angular_devkit/architect/node/BUILD.bazel b/packages/angular_devkit/architect/node/BUILD.bazel index 2dbbc9a7c3b4..1d4b9b0d2436 100644 --- a/packages/angular_devkit/architect/node/BUILD.bazel +++ b/packages/angular_devkit/architect/node/BUILD.bazel @@ -3,7 +3,7 @@ # Use of this source code is governed by an MIT-style license that can be # found in the LICENSE file at https://angular.dev/license -load("//tools:defaults2.bzl", "jasmine_test", "ts_project") +load("//tools:defaults.bzl", "jasmine_test", "ts_project") licenses(["notice"]) @@ -18,9 +18,9 @@ ts_project( module_name = "@angular-devkit/architect/node", deps = [ "//:node_modules/@types/node", - "//:node_modules/rxjs", "//packages/angular_devkit/architect", "//packages/angular_devkit/architect:node_modules/@angular-devkit/core", + "//packages/angular_devkit/architect:node_modules/rxjs", ], ) @@ -36,8 +36,8 @@ ts_project( ":node", "//:node_modules/@types/jasmine", "//:node_modules/@types/node", - "//:node_modules/rxjs", "//packages/angular_devkit/architect", + "//packages/angular_devkit/architect:node_modules/rxjs", "//packages/angular_devkit/architect/node/test:test_lib", ], ) diff --git a/packages/angular_devkit/architect/testing/BUILD.bazel b/packages/angular_devkit/architect/testing/BUILD.bazel index 589ed96abb5d..c6dfbab8a7a8 100644 --- a/packages/angular_devkit/architect/testing/BUILD.bazel +++ b/packages/angular_devkit/architect/testing/BUILD.bazel @@ -18,8 +18,8 @@ ts_project( module_name = "@angular-devkit/architect/testing", deps = [ "//:node_modules/@types/node", - "//:node_modules/rxjs", "//packages/angular_devkit/architect", "//packages/angular_devkit/architect:node_modules/@angular-devkit/core", + "//packages/angular_devkit/architect:node_modules/rxjs", ], ) diff --git a/packages/angular_devkit/architect_cli/BUILD.bazel b/packages/angular_devkit/architect_cli/BUILD.bazel index 4a8283ec9a26..1a0b94938165 100644 --- a/packages/angular_devkit/architect_cli/BUILD.bazel +++ b/packages/angular_devkit/architect_cli/BUILD.bazel @@ -1,5 +1,5 @@ load("@npm2//:defs.bzl", "npm_link_all_packages") -load("//tools:defaults2.bzl", "npm_package", "ts_project") +load("//tools:defaults.bzl", "npm_package", "ts_project") # Copyright Google Inc. All Rights Reserved. # diff --git a/packages/angular_devkit/architect_cli/package.json b/packages/angular_devkit/architect_cli/package.json index c7ae69c92df6..1f368de6a504 100644 --- a/packages/angular_devkit/architect_cli/package.json +++ b/packages/angular_devkit/architect_cli/package.json @@ -18,7 +18,6 @@ "@angular-devkit/core": "workspace:0.0.0-PLACEHOLDER", "ansi-colors": "4.1.3", "progress": "2.0.3", - "symbol-observable": "4.0.0", "yargs-parser": "21.1.1" }, "devDependencies": { diff --git a/packages/angular_devkit/build_angular/BUILD.bazel b/packages/angular_devkit/build_angular/BUILD.bazel index 5c792deac174..bcd3bbd4ca26 100644 --- a/packages/angular_devkit/build_angular/BUILD.bazel +++ b/packages/angular_devkit/build_angular/BUILD.bazel @@ -5,7 +5,7 @@ load("@devinfra//bazel/api-golden:index_rjs.bzl", "api_golden_test_npm_package") load("@npm2//:defs.bzl", "npm_link_all_packages") -load("//tools:defaults2.bzl", "copy_to_bin", "jasmine_test", "npm_package", "ts_project") +load("//tools:defaults.bzl", "copy_to_bin", "jasmine_test", "npm_package", "ts_project") load("//tools:ts_json_schema.bzl", "ts_json_schema") licenses(["notice"]) @@ -129,30 +129,64 @@ ts_project( data = RUNTIME_ASSETS, module_name = "@angular-devkit/build-angular", deps = [ + ":node_modules/@ampproject/remapping", ":node_modules/@angular-devkit/architect", ":node_modules/@angular-devkit/build-webpack", ":node_modules/@angular-devkit/core", ":node_modules/@angular/build", ":node_modules/@angular/ssr", + ":node_modules/@babel/core", + ":node_modules/@babel/generator", + ":node_modules/@babel/helper-annotate-as-pure", + ":node_modules/@babel/helper-split-export-declaration", + ":node_modules/@babel/plugin-transform-async-generator-functions", + ":node_modules/@babel/plugin-transform-async-to-generator", + ":node_modules/@babel/plugin-transform-runtime", + ":node_modules/@babel/preset-env", + ":node_modules/@babel/runtime", + ":node_modules/@discoveryjs/json-ext", ":node_modules/@ngtools/webpack", - ":node_modules/@vitejs/plugin-basic-ssl", - "//:node_modules/@ampproject/remapping", + ":node_modules/@web/test-runner", + ":node_modules/ansi-colors", + ":node_modules/autoprefixer", + ":node_modules/babel-loader", + ":node_modules/browser-sync", + ":node_modules/browserslist", + ":node_modules/copy-webpack-plugin", + ":node_modules/css-loader", + ":node_modules/http-proxy-middleware", + ":node_modules/istanbul-lib-instrument", + ":node_modules/jsonc-parser", + ":node_modules/less", + ":node_modules/less-loader", + ":node_modules/license-webpack-plugin", + ":node_modules/loader-utils", + ":node_modules/mini-css-extract-plugin", + ":node_modules/ng-packagr", + ":node_modules/open", + ":node_modules/ora", + ":node_modules/piscina", + ":node_modules/postcss", + ":node_modules/postcss-loader", + ":node_modules/resolve-url-loader", + ":node_modules/rxjs", + ":node_modules/sass", + ":node_modules/sass-loader", + ":node_modules/source-map-loader", + ":node_modules/source-map-support", + ":node_modules/terser", + ":node_modules/tree-kill", + ":node_modules/webpack", + ":node_modules/webpack-dev-middleware", + ":node_modules/webpack-dev-server", + ":node_modules/webpack-merge", + ":node_modules/webpack-subresource-integrity", "//:node_modules/@angular/common", "//:node_modules/@angular/compiler-cli", "//:node_modules/@angular/core", "//:node_modules/@angular/localize", "//:node_modules/@angular/platform-server", "//:node_modules/@angular/service-worker", - "//:node_modules/@babel/core", - "//:node_modules/@babel/generator", - "//:node_modules/@babel/helper-annotate-as-pure", - "//:node_modules/@babel/helper-split-export-declaration", - "//:node_modules/@babel/plugin-transform-async-generator-functions", - "//:node_modules/@babel/plugin-transform-async-to-generator", - "//:node_modules/@babel/plugin-transform-runtime", - "//:node_modules/@babel/preset-env", - "//:node_modules/@babel/runtime", - "//:node_modules/@discoveryjs/json-ext", "//:node_modules/@types/babel__core", "//:node_modules/@types/babel__generator", "//:node_modules/@types/browser-sync", @@ -163,50 +197,14 @@ ts_project( "//:node_modules/@types/picomatch", "//:node_modules/@types/semver", "//:node_modules/@types/watchpack", - "//:node_modules/@web/test-runner", - "//:node_modules/ajv", - "//:node_modules/ansi-colors", - "//:node_modules/autoprefixer", - "//:node_modules/babel-loader", - "//:node_modules/browser-sync", - "//:node_modules/browserslist", - "//:node_modules/copy-webpack-plugin", - "//:node_modules/css-loader", "//:node_modules/esbuild", "//:node_modules/esbuild-wasm", "//:node_modules/fast-glob", - "//:node_modules/http-proxy-middleware", - "//:node_modules/istanbul-lib-instrument", - "//:node_modules/jsonc-parser", "//:node_modules/karma", "//:node_modules/karma-source-map-support", - "//:node_modules/less", - "//:node_modules/less-loader", - "//:node_modules/license-webpack-plugin", - "//:node_modules/loader-utils", - "//:node_modules/mini-css-extract-plugin", - "//:node_modules/ng-packagr", - "//:node_modules/open", - "//:node_modules/ora", - "//:node_modules/piscina", - "//:node_modules/postcss", - "//:node_modules/postcss-loader", - "//:node_modules/resolve-url-loader", - "//:node_modules/rxjs", - "//:node_modules/sass", - "//:node_modules/sass-loader", "//:node_modules/semver", - "//:node_modules/source-map-loader", - "//:node_modules/source-map-support", - "//:node_modules/terser", - "//:node_modules/tree-kill", "//:node_modules/tslib", "//:node_modules/typescript", - "//:node_modules/webpack", - "//:node_modules/webpack-dev-middleware", - "//:node_modules/webpack-dev-server", - "//:node_modules/webpack-merge", - "//:node_modules/webpack-subresource-integrity", ], ) @@ -227,11 +225,11 @@ ts_project( deps = [ ":build_angular", ":build_angular_test_utils", + ":node_modules/webpack", "//:node_modules/@types/node", "//:node_modules/fast-glob", "//:node_modules/prettier", "//:node_modules/typescript", - "//:node_modules/webpack", "//packages/angular_devkit/architect/testing", "//packages/angular_devkit/core", ], @@ -301,9 +299,9 @@ ts_project( ":node_modules/@angular-devkit/architect", ":node_modules/@angular-devkit/core", ":node_modules/@angular/build", + ":node_modules/rxjs", "//:node_modules/@types/jasmine", "//:node_modules/@types/node", - "//:node_modules/rxjs", "//modules/testing/builder", ], ) @@ -335,7 +333,7 @@ LARGE_SPECS = { "//:node_modules/karma-jasmine", "//:node_modules/karma-jasmine-html-reporter", "//:node_modules/puppeteer", - "//:node_modules/webpack", + ":node_modules/webpack", ], }, "protractor": { @@ -365,6 +363,7 @@ LARGE_SPECS = { "//:node_modules/@types/node", "//:node_modules/@angular/animations", "//:node_modules/@angular/material", + "//:node_modules/ajv", ], }, "prerender": {}, @@ -374,7 +373,7 @@ LARGE_SPECS = { ":node_modules/@angular/ssr", "//:node_modules/@types/browser-sync", "//:node_modules/@types/node", - "//:node_modules/browser-sync", + ":node_modules/browser-sync", "//:node_modules/express", "//:node_modules/undici", ], @@ -403,9 +402,8 @@ LARGE_SPECS = { "//:node_modules/@angular/compiler-cli", "//:node_modules/@angular/core", "//:node_modules/@angular/platform-browser", - "//:node_modules/@angular/platform-browser-dynamic", "//:node_modules/@angular/router", - "//:node_modules/rxjs", + ":node_modules/rxjs", "//:node_modules/tslib", "//:node_modules/typescript", "//:node_modules/zone.js", diff --git a/packages/angular_devkit/build_angular/package.json b/packages/angular_devkit/build_angular/package.json index fe4807597918..1f8b7e88b5a4 100644 --- a/packages/angular_devkit/build_angular/package.json +++ b/packages/angular_devkit/build_angular/package.json @@ -12,14 +12,14 @@ "@angular-devkit/core": "workspace:0.0.0-PLACEHOLDER", "@angular/build": "workspace:0.0.0-PLACEHOLDER", "@babel/core": "7.26.10", - "@babel/generator": "7.26.10", + "@babel/generator": "7.27.0", "@babel/helper-annotate-as-pure": "7.25.9", "@babel/helper-split-export-declaration": "7.24.7", "@babel/plugin-transform-async-generator-functions": "7.26.8", "@babel/plugin-transform-async-to-generator": "7.25.9", "@babel/plugin-transform-runtime": "7.26.10", "@babel/preset-env": "7.26.9", - "@babel/runtime": "7.26.10", + "@babel/runtime": "7.27.0", "@discoveryjs/json-ext": "0.6.3", "@ngtools/webpack": "workspace:0.0.0-PLACEHOLDER", "@vitejs/plugin-basic-ssl": "2.0.0", @@ -29,26 +29,26 @@ "browserslist": "^4.21.5", "copy-webpack-plugin": "13.0.0", "css-loader": "7.1.2", - "esbuild-wasm": "0.25.1", + "esbuild-wasm": "0.25.2", "fast-glob": "3.3.3", - "http-proxy-middleware": "3.0.3", + "http-proxy-middleware": "3.0.5", "istanbul-lib-instrument": "6.0.3", "jsonc-parser": "3.3.1", "karma-source-map-support": "1.4.0", - "less": "4.2.2", + "less": "4.3.0", "less-loader": "12.2.0", "license-webpack-plugin": "4.0.2", "loader-utils": "3.3.1", "mini-css-extract-plugin": "2.9.2", - "open": "10.1.0", + "open": "10.1.1", "ora": "5.4.1", "picomatch": "4.0.2", - "piscina": "4.8.0", + "piscina": "4.9.2", "postcss": "8.5.3", "postcss-loader": "8.1.1", "resolve-url-loader": "5.0.0", "rxjs": "7.8.2", - "sass": "1.85.1", + "sass": "1.86.3", "sass-loader": "16.0.5", "semver": "7.7.1", "source-map-loader": "5.0.0", @@ -56,22 +56,27 @@ "terser": "5.39.0", "tree-kill": "1.2.2", "tslib": "2.8.1", - "webpack": "5.98.0", + "webpack": "5.99.5", "webpack-dev-middleware": "7.4.2", - "webpack-dev-server": "5.2.0", + "webpack-dev-server": "5.2.1", "webpack-merge": "6.0.1", "webpack-subresource-integrity": "5.1.0" }, "optionalDependencies": { - "esbuild": "0.25.1" + "esbuild": "0.25.2" }, "devDependencies": { - "undici": "7.5.0", - "@angular/ssr": "workspace:*" + "@angular/ssr": "workspace:*", + "@web/test-runner": "0.20.1", + "browser-sync": "3.0.4", + "ng-packagr": "20.0.0-next.6", + "undici": "7.8.0" }, "peerDependencies": { + "@angular/core": "0.0.0-ANGULAR-FW-PEER-DEP", "@angular/compiler-cli": "0.0.0-ANGULAR-FW-PEER-DEP", "@angular/localize": "0.0.0-ANGULAR-FW-PEER-DEP", + "@angular/platform-browser": "0.0.0-ANGULAR-FW-PEER-DEP", "@angular/platform-server": "0.0.0-ANGULAR-FW-PEER-DEP", "@angular/service-worker": "0.0.0-ANGULAR-FW-PEER-DEP", "@angular/ssr": "^0.0.0-PLACEHOLDER", @@ -86,9 +91,15 @@ "typescript": ">=5.8 <5.9" }, "peerDependenciesMeta": { + "@angular/core": { + "optional": true + }, "@angular/localize": { "optional": true }, + "@angular/platform-browser": { + "optional": true + }, "@angular/platform-server": { "optional": true }, diff --git a/packages/angular_devkit/build_angular/src/builders/app-shell/app-shell_spec.ts b/packages/angular_devkit/build_angular/src/builders/app-shell/app-shell_spec.ts index afabdb3094ac..468bdb6ff2bd 100644 --- a/packages/angular_devkit/build_angular/src/builders/app-shell/app-shell_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/app-shell/app-shell_spec.ts @@ -91,11 +91,11 @@ describe('AppShell Builder', () => { export class AppServerModule {} `, 'src/main.ts': ` - import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + import { platformBrowser } from '@angular/platform-browser'; import { AppModule } from './app/app.module'; document.addEventListener('DOMContentLoaded', () => { - platformBrowserDynamic().bootstrapModule(AppModule) + platformBrowser().bootstrapModule(AppModule) .catch(err => console.log(err)); }); `, diff --git a/packages/angular_devkit/build_angular/src/builders/browser/specs/lazy-module_spec.ts b/packages/angular_devkit/build_angular/src/builders/browser/specs/lazy-module_spec.ts index f280658ac6a6..a68936a65036 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser/specs/lazy-module_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser/specs/lazy-module_spec.ts @@ -149,15 +149,10 @@ describe('Browser Builder lazy modules', () => { 'src/main.ts': `import('./one'); import('./two');`, }); - const { files } = await browserBuild(architect, host, target, { - // Preserve symlinks to reliably verify the chunk names. When symlinks - // would be dereferenced, the `@angular/common` file can originate from a - // less predictable path in e.g. node_modules/.pnpm/<...>`. - preserveSymlinks: true, - }); + const { files } = await browserBuild(architect, host, target); expect(files['src_one_ts.js']).toBeDefined(); expect(files['src_two_ts.js']).toBeDefined(); - expect(files['default-node_modules_angular_common_fesm2022_http_mjs.js']).toBeDefined(); + expect(Object.keys(files)).toContain(jasmine.stringContaining('_angular_common_')); }); it(`supports disabling the common bundle`, async () => { diff --git a/packages/angular_devkit/build_angular/src/builders/browser/specs/rebuild_spec.ts b/packages/angular_devkit/build_angular/src/builders/browser/specs/rebuild_spec.ts index 9a89c4d5a04c..fbceb61d270d 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser/specs/rebuild_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser/specs/rebuild_spec.ts @@ -55,10 +55,10 @@ describe('Browser Builder rebuilds', () => { export let X = '$$_E2E_GOLDEN_VALUE_2'; `, 'src/main.ts': ` - import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + import { platformBrowser } from '@angular/platform-browser'; import { AppModule } from './app/app.module'; - platformBrowserDynamic().bootstrapModule(AppModule); + platformBrowser().bootstrapModule(AppModule); import * as m from './app/app.module'; console.log(m.X); diff --git a/packages/angular_devkit/build_angular/src/builders/browser/specs/svg_spec.ts b/packages/angular_devkit/build_angular/src/builders/browser/specs/svg_spec.ts index 92f5fd0cda7b..2be5e2737d43 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser/specs/svg_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser/specs/svg_spec.ts @@ -57,7 +57,11 @@ describe('Browser Builder allow svg', () => { host.scopedSync().read(join(outputPath, 'main.js')), ); - expect(content).toContain('ɵɵnamespaceSVG'); + // Verify that the svg contents are present in the main bundle, + // e.g. as template instructions. + expect(content).toContain('Hello World'); + + // Verify that the svg contents are *not* present as a separate file. expect(host.scopedSync().exists(normalize('dist/app.component.svg'))).toBe( false, 'should not copy app.component.svg to dist', diff --git a/packages/angular_devkit/build_angular/src/builders/browser/specs/web-worker_spec.ts b/packages/angular_devkit/build_angular/src/builders/browser/specs/web-worker_spec.ts index 9e23602d78fc..a9d7d0c38f71 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser/specs/web-worker_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser/specs/web-worker_spec.ts @@ -36,9 +36,9 @@ describe('Browser Builder Web Worker support', () => { }); `, 'src/main.ts': ` - import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + import { platformBrowser } from '@angular/platform-browser'; import { AppModule } from './app/app.module'; - platformBrowserDynamic().bootstrapModule(AppModule).catch(err => console.error(err)); + platformBrowser().bootstrapModule(AppModule).catch(err => console.error(err)); const worker = new Worker(new URL('./app/app.worker', import.meta.url), { type: 'module' }); worker.onmessage = ({ data }) => { diff --git a/packages/angular_devkit/build_angular/src/builders/dev-server/schema.json b/packages/angular_devkit/build_angular/src/builders/dev-server/schema.json index bb7a87a5d2f7..495f244b1722 100644 --- a/packages/angular_devkit/build_angular/src/builders/dev-server/schema.json +++ b/packages/angular_devkit/build_angular/src/builders/dev-server/schema.json @@ -108,7 +108,7 @@ }, "forceEsbuild": { "type": "boolean", - "description": "Force the development server to use the 'browser-esbuild' builder when building. This is a developer preview option for the esbuild-based build system.", + "description": "Force the development server to use the 'browser-esbuild' builder when building.", "default": false }, "prebundle": { diff --git a/packages/angular_devkit/build_angular/src/builders/jest/init-test-bed.mjs b/packages/angular_devkit/build_angular/src/builders/jest/init-test-bed.mjs index 4c229bcbc117..d8e8bb909194 100644 --- a/packages/angular_devkit/build_angular/src/builders/jest/init-test-bed.mjs +++ b/packages/angular_devkit/build_angular/src/builders/jest/init-test-bed.mjs @@ -10,12 +10,9 @@ // `@angular-devkit/build-angular` rather than the user's workspace. Should look into virtual modules to support those use cases. import { getTestBed } from '@angular/core/testing'; -import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting, -} from '@angular/platform-browser-dynamic/testing'; +import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing'; -getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { +getTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting(), { errorOnUnknownElements: true, errorOnUnknownProperties: true, }); diff --git a/packages/angular_devkit/build_angular/src/builders/karma/browser_builder.ts b/packages/angular_devkit/build_angular/src/builders/karma/browser_builder.ts index da6995ba223d..7ae7689402fb 100644 --- a/packages/angular_devkit/build_angular/src/builders/karma/browser_builder.ts +++ b/packages/angular_devkit/build_angular/src/builders/karma/browser_builder.ts @@ -153,13 +153,10 @@ function getBuiltInMainFile(): string { const content = Buffer.from( ` import { getTestBed } from '@angular/core/testing'; - import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting, - } from '@angular/platform-browser-dynamic/testing'; + import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing'; // Initialize the Angular testing environment. - getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + getTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting(), { errorOnUnknownElements: true, errorOnUnknownProperties: true }); diff --git a/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/proxy_spec.ts b/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/proxy_spec.ts index 36808413c2c7..4f1db1d17b17 100644 --- a/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/proxy_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/proxy_spec.ts @@ -39,11 +39,12 @@ describe('Serve SSR Builder', () => { server.set('view engine', 'html'); server.set('views', distFolder); - server.get('*.*', express.static(distFolder, { - maxAge: '1y' + server.use(express.static(distFolder, { + maxAge: '1y', + index: false, })); - server.get('*', (req, res, next) => { + server.use((req, res, next) => { commonEngine .render({ bootstrap: AppServerModule, diff --git a/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/ssl_spec.ts b/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/ssl_spec.ts index 4a3725c100c4..6182b2e2baba 100644 --- a/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/ssl_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/ssl_spec.ts @@ -39,11 +39,12 @@ describe('Serve SSR Builder', () => { server.set('view engine', 'html'); server.set('views', distFolder); - server.get('*.*', express.static(distFolder, { - maxAge: '1y' + server.use(express.static(distFolder, { + maxAge: '1y', + index: false, })); - server.get('*', (req, res, next) => { + server.use((req, res, next) => { commonEngine .render({ bootstrap: AppServerModule, diff --git a/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/works_spec.ts b/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/works_spec.ts index 857e6ab8ea5b..5944eb31c09d 100644 --- a/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/works_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/works_spec.ts @@ -38,11 +38,12 @@ describe('Serve SSR Builder', () => { server.set('view engine', 'html'); server.set('views', distFolder); - server.get('*.*', express.static(distFolder, { - maxAge: '1y' + server.use(express.static(distFolder, { + maxAge: '1y', + index: false, })); - server.get('*', (req, res, next) => { + server.use((req, res, next) => { commonEngine .render({ bootstrap: AppServerModule, diff --git a/packages/angular_devkit/build_angular/src/builders/web-test-runner/jasmine_runner.js b/packages/angular_devkit/build_angular/src/builders/web-test-runner/jasmine_runner.js index 994697c7ac1d..035959a7844e 100644 --- a/packages/angular_devkit/build_angular/src/builders/web-test-runner/jasmine_runner.js +++ b/packages/angular_devkit/build_angular/src/builders/web-test-runner/jasmine_runner.js @@ -7,10 +7,7 @@ */ import { getTestBed } from '@angular/core/testing'; -import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting, -} from '@angular/platform-browser-dynamic/testing'; +import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing'; import { getConfig, sessionFailed, @@ -67,7 +64,7 @@ export async function runJasmineTests(jasmineEnv) { jasmine.DEFAULT_TIMEOUT_INTERVAL = config.defaultTimeoutInterval; // Initialize `TestBed` automatically for users. This assumes we already evaluated `zone.js/testing`. - getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + getTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting(), { errorOnUnknownElements: true, errorOnUnknownProperties: true, }); diff --git a/packages/angular_devkit/build_angular/src/tools/webpack/plugins/index-html-webpack-plugin.ts b/packages/angular_devkit/build_angular/src/tools/webpack/plugins/index-html-webpack-plugin.ts index 14f7923e6435..9c1fdbbcccef 100644 --- a/packages/angular_devkit/build_angular/src/tools/webpack/plugins/index-html-webpack-plugin.ts +++ b/packages/angular_devkit/build_angular/src/tools/webpack/plugins/index-html-webpack-plugin.ts @@ -60,7 +60,7 @@ export class IndexHtmlWebpackPlugin extends IndexHtmlGenerator { } files.push({ - name: chunk.name, + name: chunk.name ?? undefined, file, extension: extname(file), }); diff --git a/packages/angular_devkit/build_angular/src/tools/webpack/plugins/remove-hash-plugin.ts b/packages/angular_devkit/build_angular/src/tools/webpack/plugins/remove-hash-plugin.ts index bf213b19ec38..f4b8c3311689 100644 --- a/packages/angular_devkit/build_angular/src/tools/webpack/plugins/remove-hash-plugin.ts +++ b/packages/angular_devkit/build_angular/src/tools/webpack/plugins/remove-hash-plugin.ts @@ -19,7 +19,7 @@ export class RemoveHashPlugin { apply(compiler: Compiler): void { compiler.hooks.compilation.tap('remove-hash-plugin', (compilation) => { - const assetPath = (path: string, data: { chunk?: { name: string } }) => { + const assetPath = (path: string, data: { chunk?: { name?: string | null } }) => { const chunkName = data.chunk?.name; const { chunkNames, hashFormat } = this.options; diff --git a/packages/angular_devkit/build_webpack/BUILD.bazel b/packages/angular_devkit/build_webpack/BUILD.bazel index 85e41f44660c..08a03a320e8d 100644 --- a/packages/angular_devkit/build_webpack/BUILD.bazel +++ b/packages/angular_devkit/build_webpack/BUILD.bazel @@ -5,7 +5,7 @@ load("@devinfra//bazel/api-golden:index_rjs.bzl", "api_golden_test_npm_package") load("@npm2//:defs.bzl", "npm_link_all_packages") -load("//tools:defaults2.bzl", "jasmine_test", "npm_package", "ts_project") +load("//tools:defaults.bzl", "jasmine_test", "npm_package", "ts_project") load("//tools:ts_json_schema.bzl", "ts_json_schema") licenses(["notice"]) @@ -48,10 +48,10 @@ ts_project( module_name = "@angular-devkit/build-webpack", deps = [ ":node_modules/@angular-devkit/architect", + ":node_modules/rxjs", + ":node_modules/webpack", + ":node_modules/webpack-dev-server", "//:node_modules/@types/node", - "//:node_modules/rxjs", - "//:node_modules/webpack", - "//:node_modules/webpack-dev-server", ], ) @@ -87,7 +87,6 @@ jasmine_test( "//:node_modules/@angular/compiler-cli", "//:node_modules/@angular/core", "//:node_modules/@angular/platform-browser", - "//:node_modules/@angular/platform-browser-dynamic", "//:node_modules/tslib", "//:node_modules/typescript", "//:node_modules/zone.js", diff --git a/packages/angular_devkit/build_webpack/package.json b/packages/angular_devkit/build_webpack/package.json index 44da2f608890..255d4e44a54e 100644 --- a/packages/angular_devkit/build_webpack/package.json +++ b/packages/angular_devkit/build_webpack/package.json @@ -22,7 +22,8 @@ "devDependencies": { "@angular-devkit/core": "workspace:0.0.0-PLACEHOLDER", "@ngtools/webpack": "workspace:0.0.0-PLACEHOLDER", - "webpack": "5.98.0" + "webpack": "5.99.5", + "webpack-dev-server": "5.2.1" }, "peerDependencies": { "webpack": "^5.30.0", diff --git a/packages/angular_devkit/build_webpack/src/utils.ts b/packages/angular_devkit/build_webpack/src/utils.ts index 218b85fbcb2a..7a0f228ec676 100644 --- a/packages/angular_devkit/build_webpack/src/utils.ts +++ b/packages/angular_devkit/build_webpack/src/utils.ts @@ -34,7 +34,7 @@ export function getEmittedFiles(compilation: Compilation): EmittedFiles[] { chunkFileNames.add(file); files.push({ id: chunk.id?.toString(), - name: chunk.name, + name: chunk.name ?? undefined, file, extension: path.extname(file), initial: chunk.isOnlyInitial(), diff --git a/packages/angular_devkit/build_webpack/test/angular-app/src/main.ts b/packages/angular_devkit/build_webpack/test/angular-app/src/main.ts index 99e8f91dd030..9fff4140458d 100644 --- a/packages/angular_devkit/build_webpack/test/angular-app/src/main.ts +++ b/packages/angular_devkit/build_webpack/test/angular-app/src/main.ts @@ -6,9 +6,9 @@ * found in the LICENSE file at https://angular.dev/license */ -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { platformBrowser } from '@angular/platform-browser'; import { AppModule } from './app/app.module'; -platformBrowserDynamic() +platformBrowser() .bootstrapModule(AppModule) .catch((err) => console.log(err)); diff --git a/packages/angular_devkit/core/BUILD.bazel b/packages/angular_devkit/core/BUILD.bazel index e3f918a57e8c..d042a8c4c6e5 100644 --- a/packages/angular_devkit/core/BUILD.bazel +++ b/packages/angular_devkit/core/BUILD.bazel @@ -1,5 +1,6 @@ load("@devinfra//bazel/api-golden:index_rjs.bzl", "api_golden_test_npm_package") -load("//tools:defaults2.bzl", "jasmine_test", "npm_package", "ts_project") +load("@npm2//:defs.bzl", "npm_link_all_packages") +load("//tools:defaults.bzl", "jasmine_test", "npm_package", "ts_project") # Copyright Google Inc. All Rights Reserved. # @@ -9,6 +10,8 @@ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) +npm_link_all_packages() + RUNTIME_ASSETS = glob( include = ["**/*.json"], # NB: we need to exclude the nested node_modules that is laid out by yarn workspaces @@ -29,19 +32,15 @@ ts_project( data = RUNTIME_ASSETS, module_name = "@angular-devkit/core", deps = [ + ":node_modules/ajv", + ":node_modules/ajv-formats", + ":node_modules/jsonc-parser", + ":node_modules/picomatch", + ":node_modules/rxjs", + ":node_modules/source-map", + "//:node_modules/@types/jasmine", "//:node_modules/@types/node", "//:node_modules/@types/picomatch", - "//:node_modules/@types/jasmine", - "//:node_modules/ajv", - "//:node_modules/ajv-formats", - "//:node_modules/jsonc-parser", - "//:node_modules/picomatch", - "//:node_modules/rxjs", - "//:node_modules/source-map", - # @node_module: typescript:es2015.proxy - # @node_module: typescript:es2015.reflect - # @node_module: typescript:es2015.symbol.wellknown - # @typings: source_map ], ) @@ -54,8 +53,8 @@ ts_project( data = glob(["src/workspace/json/test/**/*.json"]), deps = [ ":core", + ":node_modules/rxjs", "//:node_modules/@types/node", - "//:node_modules/rxjs", "//packages/angular_devkit/core/node", ], ) diff --git a/packages/angular_devkit/core/node/BUILD.bazel b/packages/angular_devkit/core/node/BUILD.bazel index 9a6bc4df3ad5..297f24903257 100644 --- a/packages/angular_devkit/core/node/BUILD.bazel +++ b/packages/angular_devkit/core/node/BUILD.bazel @@ -3,7 +3,7 @@ # Use of this source code is governed by an MIT-style license that can be # found in the LICENSE file at https://angular.dev/license -load("//tools:defaults2.bzl", "jasmine_test", "ts_project") +load("//tools:defaults.bzl", "jasmine_test", "ts_project") licenses(["notice"]) @@ -21,9 +21,9 @@ ts_project( module_name = "@angular-devkit/core/node", deps = [ "//:node_modules/@types/node", - "//:node_modules/chokidar", - "//:node_modules/rxjs", "//packages/angular_devkit/core", + "//packages/angular_devkit/core:node_modules/chokidar", + "//packages/angular_devkit/core:node_modules/rxjs", ], ) @@ -42,8 +42,8 @@ ts_project( ":node", "//:node_modules/@types/jasmine", "//:node_modules/@types/node", - "//:node_modules/rxjs", "//packages/angular_devkit/core", + "//packages/angular_devkit/core:node_modules/rxjs", ], ) diff --git a/packages/angular_devkit/core/node/testing/BUILD.bazel b/packages/angular_devkit/core/node/testing/BUILD.bazel index 473b47e5ade7..c57f3d95f55d 100644 --- a/packages/angular_devkit/core/node/testing/BUILD.bazel +++ b/packages/angular_devkit/core/node/testing/BUILD.bazel @@ -20,8 +20,8 @@ ts_project( deps = [ "//:node_modules/@types/jasmine", "//:node_modules/@types/node", - "//:node_modules/rxjs", "//packages/angular_devkit/core", + "//packages/angular_devkit/core:node_modules/rxjs", "//packages/angular_devkit/core/node", ], ) diff --git a/packages/angular_devkit/core/package.json b/packages/angular_devkit/core/package.json index a852f9459160..ae206660d818 100644 --- a/packages/angular_devkit/core/package.json +++ b/packages/angular_devkit/core/package.json @@ -32,6 +32,9 @@ "rxjs": "7.8.2", "source-map": "0.7.4" }, + "devDependencies": { + "chokidar": "4.0.3" + }, "peerDependencies": { "chokidar": "^4.0.0" }, diff --git a/packages/angular_devkit/core/src/json/schema/transforms.ts b/packages/angular_devkit/core/src/json/schema/transforms.ts index d5052a60a966..1c97b7d1e9cc 100644 --- a/packages/angular_devkit/core/src/json/schema/transforms.ts +++ b/packages/angular_devkit/core/src/json/schema/transforms.ts @@ -11,10 +11,27 @@ import { JsonPointer } from './interface'; import { JsonSchema } from './schema'; import { getTypesOfSchema } from './utility'; +export function addUndefinedObjectDefaults( + value: JsonValue, + _pointer: JsonPointer, + schema?: JsonSchema, +): JsonValue { + return transformUndefined(value, _pointer, schema, true); +} + export function addUndefinedDefaults( value: JsonValue, _pointer: JsonPointer, schema?: JsonSchema, +): JsonValue { + return transformUndefined(value, _pointer, schema, false); +} + +function transformUndefined( + value: JsonValue, + _pointer: JsonPointer, + schema?: JsonSchema, + onlyObjects?: boolean, ): JsonValue { if (typeof schema === 'boolean' || schema === undefined) { return value; @@ -45,7 +62,7 @@ export function addUndefinedDefaults( return value; } - if (type === 'array') { + if (!onlyObjects && type === 'array') { return value == undefined ? [] : value; } @@ -94,7 +111,7 @@ export function addUndefinedDefaults( }); if (adjustedSchema && isJsonObject(adjustedSchema)) { - newValue[propName] = addUndefinedDefaults(value, _pointer, adjustedSchema); + newValue[propName] = transformUndefined(value, _pointer, adjustedSchema, onlyObjects); } } } diff --git a/packages/angular_devkit/schematics/BUILD.bazel b/packages/angular_devkit/schematics/BUILD.bazel index 5ba66ae757a1..9cea80be6caf 100644 --- a/packages/angular_devkit/schematics/BUILD.bazel +++ b/packages/angular_devkit/schematics/BUILD.bazel @@ -1,6 +1,6 @@ load("@devinfra//bazel/api-golden:index_rjs.bzl", "api_golden_test_npm_package") load("@npm2//:defs.bzl", "npm_link_all_packages") -load("//tools:defaults2.bzl", "jasmine_test", "npm_package", "ts_project") +load("//tools:defaults.bzl", "jasmine_test", "npm_package", "ts_project") # Copyright Google Inc. All Rights Reserved. # @@ -28,10 +28,10 @@ ts_project( module_name = "@angular-devkit/schematics", deps = [ ":node_modules/@angular-devkit/core", + ":node_modules/jsonc-parser", + ":node_modules/magic-string", + ":node_modules/rxjs", "//:node_modules/@types/node", - "//:node_modules/jsonc-parser", - "//:node_modules/magic-string", - "//:node_modules/rxjs", ], ) @@ -41,9 +41,9 @@ ts_project( srcs = glob(["src/**/*_spec.ts"]), deps = [ ":node_modules/@angular-devkit/core", + ":node_modules/rxjs", ":schematics", "//:node_modules/@types/jasmine", - "//:node_modules/rxjs", "//packages/angular_devkit/schematics/testing", ], ) diff --git a/packages/angular_devkit/schematics/tasks/BUILD.bazel b/packages/angular_devkit/schematics/tasks/BUILD.bazel index 5ce031b6f0b0..3027c56b123f 100644 --- a/packages/angular_devkit/schematics/tasks/BUILD.bazel +++ b/packages/angular_devkit/schematics/tasks/BUILD.bazel @@ -21,9 +21,9 @@ ts_project( module_name = "@angular-devkit/schematics/tasks", deps = [ "//:node_modules/@types/node", - "//:node_modules/ora", - "//:node_modules/rxjs", "//packages/angular_devkit/schematics", "//packages/angular_devkit/schematics:node_modules/@angular-devkit/core", + "//packages/angular_devkit/schematics:node_modules/ora", + "//packages/angular_devkit/schematics:node_modules/rxjs", ], ) diff --git a/packages/angular_devkit/schematics/tasks/node/BUILD.bazel b/packages/angular_devkit/schematics/tasks/node/BUILD.bazel index c6d26d420436..ad190a93adce 100644 --- a/packages/angular_devkit/schematics/tasks/node/BUILD.bazel +++ b/packages/angular_devkit/schematics/tasks/node/BUILD.bazel @@ -19,10 +19,10 @@ ts_project( module_name = "@angular-devkit/schematics/tasks/node", deps = [ "//:node_modules/@types/node", - "//:node_modules/rxjs", "//packages/angular_devkit/core", "//packages/angular_devkit/core/node", "//packages/angular_devkit/schematics", + "//packages/angular_devkit/schematics:node_modules/rxjs", "//packages/angular_devkit/schematics/tasks", ], ) diff --git a/packages/angular_devkit/schematics/testing/BUILD.bazel b/packages/angular_devkit/schematics/testing/BUILD.bazel index 3a6e5f898598..b860574c36a4 100644 --- a/packages/angular_devkit/schematics/testing/BUILD.bazel +++ b/packages/angular_devkit/schematics/testing/BUILD.bazel @@ -16,9 +16,9 @@ ts_project( data = ["package.json"], module_name = "@angular-devkit/schematics/testing", deps = [ - "//:node_modules/rxjs", "//packages/angular_devkit/schematics", "//packages/angular_devkit/schematics:node_modules/@angular-devkit/core", + "//packages/angular_devkit/schematics:node_modules/rxjs", "//packages/angular_devkit/schematics/tasks/node", "//packages/angular_devkit/schematics/tools", ], diff --git a/packages/angular_devkit/schematics/tools/BUILD.bazel b/packages/angular_devkit/schematics/tools/BUILD.bazel index 9ade88d4cbeb..f10d5b45504a 100644 --- a/packages/angular_devkit/schematics/tools/BUILD.bazel +++ b/packages/angular_devkit/schematics/tools/BUILD.bazel @@ -1,4 +1,4 @@ -load("//tools:defaults2.bzl", "jasmine_test", "ts_project") +load("//tools:defaults.bzl", "jasmine_test", "ts_project") # Copyright Google Inc. All Rights Reserved. # @@ -21,10 +21,10 @@ ts_project( module_name = "@angular-devkit/schematics/tools", deps = [ "//:node_modules/@types/node", - "//:node_modules/jsonc-parser", - "//:node_modules/rxjs", "//packages/angular_devkit/schematics", "//packages/angular_devkit/schematics:node_modules/@angular-devkit/core", + "//packages/angular_devkit/schematics:node_modules/jsonc-parser", + "//packages/angular_devkit/schematics:node_modules/rxjs", "//packages/angular_devkit/schematics/tasks", "//packages/angular_devkit/schematics/tasks/node", ], @@ -43,9 +43,9 @@ ts_project( ":tools", "//:node_modules/@types/jasmine", "//:node_modules/@types/node", - "//:node_modules/rxjs", "//packages/angular_devkit/schematics", "//packages/angular_devkit/schematics:node_modules/@angular-devkit/core", + "//packages/angular_devkit/schematics:node_modules/rxjs", "//packages/angular_devkit/schematics/tasks", "//packages/angular_devkit/schematics/testing", "//tests/angular_devkit/schematics/tools/file-system-engine-host:file_system_engine_host_test_lib", diff --git a/packages/angular_devkit/schematics/tools/node-module-engine-host.ts b/packages/angular_devkit/schematics/tools/node-module-engine-host.ts index c24599cf345e..0bc269840c18 100644 --- a/packages/angular_devkit/schematics/tools/node-module-engine-host.ts +++ b/packages/angular_devkit/schematics/tools/node-module-engine-host.ts @@ -7,7 +7,7 @@ */ import { BaseException } from '@angular-devkit/core'; -import { dirname, join, resolve } from 'node:path'; +import { dirname, resolve } from 'node:path'; import { RuleFactory } from '../src'; import { FileSystemCollectionDesc, FileSystemSchematicDesc } from './description'; import { ExportStringRef } from './export-ref'; @@ -46,20 +46,14 @@ export class NodeModulesEngineHost extends FileSystemEngineHostBase { } } - const relativeBase = requester ? dirname(requester) : process.cwd(); let collectionPath: string | undefined = undefined; - - if (name.startsWith('.')) { - name = resolve(relativeBase, name); - } - const resolveOptions = { paths: requester ? [dirname(requester), ...(this.paths || [])] : this.paths, }; // Try to resolve as a package try { - const packageJsonPath = require.resolve(join(name, 'package.json'), resolveOptions); + const packageJsonPath = require.resolve(`${name}/package.json`, resolveOptions); const { schematics } = require(packageJsonPath); if (!schematics || typeof schematics !== 'string') { diff --git a/packages/angular_devkit/schematics_cli/BUILD.bazel b/packages/angular_devkit/schematics_cli/BUILD.bazel index 59d464306f19..01c6cb01ed01 100644 --- a/packages/angular_devkit/schematics_cli/BUILD.bazel +++ b/packages/angular_devkit/schematics_cli/BUILD.bazel @@ -1,5 +1,5 @@ load("@npm2//:defs.bzl", "npm_link_all_packages") -load("//tools:defaults2.bzl", "npm_package", "ts_project") +load("//tools:defaults.bzl", "npm_package", "ts_project") load("//tools:ts_json_schema.bzl", "ts_json_schema") # Copyright Google Inc. All Rights Reserved. @@ -48,11 +48,10 @@ ts_project( deps = [ ":node_modules/@angular-devkit/core", ":node_modules/@angular-devkit/schematics", - "//:node_modules/@inquirer/prompts", + ":node_modules/@inquirer/prompts", "//:node_modules/@types/node", "//:node_modules/@types/yargs-parser", "//:node_modules/ansi-colors", - "//:node_modules/symbol-observable", "//:node_modules/yargs-parser", ], ) diff --git a/packages/angular_devkit/schematics_cli/bin/schematics.ts b/packages/angular_devkit/schematics_cli/bin/schematics.ts index 5dab4733c13f..93e1ddbf9181 100644 --- a/packages/angular_devkit/schematics_cli/bin/schematics.ts +++ b/packages/angular_devkit/schematics_cli/bin/schematics.ts @@ -7,8 +7,6 @@ * found in the LICENSE file at https://angular.dev/license */ -// symbol polyfill must go first -import 'symbol-observable'; import { JsonValue, logging, schema } from '@angular-devkit/core'; import { ProcessOutput, createConsoleLogger } from '@angular-devkit/core/node'; import { UnsuccessfulWorkflowExecution } from '@angular-devkit/schematics'; diff --git a/packages/angular_devkit/schematics_cli/package.json b/packages/angular_devkit/schematics_cli/package.json index 9e2f0097b298..83042dc525ff 100644 --- a/packages/angular_devkit/schematics_cli/package.json +++ b/packages/angular_devkit/schematics_cli/package.json @@ -18,9 +18,8 @@ "dependencies": { "@angular-devkit/core": "workspace:0.0.0-PLACEHOLDER", "@angular-devkit/schematics": "workspace:0.0.0-PLACEHOLDER", - "@inquirer/prompts": "7.3.3", + "@inquirer/prompts": "7.4.1", "ansi-colors": "4.1.3", - "symbol-observable": "4.0.0", "yargs-parser": "21.1.1" } } diff --git a/packages/angular_devkit/schematics_cli/test/BUILD.bazel b/packages/angular_devkit/schematics_cli/test/BUILD.bazel index da03ab72ff54..d75151c168ac 100644 --- a/packages/angular_devkit/schematics_cli/test/BUILD.bazel +++ b/packages/angular_devkit/schematics_cli/test/BUILD.bazel @@ -1,5 +1,5 @@ load("@aspect_rules_js//npm:defs.bzl", "npm_link_package") -load("//tools:defaults2.bzl", "jasmine_test", "ts_project") +load("//tools:defaults.bzl", "jasmine_test", "ts_project") ts_project( name = "schematics_cli_test_lib", diff --git a/packages/ngtools/webpack/BUILD.bazel b/packages/ngtools/webpack/BUILD.bazel index 68006eee2f03..b81855de35b1 100644 --- a/packages/ngtools/webpack/BUILD.bazel +++ b/packages/ngtools/webpack/BUILD.bazel @@ -5,7 +5,7 @@ load("@devinfra//bazel/api-golden:index_rjs.bzl", "api_golden_test_npm_package") load("@npm2//:defs.bzl", "npm_link_all_packages") -load("//tools:defaults2.bzl", "jasmine_test", "npm_package", "ts_project") +load("//tools:defaults.bzl", "jasmine_test", "npm_package", "ts_project") licenses(["notice"]) @@ -31,10 +31,10 @@ ts_project( ], module_name = "@ngtools/webpack", deps = [ + ":node_modules/webpack", "//:node_modules/@angular/compiler-cli", "//:node_modules/@types/node", "//:node_modules/typescript", - "//:node_modules/webpack", ], ) @@ -61,6 +61,7 @@ jasmine_test( data = [ ":webpack_test_lib", # Needed at runtime for runtime TS compilations performed by tests. + ":node_modules/webpack", "//:node_modules/tslib", ], ) diff --git a/packages/ngtools/webpack/package.json b/packages/ngtools/webpack/package.json index f4aa7645c974..10e9ac77393c 100644 --- a/packages/ngtools/webpack/package.json +++ b/packages/ngtools/webpack/package.json @@ -27,9 +27,9 @@ }, "devDependencies": { "@angular-devkit/core": "workspace:0.0.0-PLACEHOLDER", - "@angular/compiler": "20.0.0-next.2", - "@angular/compiler-cli": "20.0.0-next.2", - "typescript": "5.8.2", - "webpack": "5.98.0" + "@angular/compiler": "20.0.0-next.7", + "@angular/compiler-cli": "20.0.0-next.7", + "typescript": "5.8.3", + "webpack": "5.99.5" } } diff --git a/packages/ngtools/webpack/src/ivy/plugin.ts b/packages/ngtools/webpack/src/ivy/plugin.ts index 6b054c605fe1..f46b1360f26a 100644 --- a/packages/ngtools/webpack/src/ivy/plugin.ts +++ b/packages/ngtools/webpack/src/ivy/plugin.ts @@ -410,6 +410,7 @@ export class AngularWebpackPlugin { this.pluginOptions.tsconfig, this.pluginOptions.compilerOptions, ); + compilerOptions.composite = false; compilerOptions.noEmitOnError = false; compilerOptions.suppressOutputPathCheck = true; compilerOptions.outDir = undefined; diff --git a/packages/schematics/angular/BUILD.bazel b/packages/schematics/angular/BUILD.bazel index 9f44e479010b..365017ed0906 100644 --- a/packages/schematics/angular/BUILD.bazel +++ b/packages/schematics/angular/BUILD.bazel @@ -4,7 +4,7 @@ # found in the LICENSE file at https://angular.dev/license load("@npm2//:defs.bzl", "npm_link_all_packages") -load("//tools:defaults2.bzl", "copy_to_bin", "jasmine_test", "npm_package", "ts_project") +load("//tools:defaults.bzl", "copy_to_bin", "jasmine_test", "npm_package", "ts_project") load("//tools:ts_json_schema.bzl", "ts_json_schema") licenses(["notice"]) @@ -90,10 +90,8 @@ ts_project( deps = [ ":node_modules/@angular-devkit/core", ":node_modules/@angular-devkit/schematics", - "//:node_modules/@inquirer/prompts", + ":node_modules/jsonc-parser", "//:node_modules/@types/node", - "//:node_modules/browserslist", - "//:node_modules/jsonc-parser", "//packages/schematics/angular/third_party/github.com/Microsoft/TypeScript", ], ) @@ -124,9 +122,9 @@ ts_project( ":angular", ":node_modules/@angular-devkit/core", ":node_modules/@angular-devkit/schematics", + ":node_modules/jsonc-parser", "//:node_modules/@types/jasmine", "//:node_modules/@types/node", - "//:node_modules/jsonc-parser", "//packages/schematics/angular/third_party/github.com/Microsoft/TypeScript", ], ) diff --git a/packages/schematics/angular/app-shell/index.ts b/packages/schematics/angular/app-shell/index.ts index 725f6d126785..6e4c11181002 100644 --- a/packages/schematics/angular/app-shell/index.ts +++ b/packages/schematics/angular/app-shell/index.ts @@ -6,34 +6,23 @@ * found in the LICENSE file at https://angular.dev/license */ -import { - Rule, - SchematicsException, - Tree, - chain, - noop, - schematic, -} from '@angular-devkit/schematics'; +import { Rule, SchematicsException, Tree, chain, schematic } from '@angular-devkit/schematics'; import { dirname, join } from 'node:path/posix'; import ts from '../third_party/github.com/Microsoft/TypeScript/lib/typescript'; import { - addSymbolToNgModuleMetadata, findNode, findNodes, getDecoratorMetadata, getSourceNodes, insertImport, - isImported, } from '../utility/ast-utils'; import { applyToUpdateRecorder } from '../utility/change'; import { getAppModulePath, isStandaloneApp } from '../utility/ng-ast-utils'; +import { targetBuildNotFoundError } from '../utility/project-targets'; import { findBootstrapApplicationCall, getMainFilePath } from '../utility/standalone/util'; -import { getWorkspace, updateWorkspace } from '../utility/workspace'; -import { Builders } from '../utility/workspace-models'; +import { getWorkspace } from '../utility/workspace'; import { Schema as AppShellOptions } from './schema'; -const APP_SHELL_ROUTE = 'shell'; - function getSourceFile(host: Tree, path: string): ts.SourceFile { const content = host.readText(path); const source = ts.createSourceFile(path, content, ts.ScriptTarget.Latest, true); @@ -156,154 +145,6 @@ function getMetadataProperty(metadata: ts.Node, propertyName: string): ts.Proper return property; } -function addAppShellConfigToWorkspace(options: AppShellOptions): Rule { - return updateWorkspace((workspace) => { - const project = workspace.projects.get(options.project); - if (!project) { - return; - } - const buildTarget = project.targets.get('build'); - if ( - buildTarget?.builder === Builders.Application || - buildTarget?.builder === Builders.BuildApplication - ) { - // Application builder configuration. - const prodConfig = buildTarget.configurations?.production; - if (!prodConfig) { - throw new SchematicsException( - `A "production" configuration is not defined for the "build" builder.`, - ); - } - prodConfig.appShell = true; - } - }); -} - -function addServerRoutes(options: AppShellOptions): Rule { - return async (host: Tree) => { - // The workspace gets updated so this needs to be reloaded - const workspace = await getWorkspace(host); - const project = workspace.projects.get(options.project); - if (!project) { - throw new SchematicsException(`Invalid project name (${options.project})`); - } - - const modulePath = getServerModulePath(host, project.sourceRoot || 'src', 'main.server.ts'); - if (modulePath === null) { - throw new SchematicsException('Server module not found.'); - } - - let moduleSource = getSourceFile(host, modulePath); - if (!isImported(moduleSource, 'Routes', '@angular/router')) { - const recorder = host.beginUpdate(modulePath); - const routesChange = insertImport(moduleSource, modulePath, 'Routes', '@angular/router'); - if (routesChange) { - applyToUpdateRecorder(recorder, [routesChange]); - } - - const imports = getSourceNodes(moduleSource) - .filter((node) => node.kind === ts.SyntaxKind.ImportDeclaration) - .sort((a, b) => a.getStart() - b.getStart()); - const insertPosition = imports[imports.length - 1].getEnd(); - const routeText = `\n\nconst routes: Routes = [ { path: '${APP_SHELL_ROUTE}', component: AppShellComponent }];`; - recorder.insertRight(insertPosition, routeText); - host.commitUpdate(recorder); - } - - moduleSource = getSourceFile(host, modulePath); - if (!isImported(moduleSource, 'RouterModule', '@angular/router')) { - const recorder = host.beginUpdate(modulePath); - const routerModuleChange = insertImport( - moduleSource, - modulePath, - 'RouterModule', - '@angular/router', - ); - - if (routerModuleChange) { - applyToUpdateRecorder(recorder, [routerModuleChange]); - } - - const metadataChange = addSymbolToNgModuleMetadata( - moduleSource, - modulePath, - 'imports', - 'RouterModule.forRoot(routes)', - ); - if (metadataChange) { - applyToUpdateRecorder(recorder, metadataChange); - } - host.commitUpdate(recorder); - } - }; -} - -function addStandaloneServerRoute(options: AppShellOptions): Rule { - return async (host: Tree) => { - const workspace = await getWorkspace(host); - const project = workspace.projects.get(options.project); - if (!project) { - throw new SchematicsException(`Project name "${options.project}" doesn't not exist.`); - } - - const configFilePath = join(project.sourceRoot ?? 'src', 'app/app.config.server.ts'); - if (!host.exists(configFilePath)) { - throw new SchematicsException(`Cannot find "${configFilePath}".`); - } - - const recorder = host.beginUpdate(configFilePath); - let configSourceFile = getSourceFile(host, configFilePath); - if (!isImported(configSourceFile, 'ROUTES', '@angular/router')) { - const routesChange = insertImport( - configSourceFile, - configFilePath, - 'ROUTES', - '@angular/router', - ); - - if (routesChange) { - applyToUpdateRecorder(recorder, [routesChange]); - } - } - - configSourceFile = getSourceFile(host, configFilePath); - const providersLiteral = findNodes(configSourceFile, ts.isPropertyAssignment).find( - (n) => ts.isArrayLiteralExpression(n.initializer) && n.name.getText() === 'providers', - )?.initializer as ts.ArrayLiteralExpression | undefined; - if (!providersLiteral) { - throw new SchematicsException( - `Cannot find the "providers" configuration in "${configFilePath}".`, - ); - } - - // Add route to providers literal. - recorder.remove(providersLiteral.getStart(), providersLiteral.getWidth()); - const updatedProvidersString = [ - ...providersLiteral.elements.map((element) => ' ' + element.getText()), - ` { - provide: ROUTES, - multi: true, - useValue: [{ - path: '${APP_SHELL_ROUTE}', - component: AppShellComponent - }] - }\n `, - ]; - - recorder.insertRight(providersLiteral.getStart(), `[\n${updatedProvidersString.join(',\n')}]`); - - applyToUpdateRecorder(recorder, [ - insertImport( - configSourceFile, - configFilePath, - 'AppShellComponent', - './app-shell/app-shell.component', - ), - ]); - host.commitUpdate(recorder); - }; -} - function addServerRoutingConfig(options: AppShellOptions, isStandalone: boolean): Rule { return async (host: Tree) => { const workspace = await getWorkspace(host); @@ -328,26 +169,21 @@ function addServerRoutingConfig(options: AppShellOptions, isStandalone: boolean) /** max */ undefined, /** recursive */ true, ).find( - (n) => ts.isIdentifier(n.expression) && n.expression.getText() === 'provideServerRouting', + (n) => ts.isIdentifier(n.expression) && n.expression.getText() === 'provideServerRendering', ); if (!functionCall) { throw new SchematicsException( - `Cannot find the "provideServerRouting" function call in "${configFilePath}".`, + `Cannot find the "provideServerRendering" function call in "${configFilePath}".`, ); } recorder = host.beginUpdate(configFilePath); - recorder.insertLeft(functionCall.end - 1, `, withAppShell(AppShellComponent)`); + recorder.insertLeft(functionCall.end - 1, `, withAppShell(AppShell)`); applyToUpdateRecorder(recorder, [ insertImport(configSourceFile, configFilePath, 'withAppShell', '@angular/ssr'), - insertImport( - configSourceFile, - configFilePath, - 'AppShellComponent', - './app-shell/app-shell.component', - ), + insertImport(configSourceFile, configFilePath, 'AppShell', './app-shell/app-shell'), ]); host.commitUpdate(recorder); @@ -359,17 +195,16 @@ export default function (options: AppShellOptions): Rule { const browserEntryPoint = await getMainFilePath(tree, options.project); const isStandalone = isStandaloneApp(tree, browserEntryPoint); + const workspace = await getWorkspace(tree); + const project = workspace.projects.get(options.project); + if (!project) { + throw targetBuildNotFoundError(); + } + return chain([ validateProject(browserEntryPoint), schematic('server', options), - ...(options.serverRouting - ? [noop()] - : isStandalone - ? [addStandaloneServerRoute(options)] - : [addServerRoutes(options)]), - options.serverRouting - ? addServerRoutingConfig(options, isStandalone) - : addAppShellConfigToWorkspace(options), + addServerRoutingConfig(options, isStandalone), schematic('component', { name: 'app-shell', module: 'app.module.server.ts', diff --git a/packages/schematics/angular/app-shell/index_spec.ts b/packages/schematics/angular/app-shell/index_spec.ts index 09fbe4ba6e17..891048d0677e 100644 --- a/packages/schematics/angular/app-shell/index_spec.ts +++ b/packages/schematics/angular/app-shell/index_spec.ts @@ -19,7 +19,6 @@ describe('App Shell Schematic', () => { ); const defaultOptions: AppShellOptions = { project: 'bar', - serverRouting: true, }; const workspaceOptions: WorkspaceOptions = { @@ -70,12 +69,12 @@ describe('App Shell Schematic', () => { }); it('should not fail when AppModule have imported RouterModule already', async () => { - const updateRecorder = appTree.beginUpdate('/projects/bar/src/app/app.module.ts'); + const updateRecorder = appTree.beginUpdate('/projects/bar/src/app/app-module.ts'); updateRecorder.insertLeft(0, "import { RouterModule } from '@angular/router';"); appTree.commitUpdate(updateRecorder); const tree = await schematicRunner.runSchematic('app-shell', defaultOptions, appTree); - const filePath = '/projects/bar/src/app/app.module.ts'; + const filePath = '/projects/bar/src/app/app-module.ts'; const content = tree.readContent(filePath); expect(content).toMatch(/import { RouterModule } from '@angular\/router';/); }); @@ -83,14 +82,14 @@ describe('App Shell Schematic', () => { it('should work if server config was added prior to running the app-shell schematic', async () => { let tree = await schematicRunner.runSchematic('server', defaultOptions, appTree); tree = await schematicRunner.runSchematic('app-shell', defaultOptions, tree); - expect(tree.exists('/projects/bar/src/app/app-shell/app-shell.component.ts')).toBe(true); + expect(tree.exists('/projects/bar/src/app/app-shell/app-shell.ts')).toBe(true); }); it('should create the shell component', async () => { const tree = await schematicRunner.runSchematic('app-shell', defaultOptions, appTree); - expect(tree.exists('/projects/bar/src/app/app-shell/app-shell.component.ts')).toBe(true); + expect(tree.exists('/projects/bar/src/app/app-shell/app-shell.ts')).toBe(true); const content = tree.readContent('/projects/bar/src/app/app.module.server.ts'); - expect(content).toMatch(/app-shell\.component/); + expect(content).toMatch(/app-shell/); }); }); @@ -118,27 +117,25 @@ describe('App Shell Schematic', () => { it('should create the shell component', async () => { const tree = await schematicRunner.runSchematic('app-shell', defaultOptions, appTree); - expect(tree.exists('/projects/bar/src/app/app-shell/app-shell.component.ts')).toBe(true); + expect(tree.exists('/projects/bar/src/app/app-shell/app-shell.ts')).toBe(true); const content = tree.readContent('/projects/bar/src/app/app.config.server.ts'); - expect(content).toMatch(/app-shell\.component/); + expect(content).toMatch(/app-shell/); }); - it(`should update the 'provideServerRouting' call to include 'withAppShell'`, async () => { + it(`should update the 'provideServerRendering' call to include 'withAppShell'`, async () => { const tree = await schematicRunner.runSchematic('app-shell', defaultOptions, appTree); const content = tree.readContent('/projects/bar/src/app/app.config.server.ts'); expect(tags.oneLine`${content}`).toContain( - tags.oneLine`provideServerRouting(serverRoutes, withAppShell(AppShellComponent))`, + tags.oneLine`provideServerRendering(withRoutes(serverRoutes), withAppShell(AppShell))`, ); }); - it(`should add import to 'AppShellComponent'`, async () => { + it(`should add import to 'AppShell'`, async () => { const tree = await schematicRunner.runSchematic('app-shell', defaultOptions, appTree); const filePath = '/projects/bar/src/app/app.config.server.ts'; const content = tree.readContent(filePath); - expect(content).toContain( - `import { AppShellComponent } from './app-shell/app-shell.component';`, - ); + expect(content).toContain(`import { AppShell } from './app-shell/app-shell';`); }); }); }); diff --git a/packages/schematics/angular/app-shell/schema.json b/packages/schematics/angular/app-shell/schema.json index 262fb3fa45b0..c087a1e1cfe1 100644 --- a/packages/schematics/angular/app-shell/schema.json +++ b/packages/schematics/angular/app-shell/schema.json @@ -12,11 +12,6 @@ "$default": { "$source": "projectName" } - }, - "serverRouting": { - "description": "Set up a server application using the Server Routing and App Engine APIs (Developer Preview).", - "type": "boolean", - "default": false } }, "required": ["project"] diff --git a/packages/schematics/angular/application/files/common-files/src/app/app.component.ng.html.template b/packages/schematics/angular/application/files/common-files/src/app/app.html.template similarity index 100% rename from packages/schematics/angular/application/files/common-files/src/app/app.component.ng.html.template rename to packages/schematics/angular/application/files/common-files/src/app/app.html.template diff --git a/packages/schematics/angular/application/files/common-files/tsconfig.app.json.template b/packages/schematics/angular/application/files/common-files/tsconfig.app.json.template index a65978e44714..12de92966bbb 100644 --- a/packages/schematics/angular/application/files/common-files/tsconfig.app.json.template +++ b/packages/schematics/angular/application/files/common-files/tsconfig.app.json.template @@ -6,10 +6,10 @@ "outDir": "<%= relativePathToWorkspaceRoot %>/out-tsc/app", "types": [] }, - "files": [ - "src/main.ts" - ], "include": [ - "src/**/*.d.ts" + "src/**/*.ts" + ], + "exclude": [ + "src/**/*.spec.ts" ] } diff --git a/packages/schematics/angular/application/files/common-files/tsconfig.spec.json.template b/packages/schematics/angular/application/files/common-files/tsconfig.spec.json.template index 3a0a2b43e8f1..11ab3b8614ff 100644 --- a/packages/schematics/angular/application/files/common-files/tsconfig.spec.json.template +++ b/packages/schematics/angular/application/files/common-files/tsconfig.spec.json.template @@ -9,7 +9,6 @@ ] }, "include": [ - "src/**/*.spec.ts", - "src/**/*.d.ts" + "src/**/*.ts" ] } diff --git a/packages/schematics/angular/application/files/module-files/src/app/app.module.ts.template b/packages/schematics/angular/application/files/module-files/src/app/app-module.ts.template similarity index 74% rename from packages/schematics/angular/application/files/module-files/src/app/app.module.ts.template rename to packages/schematics/angular/application/files/module-files/src/app/app-module.ts.template index 4279b6581c35..e210bd4f6d68 100644 --- a/packages/schematics/angular/application/files/module-files/src/app/app.module.ts.template +++ b/packages/schematics/angular/application/files/module-files/src/app/app-module.ts.template @@ -1,18 +1,18 @@ import { NgModule<% if(experimentalZoneless) { %>, provideExperimentalZonelessChangeDetection<% } %> } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; <% if (routing) { %> -import { AppRoutingModule } from './app-routing.module';<% } %> -import { AppComponent } from './app.component'; +import { AppRoutingModule } from './app-routing-module';<% } %> +import { App } from './app'; @NgModule({ declarations: [ - AppComponent + App ], imports: [ BrowserModule<% if (routing) { %>, AppRoutingModule<% } %> ], providers: [<% if (experimentalZoneless) { %>provideExperimentalZonelessChangeDetection()<% } %>], - bootstrap: [AppComponent] + bootstrap: [App] }) export class AppModule { } diff --git a/packages/schematics/angular/application/files/module-files/src/app/app.component.spec.ts.template b/packages/schematics/angular/application/files/module-files/src/app/app.spec.ts.template similarity index 79% rename from packages/schematics/angular/application/files/module-files/src/app/app.component.spec.ts.template rename to packages/schematics/angular/application/files/module-files/src/app/app.spec.ts.template index 1575222d09d9..d9e11422c77e 100644 --- a/packages/schematics/angular/application/files/module-files/src/app/app.component.spec.ts.template +++ b/packages/schematics/angular/application/files/module-files/src/app/app.spec.ts.template @@ -1,35 +1,35 @@ <% if(experimentalZoneless) { %>import { provideExperimentalZonelessChangeDetection } from '@angular/core'; <% } %>import { TestBed } from '@angular/core/testing';<% if (routing) { %> import { RouterModule } from '@angular/router';<% } %> -import { AppComponent } from './app.component'; +import { App } from './app'; -describe('AppComponent', () => { +describe('App', () => { beforeEach(async () => { await TestBed.configureTestingModule({<% if (routing) { %> imports: [ RouterModule.forRoot([]) ],<% } %> declarations: [ - AppComponent + App ],<% if(experimentalZoneless) { %> providers: [provideExperimentalZonelessChangeDetection()]<% } %> }).compileComponents(); }); it('should create the app', () => { - const fixture = TestBed.createComponent(AppComponent); + const fixture = TestBed.createComponent(App); const app = fixture.componentInstance; expect(app).toBeTruthy(); }); it(`should have as title '<%= name %>'`, () => { - const fixture = TestBed.createComponent(AppComponent); + const fixture = TestBed.createComponent(App); const app = fixture.componentInstance; expect(app.title).toEqual('<%= name %>'); }); it('should render title', () => { - const fixture = TestBed.createComponent(AppComponent); + const fixture = TestBed.createComponent(App); fixture.detectChanges(); const compiled = fixture.nativeElement as HTMLElement; expect(compiled.querySelector('h1')?.textContent).toContain('Hello, <%= name %>'); diff --git a/packages/schematics/angular/application/files/module-files/src/app/app.component.ts.template b/packages/schematics/angular/application/files/module-files/src/app/app.ts.template similarity index 72% rename from packages/schematics/angular/application/files/module-files/src/app/app.component.ts.template rename to packages/schematics/angular/application/files/module-files/src/app/app.ts.template index 82d5e35b64a6..ca94fc7bb99a 100644 --- a/packages/schematics/angular/application/files/module-files/src/app/app.component.ts.template +++ b/packages/schematics/angular/application/files/module-files/src/app/app.ts.template @@ -9,11 +9,11 @@ import { Component } from '@angular/core'; %><% } %> `,<% } else { %> - templateUrl: './app.component.ng.html',<% } %> + templateUrl: './app.html',<% } %> standalone: false,<% if(inlineStyle) { %> styles: []<% } else { %> - styleUrl: './app.component.<%= style %>'<% } %> + styleUrl: './app.<%= style %>'<% } %> }) -export class AppComponent { +export class App { title = '<%= name %>'; } diff --git a/packages/schematics/angular/application/files/module-files/src/main.ts.template b/packages/schematics/angular/application/files/module-files/src/main.ts.template index a4e16b837f8a..97d2d132989c 100644 --- a/packages/schematics/angular/application/files/module-files/src/main.ts.template +++ b/packages/schematics/angular/application/files/module-files/src/main.ts.template @@ -1,8 +1,8 @@ <% if(!!viewEncapsulation) { %>import { ViewEncapsulation } from '@angular/core'; -<% }%>import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; -import { AppModule } from './app/app.module'; +<% }%>import { platformBrowser } from '@angular/platform-browser'; +import { AppModule } from './app/app-module'; -platformBrowserDynamic().bootstrapModule(AppModule, { +platformBrowser().bootstrapModule(AppModule, { <% if(!experimentalZoneless) { %>ngZoneEventCoalescing: true,<% } %><% if(!!viewEncapsulation) { %> defaultEncapsulation: ViewEncapsulation.<%= viewEncapsulation %><% } %> }) diff --git a/packages/schematics/angular/application/files/standalone-files/src/app/app.component.spec.ts.template b/packages/schematics/angular/application/files/standalone-files/src/app/app.spec.ts.template similarity index 72% rename from packages/schematics/angular/application/files/standalone-files/src/app/app.component.spec.ts.template rename to packages/schematics/angular/application/files/standalone-files/src/app/app.spec.ts.template index 300f7b6466ae..8d52e127f1dd 100644 --- a/packages/schematics/angular/application/files/standalone-files/src/app/app.component.spec.ts.template +++ b/packages/schematics/angular/application/files/standalone-files/src/app/app.spec.ts.template @@ -1,29 +1,29 @@ <% if(experimentalZoneless) { %>import { provideExperimentalZonelessChangeDetection } from '@angular/core'; <% } %>import { TestBed } from '@angular/core/testing'; -import { AppComponent } from './app.component'; +import { App } from './app'; -describe('AppComponent', () => { +describe('App', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [AppComponent],<% if(experimentalZoneless) { %> + imports: [App],<% if(experimentalZoneless) { %> providers: [provideExperimentalZonelessChangeDetection()]<% } %> }).compileComponents(); }); it('should create the app', () => { - const fixture = TestBed.createComponent(AppComponent); + const fixture = TestBed.createComponent(App); const app = fixture.componentInstance; expect(app).toBeTruthy(); }); it(`should have the '<%= name %>' title`, () => { - const fixture = TestBed.createComponent(AppComponent); + const fixture = TestBed.createComponent(App); const app = fixture.componentInstance; expect(app.title).toEqual('<%= name %>'); }); it('should render title', () => { - const fixture = TestBed.createComponent(AppComponent); + const fixture = TestBed.createComponent(App); fixture.detectChanges(); const compiled = fixture.nativeElement as HTMLElement; expect(compiled.querySelector('h1')?.textContent).toContain('Hello, <%= name %>'); diff --git a/packages/schematics/angular/application/files/standalone-files/src/app/app.component.ts.template b/packages/schematics/angular/application/files/standalone-files/src/app/app.ts.template similarity index 74% rename from packages/schematics/angular/application/files/standalone-files/src/app/app.component.ts.template rename to packages/schematics/angular/application/files/standalone-files/src/app/app.ts.template index 29ec4bbd2c05..74ea464e5d04 100644 --- a/packages/schematics/angular/application/files/standalone-files/src/app/app.component.ts.template +++ b/packages/schematics/angular/application/files/standalone-files/src/app/app.ts.template @@ -11,10 +11,10 @@ import { RouterOutlet } from '@angular/router';<% } %> %><% } %> `,<% } else { %> - templateUrl: './app.component.ng.html',<% } if(inlineStyle) { %> + templateUrl: './app.html',<% } if(inlineStyle) { %> styles: [],<% } else { %> - styleUrl: './app.component.<%= style %>'<% } %> + styleUrl: './app.<%= style %>'<% } %> }) -export class AppComponent { +export class App { title = '<%= name %>'; } diff --git a/packages/schematics/angular/application/files/standalone-files/src/main.ts.template b/packages/schematics/angular/application/files/standalone-files/src/main.ts.template index 35b00f346331..5df75f9c838e 100644 --- a/packages/schematics/angular/application/files/standalone-files/src/main.ts.template +++ b/packages/schematics/angular/application/files/standalone-files/src/main.ts.template @@ -1,6 +1,6 @@ import { bootstrapApplication } from '@angular/platform-browser'; import { appConfig } from './app/app.config'; -import { AppComponent } from './app/app.component'; +import { App } from './app/app'; -bootstrapApplication(AppComponent, appConfig) +bootstrapApplication(App, appConfig) .catch((err) => console.error(err)); diff --git a/packages/schematics/angular/application/index.ts b/packages/schematics/angular/application/index.ts index 1704d8d89b4d..49e333f636fb 100644 --- a/packages/schematics/angular/application/index.ts +++ b/packages/schematics/angular/application/index.ts @@ -26,12 +26,28 @@ import { import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks'; import { Schema as ComponentOptions } from '../component/schema'; import { NodeDependencyType, addPackageJsonDependency } from '../utility/dependencies'; +import { JSONFile } from '../utility/json-file'; import { latestVersions } from '../utility/latest-versions'; import { relativePathToWorkspaceRoot } from '../utility/paths'; import { getWorkspace, updateWorkspace } from '../utility/workspace'; import { Builders, ProjectType } from '../utility/workspace-models'; import { Schema as ApplicationOptions, Style } from './schema'; +function addTsProjectReference(...paths: string[]) { + return (host: Tree) => { + if (!host.exists('tsconfig.json')) { + return host; + } + + const newReferences = paths.map((path) => ({ path })); + + const file = new JSONFile(host, 'tsconfig.json'); + const jsonPath = ['references']; + const value = file.get(jsonPath); + file.modify(jsonPath, Array.isArray(value) ? [...value, ...newReferences] : newReferences); + }; +} + export default function (options: ApplicationOptions): Rule { return async (host: Tree, context: SchematicContext) => { const { appDir, appRootSelector, componentOptions, folderName, sourceDir } = @@ -39,6 +55,10 @@ export default function (options: ApplicationOptions): Rule { return chain([ addAppToWorkspaceFile(options, appDir, folderName), + addTsProjectReference('./' + join(normalize(appDir), 'tsconfig.app.json')), + options.skipTests + ? noop() + : addTsProjectReference('./' + join(normalize(appDir), 'tsconfig.spec.json')), options.standalone ? noop() : schematic('module', { @@ -84,7 +104,7 @@ export default function (options: ApplicationOptions): Rule { ? filter((path) => !path.endsWith('tsconfig.spec.json.template')) : noop(), componentOptions.inlineTemplate - ? filter((path) => !path.endsWith('.ng.html.template')) + ? filter((path) => !path.endsWith('app.html.template')) : noop(), applyTemplates({ utils: strings, @@ -101,7 +121,6 @@ export default function (options: ApplicationOptions): Rule { options.ssr ? schematic('ssr', { project: options.name, - serverRouting: options.serverRouting, skipInstall: true, }) : noop(), @@ -237,7 +256,6 @@ function addAppToWorkspaceFile( builder: Builders.BuildApplication, defaultConfiguration: 'production', options: { - outputPath: `dist/${folderName}`, index: `${sourceRoot}/index.html`, browser: `${sourceRoot}/main.ts`, polyfills: options.experimentalZoneless ? [] : ['zone.js'], @@ -245,7 +263,6 @@ function addAppToWorkspaceFile( inlineStyleLanguage, assets: [{ 'glob': '**/*', 'input': `${projectRoot}public` }], styles: [`${sourceRoot}/styles.${options.style}`], - scripts: [], }, configurations: { production: { @@ -285,7 +302,6 @@ function addAppToWorkspaceFile( inlineStyleLanguage, assets: [{ 'glob': '**/*', 'input': `${projectRoot}public` }], styles: [`${sourceRoot}/styles.${options.style}`], - scripts: [], }, }, }, diff --git a/packages/schematics/angular/application/index_spec.ts b/packages/schematics/angular/application/index_spec.ts index 2979775eb1ea..d15db7a4a843 100644 --- a/packages/schematics/angular/application/index_spec.ts +++ b/packages/schematics/angular/application/index_spec.ts @@ -32,7 +32,6 @@ describe('Application Schematic', () => { const defaultOptions: ApplicationOptions = { name: 'foo', skipPackageJson: false, - serverRouting: false, }; let workspaceTree: UnitTestTree; @@ -55,11 +54,11 @@ describe('Application Schematic', () => { '/projects/foo/src/index.html', '/projects/foo/src/main.ts', '/projects/foo/src/styles.css', - '/projects/foo/src/app/app.module.ts', - '/projects/foo/src/app/app.component.css', - '/projects/foo/src/app/app.component.ng.html', - '/projects/foo/src/app/app.component.spec.ts', - '/projects/foo/src/app/app.component.ts', + '/projects/foo/src/app/app-module.ts', + '/projects/foo/src/app/app.css', + '/projects/foo/src/app/app.html', + '/projects/foo/src/app/app.spec.ts', + '/projects/foo/src/app/app.ts', ]), ); }); @@ -94,8 +93,13 @@ describe('Application Schematic', () => { it('should set the right paths in the tsconfig.app.json', async () => { const tree = await schematicRunner.runSchematic('application', defaultOptions, workspaceTree); - const { files, extends: _extends } = readJsonFile(tree, '/projects/foo/tsconfig.app.json'); - expect(files).toEqual(['src/main.ts']); + const { + include, + exclude, + extends: _extends, + } = readJsonFile(tree, '/projects/foo/tsconfig.app.json'); + expect(include).toEqual(['src/**/*.ts']); + expect(exclude).toEqual(['src/**/*.spec.ts']); expect(_extends).toBe('../../tsconfig.json'); }); @@ -106,6 +110,34 @@ describe('Application Schematic', () => { expect(_extends).toBe('../../tsconfig.json'); }); + it('should add project references in the root tsconfig.json', async () => { + const tree = await schematicRunner.runSchematic('application', defaultOptions, workspaceTree); + + const { references } = readJsonFile(tree, '/tsconfig.json'); + expect(references).toContain( + jasmine.objectContaining({ path: './projects/foo/tsconfig.app.json' }), + ); + expect(references).toContain( + jasmine.objectContaining({ path: './projects/foo/tsconfig.spec.json' }), + ); + }); + + it('should not add spec project reference in the root tsconfig.json with "skipTests" enabled', async () => { + const tree = await schematicRunner.runSchematic( + 'application', + { ...defaultOptions, skipTests: true }, + workspaceTree, + ); + + const { references } = readJsonFile(tree, '/tsconfig.json'); + expect(references).toContain( + jasmine.objectContaining({ path: './projects/foo/tsconfig.app.json' }), + ); + expect(references).not.toContain( + jasmine.objectContaining({ path: './projects/foo/tsconfig.spec.json' }), + ); + }); + it('should install npm dependencies when `skipInstall` is false', async () => { await schematicRunner.runSchematic( 'application', @@ -266,10 +298,10 @@ describe('Application Schematic', () => { '/src/index.html', '/src/main.ts', '/src/styles.css', - '/src/app/app.component.css', - '/src/app/app.component.ng.html', - '/src/app/app.component.spec.ts', - '/src/app/app.component.ts', + '/src/app/app.css', + '/src/app/app.html', + '/src/app/app.spec.ts', + '/src/app/app.ts', ]), ); }); @@ -447,9 +479,9 @@ describe('Application Schematic', () => { const files = tree.files; [ '/projects/foo/tsconfig.spec.json', - '/projects/foo/src/app/app.component.css', - '/projects/foo/src/app/app.component.ng.html', - '/projects/foo/src/app/app.component.spec.ts', + '/projects/foo/src/app/app.css', + '/projects/foo/src/app/app.html', + '/projects/foo/src/app/app.spec.ts', ].forEach((x) => expect(files).not.toContain(x)); expect(files).toEqual( @@ -459,7 +491,7 @@ describe('Application Schematic', () => { '/projects/foo/src/index.html', '/projects/foo/src/main.ts', '/projects/foo/src/styles.css', - '/projects/foo/src/app/app.component.ts', + '/projects/foo/src/app/app.ts', ]), ); }); @@ -473,8 +505,8 @@ describe('Application Schematic', () => { '/projects/foo/tsconfig.spec.json', '/projects/foo/karma.conf.js', '/projects/foo/src/test.ts', - '/projects/foo/src/app/app.component.ng.html', - '/projects/foo/src/app/app.component.spec.ts', + '/projects/foo/src/app/app.html', + '/projects/foo/src/app/app.spec.ts', ].forEach((x) => expect(files).not.toContain(x)); expect(files).toEqual( @@ -484,8 +516,8 @@ describe('Application Schematic', () => { '/projects/foo/src/index.html', '/projects/foo/src/main.ts', '/projects/foo/src/styles.css', - '/projects/foo/src/app/app.component.css', - '/projects/foo/src/app/app.component.ts', + '/projects/foo/src/app/app.css', + '/projects/foo/src/app/app.ts', ]), ); }); @@ -499,8 +531,8 @@ describe('Application Schematic', () => { '/projects/foo/tsconfig.spec.json', '/projects/foo/karma.conf.js', '/projects/foo/src/test.ts', - '/projects/foo/src/app/app.component.css', - '/projects/foo/src/app/app.component.spec.ts', + '/projects/foo/src/app/app.css', + '/projects/foo/src/app/app.spec.ts', ].forEach((x) => expect(files).not.toContain(x)); expect(files).toEqual( @@ -510,8 +542,8 @@ describe('Application Schematic', () => { '/projects/foo/src/index.html', '/projects/foo/src/main.ts', '/projects/foo/src/styles.css', - '/projects/foo/src/app/app.component.ng.html', - '/projects/foo/src/app/app.component.ts', + '/projects/foo/src/app/app.html', + '/projects/foo/src/app/app.ts', ]), ); }); @@ -531,10 +563,10 @@ describe('Application Schematic', () => { '/projects/foo/src/main.ts', '/projects/foo/src/styles.css', '/projects/foo/src/app/app.config.ts', - '/projects/foo/src/app/app.component.css', - '/projects/foo/src/app/app.component.ng.html', - '/projects/foo/src/app/app.component.spec.ts', - '/projects/foo/src/app/app.component.ts', + '/projects/foo/src/app/app.css', + '/projects/foo/src/app/app.html', + '/projects/foo/src/app/app.spec.ts', + '/projects/foo/src/app/app.ts', ]), ); }); @@ -543,7 +575,7 @@ describe('Application Schematic', () => { const options = { ...defaultOptions, standalone: true }; const tree = await schematicRunner.runSchematic('application', options, workspaceTree); - const moduleFiles = tree.files.filter((file) => file.endsWith('.module.ts')); + const moduleFiles = tree.files.filter((file) => file.endsWith('-module.ts')); expect(moduleFiles.length).toEqual(0); }); @@ -558,7 +590,7 @@ describe('Application Schematic', () => { it('should create a standalone component', async () => { const options = { ...defaultOptions, standalone: true }; const tree = await schematicRunner.runSchematic('application', options, workspaceTree); - const component = tree.readContent('/projects/foo/src/app/app.component.ts'); + const component = tree.readContent('/projects/foo/src/app/app.ts'); expect(component).not.toContain('standalone'); }); @@ -570,7 +602,7 @@ describe('Application Schematic', () => { expect(tree.files).toContain('/projects/foo/src/app/app.routes.ts'); - const component = tree.readContent('/projects/foo/src/app/app.component.ts'); + const component = tree.readContent('/projects/foo/src/app/app.ts'); expect(component).toContain(`import { RouterOutlet } from '@angular/router';`); expect(component).toContain(`imports: [RouterOutlet]`); @@ -626,11 +658,11 @@ describe('Application Schematic', () => { const tree = await schematicRunner.runSchematic('application', options, workspaceTree); const files = tree.files; - expect(files).toContain('/projects/foo/src/app/app.module.ts'); - expect(files).toContain('/projects/foo/src/app/app-routing.module.ts'); - const moduleContent = tree.readContent('/projects/foo/src/app/app.module.ts'); - expect(moduleContent).toMatch(/import { AppRoutingModule } from '.\/app-routing.module'/); - const routingModuleContent = tree.readContent('/projects/foo/src/app/app-routing.module.ts'); + expect(files).toContain('/projects/foo/src/app/app-module.ts'); + expect(files).toContain('/projects/foo/src/app/app-routing-module.ts'); + const moduleContent = tree.readContent('/projects/foo/src/app/app-module.ts'); + expect(moduleContent).toMatch(/import { AppRoutingModule } from '.\/app-routing-module'/); + const routingModuleContent = tree.readContent('/projects/foo/src/app/app-routing-module.ts'); expect(routingModuleContent).toMatch(/RouterModule.forRoot\(routes\)/); }); @@ -641,7 +673,7 @@ describe('Application Schematic', () => { workspaceTree, ); - const path = '/projects/foo/src/app/app.module.ts'; + const path = '/projects/foo/src/app/app-module.ts'; const content = tree.readContent(path); expect(content).toMatch(/import { BrowserModule } from '@angular\/platform-browser';/); }); @@ -653,9 +685,9 @@ describe('Application Schematic', () => { workspaceTree, ); - const path = '/projects/foo/src/app/app.module.ts'; + const path = '/projects/foo/src/app/app-module.ts'; const content = tree.readContent(path); - expect(content).toMatch(/import { AppComponent } from '\.\/app\.component';/); + expect(content).toMatch(/import { App } from '\.\/app';/); }); it('should create all files of an application', async () => { @@ -670,12 +702,12 @@ describe('Application Schematic', () => { '/projects/foo/tsconfig.spec.json', '/projects/foo/src/main.ts', '/projects/foo/src/styles.css', - '/projects/foo/src/app/app-routing.module.ts', - '/projects/foo/src/app/app.module.ts', - '/projects/foo/src/app/app.component.css', - '/projects/foo/src/app/app.component.ng.html', - '/projects/foo/src/app/app.component.spec.ts', - '/projects/foo/src/app/app.component.ts', + '/projects/foo/src/app/app-routing-module.ts', + '/projects/foo/src/app/app-module.ts', + '/projects/foo/src/app/app.css', + '/projects/foo/src/app/app.html', + '/projects/foo/src/app/app.spec.ts', + '/projects/foo/src/app/app.ts', ]), ); }); @@ -697,7 +729,7 @@ describe('Application Schematic', () => { ); }); - it('should add provideExperimentalZonelessChangeDetection() in app.module.ts when experimentalZoneless is true', async () => { + it('should add provideExperimentalZonelessChangeDetection() in app-module.ts when experimentalZoneless is true', async () => { const tree = await schematicRunner.runSchematic( 'application', { @@ -707,12 +739,12 @@ describe('Application Schematic', () => { }, workspaceTree, ); - const path = '/projects/foo/src/app/app.module.ts'; + const path = '/projects/foo/src/app/app-module.ts'; const fileContent = tree.readContent(path); expect(fileContent).toContain('provideExperimentalZonelessChangeDetection()'); }); - it('should not add provideExperimentalZonelessChangeDetection() in app.module.ts when experimentalZoneless is false', async () => { + it('should not add provideExperimentalZonelessChangeDetection() in app-module.ts when experimentalZoneless is false', async () => { const tree = await schematicRunner.runSchematic( 'application', { @@ -722,7 +754,7 @@ describe('Application Schematic', () => { }, workspaceTree, ); - const path = '/projects/foo/src/app/app.module.ts'; + const path = '/projects/foo/src/app/app-module.ts'; const fileContent = tree.readContent(path); expect(fileContent).not.toContain('provideExperimentalZonelessChangeDetection()'); }); diff --git a/packages/schematics/angular/application/schema.json b/packages/schematics/angular/application/schema.json index b7d8e382aad2..7a6ea47a2020 100644 --- a/packages/schematics/angular/application/schema.json +++ b/packages/schematics/angular/application/schema.json @@ -118,10 +118,6 @@ "default": false, "x-user-analytics": "ep.ng_ssr" }, - "serverRouting": { - "description": "Set up a server application using the Server Routing and App Engine APIs (Developer Preview).", - "type": "boolean" - }, "experimentalZoneless": { "description": "Generate an application that does not use `zone.js`.", "type": "boolean", diff --git a/packages/schematics/angular/class/files/__name@dasherize____type__.spec.ts.template b/packages/schematics/angular/class/files/__name@dasherize__.__type__.spec.ts.template similarity index 100% rename from packages/schematics/angular/class/files/__name@dasherize____type__.spec.ts.template rename to packages/schematics/angular/class/files/__name@dasherize__.__type__.spec.ts.template diff --git a/packages/schematics/angular/class/files/__name@dasherize____type__.ts.template b/packages/schematics/angular/class/files/__name@dasherize__.__type__.ts.template similarity index 100% rename from packages/schematics/angular/class/files/__name@dasherize____type__.ts.template rename to packages/schematics/angular/class/files/__name@dasherize__.__type__.ts.template diff --git a/packages/schematics/angular/class/index.ts b/packages/schematics/angular/class/index.ts index d7d6953aabbd..865ec67ccf96 100644 --- a/packages/schematics/angular/class/index.ts +++ b/packages/schematics/angular/class/index.ts @@ -11,7 +11,5 @@ import { generateFromFiles } from '../utility/generate-from-files'; import { Schema as ClassOptions } from './schema'; export default function (options: ClassOptions): Rule { - options.type = options.type ? `.${options.type}` : ''; - return generateFromFiles(options); } diff --git a/packages/schematics/angular/component/index.ts b/packages/schematics/angular/component/index.ts index c0937036d20f..acbb82fadca6 100644 --- a/packages/schematics/angular/component/index.ts +++ b/packages/schematics/angular/component/index.ts @@ -53,7 +53,18 @@ export default function (options: ComponentOptions): Rule { options.path = buildDefaultPath(project); } - options.module = findModuleFromOptions(host, options); + try { + options.module = findModuleFromOptions(host, options); + } catch { + options.module = findModuleFromOptions(host, { + ...options, + moduleExt: '-module.ts', + routingModuleExt: '-routing-module.ts', + }); + } + + // Schematic templates require a defined type value + options.type ??= ''; const parsedPath = parseName(options.path, options.name); options.name = parsedPath.name; diff --git a/packages/schematics/angular/component/index_spec.ts b/packages/schematics/angular/component/index_spec.ts index a1b31c294fbb..9140dfcba43f 100644 --- a/packages/schematics/angular/component/index_spec.ts +++ b/packages/schematics/angular/component/index_spec.ts @@ -310,13 +310,13 @@ describe('Component Schematic', () => { expect(tree.files).toContain('/projects/bar/src/app/foo/foo.component.ng.html'); }); - it('should use `.ng.html` extension when ngHtml is not present', async () => { + it('should not use `.ng.html` extension when ngHtml is not present', async () => { const options = { ...defaultOptions, ngHtml: undefined }; const tree = await schematicRunner.runSchematic('component', options, appTree); const content = tree.readContent('/projects/bar/src/app/foo/foo.component.ts'); - expect(content).toContain('foo.component.ng.html'); + expect(content).toContain('foo.component.html'); expect(tree.files).toContain('/projects/bar/src/app/foo/foo.component.css'); - expect(tree.files).toContain('/projects/bar/src/app/foo/foo.component.ng.html'); + expect(tree.files).toContain('/projects/bar/src/app/foo/foo.component.html'); }); it('should create the right selector with a path in the name', async () => { @@ -374,7 +374,7 @@ describe('Component Schematic', () => { it('should create a standalone component', async () => { const options = { ...defaultOptions, standalone: true }; const tree = await schematicRunner.runSchematic('component', options, appTree); - const moduleContent = tree.readContent('/projects/bar/src/app/app.module.ts'); + const moduleContent = tree.readContent('/projects/bar/src/app/app-module.ts'); const componentContent = tree.readContent('/projects/bar/src/app/foo/foo.component.ts'); expect(componentContent).toContain('class FooComponent'); expect(moduleContent).not.toContain('FooComponent'); @@ -416,13 +416,13 @@ describe('Component Schematic', () => { '/projects/baz/src/app/foo/foo.component.ts', ]), ); - const moduleContent = tree.readContent('/projects/baz/src/app/app.module.ts'); + const moduleContent = tree.readContent('/projects/baz/src/app/app-module.ts'); expect(moduleContent).toMatch(/import.*Foo.*from '.\/foo\/foo.component'/); expect(moduleContent).toMatch(/declarations:\s*\[[^\]]+?,\r?\n\s+FooComponent\r?\n/m); }); it('should use the module flag even if the module is a routing module', async () => { - const routingFileName = 'app-routing.module.ts'; + const routingFileName = 'app-routing-module.ts'; const routingModulePath = `/projects/baz/src/app/${routingFileName}`; const newTree = createAppModule(appTree, routingModulePath); const options = { ...defaultNonStandaloneOptions, module: routingFileName }; @@ -435,7 +435,7 @@ describe('Component Schematic', () => { const options = { ...defaultNonStandaloneOptions, name: 'dir/test-component' }; const tree = await schematicRunner.runSchematic('component', options, appTree); - const content = tree.readContent('/projects/baz/src/app/app.module.ts'); + const content = tree.readContent('/projects/baz/src/app/app-module.ts'); expect(content).toMatch( /import { TestComponentComponent } from '\.\/dir\/test-component\/test-component.component'/, ); @@ -455,7 +455,7 @@ describe('Component Schematic', () => { }; appTree = await schematicRunner.runSchematic('component', options, appTree); - const content = appTree.readContent('/projects/baz/src/app/admin/module/module.module.ts'); + const content = appTree.readContent('/projects/baz/src/app/admin/module/module-module.ts'); expect(content).toMatch( /import { TestComponentComponent } from '..\/..\/other\/test-component\/test-component.component'/, ); @@ -463,7 +463,7 @@ describe('Component Schematic', () => { it('should find the closest module', async () => { const options = { ...defaultNonStandaloneOptions }; - const fooModule = '/projects/baz/src/app/foo/foo.module.ts'; + const fooModule = '/projects/baz/src/app/foo/foo-module.ts'; appTree.create( fooModule, ` @@ -486,15 +486,15 @@ describe('Component Schematic', () => { const options = { ...defaultNonStandaloneOptions, export: true }; const tree = await schematicRunner.runSchematic('component', options, appTree); - const appModuleContent = tree.readContent('/projects/baz/src/app/app.module.ts'); + const appModuleContent = tree.readContent('/projects/baz/src/app/app-module.ts'); expect(appModuleContent).toMatch(/exports: \[\n(\s*) {2}FooComponent\n\1\]/); }); it('should import into a specified module', async () => { - const options = { ...defaultNonStandaloneOptions, module: 'app.module.ts' }; + const options = { ...defaultNonStandaloneOptions, module: 'app-module.ts' }; const tree = await schematicRunner.runSchematic('component', options, appTree); - const appModule = tree.readContent('/projects/baz/src/app/app.module.ts'); + const appModule = tree.readContent('/projects/baz/src/app/app-module.ts'); expect(appModule).toMatch(/import { FooComponent } from '.\/foo\/foo.component'/); }); @@ -511,8 +511,8 @@ describe('Component Schematic', () => { // move the module appTree.rename( - '/projects/baz/src/app/app.module.ts', - '/projects/baz/custom/app/app.module.ts', + '/projects/baz/src/app/app-module.ts', + '/projects/baz/custom/app/app-module.ts', ); appTree = await schematicRunner.runSchematic( 'component', diff --git a/packages/schematics/angular/component/schema.json b/packages/schematics/angular/component/schema.json index 549e285fc397..dfbc702f451e 100644 --- a/packages/schematics/angular/component/schema.json +++ b/packages/schematics/angular/component/schema.json @@ -93,8 +93,7 @@ }, "type": { "type": "string", - "description": "Append a custom type to the component's filename. For example, if you set the type to `container`, the file will be named `my-component.container.ts`.", - "default": "Component" + "description": "Append a custom type to the component's filename. For example, if you set the type to `container`, the file will be named `my-component.container.ts`." }, "skipTests": { "type": "boolean", @@ -138,8 +137,8 @@ }, "ngHtml": { "type": "boolean", - "default": true, - "description": "Generate component template files with an '.ng.html' file extension instead of '.html'. The '.ng.html' file extension is recommended by the Angular style guide." + "default": false, + "description": "Generate component template files with an '.ng.html' file extension instead of '.html'." } }, "required": ["name", "project"] diff --git a/packages/schematics/angular/directive/files/__name@dasherize@if-flat__/__name@dasherize__.directive.spec.ts.template b/packages/schematics/angular/directive/files/__name@dasherize@if-flat__/__name@dasherize__.directive.spec.ts.template deleted file mode 100644 index d8e001680f09..000000000000 --- a/packages/schematics/angular/directive/files/__name@dasherize@if-flat__/__name@dasherize__.directive.spec.ts.template +++ /dev/null @@ -1,8 +0,0 @@ -import { <%= classify(name) %>Directive } from './<%= dasherize(name) %>.directive'; - -describe('<%= classify(name) %>Directive', () => { - it('should create an instance', () => { - const directive = new <%= classify(name) %>Directive(); - expect(directive).toBeTruthy(); - }); -}); diff --git a/packages/schematics/angular/directive/files/__name@dasherize__.__type@dasherize__.spec.ts.template b/packages/schematics/angular/directive/files/__name@dasherize__.__type@dasherize__.spec.ts.template new file mode 100644 index 000000000000..59bddc63660a --- /dev/null +++ b/packages/schematics/angular/directive/files/__name@dasherize__.__type@dasherize__.spec.ts.template @@ -0,0 +1,8 @@ +import { <%= classify(name) %><%= classify(type) %> } from './<%= dasherize(name) %><%= type ? '.' + dasherize(type) : '' %>'; + +describe('<%= classify(name) %><%= classify(type) %>', () => { + it('should create an instance', () => { + const directive = new <%= classify(name) %><%= classify(type) %>(); + expect(directive).toBeTruthy(); + }); +}); diff --git a/packages/schematics/angular/directive/files/__name@dasherize@if-flat__/__name@dasherize__.directive.ts.template b/packages/schematics/angular/directive/files/__name@dasherize__.__type@dasherize__.ts.template similarity index 73% rename from packages/schematics/angular/directive/files/__name@dasherize@if-flat__/__name@dasherize__.directive.ts.template rename to packages/schematics/angular/directive/files/__name@dasherize__.__type@dasherize__.ts.template index a63130fdf334..4e55f9d19e6b 100644 --- a/packages/schematics/angular/directive/files/__name@dasherize@if-flat__/__name@dasherize__.directive.ts.template +++ b/packages/schematics/angular/directive/files/__name@dasherize__.__type@dasherize__.ts.template @@ -4,7 +4,7 @@ import { Directive } from '@angular/core'; selector: '[<%= selector %>]'<% if(!standalone) {%>, standalone: false<%}%> }) -export class <%= classify(name) %>Directive { +export class <%= classify(name) %><%= classify(type) %> { constructor() { } diff --git a/packages/schematics/angular/directive/index.ts b/packages/schematics/angular/directive/index.ts index 97e6a9deaa18..e05c64ca9e5b 100644 --- a/packages/schematics/angular/directive/index.ts +++ b/packages/schematics/angular/directive/index.ts @@ -6,22 +6,10 @@ * found in the LICENSE file at https://angular.dev/license */ -import { - Rule, - SchematicsException, - Tree, - apply, - applyTemplates, - chain, - filter, - mergeWith, - move, - noop, - strings, - url, -} from '@angular-devkit/schematics'; +import { Rule, SchematicsException, Tree, chain, strings } from '@angular-devkit/schematics'; import { addDeclarationToNgModule } from '../utility/add-declaration-to-ng-module'; import { findModuleFromOptions } from '../utility/find-module'; +import { generateFromFiles } from '../utility/generate-from-files'; import { parseName } from '../utility/parse-name'; import { validateClassName, validateHtmlSelector } from '../utility/validation'; import { buildDefaultPath, getWorkspace } from '../utility/workspace'; @@ -50,8 +38,15 @@ export default function (options: DirectiveOptions): Rule { options.path = buildDefaultPath(project); } - options.module = findModuleFromOptions(host, options); - + try { + options.module = findModuleFromOptions(host, options); + } catch { + options.module = findModuleFromOptions(host, { + ...options, + moduleExt: '-module.ts', + routingModuleExt: '-routing-module.ts', + }); + } const parsedPath = parseName(options.path, options.name); options.name = parsedPath.name; options.path = parsedPath.path; @@ -60,23 +55,13 @@ export default function (options: DirectiveOptions): Rule { validateHtmlSelector(options.selector); validateClassName(strings.classify(options.name)); - const templateSource = apply(url('./files'), [ - options.skipTests ? filter((path) => !path.endsWith('.spec.ts.template')) : noop(), - applyTemplates({ - ...strings, - 'if-flat': (s: string) => (options.flat ? '' : s), - ...options, - }), - move(parsedPath.path), - ]); - return chain([ addDeclarationToNgModule({ type: 'directive', ...options, }), - mergeWith(templateSource), + generateFromFiles(options), ]); }; } diff --git a/packages/schematics/angular/directive/index_spec.ts b/packages/schematics/angular/directive/index_spec.ts index 1fbdad0ef713..e5dd8dd058df 100644 --- a/packages/schematics/angular/directive/index_spec.ts +++ b/packages/schematics/angular/directive/index_spec.ts @@ -50,15 +50,15 @@ describe('Directive Schematic', () => { const tree = await schematicRunner.runSchematic('directive', options, appTree); const files = tree.files; - expect(files).toContain('/projects/bar/src/app/foo/foo.directive.spec.ts'); - expect(files).toContain('/projects/bar/src/app/foo/foo.directive.ts'); + expect(files).toContain('/projects/bar/src/app/foo/foo.spec.ts'); + expect(files).toContain('/projects/bar/src/app/foo/foo.ts'); }); it('should converts dash-cased-name to a camelCasedSelector', async () => { const options = { ...defaultOptions, name: 'my-dir' }; const tree = await schematicRunner.runSchematic('directive', options, appTree); - const content = tree.readContent('/projects/bar/src/app/my-dir.directive.ts'); + const content = tree.readContent('/projects/bar/src/app/my-dir.ts'); expect(content).toMatch(/selector: '\[appMyDir\]'/); }); @@ -66,7 +66,7 @@ describe('Directive Schematic', () => { const options = { ...defaultOptions, name: 'sub/test' }; appTree = await schematicRunner.runSchematic('directive', options, appTree); - const content = appTree.readContent('/projects/bar/src/app/sub/test.directive.ts'); + const content = appTree.readContent('/projects/bar/src/app/sub/test.ts'); expect(content).toMatch(/selector: '\[appTest\]'/); }); @@ -74,7 +74,7 @@ describe('Directive Schematic', () => { const options = { ...defaultOptions, prefix: 'pre' }; const tree = await schematicRunner.runSchematic('directive', options, appTree); - const content = tree.readContent('/projects/bar/src/app/foo.directive.ts'); + const content = tree.readContent('/projects/bar/src/app/foo.ts'); expect(content).toMatch(/selector: '\[preFoo\]'/); }); @@ -82,7 +82,7 @@ describe('Directive Schematic', () => { const options = { ...defaultOptions, prefix: undefined }; const tree = await schematicRunner.runSchematic('directive', options, appTree); - const content = tree.readContent('/projects/bar/src/app/foo.directive.ts'); + const content = tree.readContent('/projects/bar/src/app/foo.ts'); expect(content).toMatch(/selector: '\[appFoo\]'/); }); @@ -90,7 +90,7 @@ describe('Directive Schematic', () => { const options = { ...defaultOptions, prefix: '' }; const tree = await schematicRunner.runSchematic('directive', options, appTree); - const content = tree.readContent('/projects/bar/src/app/foo.directive.ts'); + const content = tree.readContent('/projects/bar/src/app/foo.ts'); expect(content).toMatch(/selector: '\[foo\]'/); }); @@ -99,16 +99,16 @@ describe('Directive Schematic', () => { const tree = await schematicRunner.runSchematic('directive', options, appTree); const files = tree.files; - expect(files).toContain('/projects/bar/src/app/foo.directive.ts'); - expect(files).not.toContain('/projects/bar/src/app/foo.directive.spec.ts'); + expect(files).toContain('/projects/bar/src/app/foo.ts'); + expect(files).not.toContain('/projects/bar/src/app/foo.spec.ts'); }); it('should create a standalone directive', async () => { const options = { ...defaultOptions, standalone: true }; const tree = await schematicRunner.runSchematic('directive', options, appTree); - const directiveContent = tree.readContent('/projects/bar/src/app/foo.directive.ts'); + const directiveContent = tree.readContent('/projects/bar/src/app/foo.ts'); expect(directiveContent).not.toContain('standalone'); - expect(directiveContent).toContain('class FooDirective'); + expect(directiveContent).toContain('class Foo'); }); it('should error when class name contains invalid characters', async () => { @@ -119,6 +119,24 @@ describe('Directive Schematic', () => { ).toBeRejectedWithError('Class name "404" is invalid.'); }); + it('should respect the type option', async () => { + const options = { ...defaultOptions, type: 'Directive' }; + const tree = await schematicRunner.runSchematic('directive', options, appTree); + const content = tree.readContent('/projects/bar/src/app/foo.directive.ts'); + const testContent = tree.readContent('/projects/bar/src/app/foo.directive.spec.ts'); + expect(content).toContain('export class FooDirective'); + expect(testContent).toContain("describe('FooDirective'"); + }); + + it('should allow empty string in the type option', async () => { + const options = { ...defaultOptions, type: '' }; + const tree = await schematicRunner.runSchematic('directive', options, appTree); + const content = tree.readContent('/projects/bar/src/app/foo.ts'); + const testContent = tree.readContent('/projects/bar/src/app/foo.spec.ts'); + expect(content).toContain('export class Foo'); + expect(testContent).toContain("describe('Foo'"); + }); + describe('standalone=false', () => { const defaultNonStandaloneOptions: DirectiveOptions = { ...defaultOptions, @@ -139,11 +157,11 @@ describe('Directive Schematic', () => { const tree = await schematicRunner.runSchematic('directive', options, appTree); const files = tree.files; - expect(files).toContain('/projects/baz/src/app/foo.directive.spec.ts'); - expect(files).toContain('/projects/baz/src/app/foo.directive.ts'); - const moduleContent = tree.readContent('/projects/baz/src/app/app.module.ts'); - expect(moduleContent).toMatch(/import.*Foo.*from '.\/foo.directive'/); - expect(moduleContent).toMatch(/declarations:\s*\[[^\]]+?,\r?\n\s+FooDirective\r?\n/m); + expect(files).toContain('/projects/baz/src/app/foo.spec.ts'); + expect(files).toContain('/projects/baz/src/app/foo.ts'); + const moduleContent = tree.readContent('/projects/baz/src/app/app-module.ts'); + expect(moduleContent).toMatch(/import.*Foo.*from '.\/foo'/); + expect(moduleContent).toMatch(/declarations:\s*\[[^\]]+?,\r?\n\s+Foo\r?\n/m); }); it('should respect the sourceRoot value', async () => { @@ -158,8 +176,8 @@ describe('Directive Schematic', () => { // move the module appTree.rename( - '/projects/baz/src/app/app.module.ts', - '/projects/baz/custom/app/app.module.ts', + '/projects/baz/src/app/app-module.ts', + '/projects/baz/custom/app/app-module.ts', ); appTree = await schematicRunner.runSchematic( 'directive', @@ -167,12 +185,12 @@ describe('Directive Schematic', () => { appTree, ); - expect(appTree.files).toContain('/projects/baz/custom/app/foo.directive.ts'); + expect(appTree.files).toContain('/projects/baz/custom/app/foo.ts'); }); it('should find the closest module', async () => { const options = { ...defaultNonStandaloneOptions, flat: false }; - const fooModule = '/projects/baz/src/app/foo/foo.module.ts'; + const fooModule = '/projects/baz/src/app/foo/foo-module.ts'; appTree.create( fooModule, ` @@ -188,24 +206,24 @@ describe('Directive Schematic', () => { const tree = await schematicRunner.runSchematic('directive', options, appTree); const fooModuleContent = tree.readContent(fooModule); - expect(fooModuleContent).toMatch(/import { FooDirective } from '.\/foo.directive'/); + expect(fooModuleContent).toMatch(/import { Foo } from '.\/foo'/); }); it('should export the directive', async () => { const options = { ...defaultNonStandaloneOptions, export: true }; const tree = await schematicRunner.runSchematic('directive', options, appTree); - const appModuleContent = tree.readContent('/projects/baz/src/app/app.module.ts'); - expect(appModuleContent).toMatch(/exports: \[\n(\s*) {2}FooDirective\n\1\]/); + const appModuleContent = tree.readContent('/projects/baz/src/app/app-module.ts'); + expect(appModuleContent).toMatch(/exports: \[\n(\s*) {2}Foo\n\1\]/); }); it('should import into a specified module', async () => { - const options = { ...defaultNonStandaloneOptions, module: 'app.module.ts' }; + const options = { ...defaultNonStandaloneOptions, module: 'app-module.ts' }; const tree = await schematicRunner.runSchematic('directive', options, appTree); - const appModule = tree.readContent('/projects/baz/src/app/app.module.ts'); + const appModule = tree.readContent('/projects/baz/src/app/app-module.ts'); - expect(appModule).toMatch(/import { FooDirective } from '.\/foo.directive'/); + expect(appModule).toMatch(/import { Foo } from '.\/foo'/); }); it('should fail if specified module does not exist', async () => { diff --git a/packages/schematics/angular/directive/schema.json b/packages/schematics/angular/directive/schema.json index 753c520774ee..4a4041604fb0 100644 --- a/packages/schematics/angular/directive/schema.json +++ b/packages/schematics/angular/directive/schema.json @@ -80,6 +80,10 @@ "type": "boolean", "default": false, "description": "Automatically export the directive from the specified NgModule, making it accessible to other modules in the application." + }, + "type": { + "type": "string", + "description": "Append a custom type to the directive's filename. For example, if you set the type to `directive`, the file will be named `example.directive.ts`." } }, "required": ["name", "project"] diff --git a/packages/schematics/angular/enum/files/__name@dasherize____type__.ts.template b/packages/schematics/angular/enum/files/__name@dasherize__.__type__.ts.template similarity index 100% rename from packages/schematics/angular/enum/files/__name@dasherize____type__.ts.template rename to packages/schematics/angular/enum/files/__name@dasherize__.__type__.ts.template diff --git a/packages/schematics/angular/enum/index.ts b/packages/schematics/angular/enum/index.ts index 34f1c04477ff..e008a88b43d2 100644 --- a/packages/schematics/angular/enum/index.ts +++ b/packages/schematics/angular/enum/index.ts @@ -6,12 +6,10 @@ * found in the LICENSE file at https://angular.dev/license */ -import { Rule } from '@angular-devkit/schematics'; +import type { Rule } from '@angular-devkit/schematics'; import { generateFromFiles } from '../utility/generate-from-files'; -import { Schema as EnumOptions } from './schema'; +import type { Schema as EnumOptions } from './schema'; export default function (options: EnumOptions): Rule { - options.type = options.type ? `.${options.type}` : ''; - return generateFromFiles(options); } diff --git a/packages/schematics/angular/guard/implements-files/__name@dasherize__.guard.spec.ts.template b/packages/schematics/angular/guard/implements-files/__name@dasherize____typeSeparator__guard.spec.ts.template similarity index 92% rename from packages/schematics/angular/guard/implements-files/__name@dasherize__.guard.spec.ts.template rename to packages/schematics/angular/guard/implements-files/__name@dasherize____typeSeparator__guard.spec.ts.template index 0ce1ff44c67c..fefa3afee2b0 100644 --- a/packages/schematics/angular/guard/implements-files/__name@dasherize__.guard.spec.ts.template +++ b/packages/schematics/angular/guard/implements-files/__name@dasherize____typeSeparator__guard.spec.ts.template @@ -1,6 +1,6 @@ import { TestBed } from '@angular/core/testing'; -import { <%= classify(name) %>Guard } from './<%= dasherize(name) %>.guard'; +import { <%= classify(name) %>Guard } from './<%= dasherize(name) %><%= typeSeparator %>guard'; describe('<%= classify(name) %>Guard', () => { let guard: <%= classify(name) %>Guard; diff --git a/packages/schematics/angular/guard/implements-files/__name@dasherize__.guard.ts.template b/packages/schematics/angular/guard/implements-files/__name@dasherize____typeSeparator__guard.ts.template similarity index 100% rename from packages/schematics/angular/guard/implements-files/__name@dasherize__.guard.ts.template rename to packages/schematics/angular/guard/implements-files/__name@dasherize____typeSeparator__guard.ts.template diff --git a/packages/schematics/angular/guard/index_spec.ts b/packages/schematics/angular/guard/index_spec.ts index 05abf2a525ad..3b0c0da2059b 100644 --- a/packages/schematics/angular/guard/index_spec.ts +++ b/packages/schematics/angular/guard/index_spec.ts @@ -51,8 +51,8 @@ describe('Guard Schematic', () => { ); const files = tree.files; - expect(files).toContain('/projects/bar/src/app/foo.guard.spec.ts'); - expect(files).toContain('/projects/bar/src/app/foo.guard.ts'); + expect(files).toContain('/projects/bar/src/app/foo-guard.spec.ts'); + expect(files).toContain('/projects/bar/src/app/foo-guard.ts'); }); it('should respect the skipTests flag', async () => { @@ -60,8 +60,30 @@ describe('Guard Schematic', () => { const tree = await schematicRunner.runSchematic('guard', options, appTree); const files = tree.files; - expect(files).not.toContain('/projects/bar/src/app/foo.guard.spec.ts'); + expect(files).not.toContain('/projects/bar/src/app/foo-guard.spec.ts'); + expect(files).toContain('/projects/bar/src/app/foo-guard.ts'); + }); + + it('should use a `.` type separator when specified', async () => { + const options = { ...defaultOptions, typeSeparator: '.' }; + + const tree = await schematicRunner.runSchematic('guard', options, appTree); + const files = tree.files; + expect(files).toContain('/projects/bar/src/app/foo.guard.spec.ts'); expect(files).toContain('/projects/bar/src/app/foo.guard.ts'); + const specContent = tree.readContent('/projects/bar/src/app/foo.guard.spec.ts'); + expect(specContent).toContain(`'./foo.guard'`); + }); + + it('should use a `-` type separator when specified', async () => { + const options = { ...defaultOptions, typeSeparator: '-' }; + + const tree = await schematicRunner.runSchematic('guard', options, appTree); + const files = tree.files; + expect(files).toContain('/projects/bar/src/app/foo-guard.spec.ts'); + expect(files).toContain('/projects/bar/src/app/foo-guard.ts'); + const specContent = tree.readContent('/projects/bar/src/app/foo-guard.spec.ts'); + expect(specContent).toContain(`'./foo-guard'`); }); it('should respect the flat flag', async () => { @@ -69,8 +91,8 @@ describe('Guard Schematic', () => { const tree = await schematicRunner.runSchematic('guard', options, appTree); const files = tree.files; - expect(files).toContain('/projects/bar/src/app/foo/foo.guard.spec.ts'); - expect(files).toContain('/projects/bar/src/app/foo/foo.guard.ts'); + expect(files).toContain('/projects/bar/src/app/foo/foo-guard.spec.ts'); + expect(files).toContain('/projects/bar/src/app/foo/foo-guard.ts'); }); it('should respect the sourceRoot value', async () => { @@ -78,13 +100,13 @@ describe('Guard Schematic', () => { config.projects.bar.sourceRoot = 'projects/bar/custom'; appTree.overwrite('/angular.json', JSON.stringify(config, null, 2)); appTree = await schematicRunner.runSchematic('guard', defaultOptions, appTree); - expect(appTree.files).toContain('/projects/bar/custom/app/foo.guard.ts'); + expect(appTree.files).toContain('/projects/bar/custom/app/foo-guard.ts'); }); it('should respect the implements value', async () => { const options = { ...defaultOptions, implements: ['CanActivate'], functional: false }; const tree = await schematicRunner.runSchematic('guard', options, appTree); - const fileString = tree.readContent('/projects/bar/src/app/foo.guard.ts'); + const fileString = tree.readContent('/projects/bar/src/app/foo-guard.ts'); expect(fileString).toContain('CanActivate'); expect(fileString).toContain('canActivate'); expect(fileString).not.toContain('CanActivateChild'); @@ -96,7 +118,7 @@ describe('Guard Schematic', () => { it('should generate a functional guard by default', async () => { const options = { ...defaultOptions, implements: ['CanActivate'] }; const tree = await schematicRunner.runSchematic('guard', options, appTree); - const fileString = tree.readContent('/projects/bar/src/app/foo.guard.ts'); + const fileString = tree.readContent('/projects/bar/src/app/foo-guard.ts'); expect(fileString).toContain('export const fooGuard: CanActivateFn = (route, state) => {'); expect(fileString).not.toContain('CanActivateChild'); expect(fileString).not.toContain('canActivateChild'); @@ -107,7 +129,7 @@ describe('Guard Schematic', () => { it('should generate a helper function to execute the guard in a test', async () => { const options = { ...defaultOptions, implements: ['CanActivate'] }; const tree = await schematicRunner.runSchematic('guard', options, appTree); - const fileString = tree.readContent('/projects/bar/src/app/foo.guard.spec.ts'); + const fileString = tree.readContent('/projects/bar/src/app/foo-guard.spec.ts'); expect(fileString).toContain('const executeGuard: CanActivateFn = (...guardParameters) => '); expect(fileString).toContain( 'TestBed.runInInjectionContext(() => fooGuard(...guardParameters));', @@ -117,7 +139,7 @@ describe('Guard Schematic', () => { it('should generate CanDeactivateFn with unknown functional guard', async () => { const options = { ...defaultOptions, implements: ['CanDeactivate'] }; const tree = await schematicRunner.runSchematic('guard', options, appTree); - const fileString = tree.readContent('/projects/bar/src/app/foo.guard.ts'); + const fileString = tree.readContent('/projects/bar/src/app/foo-guard.ts'); expect(fileString).toContain( 'export const fooGuard: CanDeactivateFn = ' + '(component, currentRoute, currentState, nextState) => {', @@ -128,7 +150,7 @@ describe('Guard Schematic', () => { const implementationOptions = ['CanActivate', 'CanDeactivate', 'CanActivateChild']; const options = { ...defaultOptions, implements: implementationOptions, functional: false }; const tree = await schematicRunner.runSchematic('guard', options, appTree); - const fileString = tree.readContent('/projects/bar/src/app/foo.guard.ts'); + const fileString = tree.readContent('/projects/bar/src/app/foo-guard.ts'); // Should contain all implementations implementationOptions.forEach((implementation: string) => { @@ -142,7 +164,7 @@ describe('Guard Schematic', () => { const implementationOptions = ['CanMatch']; const options = { ...defaultOptions, implements: implementationOptions, functional: false }; const tree = await schematicRunner.runSchematic('guard', options, appTree); - const fileString = tree.readContent('/projects/bar/src/app/foo.guard.ts'); + const fileString = tree.readContent('/projects/bar/src/app/foo-guard.ts'); const expectedImports = `import { CanMatch, GuardResult, MaybeAsync, Route, subPath } from '@angular/router';`; expect(fileString).toContain(expectedImports); @@ -152,7 +174,7 @@ describe('Guard Schematic', () => { const implementationOptions = ['CanActivate']; const options = { ...defaultOptions, implements: implementationOptions, functional: false }; const tree = await schematicRunner.runSchematic('guard', options, appTree); - const fileString = tree.readContent('/projects/bar/src/app/foo.guard.ts'); + const fileString = tree.readContent('/projects/bar/src/app/foo-guard.ts'); const expectedImports = `import { ActivatedRouteSnapshot, CanActivate, GuardResult, ` + `MaybeAsync, RouterStateSnapshot } from '@angular/router';`; @@ -163,7 +185,7 @@ describe('Guard Schematic', () => { it('should add correct imports based on canActivate functional guard', async () => { const options = { ...defaultOptions, implements: ['CanActivate'] }; const tree = await schematicRunner.runSchematic('guard', options, appTree); - const fileString = tree.readContent('/projects/bar/src/app/foo.guard.ts'); + const fileString = tree.readContent('/projects/bar/src/app/foo-guard.ts'); const expectedImports = `import { CanActivateFn } from '@angular/router';`; expect(fileString).toContain(expectedImports); @@ -173,7 +195,7 @@ describe('Guard Schematic', () => { const implementationOptions = ['CanActivate', 'CanMatch', 'CanActivateChild']; const options = { ...defaultOptions, implements: implementationOptions, functional: false }; const tree = await schematicRunner.runSchematic('guard', options, appTree); - const fileString = tree.readContent('/projects/bar/src/app/foo.guard.ts'); + const fileString = tree.readContent('/projects/bar/src/app/foo-guard.ts'); const expectedImports = `import { ActivatedRouteSnapshot, CanActivate, CanActivateChild, CanMatch, GuardResult, ` + `MaybeAsync, Route, RouterStateSnapshot, subPath } from '@angular/router';`; diff --git a/packages/schematics/angular/guard/schema.json b/packages/schematics/angular/guard/schema.json index 0f6952c459f6..9e1a9f3084c6 100644 --- a/packages/schematics/angular/guard/schema.json +++ b/packages/schematics/angular/guard/schema.json @@ -58,6 +58,12 @@ }, "default": ["CanActivate"], "x-prompt": "Which type of guard would you like to create?" + }, + "typeSeparator": { + "type": "string", + "default": "-", + "enum": ["-", "."], + "description": "The separator character to use before the type within the generated file's name. For example, if you set the option to `.`, the file will be named `example.guard.ts`." } }, "required": ["name", "project"] diff --git a/packages/schematics/angular/guard/type-files/__name@dasherize__.guard.spec.ts.template b/packages/schematics/angular/guard/type-files/__name@dasherize____typeSeparator__guard.spec.ts.template similarity index 94% rename from packages/schematics/angular/guard/type-files/__name@dasherize__.guard.spec.ts.template rename to packages/schematics/angular/guard/type-files/__name@dasherize____typeSeparator__guard.spec.ts.template index d068b5f353d7..9bad0a553eb4 100644 --- a/packages/schematics/angular/guard/type-files/__name@dasherize__.guard.spec.ts.template +++ b/packages/schematics/angular/guard/type-files/__name@dasherize____typeSeparator__guard.spec.ts.template @@ -1,7 +1,7 @@ import { TestBed } from '@angular/core/testing'; import { <%= guardType %> } from '@angular/router'; -import { <%= camelize(name) %>Guard } from './<%= dasherize(name) %>.guard'; +import { <%= camelize(name) %>Guard } from './<%= dasherize(name) %><%= typeSeparator %>guard'; describe('<%= camelize(name) %>Guard', () => { const executeGuard: <%= guardType %><% if (guardType === 'CanDeactivateFn') { %><% } %> = (...guardParameters) => diff --git a/packages/schematics/angular/guard/type-files/__name@dasherize__.guard.ts.template b/packages/schematics/angular/guard/type-files/__name@dasherize____typeSeparator__guard.ts.template similarity index 100% rename from packages/schematics/angular/guard/type-files/__name@dasherize__.guard.ts.template rename to packages/schematics/angular/guard/type-files/__name@dasherize____typeSeparator__guard.ts.template diff --git a/packages/schematics/angular/interceptor/class-files/__name@dasherize@if-flat__/__name@dasherize__.interceptor.spec.ts.template b/packages/schematics/angular/interceptor/class-files/__name@dasherize____typeSeparator__interceptor.spec.ts.template similarity index 91% rename from packages/schematics/angular/interceptor/class-files/__name@dasherize@if-flat__/__name@dasherize__.interceptor.spec.ts.template rename to packages/schematics/angular/interceptor/class-files/__name@dasherize____typeSeparator__interceptor.spec.ts.template index d136abd5f7dc..9af595489571 100755 --- a/packages/schematics/angular/interceptor/class-files/__name@dasherize@if-flat__/__name@dasherize__.interceptor.spec.ts.template +++ b/packages/schematics/angular/interceptor/class-files/__name@dasherize____typeSeparator__interceptor.spec.ts.template @@ -1,6 +1,6 @@ import { TestBed } from '@angular/core/testing'; -import { <%= classify(name) %>Interceptor } from './<%= dasherize(name) %>.interceptor'; +import { <%= classify(name) %>Interceptor } from './<%= dasherize(name) %><%= typeSeparator %>interceptor'; describe('<%= classify(name) %>Interceptor', () => { beforeEach(() => TestBed.configureTestingModule({ diff --git a/packages/schematics/angular/interceptor/class-files/__name@dasherize@if-flat__/__name@dasherize__.interceptor.ts.template b/packages/schematics/angular/interceptor/class-files/__name@dasherize____typeSeparator__interceptor.ts.template similarity index 100% rename from packages/schematics/angular/interceptor/class-files/__name@dasherize@if-flat__/__name@dasherize__.interceptor.ts.template rename to packages/schematics/angular/interceptor/class-files/__name@dasherize____typeSeparator__interceptor.ts.template diff --git a/packages/schematics/angular/interceptor/functional-files/__name@dasherize@if-flat__/__name@dasherize__.interceptor.spec.ts.template b/packages/schematics/angular/interceptor/functional-files/__name@dasherize____typeSeparator__interceptor.spec.ts.template similarity index 92% rename from packages/schematics/angular/interceptor/functional-files/__name@dasherize@if-flat__/__name@dasherize__.interceptor.spec.ts.template rename to packages/schematics/angular/interceptor/functional-files/__name@dasherize____typeSeparator__interceptor.spec.ts.template index 58b6b7e709b8..ee1662c6530f 100755 --- a/packages/schematics/angular/interceptor/functional-files/__name@dasherize@if-flat__/__name@dasherize__.interceptor.spec.ts.template +++ b/packages/schematics/angular/interceptor/functional-files/__name@dasherize____typeSeparator__interceptor.spec.ts.template @@ -1,7 +1,7 @@ import { TestBed } from '@angular/core/testing'; import { HttpInterceptorFn } from '@angular/common/http'; -import { <%= camelize(name) %>Interceptor } from './<%= dasherize(name) %>.interceptor'; +import { <%= camelize(name) %>Interceptor } from './<%= dasherize(name) %><%= typeSeparator %>interceptor'; describe('<%= camelize(name) %>Interceptor', () => { const interceptor: HttpInterceptorFn = (req, next) => diff --git a/packages/schematics/angular/interceptor/functional-files/__name@dasherize@if-flat__/__name@dasherize__.interceptor.ts.template b/packages/schematics/angular/interceptor/functional-files/__name@dasherize____typeSeparator__interceptor.ts.template similarity index 100% rename from packages/schematics/angular/interceptor/functional-files/__name@dasherize@if-flat__/__name@dasherize__.interceptor.ts.template rename to packages/schematics/angular/interceptor/functional-files/__name@dasherize____typeSeparator__interceptor.ts.template diff --git a/packages/schematics/angular/interceptor/index.ts b/packages/schematics/angular/interceptor/index.ts index b590c27f9aff..a057e80c506f 100755 --- a/packages/schematics/angular/interceptor/index.ts +++ b/packages/schematics/angular/interceptor/index.ts @@ -6,25 +6,12 @@ * found in the LICENSE file at https://angular.dev/license */ -import { Rule } from '@angular-devkit/schematics'; +import type { Rule } from '@angular-devkit/schematics'; import { generateFromFiles } from '../utility/generate-from-files'; -import { Schema as InterceptorOptions } from './schema'; +import type { Schema as InterceptorOptions } from './schema'; export default function (options: InterceptorOptions): Rule { - // This schematic uses an older method to implement the flat option - const flat = options.flat; - options.flat = true; - const extraTemplateValues = { - 'if-flat': (s: string) => (flat ? '' : s), - }; + const templateFilesDirectory = options.functional ? './functional-files' : './class-files'; - return options.functional - ? generateFromFiles( - { ...options, templateFilesDirectory: './functional-files' }, - extraTemplateValues, - ) - : generateFromFiles( - { ...options, templateFilesDirectory: './class-files' }, - extraTemplateValues, - ); + return generateFromFiles({ ...options, templateFilesDirectory }); } diff --git a/packages/schematics/angular/interceptor/index_spec.ts b/packages/schematics/angular/interceptor/index_spec.ts index 8a9286f76fff..a657ee7e4225 100755 --- a/packages/schematics/angular/interceptor/index_spec.ts +++ b/packages/schematics/angular/interceptor/index_spec.ts @@ -46,9 +46,31 @@ describe('Interceptor Schematic', () => { const tree = await schematicRunner.runSchematic('interceptor', options, appTree); + const files = tree.files; + expect(files).toContain('/projects/bar/src/app/foo/foo-interceptor.spec.ts'); + expect(files).toContain('/projects/bar/src/app/foo/foo-interceptor.ts'); + }); + + it('should use a `.` type separator when specified', async () => { + const options = { ...defaultOptions, typeSeparator: '.' }; + + const tree = await schematicRunner.runSchematic('interceptor', options, appTree); const files = tree.files; expect(files).toContain('/projects/bar/src/app/foo/foo.interceptor.spec.ts'); expect(files).toContain('/projects/bar/src/app/foo/foo.interceptor.ts'); + const specContent = tree.readContent('/projects/bar/src/app/foo/foo.interceptor.spec.ts'); + expect(specContent).toContain(`'./foo.interceptor'`); + }); + + it('should use a `-` type separator when specified', async () => { + const options = { ...defaultOptions, typeSeparator: '-' }; + + const tree = await schematicRunner.runSchematic('interceptor', options, appTree); + const files = tree.files; + expect(files).toContain('/projects/bar/src/app/foo/foo-interceptor.spec.ts'); + expect(files).toContain('/projects/bar/src/app/foo/foo-interceptor.ts'); + const specContent = tree.readContent('/projects/bar/src/app/foo/foo-interceptor.spec.ts'); + expect(specContent).toContain(`'./foo-interceptor'`); }); it('should respect the skipTests flag', async () => { @@ -57,8 +79,8 @@ describe('Interceptor Schematic', () => { const tree = await schematicRunner.runSchematic('interceptor', options, appTree); const files = tree.files; - expect(files).toContain('/projects/bar/src/app/foo/foo.interceptor.ts'); - expect(files).not.toContain('/projects/bar/src/app/foo/foo.interceptor.spec.ts'); + expect(files).toContain('/projects/bar/src/app/foo/foo-interceptor.ts'); + expect(files).not.toContain('/projects/bar/src/app/foo/foo-interceptor.spec.ts'); }); it('should respect the sourceRoot value', async () => { @@ -67,7 +89,7 @@ describe('Interceptor Schematic', () => { appTree.overwrite('/angular.json', JSON.stringify(config, null, 2)); appTree = await schematicRunner.runSchematic('interceptor', defaultOptions, appTree); - expect(appTree.files).toContain('/projects/bar/custom/app/foo/foo.interceptor.ts'); + expect(appTree.files).toContain('/projects/bar/custom/app/foo/foo-interceptor.ts'); }); it('should create a functional interceptor', async () => { @@ -77,7 +99,7 @@ describe('Interceptor Schematic', () => { appTree, ); - const fileString = tree.readContent('/projects/bar/src/app/foo/foo.interceptor.ts'); + const fileString = tree.readContent('/projects/bar/src/app/foo/foo-interceptor.ts'); expect(fileString).toContain( 'export const fooInterceptor: HttpInterceptorFn = (req, next) => {', ); @@ -90,7 +112,7 @@ describe('Interceptor Schematic', () => { appTree, ); - const fileString = tree.readContent('/projects/bar/src/app/foo/foo.interceptor.spec.ts'); + const fileString = tree.readContent('/projects/bar/src/app/foo/foo-interceptor.spec.ts'); expect(fileString).toContain('const interceptor: HttpInterceptorFn = (req, next) => '); expect(fileString).toContain('TestBed.runInInjectionContext(() => fooInterceptor(req, next));'); }); diff --git a/packages/schematics/angular/interceptor/schema.json b/packages/schematics/angular/interceptor/schema.json index ff072a5557d2..e42e0c675e8e 100755 --- a/packages/schematics/angular/interceptor/schema.json +++ b/packages/schematics/angular/interceptor/schema.json @@ -45,6 +45,12 @@ "type": "boolean", "description": "Creates the interceptor as a function `HttpInterceptorFn` instead of a class. Functional interceptors can be simpler for basic scenarios.", "default": true + }, + "typeSeparator": { + "type": "string", + "default": "-", + "enum": ["-", "."], + "description": "The separator character to use before the type within the generated file's name. For example, if you set the option to `.`, the file will be named `example.interceptor.ts`." } }, "required": ["name", "project"] diff --git a/packages/schematics/angular/interface/files/__name@dasherize____type__.ts.template b/packages/schematics/angular/interface/files/__name@dasherize__.__type__.ts.template similarity index 100% rename from packages/schematics/angular/interface/files/__name@dasherize____type__.ts.template rename to packages/schematics/angular/interface/files/__name@dasherize__.__type__.ts.template diff --git a/packages/schematics/angular/interface/index.ts b/packages/schematics/angular/interface/index.ts index 775a1017eb63..b04a5343fa39 100644 --- a/packages/schematics/angular/interface/index.ts +++ b/packages/schematics/angular/interface/index.ts @@ -11,7 +11,5 @@ import { generateFromFiles } from '../utility/generate-from-files'; import { Schema as InterfaceOptions } from './schema'; export default function (options: InterfaceOptions): Rule { - options.type = options.type ? `.${options.type}` : ''; - return generateFromFiles(options); } diff --git a/packages/schematics/angular/library/files/src/__entryFile__.ts.template b/packages/schematics/angular/library/files/src/__entryFile__.ts.template index d88dc4f34551..2d13ba01016f 100644 --- a/packages/schematics/angular/library/files/src/__entryFile__.ts.template +++ b/packages/schematics/angular/library/files/src/__entryFile__.ts.template @@ -2,6 +2,5 @@ * Public API Surface of <%= dasherize(name) %> */ -export * from './lib/<%= dasherize(name) %>.service'; -export * from './lib/<%= dasherize(name) %>.component';<% if (!standalone) { %> -export * from './lib/<%= dasherize(name) %>.module';<% } %> +export * from './lib/<%= dasherize(name) %>';<% if (!standalone) { %> +export * from './lib/<%= dasherize(name) %>-module';<% } %> diff --git a/packages/schematics/angular/library/index.ts b/packages/schematics/angular/library/index.ts index 6bee27bc9ec1..52ca74bc65ce 100644 --- a/packages/schematics/angular/library/index.ts +++ b/packages/schematics/angular/library/index.ts @@ -93,9 +93,6 @@ function addLibToWorkspaceFile( build: { builder: Builders.BuildNgPackagr, defaultConfiguration: 'production', - options: { - project: `${projectRoot}/ng-package.json`, - }, configurations: { production: { tsConfig: `${projectRoot}/tsconfig.lib.prod.json`, @@ -184,12 +181,10 @@ export default function (options: LibraryOptions): Rule { export: true, standalone: options.standalone, project: packageName, - }), - schematic('service', { - name: options.name, - flat: true, - path: sourceDir, - project: packageName, + // Explicitly set an empty `type` since it doesn't necessarily make sense in a library. + // This also ensures that the generated files are valid even if the `component` schematic + // inherits its `type` from the workspace. + type: '', }), (_tree: Tree, context: SchematicContext) => { if (!options.skipPackageJson && !options.skipInstall) { diff --git a/packages/schematics/angular/library/index_spec.ts b/packages/schematics/angular/library/index_spec.ts index 49fd7a12e4ac..caedfb2b1739 100644 --- a/packages/schematics/angular/library/index_spec.ts +++ b/packages/schematics/angular/library/index_spec.ts @@ -55,22 +55,20 @@ describe('Library Schematic', () => { '/projects/foo/tsconfig.lib.json', '/projects/foo/tsconfig.lib.prod.json', '/projects/foo/src/my-index.ts', - '/projects/foo/src/lib/foo.component.spec.ts', - '/projects/foo/src/lib/foo.component.ts', - '/projects/foo/src/lib/foo.service.spec.ts', - '/projects/foo/src/lib/foo.service.ts', + '/projects/foo/src/lib/foo.spec.ts', + '/projects/foo/src/lib/foo.ts', ]), ); }); it('should not add reference to module file in entry-file', async () => { const tree = await schematicRunner.runSchematic('library', defaultOptions, workspaceTree); - expect(tree.readContent('/projects/foo/src/my-index.ts')).not.toContain('foo.module'); + expect(tree.readContent('/projects/foo/src/my-index.ts')).not.toContain('foo-module'); }); it('should create a standalone component', async () => { const tree = await schematicRunner.runSchematic('library', defaultOptions, workspaceTree); - const componentContent = tree.readContent('/projects/foo/src/lib/foo.component.ts'); + const componentContent = tree.readContent('/projects/foo/src/lib/foo.ts'); expect(componentContent).not.toContain('standalone'); }); @@ -100,10 +98,8 @@ describe('Library Schematic', () => { '/some/other/directory/bar/tsconfig.lib.json', '/some/other/directory/bar/tsconfig.lib.prod.json', '/some/other/directory/bar/src/my-index.ts', - '/some/other/directory/bar/src/lib/foo.component.spec.ts', - '/some/other/directory/bar/src/lib/foo.component.ts', - '/some/other/directory/bar/src/lib/foo.service.spec.ts', - '/some/other/directory/bar/src/lib/foo.service.ts', + '/some/other/directory/bar/src/lib/foo.spec.ts', + '/some/other/directory/bar/src/lib/foo.ts', ]), ); }); @@ -207,10 +203,8 @@ describe('Library Schematic', () => { const project = config.projects.pascalCasedName; expect(project).toBeDefined(); expect(project.root).toEqual('projects/pascal-cased-name'); - const svcContent = tree.readContent( - '/projects/pascal-cased-name/src/lib/pascal-cased-name.service.ts', - ); - expect(svcContent).toMatch(/providedIn: 'root'/); + const svcContent = tree.readContent('/projects/pascal-cased-name/src/lib/pascal-cased-name.ts'); + expect(svcContent).toContain('@Component'); }); describe(`update package.json`, () => { @@ -310,7 +304,7 @@ describe('Library Schematic', () => { project: 'foo', }; tree = await schematicRunner.runSchematic('component', componentOptions, tree); - expect(tree.exists('/projects/foo/src/lib/comp/comp.component.ts')).toBe(true); + expect(tree.exists('/projects/foo/src/lib/comp/comp.ts')).toBe(true); }); it(`should support creating scoped libraries`, async () => { @@ -320,8 +314,7 @@ describe('Library Schematic', () => { const pkgJsonPath = '/projects/myscope/mylib/package.json'; expect(tree.files).toContain(pkgJsonPath); - expect(tree.files).toContain('/projects/myscope/mylib/src/lib/mylib.service.ts'); - expect(tree.files).toContain('/projects/myscope/mylib/src/lib/mylib.component.ts'); + expect(tree.files).toContain('/projects/myscope/mylib/src/lib/mylib.ts'); const pkgJson = JSON.parse(tree.readContent(pkgJsonPath)); expect(pkgJson.name).toEqual(scopedName); @@ -368,7 +361,6 @@ describe('Library Schematic', () => { const project = config.projects.foo; expect(project.root).toEqual('foo'); const { options, configurations } = project.architect.build; - expect(options.project).toEqual('foo/ng-package.json'); expect(configurations.production.tsConfig).toEqual('foo/tsconfig.lib.prod.json'); const libTsConfig = getJsonFileContent(tree, '/foo/tsconfig.lib.json'); @@ -408,8 +400,8 @@ describe('Library Schematic', () => { workspaceTree, ); - const fileContent = getFileContent(tree, '/projects/foo/src/lib/foo.module.ts'); - expect(fileContent).toMatch(/exports: \[\n(\s*) {2}FooComponent\n\1\]/); + const fileContent = getFileContent(tree, '/projects/foo/src/lib/foo-module.ts'); + expect(fileContent).toMatch(/exports: \[\n(\s*) {2}Foo\n\1\]/); }); it('should create files', async () => { @@ -428,11 +420,9 @@ describe('Library Schematic', () => { '/projects/foo/tsconfig.lib.json', '/projects/foo/tsconfig.lib.prod.json', '/projects/foo/src/my-index.ts', - '/projects/foo/src/lib/foo.module.ts', - '/projects/foo/src/lib/foo.component.spec.ts', - '/projects/foo/src/lib/foo.component.ts', - '/projects/foo/src/lib/foo.service.spec.ts', - '/projects/foo/src/lib/foo.service.ts', + '/projects/foo/src/lib/foo-module.ts', + '/projects/foo/src/lib/foo.spec.ts', + '/projects/foo/src/lib/foo.ts', ]), ); }); diff --git a/packages/schematics/angular/migrations/migration-collection.json b/packages/schematics/angular/migrations/migration-collection.json index 14815a63d5a6..659dd48728cd 100644 --- a/packages/schematics/angular/migrations/migration-collection.json +++ b/packages/schematics/angular/migrations/migration-collection.json @@ -1,5 +1,25 @@ { "schematics": { + "replace-provide-server-rendering-import": { + "version": "20.0.0", + "factory": "./replace-provide-server-rendering-import/migration", + "description": "Migrate imports of 'provideServerRendering' from '@angular/platform-server' to '@angular/ssr'." + }, + "replace-provide-server-routing": { + "version": "20.0.0", + "factory": "./replace-provide-server-routing/migration", + "description": "Migrate 'provideServerRendering' to use 'withRoutes' and remove 'provideServerRouting' from '@angular/ssr'." + }, + "update-module-resolution": { + "version": "20.0.0", + "factory": "./update-module-resolution/migration", + "description": "Update 'moduleResolution' to 'bundler' in TypeScript configurations. You can read more about this, here: https://www.typescriptlang.org/tsconfig/#moduleResolution" + }, + "previous-style-guide": { + "version": "20.0.0", + "factory": "./previous-style-guide/migration", + "description": "Update workspace generation defaults to maintain previous style guide behavior." + }, "use-application-builder": { "version": "20.0.0", "factory": "./use-application-builder/migration", diff --git a/packages/schematics/angular/migrations/previous-style-guide/migration.ts b/packages/schematics/angular/migrations/previous-style-guide/migration.ts new file mode 100644 index 000000000000..1590948b243d --- /dev/null +++ b/packages/schematics/angular/migrations/previous-style-guide/migration.ts @@ -0,0 +1,51 @@ +/** + * @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 { Rule } from '@angular-devkit/schematics'; +import { updateWorkspace } from '../../utility/workspace'; + +const TYPE_SCHEMATICS = ['component', 'directive', 'service'] as const; + +const SEPARATOR_SCHEMATICS = ['guard', 'interceptor', 'module', 'pipe', 'resolver'] as const; + +export default function (): Rule { + return updateWorkspace((workspace) => { + let schematicsDefaults = workspace.extensions['schematics']; + + // Ensure "schematics" field is an object + if ( + !schematicsDefaults || + typeof schematicsDefaults !== 'object' || + Array.isArray(schematicsDefaults) + ) { + schematicsDefaults = workspace.extensions['schematics'] = {}; + } + + // Add "type" value for each schematic to continue generating a type suffix. + // New default is an empty type value. + for (const schematicName of TYPE_SCHEMATICS) { + const schematic = (schematicsDefaults[`@schematics/angular:${schematicName}`] ??= {}); + if (typeof schematic === 'object' && !Array.isArray(schematic) && !('type' in schematic)) { + schematic['type'] = schematicName; + } + } + + // Add "typeSeparator" value for each schematic to continue generating "." before type. + // New default is an "-" type value. + for (const schematicName of SEPARATOR_SCHEMATICS) { + const schematic = (schematicsDefaults[`@schematics/angular:${schematicName}`] ??= {}); + if ( + typeof schematic === 'object' && + !Array.isArray(schematic) && + !('typeSeparator' in schematic) + ) { + schematic['typeSeparator'] = '.'; + } + } + }); +} diff --git a/packages/schematics/angular/migrations/previous-style-guide/migration_spec.ts b/packages/schematics/angular/migrations/previous-style-guide/migration_spec.ts new file mode 100644 index 000000000000..342da3910e74 --- /dev/null +++ b/packages/schematics/angular/migrations/previous-style-guide/migration_spec.ts @@ -0,0 +1,141 @@ +/** + * @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 { ProjectType, WorkspaceSchema } from '../../utility/workspace-models'; + +function createWorkSpaceConfig(tree: UnitTestTree, initialSchematicsValue?: unknown) { + const angularConfig: WorkspaceSchema = { + version: 1, + projects: { + app: { + root: '/project/lib', + sourceRoot: '/project/app/src', + projectType: ProjectType.Application, + prefix: 'app', + architect: {}, + }, + }, + }; + + if (initialSchematicsValue !== undefined) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (angularConfig as any).schematics = initialSchematicsValue; + } + + tree.create('/angular.json', JSON.stringify(angularConfig, undefined, 2)); +} + +describe(`Migration to update 'angular.json'.`, () => { + const schematicName = 'previous-style-guide'; + const schematicRunner = new SchematicTestRunner( + 'migrations', + require.resolve('../migration-collection.json'), + ); + + let tree: UnitTestTree; + beforeEach(() => { + tree = new UnitTestTree(new EmptyTree()); + }); + + it(`should add defaults if no "schematics" workspace field is present`, async () => { + createWorkSpaceConfig(tree); + + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + const { schematics } = JSON.parse(newTree.readContent('/angular.json')); + + expect(schematics).toEqual({ + '@schematics/angular:component': { type: 'component' }, + '@schematics/angular:directive': { type: 'directive' }, + '@schematics/angular:service': { type: 'service' }, + '@schematics/angular:guard': { typeSeparator: '.' }, + '@schematics/angular:interceptor': { typeSeparator: '.' }, + '@schematics/angular:module': { typeSeparator: '.' }, + '@schematics/angular:pipe': { typeSeparator: '.' }, + '@schematics/angular:resolver': { typeSeparator: '.' }, + }); + }); + + it(`should add defaults if empty "schematics" workspace field is present`, async () => { + createWorkSpaceConfig(tree, {}); + + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + const { schematics } = JSON.parse(newTree.readContent('/angular.json')); + + expect(schematics).toEqual({ + '@schematics/angular:component': { type: 'component' }, + '@schematics/angular:directive': { type: 'directive' }, + '@schematics/angular:service': { type: 'service' }, + '@schematics/angular:guard': { typeSeparator: '.' }, + '@schematics/angular:interceptor': { typeSeparator: '.' }, + '@schematics/angular:module': { typeSeparator: '.' }, + '@schematics/angular:pipe': { typeSeparator: '.' }, + '@schematics/angular:resolver': { typeSeparator: '.' }, + }); + }); + + it(`should add defaults if invalid "schematics" workspace field is present`, async () => { + createWorkSpaceConfig(tree, 10); + + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + const { schematics } = JSON.parse(newTree.readContent('/angular.json')); + + expect(schematics).toEqual({ + '@schematics/angular:component': { type: 'component' }, + '@schematics/angular:directive': { type: 'directive' }, + '@schematics/angular:service': { type: 'service' }, + '@schematics/angular:guard': { typeSeparator: '.' }, + '@schematics/angular:interceptor': { typeSeparator: '.' }, + '@schematics/angular:module': { typeSeparator: '.' }, + '@schematics/angular:pipe': { typeSeparator: '.' }, + '@schematics/angular:resolver': { typeSeparator: '.' }, + }); + }); + + it(`should add defaults if existing unrelated "schematics" workspace defaults are present`, async () => { + createWorkSpaceConfig(tree, { + '@schematics/angular:component': { style: 'scss' }, + }); + + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + const { schematics } = JSON.parse(newTree.readContent('/angular.json')); + + expect(schematics).toEqual({ + '@schematics/angular:component': { style: 'scss', type: 'component' }, + '@schematics/angular:directive': { type: 'directive' }, + '@schematics/angular:service': { type: 'service' }, + '@schematics/angular:guard': { typeSeparator: '.' }, + '@schematics/angular:interceptor': { typeSeparator: '.' }, + '@schematics/angular:module': { typeSeparator: '.' }, + '@schematics/angular:pipe': { typeSeparator: '.' }, + '@schematics/angular:resolver': { typeSeparator: '.' }, + }); + }); + + it(`should not overwrite defaults if existing "schematics" workspace defaults are present`, async () => { + createWorkSpaceConfig(tree, { + '@schematics/angular:component': { type: 'example' }, + '@schematics/angular:guard': { typeSeparator: '-' }, + }); + + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + const { schematics } = JSON.parse(newTree.readContent('/angular.json')); + + expect(schematics).toEqual({ + '@schematics/angular:component': { type: 'example' }, + '@schematics/angular:directive': { type: 'directive' }, + '@schematics/angular:service': { type: 'service' }, + '@schematics/angular:guard': { typeSeparator: '-' }, + '@schematics/angular:interceptor': { typeSeparator: '.' }, + '@schematics/angular:module': { typeSeparator: '.' }, + '@schematics/angular:pipe': { typeSeparator: '.' }, + '@schematics/angular:resolver': { typeSeparator: '.' }, + }); + }); +}); diff --git a/packages/schematics/angular/migrations/replace-provide-server-rendering-import/migration.ts b/packages/schematics/angular/migrations/replace-provide-server-rendering-import/migration.ts new file mode 100644 index 000000000000..ed8e0d7598f3 --- /dev/null +++ b/packages/schematics/angular/migrations/replace-provide-server-rendering-import/migration.ts @@ -0,0 +1,116 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import { DirEntry, Rule } from '@angular-devkit/schematics'; +import * as ts from '../../third_party/github.com/Microsoft/TypeScript/lib/typescript'; +import { NodeDependencyType, addPackageJsonDependency } from '../../utility/dependencies'; +import { latestVersions } from '../../utility/latest-versions'; + +function* visit(directory: DirEntry): IterableIterator<[fileName: string, contents: string]> { + for (const path of directory.subfiles) { + if (path.endsWith('.ts') && !path.endsWith('.d.ts')) { + const entry = directory.file(path); + if (entry) { + const content = entry.content; + if ( + content.includes('provideServerRendering') && + content.includes('@angular/platform-server') + ) { + // Only need to rename the import so we can just string replacements. + yield [entry.path, content.toString()]; + } + } + } + } + + for (const path of directory.subdirs) { + if (path === 'node_modules' || path.startsWith('.')) { + continue; + } + + yield* visit(directory.dir(path)); + } +} + +export default function (): Rule { + return async (tree) => { + let angularSSRAdded = false; + + for (const [filePath, content] of visit(tree.root)) { + let updatedContent = content; + const ssrImports = new Set(); + const platformServerImports = new Set(); + const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true); + + sourceFile.forEachChild((node) => { + if (ts.isImportDeclaration(node)) { + const moduleSpecifier = node.moduleSpecifier.getText(sourceFile); + if (moduleSpecifier.includes('@angular/platform-server')) { + const importClause = node.importClause; + if ( + importClause && + importClause.namedBindings && + ts.isNamedImports(importClause.namedBindings) + ) { + const namedImports = importClause.namedBindings.elements.map((e) => + e.getText(sourceFile), + ); + namedImports.forEach((importName) => { + if (importName === 'provideServerRendering') { + ssrImports.add(importName); + } else { + platformServerImports.add(importName); + } + }); + } + updatedContent = updatedContent.replace(node.getFullText(sourceFile), ''); + } else if (moduleSpecifier.includes('@angular/ssr')) { + const importClause = node.importClause; + if ( + importClause && + importClause.namedBindings && + ts.isNamedImports(importClause.namedBindings) + ) { + importClause.namedBindings.elements.forEach((e) => { + ssrImports.add(e.getText(sourceFile)); + }); + } + updatedContent = updatedContent.replace(node.getFullText(sourceFile), ''); + } + } + }); + + if (platformServerImports.size > 0) { + updatedContent = + `import { ${Array.from(platformServerImports).sort().join(', ')} } from '@angular/platform-server';\n` + + updatedContent; + } + + if (ssrImports.size > 0) { + updatedContent = + `import { ${Array.from(ssrImports).sort().join(', ')} } from '@angular/ssr';\n` + + updatedContent; + } + + if (content !== updatedContent) { + tree.overwrite(filePath, updatedContent); + + if (!angularSSRAdded) { + addPackageJsonDependency(tree, { + name: '@angular/ssr', + version: latestVersions.AngularSSR, + type: NodeDependencyType.Default, + overwrite: false, + }); + + angularSSRAdded = true; + } + } + } + }; +} diff --git a/packages/schematics/angular/migrations/replace-provide-server-rendering-import/migration_spec.ts b/packages/schematics/angular/migrations/replace-provide-server-rendering-import/migration_spec.ts new file mode 100644 index 000000000000..6746172882fb --- /dev/null +++ b/packages/schematics/angular/migrations/replace-provide-server-rendering-import/migration_spec.ts @@ -0,0 +1,91 @@ +/** + * @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'; + +describe(`Migration to use the 'provideServerRendering' from '@angular/ssr'`, () => { + const schematicRunner = new SchematicTestRunner( + 'migrations', + require.resolve('../migration-collection.json'), + ); + + let tree: UnitTestTree; + const schematicName = 'replace-provide-server-rendering-import'; + + beforeEach(() => { + tree = new UnitTestTree(new EmptyTree()); + tree.create( + '/package.json', + JSON.stringify({ + dependencies: {}, + }), + ); + }); + + it('should replace provideServerRendering with @angular/ssr and keep other imports', async () => { + tree.create( + 'test.ts', + `import { provideServerRendering, otherFunction } from '@angular/platform-server';`, + ); + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + const content = newTree.readContent('test.ts'); + expect(content).toContain("import { provideServerRendering } from '@angular/ssr';"); + expect(content).toContain("import { otherFunction } from '@angular/platform-server';"); + }); + + it('should not replace provideServerRendering that is imported from @angular/ssr', async () => { + tree.create( + 'test.ts', + ` + import { otherFunction } from '@angular/platform-server'; + import { provideServerRendering, provideServerRouting } from '@angular/ssr'; + `, + ); + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + const content = newTree.readContent('test.ts'); + expect(content).toContain( + "import { provideServerRendering, provideServerRouting } from '@angular/ssr';", + ); + expect(content).toContain("import { otherFunction } from '@angular/platform-server';"); + }); + + it('should merge with existing @angular/ssr imports', async () => { + tree.create( + 'test.ts', + ` + import { provideServerRouting } from '@angular/ssr'; + import { provideServerRendering } from '@angular/platform-server'; + `, + ); + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + const content = newTree.readContent('test.ts'); + expect(content).toContain( + "import { provideServerRendering, provideServerRouting } from '@angular/ssr';", + ); + expect(content.match(/@angular\/ssr/g) || []).toHaveSize(1); + }); + + it(`should add '@angular/ssr' when import has been changed`, async () => { + tree.create('test.ts', `import { provideServerRendering } from '@angular/platform-server';`); + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + const { dependencies } = newTree.readJson('package.json') as { + dependencies: Record; + }; + expect(dependencies['@angular/ssr']).toBeDefined(); + }); + + it(`should not add '@angular/ssr' dependency if no imports have been updated`, async () => { + tree.create('test.ts', `import { provideClientHydration } from '@angular/platform-browser';`); + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + const { dependencies } = newTree.readJson('package.json') as { + dependencies: Record; + }; + expect(dependencies['@angular/ssr']).toBeUndefined(); + }); +}); diff --git a/packages/schematics/angular/migrations/replace-provide-server-routing/migration.ts b/packages/schematics/angular/migrations/replace-provide-server-routing/migration.ts new file mode 100644 index 000000000000..8fc662b6b69a --- /dev/null +++ b/packages/schematics/angular/migrations/replace-provide-server-routing/migration.ts @@ -0,0 +1,114 @@ +/** + * @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 { DirEntry, Rule } from '@angular-devkit/schematics'; +import * as ts from '../../third_party/github.com/Microsoft/TypeScript/lib/typescript'; +import { getPackageJsonDependency } from '../../utility/dependencies'; + +function* visit(directory: DirEntry): IterableIterator<[fileName: string, contents: string]> { + for (const path of directory.subfiles) { + if (path.endsWith('.ts') && !path.endsWith('.d.ts')) { + const entry = directory.file(path); + if (entry) { + const content = entry.content; + if (content.includes('provideServerRouting') && content.includes('@angular/ssr')) { + // Only need to rename the import so we can just string replacements. + yield [entry.path, content.toString()]; + } + } + } + } + + for (const path of directory.subdirs) { + if (path === 'node_modules' || path.startsWith('.')) { + continue; + } + + yield* visit(directory.dir(path)); + } +} + +export default function (): Rule { + return async (tree) => { + if (!getPackageJsonDependency(tree, '@angular/ssr')) { + return; + } + + for (const [filePath, content] of visit(tree.root)) { + const recorder = tree.beginUpdate(filePath); + const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true); + + function visit(node: ts.Node) { + if ( + ts.isPropertyAssignment(node) && + ts.isIdentifier(node.name) && + node.name.text === 'providers' && + ts.isArrayLiteralExpression(node.initializer) + ) { + const providersArray = node.initializer; + const newProviders = providersArray.elements + .filter((el) => { + return !( + ts.isCallExpression(el) && + ts.isIdentifier(el.expression) && + el.expression.text === 'provideServerRendering' + ); + }) + .map((el) => { + if ( + ts.isCallExpression(el) && + ts.isIdentifier(el.expression) && + el.expression.text === 'provideServerRouting' + ) { + const [withRouteVal, ...others] = el.arguments.map((arg) => arg.getText()); + + return `provideServerRendering(withRoutes(${withRouteVal})${others.length ? ', ' + others.join(', ') : ''})`; + } + + return el.getText(); + }); + + // Update the 'providers' array in the source file + recorder.remove(providersArray.getStart(), providersArray.getWidth()); + recorder.insertRight(providersArray.getStart(), `[${newProviders.join(', ')}]`); + } + + ts.forEachChild(node, visit); + } + + // Visit all nodes to update 'providers' + visit(sourceFile); + + // Update imports by removing 'provideServerRouting' + const importDecl = sourceFile.statements.find( + (stmt) => + ts.isImportDeclaration(stmt) && + ts.isStringLiteral(stmt.moduleSpecifier) && + stmt.moduleSpecifier.text === '@angular/ssr', + ) as ts.ImportDeclaration | undefined; + + if (importDecl?.importClause?.namedBindings) { + const namedBindings = importDecl?.importClause.namedBindings; + + if (ts.isNamedImports(namedBindings)) { + const elements = namedBindings.elements; + const updatedElements = elements + .map((el) => el.getText()) + .filter((x) => x !== 'provideServerRouting'); + + updatedElements.push('withRoutes'); + + recorder.remove(namedBindings.getStart(), namedBindings.getWidth()); + recorder.insertLeft(namedBindings.getStart(), `{ ${updatedElements.sort().join(', ')} }`); + } + } + + tree.commitUpdate(recorder); + } + }; +} diff --git a/packages/schematics/angular/migrations/replace-provide-server-routing/migration_spec.ts b/packages/schematics/angular/migrations/replace-provide-server-routing/migration_spec.ts new file mode 100644 index 000000000000..a0ab33aa15f1 --- /dev/null +++ b/packages/schematics/angular/migrations/replace-provide-server-routing/migration_spec.ts @@ -0,0 +1,89 @@ +/** + * @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'; + +describe(`Migration to replace 'provideServerRouting' with 'provideServerRendering' from '@angular/ssr'`, () => { + const schematicRunner = new SchematicTestRunner( + 'migrations', + require.resolve('../migration-collection.json'), + ); + + const schematicName = 'replace-provide-server-routing'; + let tree: UnitTestTree; + + beforeEach(async () => { + tree = new UnitTestTree(new EmptyTree()); + tree.create( + '/package.json', + JSON.stringify({ + dependencies: { + '@angular/ssr': '0.0.0', + }, + }), + ); + + tree.create( + 'src/app/app.config.ts', + ` + import { ApplicationConfig } from '@angular/core'; + import { provideServerRendering, provideServerRouting } from '@angular/ssr'; + import { serverRoutes } from './app.routes'; + + const serverConfig: ApplicationConfig = { + providers: [ + provideServerRendering(), + provideServerRouting(serverRoutes) + ] + }; + `, + ); + }); + + it('should add "withRoutes" to the import statement', async () => { + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + const content = newTree.readContent('src/app/app.config.ts'); + + expect(content).toContain(`import { provideServerRendering, withRoutes } from '@angular/ssr';`); + }); + + it('should remove "provideServerRouting" and update "provideServerRendering"', async () => { + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + const content = newTree.readContent('src/app/app.config.ts'); + + expect(content).toContain(`providers: [provideServerRendering(withRoutes(serverRoutes))]`); + expect(content).not.toContain(`provideServerRouting(serverRoutes)`); + }); + + it('should correctly handle provideServerRouting with extra arguments', async () => { + tree.overwrite( + 'src/app/app.config.ts', + ` + import { ApplicationConfig } from '@angular/core'; + import { provideServerRendering, provideServerRouting } from '@angular/ssr'; + import { serverRoutes } from './app.routes'; + + const serverConfig: ApplicationConfig = { + providers: [ + provideServerRendering(), + provideServerRouting(serverRoutes, withAppShell(AppShellComponent)) + ] + }; + `, + ); + + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + const content = newTree.readContent('src/app/app.config.ts'); + + expect(content).toContain( + `providers: [provideServerRendering(withRoutes(serverRoutes), withAppShell(AppShellComponent))]`, + ); + expect(content).not.toContain(`provideServerRouting(serverRoutes)`); + }); +}); diff --git a/packages/schematics/angular/migrations/update-module-resolution/migration.ts b/packages/schematics/angular/migrations/update-module-resolution/migration.ts new file mode 100644 index 000000000000..ca0419a4eeab --- /dev/null +++ b/packages/schematics/angular/migrations/update-module-resolution/migration.ts @@ -0,0 +1,60 @@ +/** + * @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 { JsonObject } from '@angular-devkit/core'; +import { Rule, Tree } from '@angular-devkit/schematics'; +import { JSONFile } from '../../utility/json-file'; +import { allTargetOptions, allWorkspaceTargets, getWorkspace } from '../../utility/workspace'; + +export default function (): Rule { + return async (host) => { + const uniqueTsConfigs = new Set(); + + if (host.exists('tsconfig.json')) { + // Workspace level tsconfig + uniqueTsConfigs.add('tsconfig.json'); + } + + const workspace = await getWorkspace(host); + for (const [, target] of allWorkspaceTargets(workspace)) { + for (const [, opt] of allTargetOptions(target)) { + if (typeof opt?.tsConfig === 'string') { + uniqueTsConfigs.add(opt.tsConfig); + } + } + } + + for (const tsConfig of uniqueTsConfigs) { + if (host.exists(tsConfig)) { + updateModuleResolution(host, tsConfig); + } + } + }; +} + +function updateModuleResolution(host: Tree, tsConfigPath: string): void { + const json = new JSONFile(host, tsConfigPath); + const jsonPath = ['compilerOptions']; + const compilerOptions = json.get(jsonPath); + + if (compilerOptions && typeof compilerOptions === 'object') { + const { moduleResolution, module } = compilerOptions as JsonObject; + if (typeof moduleResolution !== 'string' || moduleResolution.toLowerCase() === 'bundler') { + return; + } + + if (typeof module === 'string' && module.toLowerCase() === 'preserve') { + return; + } + + json.modify(jsonPath, { + ...compilerOptions, + 'moduleResolution': 'bundler', + }); + } +} diff --git a/packages/schematics/angular/migrations/update-module-resolution/migration_spec.ts b/packages/schematics/angular/migrations/update-module-resolution/migration_spec.ts new file mode 100644 index 000000000000..53448e80b66a --- /dev/null +++ b/packages/schematics/angular/migrations/update-module-resolution/migration_spec.ts @@ -0,0 +1,118 @@ +/** + * @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 { isJsonObject } from '@angular-devkit/core'; +import { EmptyTree } from '@angular-devkit/schematics'; +import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; +import { Builders, ProjectType, WorkspaceSchema } from '../../utility/workspace-models'; + +describe('Migration to update moduleResolution', () => { + const schematicName = 'update-module-resolution'; + const schematicRunner = new SchematicTestRunner( + 'migrations', + require.resolve('../migration-collection.json'), + ); + + function createJsonFile(tree: UnitTestTree, filePath: string, content: {}): void { + const stringifiedContent = JSON.stringify(content, undefined, 2); + if (tree.exists(filePath)) { + tree.overwrite(filePath, stringifiedContent); + } else { + tree.create(filePath, stringifiedContent); + } + } + + function getCompilerOptionsValue(tree: UnitTestTree, filePath: string): Record { + const json = tree.readJson(filePath); + if (isJsonObject(json) && isJsonObject(json.compilerOptions)) { + return json.compilerOptions; + } + + throw new Error(`Cannot retrieve 'compilerOptions'.`); + } + + const angularConfig: WorkspaceSchema = { + version: 1, + projects: { + app: { + root: '', + sourceRoot: 'src', + projectType: ProjectType.Application, + prefix: 'app', + architect: { + build: { + builder: Builders.Browser, + options: { + tsConfig: 'src/tsconfig.app.json', + main: '', + polyfills: '', + }, + configurations: { + production: { + tsConfig: 'src/tsconfig.app.prod.json', + }, + }, + }, + test: { + builder: Builders.Karma, + options: { + karmaConfig: '', + tsConfig: 'src/tsconfig.spec.json', + }, + }, + }, + }, + }, + }; + + let tree: UnitTestTree; + beforeEach(() => { + tree = new UnitTestTree(new EmptyTree()); + const compilerOptions = { module: 'es2020', moduleResolution: 'node' }; + const configWithExtends = { extends: './tsconfig.json', compilerOptions }; + + // Workspace + createJsonFile(tree, 'angular.json', angularConfig); + createJsonFile(tree, 'tsconfig.json', { compilerOptions }); + + // Application + createJsonFile(tree, 'src/tsconfig.app.json', configWithExtends); + createJsonFile(tree, 'src/tsconfig.app.prod.json', configWithExtends); + createJsonFile(tree, 'src/tsconfig.spec.json', { compilerOptions }); + }); + + it(`should update moduleResolution to 'bundler' in workspace 'tsconfig.json'`, async () => { + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + const compilerOptions = getCompilerOptionsValue(newTree, 'tsconfig.json'); + expect(compilerOptions).toEqual( + jasmine.objectContaining({ + moduleResolution: 'bundler', + }), + ); + }); + + it(`should update moduleResolution to 'bundler' in builder tsconfig`, async () => { + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + const compilerOptions = getCompilerOptionsValue(newTree, 'src/tsconfig.spec.json'); + expect(compilerOptions).toEqual( + jasmine.objectContaining({ + moduleResolution: 'bundler', + }), + ); + }); + + it('should not update moduleResolution when module is preserve', async () => { + createJsonFile(tree, 'tsconfig.json', { + compilerOptions: { module: 'preserve', moduleResolution: 'node' }, + }); + + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + const compilerOptions = getCompilerOptionsValue(newTree, 'tsconfig.json'); + expect(compilerOptions).toEqual({ module: 'preserve', moduleResolution: 'node' }); + }); +}); diff --git a/packages/schematics/angular/migrations/use-application-builder/migration.ts b/packages/schematics/angular/migrations/use-application-builder/migration.ts index 464f6b4bf560..396ba48430d2 100644 --- a/packages/schematics/angular/migrations/use-application-builder/migration.ts +++ b/packages/schematics/angular/migrations/use-application-builder/migration.ts @@ -158,7 +158,6 @@ function* updateBuildTarget( yield externalSchematic('@schematics/angular', 'ssr', { project: projectName, - skipInstall: true, }); } } @@ -218,6 +217,7 @@ function updateProjects(tree: Tree, context: SchematicContext) { case Builders.Application: case Builders.DevServer: case Builders.ExtractI18n: + case Builders.Karma: case Builders.NgPackagr: // Ignore application, dev server, and i18n extraction for devkit usage check. // Both will be replaced if no other usage is found. @@ -243,6 +243,13 @@ function updateProjects(tree: Tree, context: SchematicContext) { case Builders.ExtractI18n: target.builder = '@angular/build:extract-i18n'; break; + case Builders.Karma: + target.builder = '@angular/build:karma'; + // Remove "builderMode" option since the builder will always use "application" + for (const [, karmaOptions] of allTargetOptions(target)) { + delete karmaOptions['builderMode']; + } + break; case Builders.NgPackagr: target.builder = '@angular/build:ng-packagr'; break; 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 587c60016ceb..3adef7d419eb 100644 --- a/packages/schematics/angular/migrations/use-application-builder/migration_spec.ts +++ b/packages/schematics/angular/migrations/use-application-builder/migration_spec.ts @@ -40,6 +40,15 @@ function createWorkSpaceConfig(tree: UnitTestTree) { tree.create('/package.json', JSON.stringify({}, undefined, 2)); } +function addWorkspaceTarget(tree: UnitTestTree, targetName: string, targetEntry: unknown): void { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const workspaceContent = tree.readJson('/angular.json') as Record; + + workspaceContent['projects']['app']['architect'][targetName] = targetEntry; + + tree.overwrite('/angular.json', JSON.stringify(workspaceContent)); +} + describe(`Migration to use the application builder`, () => { const schematicName = 'use-application-builder'; const schematicRunner = new SchematicTestRunner( @@ -102,6 +111,25 @@ describe(`Migration to use the application builder`, () => { }); }); + it(`should remove 'builderMode' from karma options`, async () => { + addWorkspaceTarget(tree, 'test', { + 'builder': Builders.Karma, + 'options': { + 'builderMode': 'detect', + 'polyfills': ['zone.js', 'zone.js/testing'], + 'tsConfig': 'projects/app-a/tsconfig.spec.json', + }, + }); + + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + const { + projects: { app }, + } = JSON.parse(newTree.readContent('/angular.json')); + + const { builderMode } = app.architect['test'].options; + expect(builderMode).toBeUndefined(); + }); + it('should remove tilde prefix from CSS @import specifiers', async () => { // Replace outputPath tree.create( diff --git a/packages/schematics/angular/module/files/__name@dasherize@if-flat__/__name@dasherize__-routing.module.ts.template b/packages/schematics/angular/module/files/__name@dasherize@if-flat__/__name@dasherize__-routing__typeSeparator__module.ts.template similarity index 70% rename from packages/schematics/angular/module/files/__name@dasherize@if-flat__/__name@dasherize__-routing.module.ts.template rename to packages/schematics/angular/module/files/__name@dasherize@if-flat__/__name@dasherize__-routing__typeSeparator__module.ts.template index 63c372de607c..5d7368582ad2 100644 --- a/packages/schematics/angular/module/files/__name@dasherize@if-flat__/__name@dasherize__-routing.module.ts.template +++ b/packages/schematics/angular/module/files/__name@dasherize@if-flat__/__name@dasherize__-routing__typeSeparator__module.ts.template @@ -1,8 +1,8 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router';<% if (lazyRoute) { %> -import { <%= classify(name) %>Component } from './<%= dasherize(name) %>.component';<% } %> +import { <%= classify(name) %> } from './<%= dasherize(name) %>';<% } %> -const routes: Routes = [<% if (lazyRoute) { %>{ path: '', component: <%= classify(name) %>Component }<% } %>]; +const routes: Routes = [<% if (lazyRoute) { %>{ path: '', component: <%= classify(name) %> }<% } %>]; @NgModule({ imports: [RouterModule.for<%= routingScope %>(routes)], diff --git a/packages/schematics/angular/module/files/__name@dasherize@if-flat__/__name@dasherize__.module.ts.template b/packages/schematics/angular/module/files/__name@dasherize@if-flat__/__name@dasherize____typeSeparator__module.ts.template similarity index 88% rename from packages/schematics/angular/module/files/__name@dasherize@if-flat__/__name@dasherize__.module.ts.template rename to packages/schematics/angular/module/files/__name@dasherize@if-flat__/__name@dasherize____typeSeparator__module.ts.template index 252b9bb03397..01ab7af167d1 100644 --- a/packages/schematics/angular/module/files/__name@dasherize@if-flat__/__name@dasherize__.module.ts.template +++ b/packages/schematics/angular/module/files/__name@dasherize@if-flat__/__name@dasherize____typeSeparator__module.ts.template @@ -2,10 +2,10 @@ import { NgModule } from '@angular/core';<% if (commonModule) { %> import { CommonModule } from '@angular/common';<% } %><% if (lazyRouteWithoutRouteModule) { %> import { Routes, RouterModule } from '@angular/router';<% } %> <% if ((!lazyRoute && routing) || lazyRouteWithRouteModule) { %> -import { <%= classify(name) %>RoutingModule } from './<%= dasherize(name) %>-routing.module';<% } %> +import { <%= classify(name) %>RoutingModule } from './<%= dasherize(name) %>-routing<%= typeSeparator %>module';<% } %> <% if (lazyRouteWithoutRouteModule) { %> const routes: Routes = [ - { path: '', component: <%= classify(name) %>Component } + { path: '', component: <%= classify(name) %> } ];<% } %> @NgModule({ diff --git a/packages/schematics/angular/module/index.ts b/packages/schematics/angular/module/index.ts index 0bc257e6c21b..f7657783d866 100644 --- a/packages/schematics/angular/module/index.ts +++ b/packages/schematics/angular/module/index.ts @@ -40,7 +40,7 @@ function buildRelativeModulePath(options: ModuleOptions, modulePath: string): st const importModulePath = join( options.path ?? '', options.flat ? '' : strings.dasherize(options.name), - strings.dasherize(options.name) + '.module', + strings.dasherize(options.name) + options.typeSeparator + 'module', ); return buildRelativePath(modulePath, importModulePath); @@ -113,9 +113,12 @@ function addRouteDeclarationToNgModule( } function getRoutingModulePath(host: Tree, modulePath: string): string | undefined { - const routingModulePath = modulePath.endsWith(ROUTING_MODULE_EXT) - ? modulePath - : modulePath.replace(MODULE_EXT, ROUTING_MODULE_EXT); + const routingModulePath = + modulePath.endsWith(ROUTING_MODULE_EXT) || modulePath.endsWith('-routing-module.ts') + ? modulePath + : modulePath + .replace(MODULE_EXT, ROUTING_MODULE_EXT) + .replace('-module.ts', '-routing-module.ts'); return host.exists(routingModulePath) ? routingModulePath : undefined; } @@ -135,7 +138,15 @@ export default function (options: ModuleOptions): Rule { } if (options.module) { - options.module = findModuleFromOptions(host, options); + try { + options.module = findModuleFromOptions(host, options); + } catch { + options.module = findModuleFromOptions(host, { + ...options, + moduleExt: '-module.ts', + routingModuleExt: '-routing-module.ts', + }); + } } let routingModulePath; @@ -153,7 +164,7 @@ export default function (options: ModuleOptions): Rule { const templateSource = apply(url('./files'), [ options.routing || (isLazyLoadedModuleGen && routingModulePath) ? noop() - : filter((path) => !path.endsWith('-routing.module.ts.template')), + : filter((path) => !path.includes('-routing')), applyTemplates({ ...strings, 'if-flat': (s: string) => (options.flat ? '' : s), @@ -167,7 +178,7 @@ export default function (options: ModuleOptions): Rule { const moduleDasherized = strings.dasherize(options.name); const modulePath = `${ !options.flat ? moduleDasherized + '/' : '' - }${moduleDasherized}.module.ts`; + }${moduleDasherized}${options.typeSeparator}module.ts`; const componentOptions: ComponentOptions = { module: modulePath, diff --git a/packages/schematics/angular/module/index_spec.ts b/packages/schematics/angular/module/index_spec.ts index ef04ddb5c81b..661142b66fc7 100644 --- a/packages/schematics/angular/module/index_spec.ts +++ b/packages/schematics/angular/module/index_spec.ts @@ -49,33 +49,33 @@ describe('Module Schematic', () => { const tree = await schematicRunner.runSchematic('module', options, appTree); const files = tree.files; - expect(files).toContain('/projects/bar/src/app/foo/foo.module.ts'); + expect(files).toContain('/projects/bar/src/app/foo/foo-module.ts'); }); it('should import into another module', async () => { - const options = { ...defaultOptions, module: 'app.module.ts' }; + const options = { ...defaultOptions, module: 'app-module.ts' }; const tree = await schematicRunner.runSchematic('module', options, appTree); - const content = tree.readContent('/projects/bar/src/app/app.module.ts'); - expect(content).toMatch(/import { FooModule } from '.\/foo\/foo.module'/); + const content = tree.readContent('/projects/bar/src/app/app-module.ts'); + expect(content).toMatch(/import { FooModule } from '.\/foo\/foo-module'/); expect(content).toMatch(/imports: \[[^\]]*FooModule[^\]]*\]/m); }); it('should import into another module when using flat', async () => { - const options = { ...defaultOptions, flat: true, module: 'app.module.ts' }; + const options = { ...defaultOptions, flat: true, module: 'app-module.ts' }; const tree = await schematicRunner.runSchematic('module', options, appTree); - const content = tree.readContent('/projects/bar/src/app/app.module.ts'); - expect(content).toMatch(/import { FooModule } from '.\/foo.module'/); + const content = tree.readContent('/projects/bar/src/app/app-module.ts'); + expect(content).toMatch(/import { FooModule } from '.\/foo-module'/); expect(content).toMatch(/imports: \[[^\]]*FooModule[^\]]*\]/m); }); it('should import into another module when using flat', async () => { - const options = { ...defaultOptions, flat: true, module: 'app.module.ts' }; + const options = { ...defaultOptions, flat: true, module: 'app-module.ts' }; const tree = await schematicRunner.runSchematic('module', options, appTree); - const content = tree.readContent('/projects/bar/src/app/app.module.ts'); - expect(content).toMatch(/import { FooModule } from '.\/foo.module'/); + const content = tree.readContent('/projects/bar/src/app/app-module.ts'); + expect(content).toMatch(/import { FooModule } from '.\/foo-module'/); expect(content).toMatch(/imports: \[[^\]]*FooModule[^\]]*\]/m); }); @@ -102,8 +102,8 @@ describe('Module Schematic', () => { tree, ); - const content = tree.readContent('/projects/bar/src/app/sub1/test1/test1.module.ts'); - expect(content).toMatch(/import { Test2Module } from '..\/..\/sub2\/test2\/test2.module'/); + const content = tree.readContent('/projects/bar/src/app/sub1/test1/test1-module.ts'); + expect(content).toMatch(/import { Test2Module } from '..\/..\/sub2\/test2\/test2-module'/); }); it('should create a routing module', async () => { @@ -111,12 +111,12 @@ describe('Module Schematic', () => { const tree = await schematicRunner.runSchematic('module', options, appTree); const files = tree.files; - expect(files).toContain('/projects/bar/src/app/foo/foo.module.ts'); - expect(files).toContain('/projects/bar/src/app/foo/foo-routing.module.ts'); - const moduleContent = tree.readContent('/projects/bar/src/app/foo/foo.module.ts'); - expect(moduleContent).toMatch(/import { FooRoutingModule } from '.\/foo-routing.module'/); + expect(files).toContain('/projects/bar/src/app/foo/foo-module.ts'); + expect(files).toContain('/projects/bar/src/app/foo/foo-routing-module.ts'); + const moduleContent = tree.readContent('/projects/bar/src/app/foo/foo-module.ts'); + expect(moduleContent).toMatch(/import { FooRoutingModule } from '.\/foo-routing-module'/); const routingModuleContent = tree.readContent( - '/projects/bar/src/app/foo/foo-routing.module.ts', + '/projects/bar/src/app/foo/foo-routing-module.ts', ); expect(routingModuleContent).toMatch(/RouterModule.forChild\(routes\)/); }); @@ -126,7 +126,7 @@ describe('Module Schematic', () => { const tree = await schematicRunner.runSchematic('module', options, appTree); const files = tree.files; - expect(files).toContain('/projects/bar/src/app/two-word/two-word.module.ts'); + expect(files).toContain('/projects/bar/src/app/two-word/two-word-module.ts'); }); it('should respect the sourceRoot value', async () => { @@ -134,7 +134,7 @@ describe('Module Schematic', () => { config.projects.bar.sourceRoot = 'projects/bar/custom'; appTree.overwrite('/angular.json', JSON.stringify(config, null, 2)); appTree = await schematicRunner.runSchematic('module', defaultOptions, appTree); - expect(appTree.files).toContain('/projects/bar/custom/app/foo/foo.module.ts'); + expect(appTree.files).toContain('/projects/bar/custom/app/foo/foo-module.ts'); }); describe('lazy route generator', () => { @@ -150,36 +150,36 @@ describe('Module Schematic', () => { expect(files).toEqual( jasmine.arrayContaining([ - '/projects/bar/src/app/foo/foo.module.ts', - '/projects/bar/src/app/foo/foo-routing.module.ts', - '/projects/bar/src/app/foo/foo.component.ts', - '/projects/bar/src/app/foo/foo.component.ng.html', - '/projects/bar/src/app/foo/foo.component.css', + '/projects/bar/src/app/foo/foo-module.ts', + '/projects/bar/src/app/foo/foo-routing-module.ts', + '/projects/bar/src/app/foo/foo.ts', + '/projects/bar/src/app/foo/foo.html', + '/projects/bar/src/app/foo/foo.css', ]), ); const appRoutingModuleContent = tree.readContent( - '/projects/bar/src/app/app-routing.module.ts', + '/projects/bar/src/app/app-routing-module.ts', ); expect(appRoutingModuleContent).toMatch( - /path: '\/new-route', loadChildren: \(\) => import\('.\/foo\/foo.module'\).then\(m => m.FooModule\)/, + /path: '\/new-route', loadChildren: \(\) => import\('.\/foo\/foo-module'\).then\(m => m.FooModule\)/, ); const fooRoutingModuleContent = tree.readContent( - '/projects/bar/src/app/foo/foo-routing.module.ts', + '/projects/bar/src/app/foo/foo-routing-module.ts', ); expect(fooRoutingModuleContent).toMatch(/RouterModule.forChild\(routes\)/); expect(fooRoutingModuleContent).toMatch( - /const routes: Routes = \[\r?\n?\s*{ path: '', component: FooComponent }\r?\n?\s*\];/, + /const routes: Routes = \[\r?\n?\s*{ path: '', component: Foo }\r?\n?\s*\];/, ); }); it('should generate a lazy loaded module with embedded route declarations', async () => { appTree.overwrite( - '/projects/bar/src/app/app.module.ts', + '/projects/bar/src/app/app-module.ts', ` import { NgModule } from '@angular/core'; - import { AppComponent } from './app.component'; + import { AppComponent } from './app'; @NgModule({ declarations: [ @@ -195,26 +195,26 @@ describe('Module Schematic', () => { export class AppModule { } `, ); - appTree.delete('/projects/bar/src/app/app-routing.module.ts'); + appTree.delete('/projects/bar/src/app/app-routing-module.ts'); const tree = await schematicRunner.runSchematic('module', options, appTree); const files = tree.files; - expect(files).toContain('/projects/bar/src/app/foo/foo.module.ts'); - expect(files).not.toContain('/projects/bar/src/app/foo/foo-routing.module.ts'); - expect(files).toContain('/projects/bar/src/app/foo/foo.component.ts'); - expect(files).toContain('/projects/bar/src/app/foo/foo.component.ng.html'); - expect(files).toContain('/projects/bar/src/app/foo/foo.component.css'); + expect(files).toContain('/projects/bar/src/app/foo/foo-module.ts'); + expect(files).not.toContain('/projects/bar/src/app/foo/foo-routing-module.ts'); + expect(files).toContain('/projects/bar/src/app/foo/foo.ts'); + expect(files).toContain('/projects/bar/src/app/foo/foo.html'); + expect(files).toContain('/projects/bar/src/app/foo/foo.css'); - const appModuleContent = tree.readContent('/projects/bar/src/app/app.module.ts'); + const appModuleContent = tree.readContent('/projects/bar/src/app/app-module.ts'); expect(appModuleContent).toMatch( - /path: '\/new-route', loadChildren: \(\) => import\('.\/foo\/foo.module'\).then\(m => m.FooModule\)/, + /path: '\/new-route', loadChildren: \(\) => import\('.\/foo\/foo-module'\).then\(m => m.FooModule\)/, ); - const fooModuleContent = tree.readContent('/projects/bar/src/app/foo/foo.module.ts'); + const fooModuleContent = tree.readContent('/projects/bar/src/app/foo/foo-module.ts'); expect(fooModuleContent).toMatch(/RouterModule.forChild\(routes\)/); expect(fooModuleContent).toMatch( - /const routes: Routes = \[\r?\n?\s*{ path: '', component: FooComponent }\r?\n?\s*\];/, + /const routes: Routes = \[\r?\n?\s*{ path: '', component: Foo }\r?\n?\s*\];/, ); }); @@ -228,19 +228,19 @@ describe('Module Schematic', () => { expect(files).toEqual( jasmine.arrayContaining([ - '/projects/bar/src/app/foo.module.ts', - '/projects/bar/src/app/foo-routing.module.ts', - '/projects/bar/src/app/foo.component.ts', - '/projects/bar/src/app/foo.component.ng.html', - '/projects/bar/src/app/foo.component.css', + '/projects/bar/src/app/foo-module.ts', + '/projects/bar/src/app/foo-routing-module.ts', + '/projects/bar/src/app/foo.ts', + '/projects/bar/src/app/foo.html', + '/projects/bar/src/app/foo.css', ]), ); const appRoutingModuleContent = tree.readContent( - '/projects/bar/src/app/app-routing.module.ts', + '/projects/bar/src/app/app-routing-module.ts', ); expect(appRoutingModuleContent).toMatch( - /path: '\/new-route', loadChildren: \(\) => import\('.\/foo.module'\).then\(m => m.FooModule\)/, + /path: '\/new-route', loadChildren: \(\) => import\('.\/foo-module'\).then\(m => m.FooModule\)/, ); }); @@ -267,34 +267,34 @@ describe('Module Schematic', () => { ); expect(tree.files).toEqual( jasmine.arrayContaining([ - '/projects/bar/src/app/foo/foo-routing.module.ts', - '/projects/bar/src/app/foo/foo.module.ts', - '/projects/bar/src/app/bar/bar-routing.module.ts', - '/projects/bar/src/app/bar/bar.module.ts', - '/projects/bar/src/app/bar/bar.component.ts', + '/projects/bar/src/app/foo/foo-routing-module.ts', + '/projects/bar/src/app/foo/foo-module.ts', + '/projects/bar/src/app/bar/bar-routing-module.ts', + '/projects/bar/src/app/bar/bar-module.ts', + '/projects/bar/src/app/bar/bar.ts', ]), ); const barRoutingModuleContent = tree.readContent( - '/projects/bar/src/app/bar/bar-routing.module.ts', + '/projects/bar/src/app/bar/bar-routing-module.ts', ); - expect(barRoutingModuleContent).toContain(`path: '', component: BarComponent `); + expect(barRoutingModuleContent).toContain(`path: '', component: Bar `); const fooRoutingModuleContent = tree.readContent( - '/projects/bar/src/app/foo/foo-routing.module.ts', + '/projects/bar/src/app/foo/foo-routing-module.ts', ); expect(fooRoutingModuleContent).toContain( - `loadChildren: () => import('../bar/bar.module').then(m => m.BarModule)`, + `loadChildren: () => import('../bar/bar-module').then(m => m.BarModule)`, ); }); it('should not add reference to RouterModule when referencing lazy routing module', async () => { // Delete routing module - appTree.delete('/projects/bar/src/app/app-routing.module.ts'); + appTree.delete('/projects/bar/src/app/app-routing-module.ts'); - // Update app.module to contain the route config. + // Update app-module to contain the route config. appTree.overwrite( - 'projects/bar/src/app/app.module.ts', + 'projects/bar/src/app/app-module.ts', ` import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; @@ -317,11 +317,11 @@ describe('Module Schematic', () => { name: 'bar', route: 'bar', routing: true, - module: 'app.module.ts', + module: 'app-module.ts', }, appTree, ); - const content = tree.readContent('/projects/bar/src/app/bar/bar.module.ts'); + const content = tree.readContent('/projects/bar/src/app/bar/bar-module.ts'); expect(content).toContain('RouterModule.forChild(routes)'); expect(content).not.toContain('BarRoutingModule'); }); diff --git a/packages/schematics/angular/module/schema.json b/packages/schematics/angular/module/schema.json index 2be42b4b2d5c..d433aa17c6d4 100644 --- a/packages/schematics/angular/module/schema.json +++ b/packages/schematics/angular/module/schema.json @@ -62,6 +62,12 @@ "type": "string", "description": "The declaring NgModule.", "alias": "m" + }, + "typeSeparator": { + "type": "string", + "default": "-", + "enum": ["-", "."], + "description": "The separator character to use before the type within the generated file's name. For example, if you set the option to `.`, the file will be named `example.module.ts`." } }, "required": ["name", "project"] diff --git a/packages/schematics/angular/ng-new/index.ts b/packages/schematics/angular/ng-new/index.ts index 133b1083ee5c..f5e37ccccf40 100644 --- a/packages/schematics/angular/ng-new/index.ts +++ b/packages/schematics/angular/ng-new/index.ts @@ -57,7 +57,6 @@ export default function (options: NgNewOptions): Rule { minimal: options.minimal, standalone: options.standalone, ssr: options.ssr, - serverRouting: options.serverRouting, experimentalZoneless: options.experimentalZoneless, }; diff --git a/packages/schematics/angular/ng-new/index_spec.ts b/packages/schematics/angular/ng-new/index_spec.ts index a86d44cd6f79..413cc6841934 100644 --- a/packages/schematics/angular/ng-new/index_spec.ts +++ b/packages/schematics/angular/ng-new/index_spec.ts @@ -41,7 +41,7 @@ describe('Ng New Schematic', () => { ]), ); - expect(files).not.toEqual(jasmine.arrayContaining(['/bar/src/app/app.module.ts'])); + expect(files).not.toEqual(jasmine.arrayContaining(['/bar/src/app/app-module.ts'])); }); it('should create module files of a standalone=false application', async () => { @@ -53,12 +53,12 @@ describe('Ng New Schematic', () => { jasmine.arrayContaining([ '/bar/tsconfig.app.json', '/bar/src/main.ts', - '/bar/src/app/app.module.ts', + '/bar/src/app/app-module.ts', ]), ); }); - it('should should set the prefix in angular.json and in app.component.ts', async () => { + it('should should set the prefix in angular.json and in app.ts', async () => { const options = { ...defaultOptions, prefix: 'pre' }; const tree = await schematicRunner.runSchematic('ng-new', options); @@ -74,8 +74,8 @@ describe('Ng New Schematic', () => { }; const tree = await schematicRunner.runSchematic('ng-new', options); - const moduleContent = tree.readContent('/foo/src/app/app.module.ts'); - expect(moduleContent).toMatch(/declarations:\s*\[\s*AppComponent\s*\]/m); + const moduleContent = tree.readContent('/foo/src/app/app-module.ts'); + expect(moduleContent).toMatch(/declarations:\s*\[\s*App\s*\]/m); }); it('createApplication=false should create an empty workspace', async () => { diff --git a/packages/schematics/angular/ng-new/schema.json b/packages/schematics/angular/ng-new/schema.json index 5b214c73b141..be65f561bc88 100644 --- a/packages/schematics/angular/ng-new/schema.json +++ b/packages/schematics/angular/ng-new/schema.json @@ -139,10 +139,6 @@ "type": "boolean", "x-user-analytics": "ep.ng_ssr" }, - "serverRouting": { - "description": "Create a server application in the initial project using the Server Routing and App Engine APIs (Developer Preview).", - "type": "boolean" - }, "experimentalZoneless": { "description": "Create an initial application that does not utilize `zone.js`.", "type": "boolean", diff --git a/packages/schematics/angular/pipe/files/__name@dasherize@if-flat__/__name@dasherize__.pipe.spec.ts.template b/packages/schematics/angular/pipe/files/__name@dasherize____typeSeparator__pipe.spec.ts.template similarity index 88% rename from packages/schematics/angular/pipe/files/__name@dasherize@if-flat__/__name@dasherize__.pipe.spec.ts.template rename to packages/schematics/angular/pipe/files/__name@dasherize____typeSeparator__pipe.spec.ts.template index 04bcd1dda379..aba0bb94aa66 100644 --- a/packages/schematics/angular/pipe/files/__name@dasherize@if-flat__/__name@dasherize__.pipe.spec.ts.template +++ b/packages/schematics/angular/pipe/files/__name@dasherize____typeSeparator__pipe.spec.ts.template @@ -1,4 +1,4 @@ -import { <%= classify(name) %>Pipe } from './<%= dasherize(name) %>.pipe'; +import { <%= classify(name) %>Pipe } from './<%= dasherize(name) %><%= typeSeparator %>pipe'; describe('<%= classify(name) %>Pipe', () => { it('create an instance', () => { diff --git a/packages/schematics/angular/pipe/files/__name@dasherize@if-flat__/__name@dasherize__.pipe.ts.template b/packages/schematics/angular/pipe/files/__name@dasherize____typeSeparator__pipe.ts.template similarity index 100% rename from packages/schematics/angular/pipe/files/__name@dasherize@if-flat__/__name@dasherize__.pipe.ts.template rename to packages/schematics/angular/pipe/files/__name@dasherize____typeSeparator__pipe.ts.template diff --git a/packages/schematics/angular/pipe/index.ts b/packages/schematics/angular/pipe/index.ts index 10b871ebff32..150b0bc20c57 100644 --- a/packages/schematics/angular/pipe/index.ts +++ b/packages/schematics/angular/pipe/index.ts @@ -6,21 +6,10 @@ * found in the LICENSE file at https://angular.dev/license */ -import { - Rule, - Tree, - apply, - applyTemplates, - chain, - filter, - mergeWith, - move, - noop, - strings, - url, -} from '@angular-devkit/schematics'; +import { Rule, Tree, chain, strings } from '@angular-devkit/schematics'; import { addDeclarationToNgModule } from '../utility/add-declaration-to-ng-module'; import { findModuleFromOptions } from '../utility/find-module'; +import { generateFromFiles } from '../utility/generate-from-files'; import { parseName } from '../utility/parse-name'; import { validateClassName } from '../utility/validation'; import { createDefaultPath } from '../utility/workspace'; @@ -29,30 +18,27 @@ import { Schema as PipeOptions } from './schema'; export default function (options: PipeOptions): Rule { return async (host: Tree) => { options.path ??= await createDefaultPath(host, options.project); - options.module = findModuleFromOptions(host, options); + try { + options.module = findModuleFromOptions(host, options); + } catch { + options.module = findModuleFromOptions(host, { + ...options, + moduleExt: '-module.ts', + routingModuleExt: '-routing-module.ts', + }); + } const parsedPath = parseName(options.path, options.name); options.name = parsedPath.name; options.path = parsedPath.path; validateClassName(strings.classify(options.name)); - const templateSource = apply(url('./files'), [ - options.skipTests ? filter((path) => !path.endsWith('.spec.ts.template')) : noop(), - applyTemplates({ - ...strings, - 'if-flat': (s: string) => (options.flat ? '' : s), - ...options, - }), - move(parsedPath.path), - ]); - return chain([ addDeclarationToNgModule({ type: 'pipe', - ...options, }), - mergeWith(templateSource), + generateFromFiles(options), ]); }; } diff --git a/packages/schematics/angular/pipe/index_spec.ts b/packages/schematics/angular/pipe/index_spec.ts index 6a0da2fbffb8..51f890e54ee1 100644 --- a/packages/schematics/angular/pipe/index_spec.ts +++ b/packages/schematics/angular/pipe/index_spec.ts @@ -56,22 +56,60 @@ describe('Pipe Schematic', () => { it('should create a pipe', async () => { const tree = await schematicRunner.runSchematic('pipe', defaultNonStandaloneOptions, appTree); const files = tree.files; + expect(files).toContain('/projects/bar/src/app/foo-pipe.spec.ts'); + expect(files).toContain('/projects/bar/src/app/foo-pipe.ts'); + const moduleContent = getFileContent(tree, '/projects/bar/src/app/app-module.ts'); + expect(moduleContent).toMatch(/import.*Foo.*from '.\/foo-pipe'/); + expect(moduleContent).toMatch(/declarations:\s*\[[^\]]+?,\r?\n\s+FooPipe\r?\n/m); + const fileContent = tree.readContent('/projects/bar/src/app/foo-pipe.ts'); + expect(fileContent).toContain('transform(value: unknown, ...args: unknown[])'); + }); + + it('should use a `.` type separator when specified', async () => { + const tree = await schematicRunner.runSchematic( + 'pipe', + { + ...defaultNonStandaloneOptions, + typeSeparator: '.', + }, + appTree, + ); + const files = tree.files; expect(files).toContain('/projects/bar/src/app/foo.pipe.spec.ts'); expect(files).toContain('/projects/bar/src/app/foo.pipe.ts'); - const moduleContent = getFileContent(tree, '/projects/bar/src/app/app.module.ts'); + const moduleContent = getFileContent(tree, '/projects/bar/src/app/app-module.ts'); expect(moduleContent).toMatch(/import.*Foo.*from '.\/foo.pipe'/); expect(moduleContent).toMatch(/declarations:\s*\[[^\]]+?,\r?\n\s+FooPipe\r?\n/m); const fileContent = tree.readContent('/projects/bar/src/app/foo.pipe.ts'); expect(fileContent).toContain('transform(value: unknown, ...args: unknown[])'); }); + it('should use a `-` type separator when specified', async () => { + const tree = await schematicRunner.runSchematic( + 'pipe', + { + ...defaultNonStandaloneOptions, + typeSeparator: '-', + }, + appTree, + ); + const files = tree.files; + expect(files).toContain('/projects/bar/src/app/foo-pipe.spec.ts'); + expect(files).toContain('/projects/bar/src/app/foo-pipe.ts'); + const moduleContent = getFileContent(tree, '/projects/bar/src/app/app-module.ts'); + expect(moduleContent).toMatch(/import.*Foo.*from '.\/foo-pipe'/); + expect(moduleContent).toMatch(/declarations:\s*\[[^\]]+?,\r?\n\s+FooPipe\r?\n/m); + const fileContent = tree.readContent('/projects/bar/src/app/foo-pipe.ts'); + expect(fileContent).toContain('transform(value: unknown, ...args: unknown[])'); + }); + it('should import into a specified module', async () => { - const options = { ...defaultNonStandaloneOptions, module: 'app.module.ts' }; + const options = { ...defaultNonStandaloneOptions, module: 'app-module.ts' }; const tree = await schematicRunner.runSchematic('pipe', options, appTree); - const appModule = getFileContent(tree, '/projects/bar/src/app/app.module.ts'); + const appModule = getFileContent(tree, '/projects/bar/src/app/app-module.ts'); - expect(appModule).toMatch(/import { FooPipe } from '.\/foo.pipe'/); + expect(appModule).toMatch(/import { FooPipe } from '.\/foo-pipe'/); }); it('should fail if specified module does not exist', async () => { @@ -93,15 +131,15 @@ describe('Pipe Schematic', () => { const options = { ...defaultNonStandaloneOptions, module: 'admin/module' }; appTree = await schematicRunner.runSchematic('pipe', options, appTree); - const content = appTree.readContent('/projects/bar/src/app/admin/module/module.module.ts'); - expect(content).toMatch(/import { FooPipe } from '\.\.\/\.\.\/foo.pipe'/); + const content = appTree.readContent('/projects/bar/src/app/admin/module/module-module.ts'); + expect(content).toMatch(/import { FooPipe } from '\.\.\/\.\.\/foo-pipe'/); }); it('should export the pipe', async () => { const options = { ...defaultNonStandaloneOptions, export: true }; const tree = await schematicRunner.runSchematic('pipe', options, appTree); - const appModuleContent = getFileContent(tree, '/projects/bar/src/app/app.module.ts'); + const appModuleContent = getFileContent(tree, '/projects/bar/src/app/app-module.ts'); expect(appModuleContent).toMatch(/exports: \[\n(\s*) {2}FooPipe\n\1\]/); }); @@ -110,21 +148,21 @@ describe('Pipe Schematic', () => { const tree = await schematicRunner.runSchematic('pipe', options, appTree); const files = tree.files; - expect(files).toContain('/projects/bar/src/app/foo/foo.pipe.spec.ts'); - expect(files).toContain('/projects/bar/src/app/foo/foo.pipe.ts'); - const moduleContent = getFileContent(tree, '/projects/bar/src/app/app.module.ts'); - expect(moduleContent).toMatch(/import.*Foo.*from '.\/foo\/foo.pipe'/); + expect(files).toContain('/projects/bar/src/app/foo/foo-pipe.spec.ts'); + expect(files).toContain('/projects/bar/src/app/foo/foo-pipe.ts'); + const moduleContent = getFileContent(tree, '/projects/bar/src/app/app-module.ts'); + expect(moduleContent).toMatch(/import.*Foo.*from '.\/foo\/foo-pipe'/); expect(moduleContent).toMatch(/declarations:\s*\[[^\]]+?,\r?\n\s+FooPipe\r?\n/m); }); it('should use the module flag even if the module is a routing module', async () => { - const routingFileName = 'app-routing.module.ts'; + const routingFileName = 'app-routing-module.ts'; const routingModulePath = `/projects/bar/src/app/${routingFileName}`; const newTree = createAppModule(appTree, routingModulePath); const options = { ...defaultNonStandaloneOptions, module: routingFileName }; const tree = await schematicRunner.runSchematic('pipe', options, newTree); const content = getFileContent(tree, routingModulePath); - expect(content).toMatch(/import { FooPipe } from '.\/foo.pipe/); + expect(content).toMatch(/import { FooPipe } from '.\/foo-pipe/); }); it('should respect the sourceRoot value', async () => { @@ -139,11 +177,11 @@ describe('Pipe Schematic', () => { // move the module appTree.rename( - '/projects/bar/src/app/app.module.ts', - '/projects/bar/custom/app/app.module.ts', + '/projects/bar/src/app/app-module.ts', + '/projects/bar/custom/app/app-module.ts', ); appTree = await schematicRunner.runSchematic('pipe', defaultNonStandaloneOptions, appTree); - expect(appTree.files).toContain('/projects/bar/custom/app/foo.pipe.ts'); + expect(appTree.files).toContain('/projects/bar/custom/app/foo-pipe.ts'); }); }); @@ -154,8 +192,8 @@ describe('Pipe Schematic', () => { }); it('should create a standalone pipe', async () => { const tree = await schematicRunner.runSchematic('pipe', defaultOptions, appTree); - const moduleContent = tree.readContent('/projects/bar/src/app/app.module.ts'); - const pipeContent = tree.readContent('/projects/bar/src/app/foo.pipe.ts'); + const moduleContent = tree.readContent('/projects/bar/src/app/app-module.ts'); + const pipeContent = tree.readContent('/projects/bar/src/app/foo-pipe.ts'); expect(pipeContent).not.toContain('standalone'); expect(pipeContent).toContain('class FooPipe'); expect(moduleContent).not.toContain('FooPipe'); @@ -166,8 +204,8 @@ describe('Pipe Schematic', () => { const tree = await schematicRunner.runSchematic('pipe', options, appTree); const files = tree.files; - expect(files).not.toContain('/projects/bar/src/app/foo.pipe.spec.ts'); - expect(files).toContain('/projects/bar/src/app/foo.pipe.ts'); + expect(files).not.toContain('/projects/bar/src/app/foo-pipe.spec.ts'); + expect(files).toContain('/projects/bar/src/app/foo-pipe.ts'); }); it('should error when class name contains invalid characters', async () => { diff --git a/packages/schematics/angular/pipe/schema.json b/packages/schematics/angular/pipe/schema.json index 62dc7fa217b4..19803a524ed4 100644 --- a/packages/schematics/angular/pipe/schema.json +++ b/packages/schematics/angular/pipe/schema.json @@ -61,6 +61,12 @@ "type": "boolean", "default": false, "description": "Automatically export the pipe from the specified NgModule, making it accessible to other modules in the application." + }, + "typeSeparator": { + "type": "string", + "default": "-", + "enum": ["-", "."], + "description": "The separator character to use before the type within the generated file's name. For example, if you set the option to `.`, the file will be named `example.pipe.ts`." } }, "required": ["name", "project"] diff --git a/packages/schematics/angular/resolver/class-files/__name@dasherize__.resolver.spec.ts.template b/packages/schematics/angular/resolver/class-files/__name@dasherize____typeSeparator__resolver.spec.ts.template similarity index 91% rename from packages/schematics/angular/resolver/class-files/__name@dasherize__.resolver.spec.ts.template rename to packages/schematics/angular/resolver/class-files/__name@dasherize____typeSeparator__resolver.spec.ts.template index 3cd1e381185e..af27433460e5 100644 --- a/packages/schematics/angular/resolver/class-files/__name@dasherize__.resolver.spec.ts.template +++ b/packages/schematics/angular/resolver/class-files/__name@dasherize____typeSeparator__resolver.spec.ts.template @@ -1,6 +1,6 @@ import { TestBed } from '@angular/core/testing'; -import { <%= classify(name) %>Resolver } from './<%= dasherize(name) %>.resolver'; +import { <%= classify(name) %>Resolver } from './<%= dasherize(name) %><%= typeSeparator %>resolver'; describe('<%= classify(name) %>Resolver', () => { let resolver: <%= classify(name) %>Resolver; diff --git a/packages/schematics/angular/resolver/class-files/__name@dasherize__.resolver.ts.template b/packages/schematics/angular/resolver/class-files/__name@dasherize____typeSeparator__resolver.ts.template similarity index 100% rename from packages/schematics/angular/resolver/class-files/__name@dasherize__.resolver.ts.template rename to packages/schematics/angular/resolver/class-files/__name@dasherize____typeSeparator__resolver.ts.template diff --git a/packages/schematics/angular/resolver/functional-files/__name@dasherize__.resolver.spec.ts.template b/packages/schematics/angular/resolver/functional-files/__name@dasherize____typeSeparator__resolver.spec.ts.template similarity index 93% rename from packages/schematics/angular/resolver/functional-files/__name@dasherize__.resolver.spec.ts.template rename to packages/schematics/angular/resolver/functional-files/__name@dasherize____typeSeparator__resolver.spec.ts.template index 4e03cb15174e..c9f42a1a0bd5 100644 --- a/packages/schematics/angular/resolver/functional-files/__name@dasherize__.resolver.spec.ts.template +++ b/packages/schematics/angular/resolver/functional-files/__name@dasherize____typeSeparator__resolver.spec.ts.template @@ -1,7 +1,7 @@ import { TestBed } from '@angular/core/testing'; import { ResolveFn } from '@angular/router'; -import { <%= camelize(name) %>Resolver } from './<%= dasherize(name) %>.resolver'; +import { <%= camelize(name) %>Resolver } from './<%= dasherize(name) %><%= typeSeparator %>resolver'; describe('<%= camelize(name) %>Resolver', () => { const executeResolver: ResolveFn = (...resolverParameters) => diff --git a/packages/schematics/angular/resolver/functional-files/__name@dasherize__.resolver.ts.template b/packages/schematics/angular/resolver/functional-files/__name@dasherize____typeSeparator__resolver.ts.template similarity index 100% rename from packages/schematics/angular/resolver/functional-files/__name@dasherize__.resolver.ts.template rename to packages/schematics/angular/resolver/functional-files/__name@dasherize____typeSeparator__resolver.ts.template diff --git a/packages/schematics/angular/resolver/index.ts b/packages/schematics/angular/resolver/index.ts index c1b2b43daed1..ed5ec80ce2d7 100644 --- a/packages/schematics/angular/resolver/index.ts +++ b/packages/schematics/angular/resolver/index.ts @@ -6,12 +6,12 @@ * found in the LICENSE file at https://angular.dev/license */ -import { Rule } from '@angular-devkit/schematics'; +import type { Rule } from '@angular-devkit/schematics'; import { generateFromFiles } from '../utility/generate-from-files'; -import { Schema } from './schema'; +import type { Schema as ResolverOptions } from './schema'; -export default function (options: Schema): Rule { - return options.functional - ? generateFromFiles({ ...options, templateFilesDirectory: './functional-files' }) - : generateFromFiles({ ...options, templateFilesDirectory: './class-files' }); +export default function (options: ResolverOptions): Rule { + const templateFilesDirectory = options.functional ? './functional-files' : './class-files'; + + return generateFromFiles({ ...options, templateFilesDirectory }); } diff --git a/packages/schematics/angular/resolver/index_spec.ts b/packages/schematics/angular/resolver/index_spec.ts index 66a935e45261..1315ee6f01ce 100644 --- a/packages/schematics/angular/resolver/index_spec.ts +++ b/packages/schematics/angular/resolver/index_spec.ts @@ -48,9 +48,9 @@ describe('resolver Schematic', () => { appTree, ); const files = tree.files; - expect(files).toContain('/projects/bar/src/app/foo.resolver.spec.ts'); - expect(files).toContain('/projects/bar/src/app/foo.resolver.ts'); - const fileString = tree.readContent('/projects/bar/src/app/foo.resolver.ts'); + expect(files).toContain('/projects/bar/src/app/foo-resolver.spec.ts'); + expect(files).toContain('/projects/bar/src/app/foo-resolver.ts'); + const fileString = tree.readContent('/projects/bar/src/app/foo-resolver.ts'); expect(fileString).toContain('export class FooResolver implements Resolve'); }); @@ -59,8 +59,30 @@ describe('resolver Schematic', () => { const tree = await schematicRunner.runSchematic('resolver', options, appTree); const files = tree.files; - expect(files).not.toContain('/projects/bar/src/app/foo.resolver.spec.ts'); + expect(files).not.toContain('/projects/bar/src/app/foo-resolver.spec.ts'); + expect(files).toContain('/projects/bar/src/app/foo-resolver.ts'); + }); + + it('should use a `.` type separator when specified', async () => { + const options = { ...defaultOptions, typeSeparator: '.' }; + + const tree = await schematicRunner.runSchematic('resolver', options, appTree); + const files = tree.files; + expect(files).toContain('/projects/bar/src/app/foo.resolver.spec.ts'); expect(files).toContain('/projects/bar/src/app/foo.resolver.ts'); + const specContent = tree.readContent('/projects/bar/src/app/foo.resolver.spec.ts'); + expect(specContent).toContain(`'./foo.resolver'`); + }); + + it('should use a `-` type separator when specified', async () => { + const options = { ...defaultOptions, typeSeparator: '-' }; + + const tree = await schematicRunner.runSchematic('resolver', options, appTree); + const files = tree.files; + expect(files).toContain('/projects/bar/src/app/foo-resolver.spec.ts'); + expect(files).toContain('/projects/bar/src/app/foo-resolver.ts'); + const specContent = tree.readContent('/projects/bar/src/app/foo-resolver.spec.ts'); + expect(specContent).toContain(`'./foo-resolver'`); }); it('should respect the flat flag', async () => { @@ -68,8 +90,8 @@ describe('resolver Schematic', () => { const tree = await schematicRunner.runSchematic('resolver', options, appTree); const files = tree.files; - expect(files).toContain('/projects/bar/src/app/foo/foo.resolver.spec.ts'); - expect(files).toContain('/projects/bar/src/app/foo/foo.resolver.ts'); + expect(files).toContain('/projects/bar/src/app/foo/foo-resolver.spec.ts'); + expect(files).toContain('/projects/bar/src/app/foo/foo-resolver.ts'); }); it('should respect the sourceRoot value', async () => { @@ -77,12 +99,12 @@ describe('resolver Schematic', () => { config.projects.bar.sourceRoot = 'projects/bar/custom'; appTree.overwrite('/angular.json', JSON.stringify(config, null, 2)); appTree = await schematicRunner.runSchematic('resolver', defaultOptions, appTree); - expect(appTree.files).toContain('/projects/bar/custom/app/foo.resolver.ts'); + expect(appTree.files).toContain('/projects/bar/custom/app/foo-resolver.ts'); }); it('should create a functional resolver', async () => { const tree = await schematicRunner.runSchematic('resolver', defaultOptions, appTree); - const fileString = tree.readContent('/projects/bar/src/app/foo.resolver.ts'); + const fileString = tree.readContent('/projects/bar/src/app/foo-resolver.ts'); expect(fileString).toContain( 'export const fooResolver: ResolveFn = (route, state) => {', ); @@ -90,7 +112,7 @@ describe('resolver Schematic', () => { it('should create a helper function to run a functional resolver in a test', async () => { const tree = await schematicRunner.runSchematic('resolver', defaultOptions, appTree); - const fileString = tree.readContent('/projects/bar/src/app/foo.resolver.spec.ts'); + const fileString = tree.readContent('/projects/bar/src/app/foo-resolver.spec.ts'); expect(fileString).toContain( 'const executeResolver: ResolveFn = (...resolverParameters) => ', ); diff --git a/packages/schematics/angular/resolver/schema.json b/packages/schematics/angular/resolver/schema.json index a364e9271397..1a5654f3c7cf 100644 --- a/packages/schematics/angular/resolver/schema.json +++ b/packages/schematics/angular/resolver/schema.json @@ -45,6 +45,12 @@ "$default": { "$source": "projectName" } + }, + "typeSeparator": { + "type": "string", + "default": "-", + "enum": ["-", "."], + "description": "The separator character to use before the type within the generated file's name. For example, if you set the option to `.`, the file will be named `example.resolver.ts`." } }, "required": ["name", "project"] diff --git a/packages/schematics/angular/server/files/application-builder/ngmodule-src/app/app.module.server.ts.template b/packages/schematics/angular/server/files/application-builder/ngmodule-src/app/app.module.server.ts.template index 107232f9107f..5ffb915ae45c 100644 --- a/packages/schematics/angular/server/files/application-builder/ngmodule-src/app/app.module.server.ts.template +++ b/packages/schematics/angular/server/files/application-builder/ngmodule-src/app/app.module.server.ts.template @@ -1,13 +1,12 @@ import { NgModule } from '@angular/core'; -import { ServerModule } from '@angular/platform-server';<% if(serverRouting) { %> -import { provideServerRouting } from '@angular/ssr';<% } %> -import { AppComponent } from './app.component'; -import { AppModule } from './app.module';<% if(serverRouting) { %> -import { serverRoutes } from './app.routes.server';<% } %> +import { provideServerRendering, withRoutes } from '@angular/ssr'; +import { <%= appComponentName %> } from '<%= appComponentPath %>'; +import { <%= appModuleName %> } from '<%= appModulePath %>'; +import { serverRoutes } from './app.routes.server'; @NgModule({ - imports: [AppModule, ServerModule],<% if(serverRouting) { %> - providers: [provideServerRouting(serverRoutes)],<% } %> - bootstrap: [AppComponent], + imports: [<%= appModuleName %>], + providers: [provideServerRendering(withRoutes(serverRoutes))], + bootstrap: [<%= appComponentName %>], }) export class AppServerModule {} diff --git a/packages/schematics/angular/server/files/application-builder/standalone-src/app/app.config.server.ts.template b/packages/schematics/angular/server/files/application-builder/standalone-src/app/app.config.server.ts.template index a7fd3d0b4fe7..41031f1165dd 100644 --- a/packages/schematics/angular/server/files/application-builder/standalone-src/app/app.config.server.ts.template +++ b/packages/schematics/angular/server/files/application-builder/standalone-src/app/app.config.server.ts.template @@ -1,13 +1,11 @@ import { mergeApplicationConfig, ApplicationConfig } from '@angular/core'; -import { provideServerRendering } from '@angular/platform-server';<% if(serverRouting) { %> -import { provideServerRouting } from '@angular/ssr';<% } %> -import { appConfig } from './app.config';<% if(serverRouting) { %> -import { serverRoutes } from './app.routes.server';<% } %> +import { provideServerRendering, withRoutes } from '@angular/ssr'; +import { appConfig } from './app.config'; +import { serverRoutes } from './app.routes.server'; const serverConfig: ApplicationConfig = { providers: [ - provideServerRendering(),<% if(serverRouting) { %> - provideServerRouting(serverRoutes)<% } %> + provideServerRendering(withRoutes(serverRoutes)) ] }; diff --git a/packages/schematics/angular/server/files/application-builder/standalone-src/main.server.ts.template b/packages/schematics/angular/server/files/application-builder/standalone-src/main.server.ts.template index 4b9d4d1545c1..bc0b6ba59758 100644 --- a/packages/schematics/angular/server/files/application-builder/standalone-src/main.server.ts.template +++ b/packages/schematics/angular/server/files/application-builder/standalone-src/main.server.ts.template @@ -1,7 +1,7 @@ import { bootstrapApplication } from '@angular/platform-browser'; -import { AppComponent } from './app/app.component'; +import { <%= appComponentName %> } from '<%= appComponentPath %>'; import { config } from './app/app.config.server'; -const bootstrap = () => bootstrapApplication(AppComponent, config); +const bootstrap = () => bootstrapApplication(<%= appComponentName %>, config); export default bootstrap; diff --git a/packages/schematics/angular/server/files/server-builder/ngmodule-src/app/app.module.server.ts.template b/packages/schematics/angular/server/files/server-builder/ngmodule-src/app/app.module.server.ts.template index 795380cd2294..eeffba7f902b 100644 --- a/packages/schematics/angular/server/files/server-builder/ngmodule-src/app/app.module.server.ts.template +++ b/packages/schematics/angular/server/files/server-builder/ngmodule-src/app/app.module.server.ts.template @@ -1,14 +1,14 @@ import { NgModule } from '@angular/core'; import { ServerModule } from '@angular/platform-server'; -import { AppModule } from './app.module'; -import { AppComponent } from './app.component'; +import { <%= appModuleName %> } from '<%= appModulePath %>'; +import { <%= appComponentName %> } from '<%= appComponentPath %>'; @NgModule({ imports: [ - AppModule, + <%= appModuleName %>, ServerModule, ], - bootstrap: [AppComponent], + bootstrap: [<%= appComponentName %>], }) export class AppServerModule {} diff --git a/packages/schematics/angular/server/files/server-builder/standalone-src/app/app.config.server.ts.template b/packages/schematics/angular/server/files/server-builder/standalone-src/app/app.config.server.ts.template index b4d57c94235f..05c29319d5c4 100644 --- a/packages/schematics/angular/server/files/server-builder/standalone-src/app/app.config.server.ts.template +++ b/packages/schematics/angular/server/files/server-builder/standalone-src/app/app.config.server.ts.template @@ -1,5 +1,5 @@ import { mergeApplicationConfig, ApplicationConfig } from '@angular/core'; -import { provideServerRendering } from '@angular/platform-server'; +import { provideServerRendering } from '@angular/ssr'; import { appConfig } from './app.config'; const serverConfig: ApplicationConfig = { diff --git a/packages/schematics/angular/server/files/server-builder/standalone-src/main.server.ts.template b/packages/schematics/angular/server/files/server-builder/standalone-src/main.server.ts.template index 4b9d4d1545c1..bc0b6ba59758 100644 --- a/packages/schematics/angular/server/files/server-builder/standalone-src/main.server.ts.template +++ b/packages/schematics/angular/server/files/server-builder/standalone-src/main.server.ts.template @@ -1,7 +1,7 @@ import { bootstrapApplication } from '@angular/platform-browser'; -import { AppComponent } from './app/app.component'; +import { <%= appComponentName %> } from '<%= appComponentPath %>'; import { config } from './app/app.config.server'; -const bootstrap = () => bootstrapApplication(AppComponent, config); +const bootstrap = () => bootstrapApplication(<%= appComponentName %>, config); export default bootstrap; diff --git a/packages/schematics/angular/server/index.ts b/packages/schematics/angular/server/index.ts index 846125a36f2a..50f624e078cd 100644 --- a/packages/schematics/angular/server/index.ts +++ b/packages/schematics/angular/server/index.ts @@ -14,10 +14,8 @@ import { apply, applyTemplates, chain, - filter, mergeWith, move, - noop, strings, url, } from '@angular-devkit/schematics'; @@ -28,7 +26,8 @@ import { JSONFile } from '../utility/json-file'; import { latestVersions } from '../utility/latest-versions'; import { isStandaloneApp } from '../utility/ng-ast-utils'; import { relativePathToWorkspaceRoot } from '../utility/paths'; -import { targetBuildNotFoundError } from '../utility/project-targets'; +import { isUsingApplicationBuilder, targetBuildNotFoundError } from '../utility/project-targets'; +import { resolveBootstrappedComponentData } from '../utility/standalone/app_component'; import { getMainFilePath } from '../utility/standalone/util'; import { getWorkspace, updateWorkspace } from '../utility/workspace'; import { Builders } from '../utility/workspace-models'; @@ -113,19 +112,13 @@ function updateConfigFileApplicationBuilder(options: ServerOptions): Rule { serverMainEntryName, ); - if (options.serverRouting) { - buildTarget.options['outputMode'] = 'static'; - } + buildTarget.options['outputMode'] = 'static'; }); } function updateTsConfigFile(tsConfigPath: string): Rule { return (host: Tree) => { const json = new JSONFile(host, tsConfigPath); - const filesPath = ['files']; - const files = new Set((json.get(filesPath) as string[] | undefined) ?? []); - files.add('src/' + serverMainEntryName); - json.modify(filesPath, [...files]); const typePath = ['compilerOptions', 'types']; const types = new Set((json.get(typePath) as string[] | undefined) ?? []); @@ -173,13 +166,11 @@ export default function (options: ServerOptions): Rule { throw targetBuildNotFoundError(); } - const isUsingApplicationBuilder = - clientBuildTarget.builder === Builders.Application || - clientBuildTarget.builder === Builders.BuildApplication; + const usingApplicationBuilder = isUsingApplicationBuilder(clientProject); if ( clientProject.targets.has('server') || - (isUsingApplicationBuilder && clientBuildTarget.options?.server !== undefined) + (usingApplicationBuilder && clientBuildTarget.options?.server !== undefined) ) { // Server has already been added. return; @@ -190,16 +181,27 @@ export default function (options: ServerOptions): Rule { const isStandalone = isStandaloneApp(host, browserEntryPoint); const sourceRoot = clientProject.sourceRoot ?? join(normalize(clientProject.root), 'src'); - let filesUrl = `./files/${isUsingApplicationBuilder ? 'application-builder/' : 'server-builder/'}`; + let filesUrl = `./files/${usingApplicationBuilder ? 'application-builder/' : 'server-builder/'}`; filesUrl += isStandalone ? 'standalone-src' : 'ngmodule-src'; + const { componentName, componentImportPathInSameFile, moduleName, moduleImportPathInSameFile } = + resolveBootstrappedComponentData(host, browserEntryPoint) || { + componentName: 'App', + componentImportPathInSameFile: './app/app', + moduleName: 'AppModule', + moduleImportPathInSameFile: './app/app.module', + }; const templateSource = apply(url(filesUrl), [ - options.serverRouting - ? noop() - : filter((path) => !path.endsWith('app.routes.server.ts.template')), applyTemplates({ ...strings, ...options, + appComponentName: componentName, + appComponentPath: componentImportPathInSameFile, + appModuleName: moduleName, + appModulePath: + moduleImportPathInSameFile === null + ? null + : `./${posix.basename(moduleImportPathInSameFile)}`, }), move(sourceRoot), ]); @@ -210,7 +212,7 @@ export default function (options: ServerOptions): Rule { return chain([ mergeWith(templateSource), - ...(isUsingApplicationBuilder + ...(usingApplicationBuilder ? [ updateConfigFileApplicationBuilder(options), updateTsConfigFile(clientBuildOptions.tsConfig), diff --git a/packages/schematics/angular/server/index_spec.ts b/packages/schematics/angular/server/index_spec.ts index 130d4bf05cd3..f3e5e277d8ef 100644 --- a/packages/schematics/angular/server/index_spec.ts +++ b/packages/schematics/angular/server/index_spec.ts @@ -70,6 +70,84 @@ describe('Server Schematic', () => { ); }); + it('should account for renamed app component and module', async () => { + appTree.create( + '/projects/bar/src/app/my-custom-module.ts', + ` + import { NgModule } from '@angular/core'; + import { BrowserModule } from '@angular/platform-browser'; + import { MyCustomApp } from './foo/bar/baz/app.foo'; + + @NgModule({ + declarations: [MyCustomApp], + imports: [BrowserModule], + bootstrap: [MyCustomApp] + }) + export class MyCustomModule {} + `, + ); + + appTree.overwrite( + '/projects/bar/src/main.ts', + ` + import { platformBrowser } from '@angular/platform-browser'; + import { MyCustomModule } from './app/my-custom-module'; + + platformBrowser().bootstrapModule(MyCustomModule) + .catch(err => console.error(err)); + `, + ); + + const tree = await schematicRunner.runSchematic('server', defaultOptions, appTree); + const filePath = '/projects/bar/src/app/app.module.server.ts'; + expect(tree.exists(filePath)).toBeTrue(); + const contents = tree.readContent(filePath); + + expect(contents).toContain(`import { MyCustomApp } from './foo/bar/baz/app.foo';`); + expect(contents).toContain(`import { MyCustomModule } from './my-custom-module';`); + expect(contents).toContain(`imports: [MyCustomModule],`); + expect(contents).toContain(`bootstrap: [MyCustomApp],`); + }); + + it('should account for renamed app component and module that have been aliased', async () => { + appTree.create( + '/projects/bar/src/app/my-custom-module.ts', + ` + import { NgModule } from '@angular/core'; + import { BrowserModule } from '@angular/platform-browser'; + import { MyCustomApp as MyAliasedApp } from './foo/bar/baz/app.foo'; + + @NgModule({ + declarations: [MyAliasedApp], + imports: [BrowserModule], + bootstrap: [MyAliasedApp] + }) + export class MyCustomModule {} + `, + ); + + appTree.overwrite( + '/projects/bar/src/main.ts', + ` + import { platformBrowser } from '@angular/platform-browser'; + import { MyCustomModule as MyAliasedModule } from './app/my-custom-module'; + + platformBrowser().bootstrapModule(MyAliasedModule) + .catch(err => console.error(err)); + `, + ); + + const tree = await schematicRunner.runSchematic('server', defaultOptions, appTree); + const filePath = '/projects/bar/src/app/app.module.server.ts'; + expect(tree.exists(filePath)).toBeTrue(); + const contents = tree.readContent(filePath); + + expect(contents).toContain(`import { MyCustomApp } from './foo/bar/baz/app.foo';`); + expect(contents).toContain(`import { MyCustomModule } from './my-custom-module';`); + expect(contents).toContain(`imports: [MyCustomModule],`); + expect(contents).toContain(`bootstrap: [MyCustomApp],`); + }); + it('should add dependency: @angular/platform-server', async () => { const tree = await schematicRunner.runSchematic('server', defaultOptions, appTree); const filePath = '/package.json'; @@ -89,12 +167,11 @@ describe('Server Schematic', () => { const filePath = '/projects/bar/tsconfig.app.json'; const contents = parseJson(tree.readContent(filePath).toString()); expect(contents.compilerOptions.types).toEqual(['node']); - expect(contents.files).toEqual(['src/main.ts', 'src/main.server.ts']); }); it(`should add 'provideClientHydration' to the providers list`, async () => { const tree = await schematicRunner.runSchematic('server', defaultOptions, appTree); - const contents = tree.readContent('/projects/bar/src/app/app.module.ts'); + const contents = tree.readContent('/projects/bar/src/app/app-module.ts'); expect(contents).toContain(`provideClientHydration(withEventReplay())`); }); }); @@ -124,7 +201,49 @@ describe('Server Schematic', () => { const filePath = '/projects/bar/src/main.server.ts'; expect(tree.exists(filePath)).toBeTrue(); const contents = tree.readContent(filePath); - expect(contents).toContain(`bootstrapApplication(AppComponent, config)`); + expect(contents).toContain(`bootstrapApplication(App, config)`); + }); + + it('should account for renamed app component', async () => { + appTree.overwrite( + '/projects/bar/src/main.ts', + ` + import { bootstrapApplication } from '@angular/platform-browser'; + import { appConfig } from './app/app.config'; + import { MyCustomApp } from './foo/bar/baz/app.foo'; + + bootstrapApplication(MyCustomApp, appConfig) + .catch((err) => console.error(err)); + `, + ); + + const tree = await schematicRunner.runSchematic('server', defaultOptions, appTree); + const filePath = '/projects/bar/src/main.server.ts'; + expect(tree.exists(filePath)).toBeTrue(); + const contents = tree.readContent(filePath); + expect(contents).toContain(`import { MyCustomApp } from './foo/bar/baz/app.foo';`); + expect(contents).toContain(`bootstrapApplication(MyCustomApp, config)`); + }); + + it('should account for renamed app component that is aliased within the main file', async () => { + appTree.overwrite( + '/projects/bar/src/main.ts', + ` + import { bootstrapApplication } from '@angular/platform-browser'; + import { appConfig } from './app/app.config'; + import { MyCustomApp as MyCustomAlias } from './foo/bar/baz/app.foo'; + + bootstrapApplication(MyCustomAlias, appConfig) + .catch((err) => console.error(err)); + `, + ); + + const tree = await schematicRunner.runSchematic('server', defaultOptions, appTree); + const filePath = '/projects/bar/src/main.server.ts'; + expect(tree.exists(filePath)).toBeTrue(); + const contents = tree.readContent(filePath); + expect(contents).toContain(`import { MyCustomApp } from './foo/bar/baz/app.foo';`); + expect(contents).toContain(`bootstrapApplication(MyCustomApp, config)`); }); it('should create server app config file', async () => { diff --git a/packages/schematics/angular/server/schema.json b/packages/schematics/angular/server/schema.json index bad36a9ee36a..225574d92155 100644 --- a/packages/schematics/angular/server/schema.json +++ b/packages/schematics/angular/server/schema.json @@ -17,10 +17,6 @@ "description": "Skip the automatic installation of packages. You will need to manually install the dependencies later.", "type": "boolean", "default": false - }, - "serverRouting": { - "description": "Configure the server application to use the Server Routing and App Engine APIs (Developer Preview).", - "type": "boolean" } }, "required": ["project"] diff --git a/packages/schematics/angular/service-worker/index_spec.ts b/packages/schematics/angular/service-worker/index_spec.ts index 87f3a9aafc46..e67a91f6d754 100644 --- a/packages/schematics/angular/service-worker/index_spec.ts +++ b/packages/schematics/angular/service-worker/index_spec.ts @@ -171,7 +171,7 @@ describe('Service Worker Schematic', () => { nonStandaloneSWOptions, appTree, ); - const pkgText = tree.readContent('/projects/buz/src/app/app.module.ts'); + const pkgText = tree.readContent('/projects/buz/src/app/app-module.ts'); expect(pkgText).toMatch(/import \{ ServiceWorkerModule \} from '@angular\/service-worker'/); }); @@ -181,7 +181,7 @@ describe('Service Worker Schematic', () => { nonStandaloneSWOptions, appTree, ); - const pkgText = tree.readContent('/projects/buz/src/app/app.module.ts'); + const pkgText = tree.readContent('/projects/buz/src/app/app-module.ts'); expect(pkgText).toMatch( new RegExp( "(\\s+)ServiceWorkerModule\\.register\\('ngsw-worker\\.js', \\{\\n" + diff --git a/packages/schematics/angular/service/files/__name@dasherize@if-flat__/__name@dasherize__.service.spec.ts.template b/packages/schematics/angular/service/files/__name@dasherize@if-flat__/__name@dasherize__.service.spec.ts.template deleted file mode 100644 index 2c7ab1d2bdf6..000000000000 --- a/packages/schematics/angular/service/files/__name@dasherize@if-flat__/__name@dasherize__.service.spec.ts.template +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { <%= classify(name) %>Service } from './<%= dasherize(name) %>.service'; - -describe('<%= classify(name) %>Service', () => { - let service: <%= classify(name) %>Service; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(<%= classify(name) %>Service); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/packages/schematics/angular/service/files/__name@dasherize__.__type@dasherize__.spec.ts.template b/packages/schematics/angular/service/files/__name@dasherize__.__type@dasherize__.spec.ts.template new file mode 100644 index 000000000000..a57a4e043b4b --- /dev/null +++ b/packages/schematics/angular/service/files/__name@dasherize__.__type@dasherize__.spec.ts.template @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { <%= classify(name) %><%= classify(type) %> } from './<%= dasherize(name) %><%= type ? '.' + dasherize(type) : '' %>'; + +describe('<%= classify(name) %><%= classify(type) %>', () => { + let service: <%= classify(name) %><%= classify(type) %>; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(<%= classify(name) %><%= classify(type) %>); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/packages/schematics/angular/service/files/__name@dasherize@if-flat__/__name@dasherize__.service.ts.template b/packages/schematics/angular/service/files/__name@dasherize__.__type@dasherize__.ts.template similarity index 64% rename from packages/schematics/angular/service/files/__name@dasherize@if-flat__/__name@dasherize__.service.ts.template rename to packages/schematics/angular/service/files/__name@dasherize__.__type@dasherize__.ts.template index f14985e32b60..ad3685368077 100644 --- a/packages/schematics/angular/service/files/__name@dasherize@if-flat__/__name@dasherize__.service.ts.template +++ b/packages/schematics/angular/service/files/__name@dasherize__.__type@dasherize__.ts.template @@ -3,7 +3,7 @@ import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) -export class <%= classify(name) %>Service { +export class <%= classify(name) %><%= classify(type) %> { constructor() { } } diff --git a/packages/schematics/angular/service/index.ts b/packages/schematics/angular/service/index.ts index 79073504978a..640661a2addc 100644 --- a/packages/schematics/angular/service/index.ts +++ b/packages/schematics/angular/service/index.ts @@ -11,11 +11,5 @@ import { generateFromFiles } from '../utility/generate-from-files'; import { Schema as ServiceOptions } from './schema'; export default function (options: ServiceOptions): Rule { - // This schematic uses an older method to implement the flat option - const flat = options.flat; - options.flat = true; - - return generateFromFiles(options, { - 'if-flat': (s: string) => (flat ? '' : s), - }); + return generateFromFiles(options); } diff --git a/packages/schematics/angular/service/index_spec.ts b/packages/schematics/angular/service/index_spec.ts index 30e9745348dc..b5a6856e1504 100644 --- a/packages/schematics/angular/service/index_spec.ts +++ b/packages/schematics/angular/service/index_spec.ts @@ -46,15 +46,15 @@ describe('Service Schematic', () => { const tree = await schematicRunner.runSchematic('service', options, appTree); const files = tree.files; - expect(files).toContain('/projects/bar/src/app/foo/foo.service.spec.ts'); - expect(files).toContain('/projects/bar/src/app/foo/foo.service.ts'); + expect(files).toContain('/projects/bar/src/app/foo/foo.spec.ts'); + expect(files).toContain('/projects/bar/src/app/foo/foo.ts'); }); it('service should be tree-shakeable', async () => { const options = { ...defaultOptions }; const tree = await schematicRunner.runSchematic('service', options, appTree); - const content = tree.readContent('/projects/bar/src/app/foo/foo.service.ts'); + const content = tree.readContent('/projects/bar/src/app/foo/foo.ts'); expect(content).toMatch(/providedIn: 'root'/); }); @@ -63,8 +63,8 @@ describe('Service Schematic', () => { const tree = await schematicRunner.runSchematic('service', options, appTree); const files = tree.files; - expect(files).toContain('/projects/bar/src/app/foo/foo.service.ts'); - expect(files).not.toContain('/projects/bar/src/app/foo/foo.service.spec.ts'); + expect(files).toContain('/projects/bar/src/app/foo/foo.ts'); + expect(files).not.toContain('/projects/bar/src/app/foo/foo.spec.ts'); }); it('should respect the sourceRoot value', async () => { @@ -72,6 +72,24 @@ describe('Service Schematic', () => { config.projects.bar.sourceRoot = 'projects/bar/custom'; appTree.overwrite('/angular.json', JSON.stringify(config, null, 2)); appTree = await schematicRunner.runSchematic('service', defaultOptions, appTree); - expect(appTree.files).toContain('/projects/bar/custom/app/foo/foo.service.ts'); + expect(appTree.files).toContain('/projects/bar/custom/app/foo/foo.ts'); + }); + + it('should respect the type option', async () => { + const options = { ...defaultOptions, type: 'Service' }; + const tree = await schematicRunner.runSchematic('service', options, appTree); + const content = tree.readContent('/projects/bar/src/app/foo/foo.service.ts'); + const testContent = tree.readContent('/projects/bar/src/app/foo/foo.service.spec.ts'); + expect(content).toContain('export class FooService'); + expect(testContent).toContain("describe('FooService'"); + }); + + it('should allow empty string in the type option', async () => { + const options = { ...defaultOptions, type: '' }; + const tree = await schematicRunner.runSchematic('service', options, appTree); + const content = tree.readContent('/projects/bar/src/app/foo/foo.ts'); + const testContent = tree.readContent('/projects/bar/src/app/foo/foo.spec.ts'); + expect(content).toContain('export class Foo'); + expect(testContent).toContain("describe('Foo'"); }); }); diff --git a/packages/schematics/angular/service/schema.json b/packages/schematics/angular/service/schema.json index d5a4d0418acd..29f5474e68dd 100644 --- a/packages/schematics/angular/service/schema.json +++ b/packages/schematics/angular/service/schema.json @@ -39,6 +39,10 @@ "type": "boolean", "description": "Skip the generation of a unit test file `spec.ts` for the service.", "default": false + }, + "type": { + "type": "string", + "description": "Append a custom type to the service's filename. For example, if you set the type to `service`, the file will be named `my-service.service.ts`." } }, "required": ["name", "project"] diff --git a/packages/schematics/angular/ssr/files/application-builder-common-engine/server.ts.template b/packages/schematics/angular/ssr/files/application-builder-common-engine/server.ts.template deleted file mode 100644 index 63a70ae893f6..000000000000 --- a/packages/schematics/angular/ssr/files/application-builder-common-engine/server.ts.template +++ /dev/null @@ -1,67 +0,0 @@ -import { APP_BASE_HREF } from '@angular/common'; -import { CommonEngine, isMainModule } from '@angular/ssr/node'; -import express from 'express'; -import { dirname, join, resolve } from 'node:path'; -import { fileURLToPath } from 'node:url'; -import <% if (isStandalone) { %>bootstrap<% } else { %>AppServerModule<% } %> from './main.server'; - -const serverDistFolder = dirname(fileURLToPath(import.meta.url)); -const browserDistFolder = resolve(serverDistFolder, '../<%= browserDistDirectory %>'); -const indexHtml = join(serverDistFolder, 'index.server.html'); - -const app = express(); -const commonEngine = new CommonEngine(); - -/** - * Example Express Rest API endpoints can be defined here. - * Uncomment and define endpoints as necessary. - * - * Example: - * ```ts - * app.get('/api/**', (req, res) => { - * // Handle API request - * }); - * ``` - */ - -/** - * Serve static files from /<%= browserDistDirectory %> - */ -app.get( - '**', - express.static(browserDistFolder, { - maxAge: '1y', - index: 'index.html' - }), -); - -/** - * Handle all other requests by rendering the Angular application. - */ -app.get('**', (req, res, next) => { - const { protocol, originalUrl, baseUrl, headers } = req; - - commonEngine - .render({ - <% if (isStandalone) { %>bootstrap<% } else { %>bootstrap: AppServerModule<% } %>, - documentFilePath: indexHtml, - url: `${protocol}://${headers.host}${originalUrl}`, - publicPath: browserDistFolder, - providers: [{ provide: APP_BASE_HREF, useValue: baseUrl }], - }) - .then((html) => res.send(html)) - .catch((err) => next(err)); -}); - -/** - * Start the server if this module is the main entry point. - * The server listens on the port defined by the `PORT` environment variable, or defaults to 4000. - */ -if (isMainModule(import.meta.url)) { - const port = process.env['PORT'] || 4000; - app.listen(port, () => { - console.log(`Node Express server listening on http://localhost:${port}`); - }); -} - -export default app; diff --git a/packages/schematics/angular/ssr/files/application-builder/server.ts.template b/packages/schematics/angular/ssr/files/application-builder/server.ts.template index 1d07f023a713..6fb8b2c77e5a 100644 --- a/packages/schematics/angular/ssr/files/application-builder/server.ts.template +++ b/packages/schematics/angular/ssr/files/application-builder/server.ts.template @@ -5,11 +5,9 @@ import { writeResponseToNodeResponse, } from '@angular/ssr/node'; import express from 'express'; -import { dirname, resolve } from 'node:path'; -import { fileURLToPath } from 'node:url'; +import { join } from 'node:path'; -const serverDistFolder = dirname(fileURLToPath(import.meta.url)); -const browserDistFolder = resolve(serverDistFolder, '../<%= browserDistDirectory %>'); +const browserDistFolder = join(import.meta.dirname, '../<%= browserDistDirectory %>'); const app = express(); const angularApp = new AngularNodeAppEngine(); @@ -20,7 +18,7 @@ const angularApp = new AngularNodeAppEngine(); * * Example: * ```ts - * app.get('/api/**', (req, res) => { + * app.get('/api/{*splat}', (req, res) => { * // Handle API request * }); * ``` @@ -40,7 +38,7 @@ app.use( /** * Handle all other requests by rendering the Angular application. */ -app.use('/**', (req, res, next) => { +app.use((req, res, next) => { angularApp .handle(req) .then((response) => @@ -55,7 +53,11 @@ app.use('/**', (req, res, next) => { */ if (isMainModule(import.meta.url)) { const port = process.env['PORT'] || 4000; - app.listen(port, () => { + app.listen(port, (error) => { + if (error) { + throw error; + } + console.log(`Node Express server listening on http://localhost:${port}`); }); } diff --git a/packages/schematics/angular/ssr/files/server-builder/server.ts.template b/packages/schematics/angular/ssr/files/server-builder/server.ts.template index 1d985bd60030..7567fa65a81d 100644 --- a/packages/schematics/angular/ssr/files/server-builder/server.ts.template +++ b/packages/schematics/angular/ssr/files/server-builder/server.ts.template @@ -21,14 +21,15 @@ export function app(): express.Express { server.set('views', distFolder); // Example Express Rest API endpoints - // server.get('/api/**', (req, res) => { }); + // server.get('/api/{*splat}', (req, res) => { }); // Serve static files from /browser - server.get('*.*', express.static(distFolder, { - maxAge: '1y' + server.use(express.static(distFolder, { + maxAge: '1y', + index: false, })); // All regular routes use the Angular engine - server.get('*', (req, res, next) => { + server.use((req, res, next) => { const { protocol, originalUrl, baseUrl, headers } = req; commonEngine @@ -51,7 +52,11 @@ function run(): void { // Start up the Node server const server = app(); - server.listen(port, () => { + server.listen(port, (error) => { + if (error) { + throw error; + } + console.log(`Node Express server listening on http://localhost:${port}`); }); } diff --git a/packages/schematics/angular/ssr/index.ts b/packages/schematics/angular/ssr/index.ts index 6249778a8594..e589395dac73 100644 --- a/packages/schematics/angular/ssr/index.ts +++ b/packages/schematics/angular/ssr/index.ts @@ -24,6 +24,7 @@ import { posix } from 'node:path'; import { Schema as ServerOptions } from '../server/schema'; import { DependencyType, + ExistingBehavior, InstallBehavior, addDependency, readWorkspace, @@ -32,13 +33,11 @@ import { import { JSONFile } from '../utility/json-file'; import { latestVersions } from '../utility/latest-versions'; import { isStandaloneApp } from '../utility/ng-ast-utils'; -import { targetBuildNotFoundError } from '../utility/project-targets'; +import { isUsingApplicationBuilder, targetBuildNotFoundError } from '../utility/project-targets'; import { getMainFilePath } from '../utility/standalone/util'; -import { ProjectDefinition, getWorkspace } from '../utility/workspace'; -import { Builders } from '../utility/workspace-models'; +import { getWorkspace } from '../utility/workspace'; import { Schema as SSROptions } from './schema'; -import { isTTY } from './tty'; const SERVE_SSR_TARGET_NAME = 'serve-ssr'; const PRERENDER_TARGET_NAME = 'prerender'; @@ -83,12 +82,9 @@ async function getApplicationBuilderOutputPaths( throw new SchematicsException(`Cannot find 'options' for ${projectName} ${target} target.`); } - const { outputPath } = architectTarget.options; - if (outputPath === null || outputPath === undefined) { - throw new SchematicsException( - `outputPath for ${projectName} ${target} target is undefined or null.`, - ); - } + let { outputPath } = architectTarget.options; + // Use default if not explicitly specified + outputPath ??= posix.join('dist', projectName); const defaultDirs = { server: DEFAULT_SERVER_DIR, @@ -158,6 +154,13 @@ function updateApplicationBuilderTsConfigRule(options: SSROptions): Rule { } const json = new JSONFile(host, tsConfigPath); + + // Skip adding the files entry if the server entry would already be included + const include = json.get(['include']); + if (Array.isArray(include) && include.includes('src/**/*.ts')) { + return; + } + const filesPath = ['files']; const files = new Set((json.get(filesPath) as string[] | undefined) ?? []); files.add('src/server.ts'); @@ -202,8 +205,7 @@ function updateApplicationBuilderWorkspaceConfigRule( buildTarget.options = { ...buildTarget.options, outputPath, - outputMode: options.serverRouting ? 'server' : undefined, - prerender: options.serverRouting ? undefined : true, + outputMode: 'server', ssr: { entry: join(normalize(projectSourceRoot), 'server.ts'), }, @@ -305,10 +307,12 @@ function addDependencies({ skipInstall }: SSROptions, isUsingApplicationBuilder: addDependency('express', latestVersions['express'], { type: DependencyType.Default, install, + existing: ExistingBehavior.Replace, }), addDependency('@types/express', latestVersions['@types/express'], { type: DependencyType.Dev, install, + existing: ExistingBehavior.Replace, }), ]; @@ -336,46 +340,37 @@ function addServerFile( if (!project) { throw new SchematicsException(`Invalid project name (${projectName})`); } - const isUsingApplicationBuilder = usingApplicationBuilder(project); - - const browserDistDirectory = isUsingApplicationBuilder + const usingApplicationBuilder = isUsingApplicationBuilder(project); + const browserDistDirectory = usingApplicationBuilder ? (await getApplicationBuilderOutputPaths(host, projectName)).browser : await getLegacyOutputPaths(host, projectName, 'build'); - const applicationBuilderFiles = - 'application-builder' + (options.serverRouting ? '' : '-common-engine'); - return mergeWith( - apply( - url(`./files/${isUsingApplicationBuilder ? applicationBuilderFiles : 'server-builder'}`), - [ - applyTemplates({ - ...strings, - ...options, - browserDistDirectory, - isStandalone, - }), - move(projectSourceRoot), - ], - ), + apply(url(`./files/${usingApplicationBuilder ? 'application-builder' : 'server-builder'}`), [ + applyTemplates({ + ...strings, + ...options, + browserDistDirectory, + isStandalone, + }), + move(projectSourceRoot), + ]), ); }; } -export default function (inputOptions: SSROptions): Rule { +export default function (options: SSROptions): Rule { return async (host, context) => { - const browserEntryPoint = await getMainFilePath(host, inputOptions.project); + const browserEntryPoint = await getMainFilePath(host, options.project); const isStandalone = isStandaloneApp(host, browserEntryPoint); const workspace = await getWorkspace(host); - const clientProject = workspace.projects.get(inputOptions.project); + const clientProject = workspace.projects.get(options.project); if (!clientProject) { throw targetBuildNotFoundError(); } - const isUsingApplicationBuilder = usingApplicationBuilder(clientProject); - const serverRouting = await isServerRoutingEnabled(isUsingApplicationBuilder, inputOptions); - const options = { ...inputOptions, serverRouting }; + const usingApplicationBuilder = isUsingApplicationBuilder(clientProject); const sourceRoot = clientProject.sourceRoot ?? posix.join(clientProject.root, 'src'); return chain([ @@ -383,7 +378,7 @@ export default function (inputOptions: SSROptions): Rule { ...options, skipInstall: true, }), - ...(isUsingApplicationBuilder + ...(usingApplicationBuilder ? [ updateApplicationBuilderWorkspaceConfigRule(sourceRoot, options, context), updateApplicationBuilderTsConfigRule(options), @@ -393,73 +388,8 @@ export default function (inputOptions: SSROptions): Rule { updateWebpackBuilderWorkspaceConfigRule(sourceRoot, options), ]), addServerFile(sourceRoot, options, isStandalone), - addScriptsRule(options, isUsingApplicationBuilder), - addDependencies(options, isUsingApplicationBuilder), + addScriptsRule(options, usingApplicationBuilder), + addDependencies(options, usingApplicationBuilder), ]); }; } - -function usingApplicationBuilder(project: ProjectDefinition) { - const buildBuilder = project.targets.get('build')?.builder; - const isUsingApplicationBuilder = - buildBuilder === Builders.Application || buildBuilder === Builders.BuildApplication; - - return isUsingApplicationBuilder; -} - -// Wrap inquirer in a `prompt` function. -export type Prompt = (message: string, defaultValue: boolean) => Promise; -const defaultPrompter: Prompt = async (message, defaultValue) => { - const { confirm } = await import('@inquirer/prompts'); - - return await confirm({ - message, - default: defaultValue, - }); -}; - -// Allow the prompt functionality to be overridden to facilitate testing. -let prompt = defaultPrompter; -export function setPrompterForTestOnly(prompter?: Prompt): void { - prompt = prompter ?? defaultPrompter; -} - -/** Returns whether or not server routing is enabled, potentially prompting the user if necessary. */ -async function isServerRoutingEnabled( - isUsingApplicationBuilder: boolean, - options: SSROptions, -): Promise { - if (!isUsingApplicationBuilder) { - if (options.serverRouting) { - throw new SchematicsException( - 'Server routing APIs can only be added to a project using `application` builder.', - ); - } else { - return false; - } - } - - // Use explicit option if provided. - if (options.serverRouting !== undefined) { - return options.serverRouting; - } - - const serverRoutingDefault = false; - - // Use the default if not in an interactive terminal. - if (!isTTY()) { - return serverRoutingDefault; - } - - // `inquirer` requires `async_hooks` which isn't supported by webcontainers, therefore we can't prompt in that context. - // See: https://github.com/SBoudrias/Inquirer.js/issues/1426 - if (process.versions.webcontainer) { - return serverRoutingDefault; - } - - // Prompt the user if in an interactive terminal and no option was provided. - return await prompt( - 'Would you like to use the Server Routing and App Engine APIs (Developer Preview) for this server application?', - /* defaultValue */ serverRoutingDefault, - ); -} diff --git a/packages/schematics/angular/ssr/index_spec.ts b/packages/schematics/angular/ssr/index_spec.ts index a7de8d12f208..97b534aba8e1 100644 --- a/packages/schematics/angular/ssr/index_spec.ts +++ b/packages/schematics/angular/ssr/index_spec.ts @@ -10,12 +10,10 @@ import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/te import { join } from 'node:path'; import { Schema as ServerOptions } from './schema'; -import { Prompt, setPrompterForTestOnly } from './index'; describe('SSR Schematic', () => { const defaultOptions: ServerOptions = { project: 'test-app', - serverRouting: false, }; const schematicRunner = new SchematicTestRunner( @@ -32,10 +30,6 @@ describe('SSR Schematic', () => { }; beforeEach(async () => { - setPrompterForTestOnly((message) => { - return fail(`Unmocked prompt: ${message}`) as never; - }); - appTree = await schematicRunner.runExternalSchematic( '@schematics/angular', 'workspace', @@ -76,13 +70,28 @@ describe('SSR Schematic', () => { expect((schematicRunner.tasks[0].options as { command: string }).command).toBe('install'); }); - it(`should update 'tsconfig.app.json' files with Express main file`, async () => { + it(`should not update 'tsconfig.app.json' files with Express main file already included`, async () => { const tree = await schematicRunner.runSchematic('ssr', defaultOptions, appTree); const { files } = tree.readJson('/projects/test-app/tsconfig.app.json') as { files: string[]; }; - expect(files).toEqual(['src/main.ts', 'src/main.server.ts', 'src/server.ts']); + expect(files).toBeUndefined(); + }); + + it(`should update 'tsconfig.app.json' files with Express main file if not included`, async () => { + const appTsConfigContent = appTree.readJson('/projects/test-app/tsconfig.app.json') as { + include?: string[]; + }; + appTsConfigContent.include = []; + appTree.overwrite('/projects/test-app/tsconfig.app.json', JSON.stringify(appTsConfigContent)); + + const tree = await schematicRunner.runSchematic('ssr', defaultOptions, appTree); + const { files } = tree.readJson('/projects/test-app/tsconfig.app.json') as { + files: string[]; + }; + + expect(files).toContain('src/server.ts'); }); }); @@ -124,7 +133,7 @@ describe('SSR Schematic', () => { const build = config.projects['test-app'].architect.build; build.options.outputPath = { - base: build.options.outputPath, + base: 'dist/test-app', browser: 'public', server: 'node-server', }; @@ -136,7 +145,7 @@ describe('SSR Schematic', () => { expect(scripts['serve:ssr:test-app']).toBe(`node dist/test-app/node-server/server.mjs`); const serverFileContent = tree.readContent('/projects/test-app/src/server.ts'); - expect(serverFileContent).toContain(`resolve(serverDistFolder, '../public')`); + expect(serverFileContent).toContain(`join(import.meta.dirname, '../public')`); }); it(`removes "outputPath.browser" when it's an empty string`, async () => { @@ -145,7 +154,7 @@ describe('SSR Schematic', () => { const build = config.projects['test-app'].architect.build; build.options.outputPath = { - base: build.options.outputPath, + base: 'dist/test-app', browser: '', server: 'node-server', }; @@ -163,90 +172,6 @@ describe('SSR Schematic', () => { server: 'node-server', }); }); - - it('generates server routing configuration when enabled', async () => { - const tree = await schematicRunner.runSchematic( - 'ssr', - { ...defaultOptions, serverRouting: true }, - appTree, - ); - - expect(tree.exists('/projects/test-app/src/app/app.routes.server.ts')).toBeTrue(); - }); - - it('does not generate server routing configuration when disabled', async () => { - const tree = await schematicRunner.runSchematic( - 'ssr', - { ...defaultOptions, serverRouting: false }, - appTree, - ); - - expect(tree.exists('/projects/test-app/src/app/app.routes.server.ts')).toBeFalse(); - }); - - it('generates server routing configuration when prompt is accepted by the user', async () => { - const prompter = jasmine.createSpy('prompt').and.resolveTo(true); - setPrompterForTestOnly(prompter); - - process.env['NG_FORCE_TTY'] = 'TRUE'; - const tree = await schematicRunner.runSchematic( - 'ssr', - { ...defaultOptions, serverRouting: undefined }, - appTree, - ); - - expect(prompter).toHaveBeenCalledTimes(1); - - expect(tree.exists('/projects/test-app/src/app/app.routes.server.ts')).toBeTrue(); - }); - - it('does not generate server routing configuration when prompt is rejected by the user', async () => { - const prompter = jasmine.createSpy('prompt').and.resolveTo(false); - setPrompterForTestOnly(prompter); - - process.env['NG_FORCE_TTY'] = 'TRUE'; - const tree = await schematicRunner.runSchematic( - 'ssr', - { ...defaultOptions, serverRouting: undefined }, - appTree, - ); - - expect(prompter).toHaveBeenCalledTimes(1); - - expect(tree.exists('/projects/test-app/src/app/app.routes.server.ts')).toBeFalse(); - }); - - it('defaults to skipping server route generation when not in an interactive terminal', async () => { - const prompter = jasmine.createSpy('prompt').and.resolveTo(false); - setPrompterForTestOnly(prompter); - - process.env['NG_FORCE_TTY'] = 'FALSE'; - const tree = await schematicRunner.runSchematic( - 'ssr', - { ...defaultOptions, serverRouting: undefined }, - appTree, - ); - - expect(prompter).not.toHaveBeenCalled(); - - expect(tree.exists('/projects/test-app/src/app/app.routes.server.ts')).toBeFalse(); - }); - - it('does not prompt when running in a web container', async () => { - const prompter = jasmine.createSpy('prompt').and.resolveTo(false); - setPrompterForTestOnly(prompter); - - process.versions.webcontainer = 'abc123'; // Simulate webcontainer. - const tree = await schematicRunner.runSchematic( - 'ssr', - { ...defaultOptions, serverRouting: undefined }, - appTree, - ); - - expect(prompter).not.toHaveBeenCalled(); - - expect(tree.exists('/projects/test-app/src/app/app.routes.server.ts')).toBeFalse(); - }); }); describe('Legacy browser builder', () => { @@ -313,27 +238,5 @@ describe('SSR Schematic', () => { const content = tree.readContent('/projects/test-app/src/server.ts'); expect(content).toContain(`const distFolder = join(process.cwd(), 'dist/test-app/browser');`); }); - - it('throws an exception when used with `serverRouting`', async () => { - await expectAsync( - schematicRunner.runSchematic('ssr', { ...defaultOptions, serverRouting: true }, appTree), - ).toBeRejectedWithError(/Server routing APIs.*`application` builder/); - }); - - it('automatically disables `serverRouting` and does not prompt for it', async () => { - const prompter = jasmine.createSpy('prompt').and.resolveTo(false); - setPrompterForTestOnly(prompter); - - process.env['NG_FORCE_TTY'] = 'TRUE'; - const tree = await schematicRunner.runSchematic( - 'ssr', - { ...defaultOptions, serverRouting: undefined }, - appTree, - ); - - expect(prompter).not.toHaveBeenCalled(); - - expect(tree.exists('/projects/test-app/src/app/app.routes.server.ts')).toBeFalse(); - }); }); }); diff --git a/packages/schematics/angular/ssr/schema.json b/packages/schematics/angular/ssr/schema.json index 669f1449ad13..aeaf6262908a 100644 --- a/packages/schematics/angular/ssr/schema.json +++ b/packages/schematics/angular/ssr/schema.json @@ -16,10 +16,6 @@ "description": "Skip the automatic installation of packages. You will need to manually install the dependencies later.", "type": "boolean", "default": false - }, - "serverRouting": { - "description": "Configure the server application to use the Angular Server Routing API and App Engine APIs (currently in Developer Preview).", - "type": "boolean" } }, "required": ["project"], diff --git a/packages/schematics/angular/utility/add-declaration-to-ng-module.ts b/packages/schematics/angular/utility/add-declaration-to-ng-module.ts index 10abc76c58a1..239b282902c7 100644 --- a/packages/schematics/angular/utility/add-declaration-to-ng-module.ts +++ b/packages/schematics/angular/utility/add-declaration-to-ng-module.ts @@ -19,6 +19,7 @@ export interface DeclarationToNgModuleOptions { flat?: boolean; export?: boolean; type: string; + typeSeparator?: '.' | '-'; skipImport?: boolean; standalone?: boolean; } @@ -30,6 +31,8 @@ export function addDeclarationToNgModule(options: DeclarationToNgModuleOptions): return host; } + const typeSeparator = options.typeSeparator ?? '.'; + const sourceText = host.readText(modulePath); const source = ts.createSourceFile(modulePath, sourceText, ts.ScriptTarget.Latest, true); @@ -37,11 +40,11 @@ export function addDeclarationToNgModule(options: DeclarationToNgModuleOptions): `/${options.path}/` + (options.flat ? '' : strings.dasherize(options.name) + '/') + strings.dasherize(options.name) + - (options.type ? '.' : '') + - strings.dasherize(options.type); + (options.type ? typeSeparator + strings.dasherize(options.type) : ''); const importPath = buildRelativePath(modulePath, filePath); - const classifiedName = strings.classify(options.name) + strings.classify(options.type); + const classifiedName = + strings.classify(options.name) + (options.type ? strings.classify(options.type) : ''); const changes = addDeclarationToModule(source, modulePath, classifiedName, importPath); if (options.export) { diff --git a/packages/schematics/angular/utility/ast-utils.ts b/packages/schematics/angular/utility/ast-utils.ts index a39261868f50..106481688d18 100644 --- a/packages/schematics/angular/utility/ast-utils.ts +++ b/packages/schematics/angular/utility/ast-utils.ts @@ -343,7 +343,7 @@ export function getDecoratorMetadata( export function getMetadataField( node: ts.ObjectLiteralExpression, metadataField: string, -): ts.ObjectLiteralElement[] { +): ts.PropertyAssignment[] { return ( node.properties .filter(ts.isPropertyAssignment) @@ -561,13 +561,9 @@ export function getRouterModuleDeclaration(source: ts.SourceFile): ts.Expression } const matchingProperties = getMetadataField(node, 'imports'); - if (!matchingProperties) { - return; - } - - const assignment = matchingProperties[0] as ts.PropertyAssignment; + const assignment = matchingProperties[0]; - if (assignment.initializer.kind !== ts.SyntaxKind.ArrayLiteralExpression) { + if (!assignment || assignment.initializer.kind !== ts.SyntaxKind.ArrayLiteralExpression) { return; } diff --git a/packages/schematics/angular/utility/find-module.ts b/packages/schematics/angular/utility/find-module.ts index 71f4c41926a5..69e10dc1368e 100644 --- a/packages/schematics/angular/utility/find-module.ts +++ b/packages/schematics/angular/utility/find-module.ts @@ -59,7 +59,7 @@ export function findModuleFromOptions(host: Tree, options: ModuleOptions): Path ); for (const sc of candidateFiles) { - if (host.exists(sc)) { + if (host.exists(sc) && host.readText(sc).includes('@NgModule')) { return normalize(sc); } } diff --git a/packages/schematics/angular/utility/find-module_spec.ts b/packages/schematics/angular/utility/find-module_spec.ts index 7570121ea790..9680f15949c8 100644 --- a/packages/schematics/angular/utility/find-module_spec.ts +++ b/packages/schematics/angular/utility/find-module_spec.ts @@ -92,16 +92,25 @@ describe('find-module', () => { options = { name: 'foo' }; }); - it('should find a module', () => { - tree.create('/projects/my-proj/src/app.module.ts', ''); + it('should find a module with a decorator', () => { + tree.create('/projects/my-proj/src/app.module.ts', '@NgModule'); options.module = 'app.module.ts'; options.path = '/projects/my-proj/src'; const modPath = findModuleFromOptions(tree, options) as string; expect(modPath).toEqual('/projects/my-proj/src/app.module.ts'); }); + it('should not find module-like file without a decorator', () => { + tree.create('/projects/my-proj/src/app.module.ts', ''); + options.module = 'app.module.ts'; + options.path = '/projects/my-proj/src'; + expect(() => findModuleFromOptions(tree, options) as string).toThrowError( + /Specified module 'app.module.ts' does not exist/, + ); + }); + it('should find a module when name has underscore', () => { - tree.create('/projects/my-proj/src/feature_module/app_test.module.ts', ''); + tree.create('/projects/my-proj/src/feature_module/app_test.module.ts', '@NgModule'); options.path = '/projects/my-proj/src'; options.name = 'feature_module/new_component'; const modPath = findModuleFromOptions(tree, options) as string; @@ -109,7 +118,7 @@ describe('find-module', () => { }); it('should find a module when name has uppercase', () => { - tree.create('/projects/my-proj/src/featureModule/appTest.module.ts', ''); + tree.create('/projects/my-proj/src/featureModule/appTest.module.ts', '@NgModule'); options.path = '/projects/my-proj/src'; options.name = 'featureModule/newComponent'; const modPath = findModuleFromOptions(tree, options) as string; @@ -117,7 +126,7 @@ describe('find-module', () => { }); it('should find a module if flat is true', () => { - tree.create('/projects/my-proj/src/module/app_test.module.ts', ''); + tree.create('/projects/my-proj/src/module/app_test.module.ts', '@NgModule'); options.path = '/projects/my-proj/src'; options.flat = true; options.name = '/module/directive'; @@ -126,7 +135,7 @@ describe('find-module', () => { }); it('should find a module in a sub dir', () => { - tree.create('/projects/my-proj/src/admin/foo.module.ts', ''); + tree.create('/projects/my-proj/src/admin/foo.module.ts', '@NgModule'); options.name = 'other/test'; options.module = 'admin/foo'; options.path = '/projects/my-proj/src'; @@ -135,7 +144,7 @@ describe('find-module', () => { }); it('should find a module in a sub dir (2)', () => { - tree.create('/projects/my-proj/src/admin/foo.module.ts', ''); + tree.create('/projects/my-proj/src/admin/foo.module.ts', '@NgModule'); options.name = 'admin/hello'; options.module = 'foo'; options.path = '/projects/my-proj/src'; @@ -144,7 +153,7 @@ describe('find-module', () => { }); it('should find a module using custom ext', () => { - tree.create('/projects/my-proj/src/app_module.ts', ''); + tree.create('/projects/my-proj/src/app_module.ts', '@NgModule'); options.module = 'app'; options.path = '/projects/my-proj/src'; options.moduleExt = '_module.ts'; @@ -164,7 +173,7 @@ describe('find-module', () => { }); it('should ignore custom ext if module or ${module}.ts exists', () => { - tree.create('/projects/my-proj/src/app.module.ts', ''); + tree.create('/projects/my-proj/src/app.module.ts', '@NgModule'); options.path = '/projects/my-proj/src'; options.moduleExt = '_module.ts'; let modPath; diff --git a/packages/schematics/angular/utility/generate-from-files.ts b/packages/schematics/angular/utility/generate-from-files.ts index 7cb1317e3771..3f3547d5e6e2 100644 --- a/packages/schematics/angular/utility/generate-from-files.ts +++ b/packages/schematics/angular/utility/generate-from-files.ts @@ -7,12 +7,14 @@ */ import { + FileOperator, Rule, Tree, apply, applyTemplates, chain, filter, + forEach, mergeWith, move, noop, @@ -31,6 +33,7 @@ export interface GenerateFromFilesOptions { project: string; skipTests?: boolean; templateFilesDirectory?: string; + type?: string; } export function generateFromFiles( @@ -42,6 +45,9 @@ export function generateFromFiles( options.prefix ??= ''; options.flat ??= true; + // Schematic templates require a defined type value + options.type ??= ''; + const parsedPath = parseName(options.path, options.name); options.name = parsedPath.name; options.path = parsedPath.path; @@ -56,6 +62,19 @@ export function generateFromFiles( ...options, ...extraTemplateValues, }), + !options.type + ? forEach((file) => { + let filePath: string = file.path; + while (filePath.includes('..')) { + filePath = filePath.replaceAll('..', '.'); + } + + return { + content: file.content, + path: filePath, + } as ReturnType; + }) + : noop(), move(parsedPath.path + (options.flat ? '' : '/' + strings.dasherize(options.name))), ]); diff --git a/packages/schematics/angular/utility/latest-versions/package.json b/packages/schematics/angular/utility/latest-versions/package.json index 406f275d0d66..92b883e83855 100644 --- a/packages/schematics/angular/utility/latest-versions/package.json +++ b/packages/schematics/angular/utility/latest-versions/package.json @@ -3,11 +3,11 @@ "comment": "This file is needed so that dependencies are synced by Renovate.", "private": true, "dependencies": { - "@types/express": "^4.17.17", + "@types/express": "^5.0.1", "@types/jasmine": "~5.1.0", "@types/node": "^20.17.19", "browser-sync": "^3.0.0", - "express": "^4.18.2", + "express": "^5.1.0", "jasmine-core": "~5.6.0", "jasmine-spec-reporter": "~7.0.0", "karma-chrome-launcher": "~3.2.0", diff --git a/packages/schematics/angular/utility/project-targets.ts b/packages/schematics/angular/utility/project-targets.ts index 584922c8af9c..8897a3ddab66 100644 --- a/packages/schematics/angular/utility/project-targets.ts +++ b/packages/schematics/angular/utility/project-targets.ts @@ -7,7 +7,17 @@ */ import { SchematicsException } from '@angular-devkit/schematics'; +import { ProjectDefinition } from './workspace'; +import { Builders } from './workspace-models'; export function targetBuildNotFoundError(): SchematicsException { return new SchematicsException(`Project target "build" not found.`); } + +export function isUsingApplicationBuilder(project: ProjectDefinition): boolean { + const buildBuilder = project.targets.get('build')?.builder; + const isUsingApplicationBuilder = + buildBuilder === Builders.Application || buildBuilder === Builders.BuildApplication; + + return isUsingApplicationBuilder; +} diff --git a/packages/schematics/angular/utility/standalone/app_component.ts b/packages/schematics/angular/utility/standalone/app_component.ts new file mode 100644 index 000000000000..28b436c737c6 --- /dev/null +++ b/packages/schematics/angular/utility/standalone/app_component.ts @@ -0,0 +1,148 @@ +/** + * @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 { SchematicsException, Tree } from '@angular-devkit/schematics'; +import ts from '../../third_party/github.com/Microsoft/TypeScript/lib/typescript'; +import { getDecoratorMetadata, getMetadataField } from '../ast-utils'; +import { findBootstrapModuleCall, getAppModulePath } from '../ng-ast-utils'; +import { findBootstrapApplicationCall, getSourceFile } from './util'; + +/** Data resolved for a bootstrapped component. */ +interface BootstrappedComponentData { + /** Original name of the component class. */ + componentName: string; + + /** Path under which the component was imported in the main entrypoint. */ + componentImportPathInSameFile: string; + + /** Original name of the NgModule being bootstrapped, null if the app isn't module-based. */ + moduleName: string | null; + + /** + * Path under which the module was imported in the main entrypoint, + * null if the app isn't module-based. + */ + moduleImportPathInSameFile: string | null; +} + +/** + * Finds the original name and path relative to the `main.ts` of the bootrstrapped app component. + * @param tree File tree in which to look for the component. + * @param mainFilePath Path of the `main` file. + */ +export function resolveBootstrappedComponentData( + tree: Tree, + mainFilePath: string, +): BootstrappedComponentData | null { + // First try to resolve for a standalone app. + try { + const call = findBootstrapApplicationCall(tree, mainFilePath); + + if (call.arguments.length > 0 && ts.isIdentifier(call.arguments[0])) { + const resolved = resolveIdentifier(call.arguments[0]); + + if (resolved) { + return { + componentName: resolved.name, + componentImportPathInSameFile: resolved.path, + moduleName: null, + moduleImportPathInSameFile: null, + }; + } + } + } catch (e) { + // `findBootstrapApplicationCall` will throw if it can't find the `bootrstrapApplication` call. + // Catch so we can continue to the fallback logic. + if (!(e instanceof SchematicsException)) { + throw e; + } + } + + // Otherwise fall back to resolving an NgModule-based app. + return resolveNgModuleBasedData(tree, mainFilePath); +} + +/** Resolves the bootstrap data for a NgModule-based app. */ +function resolveNgModuleBasedData( + tree: Tree, + mainFilePath: string, +): BootstrappedComponentData | null { + const appModulePath = getAppModulePath(tree, mainFilePath); + const appModuleFile = getSourceFile(tree, appModulePath); + const metadataNodes = getDecoratorMetadata(appModuleFile, 'NgModule', '@angular/core'); + + for (const node of metadataNodes) { + if (!ts.isObjectLiteralExpression(node)) { + continue; + } + + const bootstrapProp = getMetadataField(node, 'bootstrap').find((prop) => { + return ( + ts.isArrayLiteralExpression(prop.initializer) && + prop.initializer.elements.length > 0 && + ts.isIdentifier(prop.initializer.elements[0]) + ); + }); + + const componentIdentifier = (bootstrapProp?.initializer as ts.ArrayLiteralExpression) + .elements[0] as ts.Identifier | undefined; + const componentResult = componentIdentifier ? resolveIdentifier(componentIdentifier) : null; + const bootstrapCall = findBootstrapModuleCall(tree, mainFilePath); + + if ( + componentResult && + bootstrapCall && + bootstrapCall.arguments.length > 0 && + ts.isIdentifier(bootstrapCall.arguments[0]) + ) { + const moduleResult = resolveIdentifier(bootstrapCall.arguments[0]); + + if (moduleResult) { + return { + componentName: componentResult.name, + componentImportPathInSameFile: componentResult.path, + moduleName: moduleResult.name, + moduleImportPathInSameFile: moduleResult.path, + }; + } + } + } + + return null; +} + +/** Resolves an identifier to its original name and path that it was imported from. */ +function resolveIdentifier(identifier: ts.Identifier): { name: string; path: string } | null { + const sourceFile = identifier.getSourceFile(); + + // Try to resolve the import path by looking at the top-level named imports of the file. + for (const node of sourceFile.statements) { + if ( + !ts.isImportDeclaration(node) || + !ts.isStringLiteral(node.moduleSpecifier) || + !node.importClause || + !node.importClause.namedBindings || + !ts.isNamedImports(node.importClause.namedBindings) + ) { + continue; + } + + for (const element of node.importClause.namedBindings.elements) { + if (element.name.text === identifier.text) { + return { + // Note that we use `propertyName` if available, because it contains + // the real name in the case where the import is aliased. + name: (element.propertyName || element.name).text, + path: node.moduleSpecifier.text, + }; + } + } + } + + return null; +} diff --git a/packages/schematics/angular/utility/standalone/rules_spec.ts b/packages/schematics/angular/utility/standalone/rules_spec.ts index 0eed95662e2b..c6e3836344f0 100644 --- a/packages/schematics/angular/utility/standalone/rules_spec.ts +++ b/packages/schematics/angular/utility/standalone/rules_spec.ts @@ -74,7 +74,7 @@ describe('standalone utilities', () => { host, ); - const content = readFile('app/app.module.ts'); + const content = readFile('app/app-module.ts'); assertContains(content, `import { MyModule } from '@my/module';`); assertContains(content, `imports: [BrowserModule, MyModule.forRoot([])]`); @@ -326,7 +326,7 @@ describe('standalone utilities', () => { host, ); - const content = readFile('app/app.module.ts'); + const content = readFile('app/app-module.ts'); assertContains(content, `import { BrowserModule as BrowserModule_alias } from '@my/module';`); assertContains(content, `imports: [BrowserModule, BrowserModule_alias.forRoot([])]`); @@ -420,7 +420,7 @@ describe('standalone utilities', () => { host, ); - const content = readFile('app/app.module.ts'); + const content = readFile('app/app-module.ts'); assertContains(content, `import { SOME_TOKEN } from '@my/module';`); assertContains(content, `providers: [{ provide: SOME_TOKEN, useValue: 123 }]`); diff --git a/packages/schematics/angular/utility/test/create-app-module.ts b/packages/schematics/angular/utility/test/create-app-module.ts index 1c76111c3a78..563f3a60ea72 100644 --- a/packages/schematics/angular/utility/test/create-app-module.ts +++ b/packages/schematics/angular/utility/test/create-app-module.ts @@ -10,7 +10,7 @@ import { UnitTestTree } from '@angular-devkit/schematics/testing'; export function createAppModule(tree: UnitTestTree, path?: string): UnitTestTree { tree.create( - path || '/src/app/app.module.ts', + path || '/src/app/app-module.ts', ` import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; diff --git a/packages/schematics/angular/web-worker/index.ts b/packages/schematics/angular/web-worker/index.ts index a3a08fb85ffe..f04ef232f955 100644 --- a/packages/schematics/angular/web-worker/index.ts +++ b/packages/schematics/angular/web-worker/index.ts @@ -39,7 +39,7 @@ function addSnippet(options: WebWorkerOptions): Rule { .getDir(options.path) .subfiles // Find all files that start with the same name, are ts files, // and aren't spec or module files. - .filter((f) => fileRegExp.test(f) && !/(module|spec)\.ts$/.test(f)) + .filter((f) => fileRegExp.test(f) && !/(module|spec|config|routes)\.ts$/.test(f)) // Sort alphabetically for consistency. .sort(); diff --git a/packages/schematics/angular/web-worker/index_spec.ts b/packages/schematics/angular/web-worker/index_spec.ts index 0ce238177838..c1ab48b8d196 100644 --- a/packages/schematics/angular/web-worker/index_spec.ts +++ b/packages/schematics/angular/web-worker/index_spec.ts @@ -70,7 +70,7 @@ describe('Web Worker Schematic', () => { it('should add snippet to sibling file', async () => { const tree = await schematicRunner.runSchematic('web-worker', defaultOptions, appTree); - const appComponent = tree.readContent('/projects/bar/src/app/app.component.ts'); + const appComponent = tree.readContent('/projects/bar/src/app/app.ts'); expect(appComponent).toContain(`new Worker(new URL('./${defaultOptions.name}.worker`); expect(appComponent).toContain('console.log(`page got message: ${data}`)'); }); diff --git a/packages/schematics/angular/workspace/files/package.json.template b/packages/schematics/angular/workspace/files/package.json.template index 51468a39dd08..4ee0cdd9ab73 100644 --- a/packages/schematics/angular/workspace/files/package.json.template +++ b/packages/schematics/angular/workspace/files/package.json.template @@ -15,7 +15,6 @@ "@angular/core": "<%= latestVersions.Angular %>", "@angular/forms": "<%= latestVersions.Angular %>", "@angular/platform-browser": "<%= latestVersions.Angular %>", - "@angular/platform-browser-dynamic": "<%= latestVersions.Angular %>", "@angular/router": "<%= latestVersions.Angular %>", "rxjs": "<%= latestVersions['rxjs'] %>", "tslib": "<%= latestVersions['tslib'] %>", diff --git a/packages/schematics/angular/workspace/files/tsconfig.json.template b/packages/schematics/angular/workspace/files/tsconfig.json.template index 45c41bcc800d..798ec8305a16 100644 --- a/packages/schematics/angular/workspace/files/tsconfig.json.template +++ b/packages/schematics/angular/workspace/files/tsconfig.json.template @@ -2,8 +2,7 @@ /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ { "compileOnSave": false, - "compilerOptions": { - "outDir": "./dist/out-tsc",<% if (strict) { %> + "compilerOptions": {<% if (strict) { %> "strict": true, "noImplicitOverride": true, "noPropertyAccessFromIndexSignature": true, @@ -20,6 +19,8 @@ "enableI18nLegacyMessageIdFormat": false<% if (strict) { %>, "strictInjectionParameters": true, "strictInputAccessModifiers": true, + "typeCheckHostBindings": true, "strictTemplates": true<% } %> - } + }, + "files": [] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a0e3e0d068d6..c482f21101a5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,144 +5,99 @@ settings: excludeLinksFromLockfile: false overrides: - typescript: 5.8.2 + typescript: 5.8.3 '@angular/build': workspace:* -packageExtensionsChecksum: ea5f588691095a73da0f9364791a5f26 +packageExtensionsChecksum: d67b1f07b351844d00c57cbace376860 importers: .: devDependencies: - '@ampproject/remapping': - specifier: 2.3.0 - version: 2.3.0 '@angular/animations': - specifier: 20.0.0-next.2 - version: 20.0.0-next.2(@angular/core@20.0.0-next.2) + specifier: 20.0.0-next.7 + version: 20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)) '@angular/cdk': - specifier: 20.0.0-next.1 - version: 20.0.0-next.1(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2)(rxjs@7.8.2) + specifier: 20.0.0-next.7 + version: 20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) '@angular/common': - specifier: 20.0.0-next.2 - version: 20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2) + specifier: 20.0.0-next.7 + version: 20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) '@angular/compiler': - specifier: 20.0.0-next.2 - version: 20.0.0-next.2(@angular/core@20.0.0-next.2) + specifier: 20.0.0-next.7 + version: 20.0.0-next.7 '@angular/compiler-cli': - specifier: 20.0.0-next.2 - version: 20.0.0-next.2(@angular/compiler@20.0.0-next.2)(typescript@5.8.2) + specifier: 20.0.0-next.7 + version: 20.0.0-next.7(@angular/compiler@20.0.0-next.7)(typescript@5.8.3) '@angular/core': - specifier: 20.0.0-next.2 - version: 20.0.0-next.2(@angular/compiler@20.0.0-next.2)(rxjs@7.8.2)(zone.js@0.15.0) + specifier: 20.0.0-next.7 + version: 20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0) '@angular/forms': - specifier: 20.0.0-next.2 - version: 20.0.0-next.2(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2)(@angular/platform-browser@20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2))(rxjs@7.8.2) + specifier: 20.0.0-next.7 + version: 20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.0.0-next.7(@angular/animations@20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2) '@angular/localize': - specifier: 20.0.0-next.2 - version: 20.0.0-next.2(@angular/compiler-cli@20.0.0-next.2(@angular/compiler@20.0.0-next.2)(typescript@5.8.2))(@angular/compiler@20.0.0-next.2) + specifier: 20.0.0-next.7 + version: 20.0.0-next.7(@angular/compiler-cli@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(typescript@5.8.3))(@angular/compiler@20.0.0-next.7) '@angular/material': - specifier: 20.0.0-next.1 - version: 20.0.0-next.1(@angular/cdk@20.0.0-next.1(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2)(@angular/forms@20.0.0-next.2(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2)(@angular/platform-browser@20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2))(rxjs@7.8.2))(@angular/platform-browser@20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2))(rxjs@7.8.2) + specifier: 20.0.0-next.7 + version: 20.0.0-next.7(ozjl26epfqhdomh6tzbizc4svy) '@angular/ng-dev': - specifier: https://github.com/angular/dev-infra-private-ng-dev-builds.git#9fd3adb2e8b9a0fef1ba5bc905a900e018445e05 - version: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/9fd3adb2e8b9a0fef1ba5bc905a900e018445e05(encoding@0.1.13) + specifier: https://github.com/angular/dev-infra-private-ng-dev-builds.git#94729f43b53fb611c71c695733d2fb3d873cd25d + version: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/94729f43b53fb611c71c695733d2fb3d873cd25d(encoding@0.1.13) '@angular/platform-browser': - specifier: 20.0.0-next.2 - version: 20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2) - '@angular/platform-browser-dynamic': - specifier: 20.0.0-next.2 - version: 20.0.0-next.2(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/compiler@20.0.0-next.2)(@angular/core@20.0.0-next.2)(@angular/platform-browser@20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2)) + specifier: 20.0.0-next.7 + version: 20.0.0-next.7(@angular/animations@20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)) '@angular/platform-server': - specifier: 20.0.0-next.2 - version: 20.0.0-next.2(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/compiler@20.0.0-next.2)(@angular/core@20.0.0-next.2)(@angular/platform-browser@20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2))(rxjs@7.8.2) + specifier: 20.0.0-next.7 + version: 20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/compiler@20.0.0-next.7)(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.0.0-next.7(@angular/animations@20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2) '@angular/router': - specifier: 20.0.0-next.2 - version: 20.0.0-next.2(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2)(@angular/platform-browser@20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2))(rxjs@7.8.2) + specifier: 20.0.0-next.7 + version: 20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.0.0-next.7(@angular/animations@20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2) '@angular/service-worker': - specifier: 20.0.0-next.2 - version: 20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2) - '@babel/core': - specifier: 7.26.10 - version: 7.26.10 - '@babel/generator': - specifier: 7.26.10 - version: 7.26.10 - '@babel/helper-annotate-as-pure': - specifier: 7.25.9 - version: 7.25.9 - '@babel/helper-split-export-declaration': - specifier: 7.24.7 - version: 7.24.7 - '@babel/plugin-syntax-import-attributes': - specifier: 7.26.0 - version: 7.26.0(@babel/core@7.26.10) - '@babel/plugin-transform-async-generator-functions': - specifier: 7.26.8 - version: 7.26.8(@babel/core@7.26.10) - '@babel/plugin-transform-async-to-generator': - specifier: 7.25.9 - version: 7.25.9(@babel/core@7.26.10) - '@babel/plugin-transform-runtime': - specifier: 7.26.10 - version: 7.26.10(@babel/core@7.26.10) - '@babel/preset-env': - specifier: 7.26.9 - version: 7.26.9(@babel/core@7.26.10) - '@babel/runtime': - specifier: 7.26.10 - version: 7.26.10 + specifier: 20.0.0-next.7 + version: 20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) '@bazel/bazelisk': - specifier: 1.25.0 - version: 1.25.0 + specifier: 1.26.0 + version: 1.26.0 '@bazel/buildifier': specifier: 8.0.3 version: 8.0.3 - '@discoveryjs/json-ext': - specifier: 0.6.3 - version: 0.6.3 '@eslint/compat': - specifier: 1.2.7 - version: 1.2.7(eslint@9.22.0(jiti@1.21.7)) + specifier: 1.2.8 + version: 1.2.8(eslint@9.24.0(jiti@1.21.7)) '@eslint/eslintrc': - specifier: 3.3.0 - version: 3.3.0 + specifier: 3.3.1 + version: 3.3.1 '@eslint/js': - specifier: 9.22.0 - version: 9.22.0 - '@inquirer/prompts': - specifier: 7.3.3 - version: 7.3.3(@types/node@20.17.24) - '@listr2/prompt-adapter-inquirer': - specifier: 2.0.18 - version: 2.0.18(@inquirer/prompts@7.3.3(@types/node@20.17.24)) + specifier: 9.24.0 + version: 9.24.0 '@rollup/plugin-alias': specifier: ^5.1.1 - version: 5.1.1(rollup@4.35.0) + version: 5.1.1(rollup@4.40.0) '@rollup/plugin-commonjs': specifier: ^28.0.0 - version: 28.0.3(rollup@4.35.0) + version: 28.0.3(rollup@4.40.0) '@rollup/plugin-json': specifier: ^6.1.0 - version: 6.1.0(rollup@4.35.0) + version: 6.1.0(rollup@4.40.0) '@rollup/plugin-node-resolve': - specifier: ^13.0.5 - version: 13.3.0(rollup@4.35.0) + specifier: 16.0.1 + version: 16.0.1(rollup@4.40.0) '@stylistic/eslint-plugin': specifier: ^4.0.0 - version: 4.2.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.8.2) + version: 4.2.0(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3) '@types/babel__core': specifier: 7.20.5 version: 7.20.5 '@types/babel__generator': specifier: ^7.6.8 - version: 7.6.8 + version: 7.27.0 '@types/browser-sync': specifier: ^2.27.0 version: 2.29.0 '@types/express': - specifier: ^4.16.0 - version: 4.17.21 + specifier: ~5.0.1 + version: 5.0.1 '@types/http-proxy': specifier: ^1.17.4 version: 1.17.16 @@ -169,7 +124,7 @@ importers: version: 4.17.16 '@types/node': specifier: ^20.17.19 - version: 20.17.24 + version: 20.17.30 '@types/npm-package-arg': specifier: ^6.1.0 version: 6.1.4 @@ -177,8 +132,8 @@ importers: specifier: ^11.1.3 version: 11.1.8 '@types/picomatch': - specifier: ^3.0.0 - version: 3.0.2 + specifier: ^4.0.0 + version: 4.0.0 '@types/progress': specifier: ^2.0.3 version: 2.0.7 @@ -187,7 +142,7 @@ importers: version: 1.20.6 '@types/semver': specifier: ^7.3.12 - version: 7.5.8 + version: 7.7.0 '@types/shelljs': specifier: ^0.8.11 version: 0.8.15 @@ -204,77 +159,44 @@ importers: specifier: ^1.1.5 version: 1.1.9 '@typescript-eslint/eslint-plugin': - specifier: 8.26.1 - version: 8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.8.2))(eslint@9.22.0(jiti@1.21.7))(typescript@5.8.2) + specifier: 8.30.1 + version: 8.30.1(@typescript-eslint/parser@8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3) '@typescript-eslint/parser': - specifier: 8.26.1 - version: 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.8.2) - '@web/test-runner': - specifier: ^0.20.0 - version: 0.20.0 - '@yarnpkg/lockfile': - specifier: 1.1.0 - version: 1.1.0 + specifier: 8.30.1 + version: 8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3) ajv: specifier: 8.17.1 version: 8.17.1 - ajv-formats: - specifier: 3.0.1 - version: 3.0.1(ajv@8.17.1) ansi-colors: specifier: 4.1.3 version: 4.1.3 - autoprefixer: - specifier: 10.4.21 - version: 10.4.21(postcss@8.5.3) - babel-loader: - specifier: 10.0.0 - version: 10.0.0(@babel/core@7.26.10)(webpack@5.98.0(esbuild@0.25.1)) beasties: - specifier: 0.2.0 - version: 0.2.0 - browser-sync: - specifier: 3.0.3 - version: 3.0.3(debug@4.4.0) - browserslist: - specifier: ^4.21.5 - version: 4.24.4 + specifier: 0.3.2 + version: 0.3.2 buffer: specifier: 6.0.3 version: 6.0.3 - chokidar: - specifier: 4.0.3 - version: 4.0.3 - copy-webpack-plugin: - specifier: 13.0.0 - version: 13.0.0(webpack@5.98.0(esbuild@0.25.1)) - css-loader: - specifier: 7.1.2 - version: 7.1.2(webpack@5.98.0(esbuild@0.25.1)) - debug: - specifier: ^4.1.1 - version: 4.4.0(supports-color@10.0.0) esbuild: - specifier: 0.25.1 - version: 0.25.1 + specifier: 0.25.2 + version: 0.25.2 esbuild-wasm: - specifier: 0.25.1 - version: 0.25.1 + specifier: 0.25.2 + version: 0.25.2 eslint: - specifier: 9.22.0 - version: 9.22.0(jiti@1.21.7) + specifier: 9.24.0 + version: 9.24.0(jiti@1.21.7) eslint-config-prettier: - specifier: 10.1.1 - version: 10.1.1(eslint@9.22.0(jiti@1.21.7)) + specifier: 10.1.2 + version: 10.1.2(eslint@9.24.0(jiti@1.21.7)) eslint-plugin-header: specifier: 3.1.1 - version: 3.1.1(eslint@9.22.0(jiti@1.21.7)) + version: 3.1.1(eslint@9.24.0(jiti@1.21.7)) eslint-plugin-import: specifier: 2.31.0 - version: 2.31.0(@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.8.2))(eslint@9.22.0(jiti@1.21.7)) + version: 2.31.0(@typescript-eslint/parser@8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.24.0(jiti@1.21.7)) express: - specifier: 4.21.2 - version: 4.21.2 + specifier: 5.1.0 + version: 5.1.0 fast-glob: specifier: 3.3.3 version: 3.3.3 @@ -285,20 +207,11 @@ importers: specifier: ^1.18.1 version: 1.18.1(debug@4.4.0) http-proxy-middleware: - specifier: 3.0.3 - version: 3.0.3 - https-proxy-agent: - specifier: 7.0.6 - version: 7.0.6(supports-color@10.0.0) + specifier: 3.0.5 + version: 3.0.5 husky: specifier: 9.1.7 version: 9.1.7 - ini: - specifier: 5.0.0 - version: 5.0.0 - istanbul-lib-instrument: - specifier: 6.0.3 - version: 6.0.3 jasmine: specifier: ~5.6.0 version: 5.6.0 @@ -311,12 +224,9 @@ importers: jasmine-spec-reporter: specifier: ~7.0.0 version: 7.0.0 - jsonc-parser: - specifier: 3.3.1 - version: 3.3.1 karma: specifier: ~6.4.0 - version: 6.4.4(debug@4.4.0) + version: 6.4.4 karma-chrome-launcher: specifier: ~3.2.0 version: 3.2.0 @@ -325,79 +235,25 @@ importers: version: 2.2.1 karma-jasmine: specifier: ~5.1.0 - version: 5.1.0(karma@6.4.4(debug@4.4.0)) + version: 5.1.0(karma@6.4.4) karma-jasmine-html-reporter: specifier: ~2.1.0 - version: 2.1.0(jasmine-core@5.6.0)(karma-jasmine@5.1.0(karma@6.4.4(debug@4.4.0)))(karma@6.4.4(debug@4.4.0)) + version: 2.1.0(jasmine-core@5.6.0)(karma-jasmine@5.1.0(karma@6.4.4))(karma@6.4.4) karma-source-map-support: specifier: 1.4.0 version: 1.4.0 - less: - specifier: 4.2.2 - version: 4.2.2 - less-loader: - specifier: 12.2.0 - version: 12.2.0(less@4.2.2)(webpack@5.98.0(esbuild@0.25.1)) - license-webpack-plugin: - specifier: 4.0.2 - version: 4.0.2(webpack@5.98.0(esbuild@0.25.1)) listr2: - specifier: 8.2.5 - version: 8.2.5 - lmdb: - specifier: 3.2.6 - version: 3.2.6 - loader-utils: - specifier: 3.3.1 - version: 3.3.1 + specifier: 8.3.2 + version: 8.3.2 lodash: specifier: ^4.17.21 version: 4.17.21 magic-string: specifier: 0.30.17 version: 0.30.17 - mini-css-extract-plugin: - specifier: 2.9.2 - version: 2.9.2(webpack@5.98.0(esbuild@0.25.1)) - mrmime: - specifier: 2.0.1 - version: 2.0.1 - ng-packagr: - specifier: 20.0.0-next.1 - version: 20.0.0-next.1(@angular/compiler-cli@20.0.0-next.2(@angular/compiler@20.0.0-next.2)(typescript@5.8.2))(tslib@2.8.1)(typescript@5.8.2) npm: specifier: ^11.0.0 - version: 11.2.0 - npm-package-arg: - specifier: 12.0.2 - version: 12.0.2 - npm-pick-manifest: - specifier: 10.0.0 - version: 10.0.0 - open: - specifier: 10.1.0 - version: 10.1.0 - ora: - specifier: 5.4.1 - version: 5.4.1 - pacote: - specifier: 20.0.0 - version: 20.0.0 - parse5-html-rewriting-stream: - specifier: 7.0.0 - version: 7.0.0 - picomatch: - specifier: 4.0.2 - version: 4.0.2 - piscina: - specifier: 4.8.0 - version: 4.8.0 - postcss: - specifier: 8.5.3 - version: 8.5.3 - postcss-loader: - specifier: 8.1.1 - version: 8.1.1(postcss@8.5.3)(typescript@5.8.2)(webpack@5.98.0(esbuild@0.25.1)) + version: 11.3.0 prettier: specifier: ^3.0.0 version: 3.5.3 @@ -410,99 +266,51 @@ importers: quicktype-core: specifier: 23.0.171 version: 23.0.171(encoding@0.1.13) - resolve-url-loader: - specifier: 5.0.0 - version: 5.0.0 rollup: - specifier: 4.35.0 - version: 4.35.0 + specifier: 4.40.0 + version: 4.40.0 rollup-license-plugin: specifier: ~3.0.1 version: 3.0.2 - rollup-plugin-sourcemaps: - specifier: ^0.6.0 - version: 0.6.3(@types/node@20.17.24)(rollup@4.35.0) - rxjs: - specifier: 7.8.2 - version: 7.8.2 - sass: - specifier: 1.85.1 - version: 1.85.1 - sass-loader: - specifier: 16.0.5 - version: 16.0.5(sass@1.85.1)(webpack@5.98.0(esbuild@0.25.1)) + rollup-plugin-dts: + specifier: 6.2.1 + version: 6.2.1(rollup@4.40.0)(typescript@5.8.3) + rollup-plugin-sourcemaps2: + specifier: 0.5.0 + version: 0.5.0(@types/node@20.17.30)(rollup@4.40.0) semver: specifier: 7.7.1 version: 7.7.1 shelljs: specifier: ^0.9.0 - version: 0.9.1 - source-map: - specifier: 0.7.4 - version: 0.7.4 - source-map-loader: - specifier: 5.0.0 - version: 5.0.0(webpack@5.98.0(esbuild@0.25.1)) + version: 0.9.2 source-map-support: specifier: 0.5.21 version: 0.5.21 - symbol-observable: - specifier: 4.0.0 - version: 4.0.0 tar: specifier: ^7.0.0 version: 7.4.3 - terser: - specifier: 5.39.0 - version: 5.39.0 - tinyglobby: - specifier: 0.2.12 - version: 0.2.12 - tree-kill: - specifier: 1.2.2 - version: 1.2.2 ts-node: specifier: ^10.9.1 - version: 10.9.2(@types/node@20.17.24)(typescript@5.8.2) + version: 10.9.2(@types/node@20.17.30)(typescript@5.8.3) tslib: specifier: 2.8.1 version: 2.8.1 typescript: - specifier: 5.8.2 - version: 5.8.2 + specifier: 5.8.3 + version: 5.8.3 undici: - specifier: 7.5.0 - version: 7.5.0 + specifier: 7.8.0 + version: 7.8.0 unenv: specifier: ^1.10.0 version: 1.10.0 verdaccio: - specifier: 6.0.5 - version: 6.0.5(encoding@0.1.13) + specifier: 6.1.2 + version: 6.1.2(encoding@0.1.13) verdaccio-auth-memory: specifier: ^10.0.0 version: 10.2.2 - watchpack: - specifier: 2.4.2 - version: 2.4.2 - webpack: - specifier: 5.98.0 - version: 5.98.0(esbuild@0.25.1) - webpack-dev-middleware: - specifier: 7.4.2 - version: 7.4.2(webpack@5.98.0(esbuild@0.25.1)) - webpack-dev-server: - specifier: 5.2.0 - version: 5.2.0(debug@4.4.0)(webpack@5.98.0(esbuild@0.25.1)) - webpack-merge: - specifier: 6.0.1 - version: 6.0.1 - webpack-subresource-integrity: - specifier: 5.1.0 - version: 5.1.0(webpack@5.98.0(esbuild@0.25.1)) - yargs: - specifier: 17.7.2 - version: 17.7.2 yargs-parser: specifier: 21.1.1 version: 21.1.1 @@ -529,6 +337,9 @@ importers: '@angular/ssr': specifier: workspace:* version: link:../../../packages/angular/ssr + rxjs: + specifier: 7.8.2 + version: 7.8.2 packages/angular/build: dependencies: @@ -547,33 +358,33 @@ importers: '@babel/helper-split-export-declaration': specifier: 7.24.7 version: 7.24.7 - '@babel/plugin-syntax-import-attributes': - specifier: 7.26.0 - version: 7.26.0(@babel/core@7.26.10) '@inquirer/confirm': - specifier: 5.1.7 - version: 5.1.7(@types/node@20.17.24) + specifier: 5.1.9 + version: 5.1.9(@types/node@20.17.30) '@vitejs/plugin-basic-ssl': specifier: 2.0.0 - version: 2.0.0(vite@6.2.1(@types/node@20.17.24)(jiti@1.21.7)(less@4.2.2)(sass@1.85.1)(terser@5.39.0)(yaml@2.7.0)) + version: 2.0.0(vite@6.2.6(@types/node@20.17.30)(jiti@1.21.7)(less@4.3.0)(sass@1.86.3)(terser@5.39.0)(yaml@2.7.1)) beasties: - specifier: 0.2.0 - version: 0.2.0 + specifier: 0.3.2 + version: 0.3.2 browserslist: specifier: ^4.23.0 version: 4.24.4 esbuild: - specifier: 0.25.1 - version: 0.25.1 + specifier: 0.25.2 + version: 0.25.2 https-proxy-agent: specifier: 7.0.6 version: 7.0.6(supports-color@10.0.0) istanbul-lib-instrument: specifier: 6.0.3 version: 6.0.3 + jsonc-parser: + specifier: 3.3.1 + version: 3.3.1 listr2: - specifier: 8.2.5 - version: 8.2.5 + specifier: 8.3.2 + version: 8.3.2 magic-string: specifier: 0.30.17 version: 0.30.17 @@ -587,14 +398,14 @@ importers: specifier: 4.0.2 version: 4.0.2 piscina: - specifier: 4.8.0 - version: 4.8.0 + specifier: 4.9.2 + version: 4.9.2 rollup: - specifier: 4.35.0 - version: 4.35.0 + specifier: 4.40.0 + version: 4.40.0 sass: - specifier: 1.85.1 - version: 1.85.1 + specifier: 1.86.3 + version: 1.86.3 semver: specifier: 7.7.1 version: 7.7.1 @@ -605,8 +416,8 @@ importers: specifier: 0.2.12 version: 0.2.12 vite: - specifier: 6.2.1 - version: 6.2.1(@types/node@20.17.24)(jiti@1.21.7)(less@4.2.2)(sass@1.85.1)(terser@5.39.0)(yaml@2.7.0) + specifier: 6.2.6 + version: 6.2.6(@types/node@20.17.30)(jiti@1.21.7)(less@4.3.0)(sass@1.86.3)(terser@5.39.0)(yaml@2.7.1) watchpack: specifier: 2.4.2 version: 2.4.2 @@ -621,6 +432,18 @@ importers: '@angular/ssr': specifier: workspace:* version: link:../ssr + less: + specifier: 4.3.0 + version: 4.3.0 + ng-packagr: + specifier: 20.0.0-next.6 + version: 20.0.0-next.6(@angular/compiler-cli@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(typescript@5.8.3))(tslib@2.8.1)(typescript@5.8.3) + postcss: + specifier: 8.5.3 + version: 8.5.3 + rxjs: + specifier: 7.8.2 + version: 7.8.2 packages/angular/cli: dependencies: @@ -634,11 +457,11 @@ importers: specifier: workspace:0.0.0-PLACEHOLDER version: link:../../angular_devkit/schematics '@inquirer/prompts': - specifier: 7.3.3 - version: 7.3.3(@types/node@20.17.24) + specifier: 7.4.1 + version: 7.4.1(@types/node@20.17.30) '@listr2/prompt-adapter-inquirer': - specifier: 2.0.18 - version: 2.0.18(@inquirer/prompts@7.3.3(@types/node@20.17.24)) + specifier: 2.0.21 + version: 2.0.21(@inquirer/prompts@7.4.1(@types/node@20.17.30)) '@schematics/angular': specifier: workspace:0.0.0-PLACEHOLDER version: link:../../schematics/angular @@ -652,8 +475,8 @@ importers: specifier: 3.3.1 version: 3.3.1 listr2: - specifier: 8.2.5 - version: 8.2.5 + specifier: 8.3.2 + version: 8.3.2 npm-package-arg: specifier: 12.0.2 version: 12.0.2 @@ -669,9 +492,6 @@ importers: semver: specifier: 7.7.1 version: 7.7.1 - symbol-observable: - specifier: 4.0.0 - version: 4.0.0 yargs: specifier: 17.7.2 version: 17.7.2 @@ -698,23 +518,23 @@ importers: specifier: workspace:* version: link:../../angular_devkit/schematics '@angular/common': - specifier: 20.0.0-next.2 - version: 20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2) + specifier: 20.0.0-next.7 + version: 20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) '@angular/compiler': - specifier: 20.0.0-next.2 - version: 20.0.0-next.2(@angular/core@20.0.0-next.2) + specifier: 20.0.0-next.7 + version: 20.0.0-next.7 '@angular/core': - specifier: 20.0.0-next.2 - version: 20.0.0-next.2(@angular/compiler@20.0.0-next.2)(rxjs@7.8.2)(zone.js@0.15.0) + specifier: 20.0.0-next.7 + version: 20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0) '@angular/platform-browser': - specifier: 20.0.0-next.2 - version: 20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2) + specifier: 20.0.0-next.7 + version: 20.0.0-next.7(@angular/animations@20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)) '@angular/platform-server': - specifier: 20.0.0-next.2 - version: 20.0.0-next.2(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/compiler@20.0.0-next.2)(@angular/core@20.0.0-next.2)(@angular/platform-browser@20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2))(rxjs@7.8.2) + specifier: 20.0.0-next.7 + version: 20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/compiler@20.0.0-next.7)(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.0.0-next.7(@angular/animations@20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2) '@angular/router': - specifier: 20.0.0-next.2 - version: 20.0.0-next.2(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2)(@angular/platform-browser@20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2))(rxjs@7.8.2) + specifier: 20.0.0-next.7 + version: 20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.0.0-next.7(@angular/animations@20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2) '@schematics/angular': specifier: workspace:* version: link:../../schematics/angular @@ -742,9 +562,6 @@ importers: progress: specifier: 2.0.3 version: 2.0.3 - symbol-observable: - specifier: 4.0.0 - version: 4.0.0 yargs-parser: specifier: 21.1.1 version: 21.1.1 @@ -774,8 +591,8 @@ importers: specifier: 7.26.10 version: 7.26.10 '@babel/generator': - specifier: 7.26.10 - version: 7.26.10 + specifier: 7.27.0 + version: 7.27.0 '@babel/helper-annotate-as-pure': specifier: 7.25.9 version: 7.25.9 @@ -795,8 +612,8 @@ importers: specifier: 7.26.9 version: 7.26.9(@babel/core@7.26.10) '@babel/runtime': - specifier: 7.26.10 - version: 7.26.10 + specifier: 7.27.0 + version: 7.27.0 '@discoveryjs/json-ext': specifier: 0.6.3 version: 0.6.3 @@ -805,7 +622,7 @@ importers: version: link:../../ngtools/webpack '@vitejs/plugin-basic-ssl': specifier: 2.0.0 - version: 2.0.0(vite@6.2.1(@types/node@20.17.24)(jiti@1.21.7)(less@4.2.2)(sass@1.85.1)(terser@5.39.0)(yaml@2.7.0)) + version: 2.0.0(vite@6.2.6(@types/node@20.17.30)(jiti@1.21.7)(less@4.3.0)(sass@1.86.3)(terser@5.39.0)(yaml@2.7.1)) ansi-colors: specifier: 4.1.3 version: 4.1.3 @@ -814,25 +631,25 @@ importers: version: 10.4.21(postcss@8.5.3) babel-loader: specifier: 10.0.0 - version: 10.0.0(@babel/core@7.26.10)(webpack@5.98.0(esbuild@0.25.1)) + version: 10.0.0(@babel/core@7.26.10)(webpack@5.99.5(esbuild@0.25.2)) browserslist: specifier: ^4.21.5 version: 4.24.4 copy-webpack-plugin: specifier: 13.0.0 - version: 13.0.0(webpack@5.98.0(esbuild@0.25.1)) + version: 13.0.0(webpack@5.99.5(esbuild@0.25.2)) css-loader: specifier: 7.1.2 - version: 7.1.2(webpack@5.98.0(esbuild@0.25.1)) + version: 7.1.2(webpack@5.99.5(esbuild@0.25.2)) esbuild-wasm: - specifier: 0.25.1 - version: 0.25.1 + specifier: 0.25.2 + version: 0.25.2 fast-glob: specifier: 3.3.3 version: 3.3.3 http-proxy-middleware: - specifier: 3.0.3 - version: 3.0.3 + specifier: 3.0.5 + version: 3.0.5 istanbul-lib-instrument: specifier: 6.0.3 version: 6.0.3 @@ -843,23 +660,23 @@ importers: specifier: 1.4.0 version: 1.4.0 less: - specifier: 4.2.2 - version: 4.2.2 + specifier: 4.3.0 + version: 4.3.0 less-loader: specifier: 12.2.0 - version: 12.2.0(less@4.2.2)(webpack@5.98.0(esbuild@0.25.1)) + version: 12.2.0(less@4.3.0)(webpack@5.99.5(esbuild@0.25.2)) license-webpack-plugin: specifier: 4.0.2 - version: 4.0.2(webpack@5.98.0(esbuild@0.25.1)) + version: 4.0.2(webpack@5.99.5(esbuild@0.25.2)) loader-utils: specifier: 3.3.1 version: 3.3.1 mini-css-extract-plugin: specifier: 2.9.2 - version: 2.9.2(webpack@5.98.0(esbuild@0.25.1)) + version: 2.9.2(webpack@5.99.5(esbuild@0.25.2)) open: - specifier: 10.1.0 - version: 10.1.0 + specifier: 10.1.1 + version: 10.1.1 ora: specifier: 5.4.1 version: 5.4.1 @@ -867,14 +684,14 @@ importers: specifier: 4.0.2 version: 4.0.2 piscina: - specifier: 4.8.0 - version: 4.8.0 + specifier: 4.9.2 + version: 4.9.2 postcss: specifier: 8.5.3 version: 8.5.3 postcss-loader: specifier: 8.1.1 - version: 8.1.1(postcss@8.5.3)(typescript@5.8.2)(webpack@5.98.0(esbuild@0.25.1)) + version: 8.1.1(postcss@8.5.3)(typescript@5.8.3)(webpack@5.99.5(esbuild@0.25.2)) resolve-url-loader: specifier: 5.0.0 version: 5.0.0 @@ -882,17 +699,17 @@ importers: specifier: 7.8.2 version: 7.8.2 sass: - specifier: 1.85.1 - version: 1.85.1 + specifier: 1.86.3 + version: 1.86.3 sass-loader: specifier: 16.0.5 - version: 16.0.5(sass@1.85.1)(webpack@5.98.0(esbuild@0.25.1)) + version: 16.0.5(sass@1.86.3)(webpack@5.99.5(esbuild@0.25.2)) semver: specifier: 7.7.1 version: 7.7.1 source-map-loader: specifier: 5.0.0 - version: 5.0.0(webpack@5.98.0(esbuild@0.25.1)) + version: 5.0.0(webpack@5.99.5(esbuild@0.25.2)) source-map-support: specifier: 0.5.21 version: 0.5.21 @@ -906,31 +723,40 @@ importers: specifier: 2.8.1 version: 2.8.1 webpack: - specifier: 5.98.0 - version: 5.98.0(esbuild@0.25.1) + specifier: 5.99.5 + version: 5.99.5(esbuild@0.25.2) webpack-dev-middleware: specifier: 7.4.2 - version: 7.4.2(webpack@5.98.0(esbuild@0.25.1)) + version: 7.4.2(webpack@5.99.5(esbuild@0.25.2)) webpack-dev-server: - specifier: 5.2.0 - version: 5.2.0(debug@4.4.0)(webpack@5.98.0(esbuild@0.25.1)) + specifier: 5.2.1 + version: 5.2.1(webpack@5.99.5(esbuild@0.25.2)) webpack-merge: specifier: 6.0.1 version: 6.0.1 webpack-subresource-integrity: specifier: 5.1.0 - version: 5.1.0(webpack@5.98.0(esbuild@0.25.1)) + version: 5.1.0(webpack@5.99.5(esbuild@0.25.2)) optionalDependencies: esbuild: - specifier: 0.25.1 - version: 0.25.1 + specifier: 0.25.2 + version: 0.25.2 devDependencies: '@angular/ssr': specifier: workspace:* version: link:../../angular/ssr + '@web/test-runner': + specifier: 0.20.1 + version: 0.20.1 + browser-sync: + specifier: 3.0.4 + version: 3.0.4 + ng-packagr: + specifier: 20.0.0-next.6 + version: 20.0.0-next.6(@angular/compiler-cli@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(typescript@5.8.3))(tslib@2.8.1)(typescript@5.8.3) undici: - specifier: 7.5.0 - version: 7.5.0 + specifier: 7.8.0 + version: 7.8.0 packages/angular_devkit/build_webpack: dependencies: @@ -948,8 +774,11 @@ importers: specifier: workspace:0.0.0-PLACEHOLDER version: link:../../ngtools/webpack webpack: - specifier: 5.98.0 - version: 5.98.0(esbuild@0.25.1) + specifier: 5.99.5 + version: 5.99.5(esbuild@0.25.2) + webpack-dev-server: + specifier: 5.2.1 + version: 5.2.1(webpack@5.99.5(esbuild@0.25.2)) packages/angular_devkit/core: dependencies: @@ -971,6 +800,10 @@ importers: source-map: specifier: 0.7.4 version: 0.7.4 + devDependencies: + chokidar: + specifier: 4.0.3 + version: 4.0.3 packages/angular_devkit/schematics: dependencies: @@ -999,14 +832,11 @@ importers: specifier: workspace:0.0.0-PLACEHOLDER version: link:../schematics '@inquirer/prompts': - specifier: 7.3.3 - version: 7.3.3(@types/node@20.17.24) + specifier: 7.4.1 + version: 7.4.1(@types/node@20.17.30) ansi-colors: specifier: 4.1.3 version: 4.1.3 - symbol-observable: - specifier: 4.0.0 - version: 4.0.0 yargs-parser: specifier: 21.1.1 version: 21.1.1 @@ -1017,17 +847,17 @@ importers: specifier: workspace:0.0.0-PLACEHOLDER version: link:../../angular_devkit/core '@angular/compiler': - specifier: 20.0.0-next.2 - version: 20.0.0-next.2(@angular/core@20.0.0-next.2) + specifier: 20.0.0-next.7 + version: 20.0.0-next.7 '@angular/compiler-cli': - specifier: 20.0.0-next.2 - version: 20.0.0-next.2(@angular/compiler@20.0.0-next.2)(typescript@5.8.2) + specifier: 20.0.0-next.7 + version: 20.0.0-next.7(@angular/compiler@20.0.0-next.7)(typescript@5.8.3) typescript: - specifier: 5.8.2 - version: 5.8.2 + specifier: 5.8.3 + version: 5.8.3 webpack: - specifier: 5.98.0 - version: 5.98.0(esbuild@0.25.1) + specifier: 5.99.5 + version: 5.99.5(esbuild@0.25.2) packages/schematics/angular: dependencies: @@ -1046,6 +876,12 @@ importers: '@angular-devkit/schematics': specifier: workspace:* version: link:../packages/angular_devkit/schematics + rxjs: + specifier: 7.8.2 + version: 7.8.2 + tree-kill: + specifier: 1.2.2 + version: 1.2.2 packages: @@ -1053,131 +889,118 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@angular/animations@20.0.0-next.2': - resolution: {integrity: sha512-4BDWr2uA/Z67Y2jNoCPius0qSDNNX5ezte2VzK0F7+v54g8FQlzHb2uZuPm7jnKMxOzoHyWHnUq1CGgH15myuQ==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + '@angular/animations@20.0.0-next.7': + resolution: {integrity: sha512-b6kmmP8OPMqWlqP3x19PXoRyE9oqLcTWlo2zj8qPyMuOr8TEZLgY38Fq65nIshmjITQ9/aeaJ4KEa5n+wc7XfA==} + engines: {node: ^20.11.1 || >=22.11.0} peerDependencies: - '@angular/core': 20.0.0-next.2 + '@angular/common': 20.0.0-next.7 + '@angular/core': 20.0.0-next.7 - '@angular/cdk@20.0.0-next.1': - resolution: {integrity: sha512-nm71L2C13lw7zv5BQ30ZeXyUwKHErVYoR02RuDRcGQFh61/PKZNaIaJHOFqgT5bMpPrlbRvUGKgYhbbYYqc44A==} + '@angular/cdk@20.0.0-next.7': + resolution: {integrity: sha512-a8o/WcUnEfEcv/3h6pbnkcG62l79tfWBNtcgPQHuJWNo+12B0kUnFsadkFFoGxeEmNDKNdFFWQYrcG3iWPDgNg==} peerDependencies: '@angular/common': ^20.0.0-0 || ^20.1.0-0 || ^20.2.0-0 || ^20.3.0-0 || ^21.0.0-0 '@angular/core': ^20.0.0-0 || ^20.1.0-0 || ^20.2.0-0 || ^20.3.0-0 || ^21.0.0-0 rxjs: ^6.5.3 || ^7.4.0 - '@angular/common@20.0.0-next.2': - resolution: {integrity: sha512-ojFSGYhIkuxEh6vjSpCiappo6xz1SXtgm5WIaYujzMnorQfeHXViSR2XxoFim5laWmtkO1bxn4udcXRXGwg7bQ==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + '@angular/common@20.0.0-next.7': + resolution: {integrity: sha512-SZvsuEGaScujA0QMYrNQK7NyzZE2t3oRtzQ7fVNXVw5vYhDg+y1VQeuTmexV7/vqJSmnUPxtzvfI5P/qIA/k0A==} + engines: {node: ^20.11.1 || >=22.11.0} peerDependencies: - '@angular/core': 20.0.0-next.2 + '@angular/core': 20.0.0-next.7 rxjs: ^6.5.3 || ^7.4.0 - '@angular/compiler-cli@20.0.0-next.2': - resolution: {integrity: sha512-AzdcEIlRb7Fi+jXRzHVkjx0KRWWnK5gtOPj6/miQvvsSIGQ9afie2ZjGAJUoRgBGLlQ6cpCiEy7FmTKo/22eDw==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + '@angular/compiler-cli@20.0.0-next.7': + resolution: {integrity: sha512-dojYeK3kjaV6XjPusUxHJN/8t7jgxB/W+Qbr071/2et3UjMOkuyPUXhWHWJERCRe8H89Tx21iF2GLoeMxiqSsg==} + engines: {node: ^20.11.1 || >=22.11.0} hasBin: true peerDependencies: - '@angular/compiler': 20.0.0-next.2 - typescript: 5.8.2 + '@angular/compiler': 20.0.0-next.7 + typescript: 5.8.3 - '@angular/compiler@20.0.0-next.2': - resolution: {integrity: sha512-wHXWSpAKqYVklB1c1ju1HBKnW2dnjVm2fYB9TiwEO0vh5LWXYJIF5e7prFZTyUzk0f7p+XCTeAB5nWg2/o02Ig==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} - peerDependencies: - '@angular/core': 20.0.0-next.2 - peerDependenciesMeta: - '@angular/core': - optional: true + '@angular/compiler@20.0.0-next.7': + resolution: {integrity: sha512-aRnY79i+ydt+lgGdqqkhPC7+HsSrPdcda8nfH32Z8FH5RlNrFudHzdiWdWwUUMjuBTJIbjPDZUYr/uyWUa65aQ==} + engines: {node: ^20.11.1 || >=22.11.0} - '@angular/core@20.0.0-next.2': - resolution: {integrity: sha512-nF1yPPXO0EZQmNsvR7p3KCPUnxVQxHEVNIBunBCoOia5DEi9E7l+VkMT/2Bnp/7h/ZCdOst4A3Uj4XqpNhUYtA==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + '@angular/core@20.0.0-next.7': + resolution: {integrity: sha512-kHW+evDiezyQESr48WBv351ORvoeqWSl9SLoh05w4LIXHAmhsKgWhOqV61Ji4zxIcF/A+Bt19vATa59/q5nt0g==} + engines: {node: ^20.11.1 || >=22.11.0} peerDependencies: - '@angular/compiler': 20.0.0-next.2 + '@angular/compiler': 20.0.0-next.7 rxjs: ^6.5.3 || ^7.4.0 zone.js: ~0.15.0 peerDependenciesMeta: '@angular/compiler': optional: true - '@angular/forms@20.0.0-next.2': - resolution: {integrity: sha512-Sd6dq+cAdBIrRlKreNEXTl12aQOnXrTiU108Ll+AnSMdAvpqOqoLWkE5vXAHLXcfS0dacerMVFR2s6+4x3DJJQ==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + '@angular/forms@20.0.0-next.7': + resolution: {integrity: sha512-4oNC7vEWRKPfw0e+2s3TT1gf1pUg/PoajkNyb8MRY6pm5xCO/cVixSejY97I7ftjYd9ksKCzGh2cQs8XlvONsA==} + engines: {node: ^20.11.1 || >=22.11.0} peerDependencies: - '@angular/common': 20.0.0-next.2 - '@angular/core': 20.0.0-next.2 - '@angular/platform-browser': 20.0.0-next.2 + '@angular/common': 20.0.0-next.7 + '@angular/core': 20.0.0-next.7 + '@angular/platform-browser': 20.0.0-next.7 rxjs: ^6.5.3 || ^7.4.0 - '@angular/localize@20.0.0-next.2': - resolution: {integrity: sha512-V9BMrHXfo3HPWp07fbeVgpy4xiMi8bcuTAhxKyKPqXfPA4MX/8Y8FGIYxcTLFqzPNBu+7qe0OgtoQT502MrJjA==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + '@angular/localize@20.0.0-next.7': + resolution: {integrity: sha512-m+Xq1lDhu1H3alNlstL8YDOxluvQTPofA7Xema+RV7nA0j0w50v+zmoGuvDgeOVEvOBeSiqedzYuOxqbAkypag==} + engines: {node: ^20.11.1 || >=22.11.0} hasBin: true peerDependencies: - '@angular/compiler': 20.0.0-next.2 - '@angular/compiler-cli': 20.0.0-next.2 + '@angular/compiler': 20.0.0-next.7 + '@angular/compiler-cli': 20.0.0-next.7 - '@angular/material@20.0.0-next.1': - resolution: {integrity: sha512-otR0S79z5JGFYVV+XbRbDJWF33BK2F/jNKQnjVaVHFaepBU6tLvjYpQL8nM34sXuzAIVrEn/wjv4bAJkxWRXOw==} + '@angular/material@20.0.0-next.7': + resolution: {integrity: sha512-l8k3z6lRWSFef74QZsfouxztKFcOWNEmwvfAmwQIFLllawLEkni4wGt5TrHLxiU9ttxdoSJ0cePEAKmWpkrIAQ==} peerDependencies: - '@angular/cdk': 20.0.0-next.1 + '@angular/cdk': 20.0.0-next.7 '@angular/common': ^20.0.0-0 || ^20.1.0-0 || ^20.2.0-0 || ^20.3.0-0 || ^21.0.0-0 '@angular/core': ^20.0.0-0 || ^20.1.0-0 || ^20.2.0-0 || ^20.3.0-0 || ^21.0.0-0 '@angular/forms': ^20.0.0-0 || ^20.1.0-0 || ^20.2.0-0 || ^20.3.0-0 || ^21.0.0-0 '@angular/platform-browser': ^20.0.0-0 || ^20.1.0-0 || ^20.2.0-0 || ^20.3.0-0 || ^21.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/9fd3adb2e8b9a0fef1ba5bc905a900e018445e05': - resolution: {tarball: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/9fd3adb2e8b9a0fef1ba5bc905a900e018445e05} - version: 0.0.0-47572aba6019f368057c00966ac7ce354b1d65bc + '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/94729f43b53fb611c71c695733d2fb3d873cd25d': + resolution: {tarball: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/94729f43b53fb611c71c695733d2fb3d873cd25d} + version: 0.0.0-64d0e9da9c4309a5a05f6c0a05383203a46a700d hasBin: true - '@angular/platform-browser-dynamic@20.0.0-next.2': - resolution: {integrity: sha512-S1BH1LPVdc3nspXwzPPIgc/U5ZMidzzJ7bSO8+9bmWtfsMgC8dLFjXnUbEmprwJe/Lw8l6lODTnfBgZXfsSo1w==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} - peerDependencies: - '@angular/common': 20.0.0-next.2 - '@angular/compiler': 20.0.0-next.2 - '@angular/core': 20.0.0-next.2 - '@angular/platform-browser': 20.0.0-next.2 - - '@angular/platform-browser@20.0.0-next.2': - resolution: {integrity: sha512-JXmDlUcq4pPHznyKVf4XtsWn7syt1X+zQCNdef+e7ZHwixFlsJtD+akj1bF8mhXvd2YACgkgN0sXGPiGZTHeBQ==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + '@angular/platform-browser@20.0.0-next.7': + resolution: {integrity: sha512-PwEbfDfY/RiOVa7XP/EoNJkYiZZWF4TYuCoE6sibyKLGnhPeSQ6235HmNNpV+exSlHV8bg9noIA4SBiHm7X1eA==} + engines: {node: ^20.11.1 || >=22.11.0} peerDependencies: - '@angular/animations': 20.0.0-next.2 - '@angular/common': 20.0.0-next.2 - '@angular/core': 20.0.0-next.2 + '@angular/animations': 20.0.0-next.7 + '@angular/common': 20.0.0-next.7 + '@angular/core': 20.0.0-next.7 peerDependenciesMeta: '@angular/animations': optional: true - '@angular/platform-server@20.0.0-next.2': - resolution: {integrity: sha512-JxWC2cEceHZH7CZ+IzdwffvFvkhHKiYkdqZU2+Fy1a9piqnpm4abE02ayXhAhw1xt80BZNYr9Q8xBO2QNwGIrA==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + '@angular/platform-server@20.0.0-next.7': + resolution: {integrity: sha512-SkOas/BtiWv8shmBSO9l7MIZYy5ypE4DkDUYNS9XotSwttet9zKaZTAv7qlr9e8LMZ6nhYwn8aV8qRJ0Nw5i0g==} + engines: {node: ^20.11.1 || >=22.11.0} peerDependencies: - '@angular/common': 20.0.0-next.2 - '@angular/compiler': 20.0.0-next.2 - '@angular/core': 20.0.0-next.2 - '@angular/platform-browser': 20.0.0-next.2 + '@angular/common': 20.0.0-next.7 + '@angular/compiler': 20.0.0-next.7 + '@angular/core': 20.0.0-next.7 + '@angular/platform-browser': 20.0.0-next.7 rxjs: ^6.5.3 || ^7.4.0 - '@angular/router@20.0.0-next.2': - resolution: {integrity: sha512-WdykD+USpP/Wxcv2fwASFuHUAU6pflSs4gFjT6hoXVOrN5JzSzBo4abE4Jn7S3i+LBV+znUeUHs0wx/mwsq2Ww==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + '@angular/router@20.0.0-next.7': + resolution: {integrity: sha512-/OHtqLjuitM4YU4hHDTzBoaWqT3ZaS03pAJNE6G/WQWmpoZbEgOTV2AY+AW8nrucyrTgn9YaDepDPPwUrAcIjg==} + engines: {node: ^20.11.1 || >=22.11.0} peerDependencies: - '@angular/common': 20.0.0-next.2 - '@angular/core': 20.0.0-next.2 - '@angular/platform-browser': 20.0.0-next.2 + '@angular/common': 20.0.0-next.7 + '@angular/core': 20.0.0-next.7 + '@angular/platform-browser': 20.0.0-next.7 rxjs: ^6.5.3 || ^7.4.0 - '@angular/service-worker@20.0.0-next.2': - resolution: {integrity: sha512-YH817tESXCUWIaSUBDUYNTqIUcXUqD7mG/WJI94de2hyCIaYBhxMyqo+IM/7OOKR0y44S5yzLJ4eGUyh5JUeiA==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + '@angular/service-worker@20.0.0-next.7': + resolution: {integrity: sha512-iYHkRowt541oPc/B46x7XSanvCRvys3/Fm6dkyFOSrtywl6egYEoOuiMEYP73zE9lMQgGSIrBj5uMgZXXFCEeQ==} + engines: {node: ^20.11.1 || >=22.11.0} hasBin: true peerDependencies: - '@angular/core': 20.0.0-next.2 + '@angular/core': 20.0.0-next.7 rxjs: ^6.5.3 || ^7.4.0 '@babel/code-frame@7.26.2': @@ -1192,36 +1015,32 @@ packages: resolution: {integrity: sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==} engines: {node: '>=6.9.0'} - '@babel/core@7.26.9': - resolution: {integrity: sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==} - engines: {node: '>=6.9.0'} - - '@babel/generator@7.26.10': - resolution: {integrity: sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==} + '@babel/generator@7.27.0': + resolution: {integrity: sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==} engines: {node: '>=6.9.0'} '@babel/helper-annotate-as-pure@7.25.9': resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.26.5': - resolution: {integrity: sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==} + '@babel/helper-compilation-targets@7.27.0': + resolution: {integrity: sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==} engines: {node: '>=6.9.0'} - '@babel/helper-create-class-features-plugin@7.26.9': - resolution: {integrity: sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg==} + '@babel/helper-create-class-features-plugin@7.27.0': + resolution: {integrity: sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-create-regexp-features-plugin@7.26.3': - resolution: {integrity: sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==} + '@babel/helper-create-regexp-features-plugin@7.27.0': + resolution: {integrity: sha512-fO8l08T76v48BhpNRW/nQ0MxfnSdoSKUJBMjubOAYffsVuGG5qOfMq7N6Es7UJvi7Y8goXXo07EfcHZXDPuELQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-define-polyfill-provider@0.6.3': - resolution: {integrity: sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==} + '@babel/helper-define-polyfill-provider@0.6.4': + resolution: {integrity: sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 @@ -1283,17 +1102,12 @@ packages: resolution: {integrity: sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.26.10': - resolution: {integrity: sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==} + '@babel/helpers@7.27.0': + resolution: {integrity: sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==} engines: {node: '>=6.9.0'} - '@babel/parser@7.26.10': - resolution: {integrity: sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/parser@7.26.9': - resolution: {integrity: sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==} + '@babel/parser@7.27.0': + resolution: {integrity: sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==} engines: {node: '>=6.0.0'} hasBin: true @@ -1375,8 +1189,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-block-scoping@7.25.9': - resolution: {integrity: sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==} + '@babel/plugin-transform-block-scoping@7.27.0': + resolution: {integrity: sha512-u1jGphZ8uDI2Pj/HJj6YQ6XQLZCNjOlprjxB5SVz6rq2T6SwAR+CdrWK0CP7F+9rDVMXdB0+r6Am5G5aobOjAQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1579,8 +1393,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-regenerator@7.25.9': - resolution: {integrity: sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==} + '@babel/plugin-transform-regenerator@7.27.0': + resolution: {integrity: sha512-LX/vCajUJQDqE7Aum/ELUMZAY19+cDpghxrnyt5I1tV6X5PyC86AOoWXWFYFeIvauyeSA6/ktn4tQVn/3ZifsA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1627,8 +1441,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-typeof-symbol@7.26.7': - resolution: {integrity: sha512-jfoTXXZTgGg36BmhqT3cAYK5qkmqvJpvNrPhaK/52Vgjhw4Rq29s9UqpWWV0D6yuRmgiFH/BUVlkl96zJWqnaw==} + '@babel/plugin-transform-typeof-symbol@7.27.0': + resolution: {integrity: sha512-+LLkxA9rKJpNoGsbLnAgOCdESl73vwYn+V6b+5wHbrE7OGKVDPHIQvbFSzqE6rwqaCw2RE+zdJrlLkcf8YOA0w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1668,32 +1482,24 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 - '@babel/runtime@7.26.10': - resolution: {integrity: sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==} + '@babel/runtime@7.27.0': + resolution: {integrity: sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==} engines: {node: '>=6.9.0'} - '@babel/template@7.26.9': - resolution: {integrity: sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==} + '@babel/template@7.27.0': + resolution: {integrity: sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.26.10': - resolution: {integrity: sha512-k8NuDrxr0WrPH5Aupqb2LCVURP/S0vBEn5mK6iH+GIYob66U5EtoZvcdudR2jQ4cmTwhEwW1DLB+Yyas9zjF6A==} + '@babel/traverse@7.27.0': + resolution: {integrity: sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.26.9': - resolution: {integrity: sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==} + '@babel/types@7.27.0': + resolution: {integrity: sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==} engines: {node: '>=6.9.0'} - '@babel/types@7.26.10': - resolution: {integrity: sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.26.9': - resolution: {integrity: sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==} - engines: {node: '>=6.9.0'} - - '@bazel/bazelisk@1.25.0': - resolution: {integrity: sha512-IgesSUh9EwwLI9+Vs5rb/sx7vh6cI97CRLPqw9+/egFzeZlB5S2fTsKwbdDxtTVPjQMGS3GY64tTNsgejVFeKg==} + '@bazel/bazelisk@1.26.0': + resolution: {integrity: sha512-bTNcHdGyEQ9r7SczEYUa0gkEQhJo1ld2BjXI8fWBvsUeoHi03QpUs2HZgDbjjrpQFQqG2ZbO7ihZvH8MjhUTHw==} hasBin: true '@bazel/buildifier@8.0.3': @@ -1708,166 +1514,166 @@ packages: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} - '@cypress/request@3.0.7': - resolution: {integrity: sha512-LzxlLEMbBOPYB85uXrDqvD4MgcenjRBLIns3zyhx7vTPj/0u2eQhzXvPiGcaJrV38Q9dbkExWp6cOHPJ+EtFYg==} + '@cypress/request@3.0.8': + resolution: {integrity: sha512-h0NFgh1mJmm1nr4jCwkGHwKneVYKghUyWe6TMNrk0B9zsjAJxpg8C4/+BAcmLgCPa1vj1V8rNUaILl+zYRUWBQ==} engines: {node: '>= 6'} '@discoveryjs/json-ext@0.6.3': resolution: {integrity: sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==} engines: {node: '>=14.17.0'} - '@esbuild/aix-ppc64@0.25.1': - resolution: {integrity: sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==} + '@esbuild/aix-ppc64@0.25.2': + resolution: {integrity: sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.25.1': - resolution: {integrity: sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==} + '@esbuild/android-arm64@0.25.2': + resolution: {integrity: sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.25.1': - resolution: {integrity: sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==} + '@esbuild/android-arm@0.25.2': + resolution: {integrity: sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.25.1': - resolution: {integrity: sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==} + '@esbuild/android-x64@0.25.2': + resolution: {integrity: sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.25.1': - resolution: {integrity: sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==} + '@esbuild/darwin-arm64@0.25.2': + resolution: {integrity: sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.25.1': - resolution: {integrity: sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==} + '@esbuild/darwin-x64@0.25.2': + resolution: {integrity: sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.25.1': - resolution: {integrity: sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==} + '@esbuild/freebsd-arm64@0.25.2': + resolution: {integrity: sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.1': - resolution: {integrity: sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==} + '@esbuild/freebsd-x64@0.25.2': + resolution: {integrity: sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.25.1': - resolution: {integrity: sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==} + '@esbuild/linux-arm64@0.25.2': + resolution: {integrity: sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.25.1': - resolution: {integrity: sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==} + '@esbuild/linux-arm@0.25.2': + resolution: {integrity: sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.25.1': - resolution: {integrity: sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==} + '@esbuild/linux-ia32@0.25.2': + resolution: {integrity: sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.25.1': - resolution: {integrity: sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==} + '@esbuild/linux-loong64@0.25.2': + resolution: {integrity: sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.25.1': - resolution: {integrity: sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==} + '@esbuild/linux-mips64el@0.25.2': + resolution: {integrity: sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.25.1': - resolution: {integrity: sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==} + '@esbuild/linux-ppc64@0.25.2': + resolution: {integrity: sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.25.1': - resolution: {integrity: sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==} + '@esbuild/linux-riscv64@0.25.2': + resolution: {integrity: sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.25.1': - resolution: {integrity: sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==} + '@esbuild/linux-s390x@0.25.2': + resolution: {integrity: sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.25.1': - resolution: {integrity: sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==} + '@esbuild/linux-x64@0.25.2': + resolution: {integrity: sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.1': - resolution: {integrity: sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==} + '@esbuild/netbsd-arm64@0.25.2': + resolution: {integrity: sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.1': - resolution: {integrity: sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==} + '@esbuild/netbsd-x64@0.25.2': + resolution: {integrity: sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.1': - resolution: {integrity: sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==} + '@esbuild/openbsd-arm64@0.25.2': + resolution: {integrity: sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.1': - resolution: {integrity: sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==} + '@esbuild/openbsd-x64@0.25.2': + resolution: {integrity: sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/sunos-x64@0.25.1': - resolution: {integrity: sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==} + '@esbuild/sunos-x64@0.25.2': + resolution: {integrity: sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.25.1': - resolution: {integrity: sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==} + '@esbuild/win32-arm64@0.25.2': + resolution: {integrity: sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.25.1': - resolution: {integrity: sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==} + '@esbuild/win32-ia32@0.25.2': + resolution: {integrity: sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.25.1': - resolution: {integrity: sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==} + '@esbuild/win32-x64@0.25.2': + resolution: {integrity: sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==} engines: {node: '>=18'} cpu: [x64] os: [win32] - '@eslint-community/eslint-utils@4.5.0': - resolution: {integrity: sha512-RoV8Xs9eNwiDvhv7M+xcL4PWyRyIXRY/FLp3buU4h1EYfdF7unWUy3dOjPqb3C7rMUewIcqwW850PgS8h1o1yg==} + '@eslint-community/eslint-utils@4.6.0': + resolution: {integrity: sha512-WhCn7Z7TauhBtmzhvKpoQs0Wwb/kBcy4CwpuI0/eEIr2Lx2auxmulAzLr91wVZJaz47iUZdkXOK7WlAfxGKCnA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 @@ -1876,8 +1682,8 @@ packages: resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/compat@1.2.7': - resolution: {integrity: sha512-xvv7hJE32yhegJ8xNAnb62ggiAwTYHBpUCWhRxEj/ksvgDJuSXfoDkBcRYaYNFiJ+jH0IE3K16hd+xXzhBgNbg==} + '@eslint/compat@1.2.8': + resolution: {integrity: sha512-LqCYHdWL/QqKIJuZ/ucMAv8d4luKGs4oCPgpt8mWztQAtPrHfXKQ/XAUc8ljCHAfJCn6SvkpTcGt5Tsh8saowA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^9.10.0 @@ -1885,32 +1691,36 @@ packages: eslint: optional: true - '@eslint/config-array@0.19.2': - resolution: {integrity: sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==} + '@eslint/config-array@0.20.0': + resolution: {integrity: sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/config-helpers@0.1.0': - resolution: {integrity: sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA==} + '@eslint/config-helpers@0.2.1': + resolution: {integrity: sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/core@0.12.0': resolution: {integrity: sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/eslintrc@3.3.0': - resolution: {integrity: sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==} + '@eslint/core@0.13.0': + resolution: {integrity: sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.1': + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.22.0': - resolution: {integrity: sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==} + '@eslint/js@9.24.0': + resolution: {integrity: sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.6': resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/plugin-kit@0.2.7': - resolution: {integrity: sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==} + '@eslint/plugin-kit@0.2.8': + resolution: {integrity: sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@glideapps/ts-necessities@2.2.3': @@ -1932,12 +1742,12 @@ packages: resolution: {integrity: sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==} engines: {node: '>=14'} - '@google-cloud/spanner@7.19.0': - resolution: {integrity: sha512-EQUGFc6l5h4spSbVKtURt+6OY+vFkACkXvdcDFISwB2++VWigeTOE0gFVJMUrko0HaKxOKfWW80+GYZCUToTcA==} + '@google-cloud/spanner@7.19.1': + resolution: {integrity: sha512-a7WlM4T3g5hslSBxQpsCxlH2IGgeVVEnDP5/v51kNlKv/W5PhBMqaHanodkUjbjegsQNlWAkqLClzIwtldfSXg==} engines: {node: '>=14.0.0'} - '@grpc/grpc-js@1.12.6': - resolution: {integrity: sha512-JXUj6PI0oqqzTGvKtzOkxtpsyPRNsrmhh41TtIz/zEB6J+AUiZZ0dxWzcMwO9Ns5rmSPuMdghlTbUuqIM48d3Q==} + '@grpc/grpc-js@1.13.3': + resolution: {integrity: sha512-FTXHdOoPbZrBjlVLHuKbDZnsTxXv2BlHF57xw6LuThXacXvtkahEPED0CKMk6obZDf65Hv4k3z62eyPNpvinIg==} engines: {node: '>=12.10.0'} '@grpc/proto-loader@0.7.13': @@ -1968,8 +1778,8 @@ packages: resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==} engines: {node: '>=18.18'} - '@inquirer/checkbox@4.1.3': - resolution: {integrity: sha512-KU1MGwf24iABJjGESxhyj+/rlQYSRoCfcuHDEHXfZ1DENmbuSRfyrUb+LLjHoee5TNOFKwaFxDXc5/zRwJUPMQ==} + '@inquirer/checkbox@4.1.5': + resolution: {integrity: sha512-swPczVU+at65xa5uPfNP9u3qx/alNwiaykiI/ExpsmMSQW55trmZcwhYWzw/7fj+n6Q8z1eENvR7vFfq9oPSAQ==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -1977,8 +1787,8 @@ packages: '@types/node': optional: true - '@inquirer/confirm@5.1.7': - resolution: {integrity: sha512-Xrfbrw9eSiHb+GsesO8TQIeHSMTP0xyvTCeeYevgZ4sKW+iz9w/47bgfG9b0niQm+xaLY2EWPBINUPldLwvYiw==} + '@inquirer/confirm@5.1.9': + resolution: {integrity: sha512-NgQCnHqFTjF7Ys2fsqK2WtnA8X1kHyInyG+nMIuHowVTIgIuS10T4AznI/PvbqSpJqjCUqNBlKGh1v3bwLFL4w==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -1986,8 +1796,8 @@ packages: '@types/node': optional: true - '@inquirer/core@10.1.8': - resolution: {integrity: sha512-HpAqR8y715zPpM9e/9Q+N88bnGwqqL8ePgZ0SMv/s3673JLMv3bIkoivGmjPqXlEgisUksSXibweQccUwEx4qQ==} + '@inquirer/core@10.1.10': + resolution: {integrity: sha512-roDaKeY1PYY0aCqhRmXihrHjoSW2A00pV3Ke5fTpMCkzcGF64R8e0lw3dK+eLEHwS4vB5RnW1wuQmvzoRul8Mw==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -1995,8 +1805,8 @@ packages: '@types/node': optional: true - '@inquirer/editor@4.2.8': - resolution: {integrity: sha512-UkGKbMFlQw5k4ZLjDwEi5z8NIVlP/3DAlLHta0o0pSsdpPThNmPtUL8mvGCHUaQtR+QrxR9yRYNWgKMsHkfIUA==} + '@inquirer/editor@4.2.10': + resolution: {integrity: sha512-5GVWJ+qeI6BzR6TIInLP9SXhWCEcvgFQYmcRG6d6RIlhFjM5TyG18paTGBgRYyEouvCmzeco47x9zX9tQEofkw==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -2004,8 +1814,8 @@ packages: '@types/node': optional: true - '@inquirer/expand@4.0.10': - resolution: {integrity: sha512-leyBouGJ77ggv51Jb/OJmLGGnU2HYc13MZ2iiPNLwe2VgFgZPVqsrRWSa1RAHKyazjOyvSNKLD1B2K7A/iWi1g==} + '@inquirer/expand@4.0.12': + resolution: {integrity: sha512-jV8QoZE1fC0vPe6TnsOfig+qwu7Iza1pkXoUJ3SroRagrt2hxiL+RbM432YAihNR7m7XnU0HWl/WQ35RIGmXHw==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -2017,8 +1827,8 @@ packages: resolution: {integrity: sha512-eOg92lvrn/aRUqbxRyvpEWnrvRuTYRifixHkYVpJiygTgVSBIHDqLh0SrMQXkafvULg3ck11V7xvR+zcgvpHFw==} engines: {node: '>=18'} - '@inquirer/input@4.1.7': - resolution: {integrity: sha512-rCQAipJNA14UTH84df/z4jDJ9LZ54H6zzuCAi7WZ0qVqx3CSqLjfXAMd5cpISIxbiHVJCPRB81gZksq6CZsqDg==} + '@inquirer/input@4.1.9': + resolution: {integrity: sha512-mshNG24Ij5KqsQtOZMgj5TwEjIf+F2HOESk6bjMwGWgcH5UBe8UoljwzNFHqdMbGYbgAf6v2wU/X9CAdKJzgOA==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -2026,8 +1836,8 @@ packages: '@types/node': optional: true - '@inquirer/number@3.0.10': - resolution: {integrity: sha512-GLsdnxzNefjCJUmWyjaAuNklHgDpCTL4RMllAVhVvAzBwRW9g38eZ5tWgzo1lirtSDTpsh593hqXVhxvdrjfwA==} + '@inquirer/number@3.0.12': + resolution: {integrity: sha512-7HRFHxbPCA4e4jMxTQglHJwP+v/kpFsCf2szzfBHy98Wlc3L08HL76UDiA87TOdX5fwj2HMOLWqRWv9Pnn+Z5Q==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -2035,8 +1845,8 @@ packages: '@types/node': optional: true - '@inquirer/password@4.0.10': - resolution: {integrity: sha512-JC538ujqeYKkFqLoWZ0ILBteIUO2yajBMVEUZSxjl9x6fiEQtM+I5Rca7M2D8edMDbyHLnXifGH1hJZdh8V5rA==} + '@inquirer/password@4.0.12': + resolution: {integrity: sha512-FlOB0zvuELPEbnBYiPaOdJIaDzb2PmJ7ghi/SVwIHDDSQ2K4opGBkF+5kXOg6ucrtSUQdLhVVY5tycH0j0l+0g==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -2044,8 +1854,8 @@ packages: '@types/node': optional: true - '@inquirer/prompts@7.3.3': - resolution: {integrity: sha512-QS1AQgJ113iE/nmym03yKZKHvGjVWwkGZT3B1yKrrMG0bJKQg1jUkntFP8aPd2FUQzu/nga7QU2eDpzIP5it0Q==} + '@inquirer/prompts@7.4.1': + resolution: {integrity: sha512-UlmM5FVOZF0gpoe1PT/jN4vk8JmpIWBlMvTL8M+hlvPmzN89K6z03+IFmyeu/oFCenwdwHDr2gky7nIGSEVvlA==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -2053,8 +1863,8 @@ packages: '@types/node': optional: true - '@inquirer/rawlist@4.0.10': - resolution: {integrity: sha512-vOQbQkmhaCsF2bUmjoyRSZJBz77UnIF/F3ZS2LMgwbgyaG2WgwKHh0WKNj0APDB72WDbZijhW5nObQbk+TnbcA==} + '@inquirer/rawlist@4.0.12': + resolution: {integrity: sha512-wNPJZy8Oc7RyGISPxp9/MpTOqX8lr0r+lCCWm7hQra+MDtYRgINv1hxw7R+vKP71Bu/3LszabxOodfV/uTfsaA==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -2062,8 +1872,8 @@ packages: '@types/node': optional: true - '@inquirer/search@3.0.10': - resolution: {integrity: sha512-EAVKAz6P1LajZOdoL+R+XC3HJYSU261fbJzO4fCkJJ7UPFcm+nP+gzC+DDZWsb2WK9PQvKsnaKiNKsY8B6dBWQ==} + '@inquirer/search@3.0.12': + resolution: {integrity: sha512-H/kDJA3kNlnNIjB8YsaXoQI0Qccgf0Na14K1h8ExWhNmUg2E941dyFPrZeugihEa9AZNW5NdsD/NcvUME83OPQ==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -2071,8 +1881,8 @@ packages: '@types/node': optional: true - '@inquirer/select@4.0.10': - resolution: {integrity: sha512-Tg8S9nESnCfISu5tCZSuXpXq0wHuDVimj7xyHstABgR34zcJnLdq/VbjB2mdZvNAMAehYBnNzSjxB06UE8LLAA==} + '@inquirer/select@4.1.1': + resolution: {integrity: sha512-IUXzzTKVdiVNMA+2yUvPxWsSgOG4kfX93jOM4Zb5FgujeInotv5SPIJVeXQ+fO4xu7tW8VowFhdG5JRmmCyQ1Q==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -2084,8 +1894,8 @@ packages: resolution: {integrity: sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA==} engines: {node: '>=18'} - '@inquirer/type@3.0.5': - resolution: {integrity: sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg==} + '@inquirer/type@3.0.6': + resolution: {integrity: sha512-/mKVCtVpyBu3IDarv0G+59KC4stsD5mDsGpYh+GKs1NZT88Jh52+cuoA1AtLk2Q0r/quNl+1cSUyLRHBFeD0XA==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -2153,8 +1963,8 @@ packages: '@leichtgewicht/ip-codec@2.0.5': resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==} - '@listr2/prompt-adapter-inquirer@2.0.18': - resolution: {integrity: sha512-0hz44rAcrphyXcA8IS7EJ2SCoaBZD2u5goE8S/e+q/DL+dOGpqpcLidVOFeLG3VgML62SXmfRLAhWt0zL1oW4Q==} + '@listr2/prompt-adapter-inquirer@2.0.21': + resolution: {integrity: sha512-can62OlOPusZwYfKfd0SV6znsSFbiuJw/lvvRSAAdzqUCTE/Vn8FydLGAfEvGbDALdfqvazSj6tnVJKQxj9iXw==} engines: {node: '>=18.0.0'} peerDependencies: '@inquirer/prompts': '>= 3 < 8' @@ -2372,23 +2182,26 @@ packages: resolution: {integrity: sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==} engines: {node: '>= 18'} - '@octokit/core@6.1.4': - resolution: {integrity: sha512-lAS9k7d6I0MPN+gb9bKDt7X8SdxknYqAMh44S5L+lNqIN2NuV8nvv3g8rPp7MuRxcOpxpUIATWprO0C34a8Qmg==} + '@octokit/core@6.1.5': + resolution: {integrity: sha512-vvmsN0r7rguA+FySiCsbaTTobSftpIDIpPW81trAmsv9TGxg3YCujAxRYp/Uy8xmDgYCzzgulG62H7KYUFmeIg==} engines: {node: '>= 18'} - '@octokit/endpoint@10.1.3': - resolution: {integrity: sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA==} + '@octokit/endpoint@10.1.4': + resolution: {integrity: sha512-OlYOlZIsfEVZm5HCSR8aSg02T2lbUWOsCQoPKfTXJwDzcHQBrVBGdGXb89dv2Kw2ToZaRtudp8O3ZIYoaOjKlA==} engines: {node: '>= 18'} - '@octokit/graphql@8.2.1': - resolution: {integrity: sha512-n57hXtOoHrhwTWdvhVkdJHdhTv0JstjDbDRhJfwIRNfFqmSo1DaK/mD2syoNUoLCyqSjBpGAKOG0BuwF392slw==} + '@octokit/graphql@8.2.2': + resolution: {integrity: sha512-Yi8hcoqsrXGdt0yObxbebHXFOiUA+2v3n53epuOg1QUgOB6c4XzvisBNVXJSl8RYA5KrDuSL2yq9Qmqe5N0ryA==} engines: {node: '>= 18'} - '@octokit/openapi-types@23.0.1': - resolution: {integrity: sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==} + '@octokit/openapi-types@24.2.0': + resolution: {integrity: sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==} + + '@octokit/openapi-types@25.0.0': + resolution: {integrity: sha512-FZvktFu7HfOIJf2BScLKIEYjDsw6RKc7rBJCdvCTfKsVnx2GEB/Nbzjr29DUdb7vQhlzS/j8qDzdditP0OC6aw==} - '@octokit/plugin-paginate-rest@11.4.3': - resolution: {integrity: sha512-tBXaAbXkqVJlRoA/zQVe9mUdb8rScmivqtpv3ovsC5xhje/a+NOCivs7eUhWBwCApJVsR4G5HMeaLbq7PxqZGA==} + '@octokit/plugin-paginate-rest@11.6.0': + resolution: {integrity: sha512-n5KPteiF7pWKgBIBJSk8qzoZWcUkza2O6A0za97pMGVrGfPdltxrfmfF5GucHYvHGZD8BdaZmmHGz5cX/3gdpw==} engines: {node: '>= 18'} peerDependencies: '@octokit/core': '>=6' @@ -2399,26 +2212,29 @@ packages: peerDependencies: '@octokit/core': '>=6' - '@octokit/plugin-rest-endpoint-methods@13.3.1': - resolution: {integrity: sha512-o8uOBdsyR+WR8MK9Cco8dCgvG13H1RlM1nWnK/W7TEACQBFux/vPREgKucxUfuDQ5yi1T3hGf4C5ZmZXAERgwQ==} + '@octokit/plugin-rest-endpoint-methods@13.5.0': + resolution: {integrity: sha512-9Pas60Iv9ejO3WlAX3maE1+38c5nqbJXV5GrncEfkndIpZrJ/WPMRd2xYDcPPEt5yzpxcjw9fWNoPhsSGzqKqw==} engines: {node: '>= 18'} peerDependencies: '@octokit/core': '>=6' - '@octokit/request-error@6.1.7': - resolution: {integrity: sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g==} + '@octokit/request-error@6.1.8': + resolution: {integrity: sha512-WEi/R0Jmq+IJKydWlKDmryPcmdYSVjL3ekaiEL1L9eo1sUnqMJ+grqmC9cjk7CA7+b2/T397tO5d8YLOH3qYpQ==} engines: {node: '>= 18'} - '@octokit/request@9.2.2': - resolution: {integrity: sha512-dZl0ZHx6gOQGcffgm1/Sf6JfEpmh34v3Af2Uci02vzUYz6qEN6zepoRtmybWXIGXFIK8K9ylE3b+duCWqhArtg==} + '@octokit/request@9.2.3': + resolution: {integrity: sha512-Ma+pZU8PXLOEYzsWf0cn/gY+ME57Wq8f49WTXA8FMHp2Ps9djKw//xYJ1je8Hm0pR2lU9FUGeJRWOtxq6olt4w==} engines: {node: '>= 18'} '@octokit/rest@21.1.1': resolution: {integrity: sha512-sTQV7va0IUVZcntzy1q3QqPm/r8rWtDCqpRAmb8eXXnKkjoQEtFe3Nt5GTVsHft+R6jJoHeSiVLcgcvhtue/rg==} engines: {node: '>= 18'} - '@octokit/types@13.8.0': - resolution: {integrity: sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==} + '@octokit/types@13.10.0': + resolution: {integrity: sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==} + + '@octokit/types@14.0.0': + resolution: {integrity: sha512-VVmZP0lEhbo2O1pdq63gZFiGCKkm8PPp8AUOijlwPO6hojEVjspA0MWKP7E4hbvGxzFKNqKr6p0IYtOH/Wf/zA==} '@opentelemetry/api@1.9.0': resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} @@ -2440,8 +2256,8 @@ packages: resolution: {integrity: sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==} engines: {node: '>=14'} - '@opentelemetry/semantic-conventions@1.30.0': - resolution: {integrity: sha512-4VlGgo32k2EQ2wcCY3vEU28A0O13aOtHz3Xt2/2U5FAh9EfhD6t6DqL5Z6yAnRCntbTFDU4YfbpyzSlHNWycPw==} + '@opentelemetry/semantic-conventions@1.32.0': + resolution: {integrity: sha512-s0OpmpQFSfMrmedAn9Lhg4KWJELHCU6uU9dtIJ28N8UGhf9Y55im5X8fEzwhwDwiSqN+ZPSNrDJF7ivf/AuRPQ==} engines: {node: '>=14'} '@parcel/watcher-android-arm64@2.5.1': @@ -2560,8 +2376,8 @@ packages: '@protobufjs/utf8@1.1.0': resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} - '@puppeteer/browsers@2.8.0': - resolution: {integrity: sha512-yTwt2KWRmCQAfhvbCRjebaSX8pV1//I0Y3g+A7f/eS7gf0l4eRJoUCvcYdVtboeU4CTOZQuqYbZNS8aBYb8ROQ==} + '@puppeteer/browsers@2.10.0': + resolution: {integrity: sha512-HdHF4rny4JCvIcm7V1dpvpctIGqM3/Me255CB44vW7hDG1zYMmcBMjpNqZEDxdCfXGLkx5kP0+Jz5DUS+ukqtA==} engines: {node: '>=18'} hasBin: true @@ -2592,12 +2408,6 @@ packages: rollup: optional: true - '@rollup/plugin-node-resolve@13.3.0': - resolution: {integrity: sha512-Lus8rbUo1eEcnS4yTFKLZrVumLPY+YayBdWXgFSHYhTT2iJbMhoaaBL3xl5NCdeRytErGr8tZ0L71BMRmnlwSw==} - engines: {node: '>= 10.0.0'} - peerDependencies: - rollup: ^2.42.0 - '@rollup/plugin-node-resolve@15.3.1': resolution: {integrity: sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==} engines: {node: '>=14.0.0'} @@ -2607,11 +2417,14 @@ packages: rollup: optional: true - '@rollup/pluginutils@3.1.0': - resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} - engines: {node: '>= 8.0.0'} + '@rollup/plugin-node-resolve@16.0.1': + resolution: {integrity: sha512-tk5YCxJWIG81umIvNkSod2qK5KyQW19qcBF/B78n1bjtOON6gzKoVeSzAE8yHCZEDmqkHKkxplExA8KzdJLJpA==} + engines: {node: '>=14.0.0'} peerDependencies: - rollup: ^1.20.0||^2.0.0 + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true '@rollup/pluginutils@5.1.4': resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} @@ -2622,103 +2435,108 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.35.0': - resolution: {integrity: sha512-uYQ2WfPaqz5QtVgMxfN6NpLD+no0MYHDBywl7itPYd3K5TjjSghNKmX8ic9S8NU8w81NVhJv/XojcHptRly7qQ==} + '@rollup/rollup-android-arm-eabi@4.40.0': + resolution: {integrity: sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.35.0': - resolution: {integrity: sha512-FtKddj9XZudurLhdJnBl9fl6BwCJ3ky8riCXjEw3/UIbjmIY58ppWwPEvU3fNu+W7FUsAsB1CdH+7EQE6CXAPA==} + '@rollup/rollup-android-arm64@4.40.0': + resolution: {integrity: sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.35.0': - resolution: {integrity: sha512-Uk+GjOJR6CY844/q6r5DR/6lkPFOw0hjfOIzVx22THJXMxktXG6CbejseJFznU8vHcEBLpiXKY3/6xc+cBm65Q==} + '@rollup/rollup-darwin-arm64@4.40.0': + resolution: {integrity: sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.35.0': - resolution: {integrity: sha512-3IrHjfAS6Vkp+5bISNQnPogRAW5GAV1n+bNCrDwXmfMHbPl5EhTmWtfmwlJxFRUCBZ+tZ/OxDyU08aF6NI/N5Q==} + '@rollup/rollup-darwin-x64@4.40.0': + resolution: {integrity: sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.35.0': - resolution: {integrity: sha512-sxjoD/6F9cDLSELuLNnY0fOrM9WA0KrM0vWm57XhrIMf5FGiN8D0l7fn+bpUeBSU7dCgPV2oX4zHAsAXyHFGcQ==} + '@rollup/rollup-freebsd-arm64@4.40.0': + resolution: {integrity: sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.35.0': - resolution: {integrity: sha512-2mpHCeRuD1u/2kruUiHSsnjWtHjqVbzhBkNVQ1aVD63CcexKVcQGwJ2g5VphOd84GvxfSvnnlEyBtQCE5hxVVw==} + '@rollup/rollup-freebsd-x64@4.40.0': + resolution: {integrity: sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.35.0': - resolution: {integrity: sha512-mrA0v3QMy6ZSvEuLs0dMxcO2LnaCONs1Z73GUDBHWbY8tFFocM6yl7YyMu7rz4zS81NDSqhrUuolyZXGi8TEqg==} + '@rollup/rollup-linux-arm-gnueabihf@4.40.0': + resolution: {integrity: sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.35.0': - resolution: {integrity: sha512-DnYhhzcvTAKNexIql8pFajr0PiDGrIsBYPRvCKlA5ixSS3uwo/CWNZxB09jhIapEIg945KOzcYEAGGSmTSpk7A==} + '@rollup/rollup-linux-arm-musleabihf@4.40.0': + resolution: {integrity: sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.35.0': - resolution: {integrity: sha512-uagpnH2M2g2b5iLsCTZ35CL1FgyuzzJQ8L9VtlJ+FckBXroTwNOaD0z0/UF+k5K3aNQjbm8LIVpxykUOQt1m/A==} + '@rollup/rollup-linux-arm64-gnu@4.40.0': + resolution: {integrity: sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.35.0': - resolution: {integrity: sha512-XQxVOCd6VJeHQA/7YcqyV0/88N6ysSVzRjJ9I9UA/xXpEsjvAgDTgH3wQYz5bmr7SPtVK2TsP2fQ2N9L4ukoUg==} + '@rollup/rollup-linux-arm64-musl@4.40.0': + resolution: {integrity: sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loongarch64-gnu@4.35.0': - resolution: {integrity: sha512-5pMT5PzfgwcXEwOaSrqVsz/LvjDZt+vQ8RT/70yhPU06PTuq8WaHhfT1LW+cdD7mW6i/J5/XIkX/1tCAkh1W6g==} + '@rollup/rollup-linux-loongarch64-gnu@4.40.0': + resolution: {integrity: sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.35.0': - resolution: {integrity: sha512-c+zkcvbhbXF98f4CtEIP1EBA/lCic5xB0lToneZYvMeKu5Kamq3O8gqrxiYYLzlZH6E3Aq+TSW86E4ay8iD8EA==} + '@rollup/rollup-linux-powerpc64le-gnu@4.40.0': + resolution: {integrity: sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.35.0': - resolution: {integrity: sha512-s91fuAHdOwH/Tad2tzTtPX7UZyytHIRR6V4+2IGlV0Cej5rkG0R61SX4l4y9sh0JBibMiploZx3oHKPnQBKe4g==} + '@rollup/rollup-linux-riscv64-gnu@4.40.0': + resolution: {integrity: sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.40.0': + resolution: {integrity: sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.35.0': - resolution: {integrity: sha512-hQRkPQPLYJZYGP+Hj4fR9dDBMIM7zrzJDWFEMPdTnTy95Ljnv0/4w/ixFw3pTBMEuuEuoqtBINYND4M7ujcuQw==} + '@rollup/rollup-linux-s390x-gnu@4.40.0': + resolution: {integrity: sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.35.0': - resolution: {integrity: sha512-Pim1T8rXOri+0HmV4CdKSGrqcBWX0d1HoPnQ0uw0bdp1aP5SdQVNBy8LjYncvnLgu3fnnCt17xjWGd4cqh8/hA==} + '@rollup/rollup-linux-x64-gnu@4.40.0': + resolution: {integrity: sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.35.0': - resolution: {integrity: sha512-QysqXzYiDvQWfUiTm8XmJNO2zm9yC9P/2Gkrwg2dH9cxotQzunBHYr6jk4SujCTqnfGxduOmQcI7c2ryuW8XVg==} + '@rollup/rollup-linux-x64-musl@4.40.0': + resolution: {integrity: sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.35.0': - resolution: {integrity: sha512-OUOlGqPkVJCdJETKOCEf1mw848ZyJ5w50/rZ/3IBQVdLfR5jk/6Sr5m3iO2tdPgwo0x7VcncYuOvMhBWZq8ayg==} + '@rollup/rollup-win32-arm64-msvc@4.40.0': + resolution: {integrity: sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.35.0': - resolution: {integrity: sha512-2/lsgejMrtwQe44glq7AFFHLfJBPafpsTa6JvP2NGef/ifOa4KBoglVf7AKN7EV9o32evBPRqfg96fEHzWo5kw==} + '@rollup/rollup-win32-ia32-msvc@4.40.0': + resolution: {integrity: sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.35.0': - resolution: {integrity: sha512-PIQeY5XDkrOysbQblSW7v3l1MDZzkTEzAfTPkj5VAu3FW8fS4ynyLg2sINp0fp3SjZ8xkRYpLqoKcYqAkhU1dw==} + '@rollup/rollup-win32-x64-msvc@4.40.0': + resolution: {integrity: sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ==} cpu: [x64] os: [win32] - '@rollup/wasm-node@4.35.0': - resolution: {integrity: sha512-mVs1GGfgeDCcMCFN5FystW0B5XjwhARAnomDBm2wTITTAioNr+YrUJ4UPjV33iXiLH1xAKWuUo30Od5HzrfQyA==} + '@rollup/wasm-node@4.40.0': + resolution: {integrity: sha512-TrH9Uwkd+ZAZIaZAceS842hZFig6s7cWJTFmrj/VqMgCmqgkxFjpMqlk8s3cdrIrsCXRshxWlKeys8xpqqA6xg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -2733,8 +2551,8 @@ packages: resolution: {integrity: sha512-nYxaSb/MtlSI+JWcwTHQxyNmWeWrUXJJ/G4liLrGG7+tS4vAz6LF3xRXqLH6wPIVUoZQel2Fs4ddLx4NCpiIYg==} engines: {node: ^18.17.0 || >=20.5.0} - '@sigstore/protobuf-specs@0.4.0': - resolution: {integrity: sha512-o09cLSIq9EKyRXwryWDOJagkml9XgQCoCSRjHOnHLnvsivaW7Qznzz6yjfV7PHJHhIvyp8OH7OX8w0Dc5bQK7A==} + '@sigstore/protobuf-specs@0.4.1': + resolution: {integrity: sha512-7MJXQhIm7dWF9zo7rRtMYh8d2gSnc3+JddeQOTIg6gUN7FjcuckZ9EwGq+ReeQtbbl3Tbf5YqRrWxA1DMfIn+w==} engines: {node: ^18.17.0 || >=20.5.0} '@sigstore/sign@3.1.0': @@ -2794,14 +2612,14 @@ packages: '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} - '@types/babel__generator@7.6.8': - resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} '@types/babel__template@7.4.4': resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - '@types/babel__traverse@7.20.6': - resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} + '@types/babel__traverse@7.20.7': + resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==} '@types/big.js@6.2.2': resolution: {integrity: sha512-e2cOW9YlVzFY2iScnGBBkplKsrn2CsObHQ2Hiw4V1sSyiGbgWL8IyqE3zFi1Pt5o1pdAtYkDAIsF3KKUPjdzaA==} @@ -2854,11 +2672,8 @@ packages: '@types/eslint@9.6.1': resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} - '@types/estree@0.0.39': - resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} - - '@types/estree@1.0.6': - resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + '@types/estree@1.0.7': + resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} '@types/express-serve-static-core@4.19.6': resolution: {integrity: sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==} @@ -2869,6 +2684,9 @@ packages: '@types/express@4.17.21': resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} + '@types/express@5.0.1': + resolution: {integrity: sha512-UZUw8vjpWFXuDnjFTh7/5c2TWDlQqeXHi6hcN7F2XSVT5P+WmUnnbFS3KA6Jnc6IsEqI2qCVu2bK0R0J4A8ZQQ==} + '@types/glob@7.2.0': resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} @@ -2947,8 +2765,8 @@ packages: '@types/node-forge@1.3.11': resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} - '@types/node@20.17.24': - resolution: {integrity: sha512-d7fGCyB96w9BnWQrOsJtpyiSaBcAYYr75bnK6ZRjDbql2cGLj/3GsL5OYmLPNq76l7Gf2q4Rv9J2o6h5CrD9sA==} + '@types/node@20.17.30': + resolution: {integrity: sha512-7zf4YyHA+jvBNfVrk2Gtvs6x7E8V+YDW05bNfG2XkWDJfYRXrTiP/DsB2zSYTaHX0bGIujTBQdMVAhb+j7mwpg==} '@types/npm-package-arg@6.1.4': resolution: {integrity: sha512-vDgdbMy2QXHnAruzlv68pUtXCjmqUk3WrBAsRboRovsOmxbfn/WiYCjmecyKjGztnMps5dWp4Uq2prp+Ilo17Q==} @@ -2968,8 +2786,8 @@ packages: '@types/parse5@6.0.3': resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==} - '@types/picomatch@3.0.2': - resolution: {integrity: sha512-n0i8TD3UDB7paoMMxA3Y65vUncFJXjcUf7lQY7YyKGl6031FNjfsLs6pdLFCy2GNFxItPJG8GvvpbZc2skH7WA==} + '@types/picomatch@4.0.0': + resolution: {integrity: sha512-J1Bng+wlyEERWSgJQU1Pi0HObCLVcr994xT/M+1wcl/yNRTGBupsCxthgkdYG+GCOMaQH7iSVUY3LJVBBqG7MQ==} '@types/progress@2.0.7': resolution: {integrity: sha512-iadjw02vte8qWx7U0YM++EybBha2CQLPGu9iJ97whVgJUT5Zq9MjAPYUnbfRI2Kpehimf1QjFJYxD0t8nqzu5w==} @@ -2989,9 +2807,6 @@ packages: '@types/request@2.48.12': resolution: {integrity: sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==} - '@types/resolve@1.17.1': - resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} - '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} @@ -3004,8 +2819,8 @@ packages: '@types/selenium-webdriver@3.0.26': resolution: {integrity: sha512-dyIGFKXfUFiwkMfNGn1+F6b80ZjR3uSYv1j6xVJSDlft5waZ2cwkHW4e7zNzvq7hiEackcgvBpmnXZrI1GltPg==} - '@types/semver@7.5.8': - resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} + '@types/semver@7.7.0': + resolution: {integrity: sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==} '@types/send@0.17.4': resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} @@ -3056,8 +2871,8 @@ packages: '@types/ws@7.4.7': resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==} - '@types/ws@8.18.0': - resolution: {integrity: sha512-8svvI3hMyvN0kKCJMvTJP/x6Y/EoQbepff882wL+Sn5QsXb3etnamgrJq4isrBxSJj5L2AuXcI0+bgkoAXGUJw==} + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} '@types/yargs-parser@21.0.3': resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} @@ -3071,135 +2886,127 @@ packages: '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - '@typescript-eslint/eslint-plugin@8.26.1': - resolution: {integrity: sha512-2X3mwqsj9Bd3Ciz508ZUtoQQYpOhU/kWoUqIf49H8Z0+Vbh6UF/y0OEYp0Q0axOGzaBGs7QxRwq0knSQ8khQNA==} + '@typescript-eslint/eslint-plugin@8.30.1': + resolution: {integrity: sha512-v+VWphxMjn+1t48/jO4t950D6KR8JaJuNXzi33Ve6P8sEmPr5k6CEXjdGwT6+LodVnEa91EQCtwjWNUCPweo+Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 eslint: ^8.57.0 || ^9.0.0 - typescript: 5.8.2 + typescript: 5.8.3 - '@typescript-eslint/parser@8.26.1': - resolution: {integrity: sha512-w6HZUV4NWxqd8BdeFf81t07d7/YV9s7TCWrQQbG5uhuvGUAW+fq1usZ1Hmz9UPNLniFnD8GLSsDpjP0hm1S4lQ==} + '@typescript-eslint/parser@8.30.1': + resolution: {integrity: sha512-H+vqmWwT5xoNrXqWs/fesmssOW70gxFlgcMlYcBaWNPIEWDgLa4W9nkSPmhuOgLnXq9QYgkZ31fhDyLhleCsAg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: 5.8.2 + typescript: 5.8.3 - '@typescript-eslint/scope-manager@8.26.1': - resolution: {integrity: sha512-6EIvbE5cNER8sqBu6V7+KeMZIC1664d2Yjt+B9EWUXrsyWpxx4lEZrmvxgSKRC6gX+efDL/UY9OpPZ267io3mg==} + '@typescript-eslint/scope-manager@8.30.1': + resolution: {integrity: sha512-+C0B6ChFXZkuaNDl73FJxRYT0G7ufVPOSQkqkpM/U198wUwUFOtgo1k/QzFh1KjpBitaK7R1tgjVz6o9HmsRPg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/type-utils@8.26.1': - resolution: {integrity: sha512-Kcj/TagJLwoY/5w9JGEFV0dclQdyqw9+VMndxOJKtoFSjfZhLXhYjzsQEeyza03rwHx2vFEGvrJWJBXKleRvZg==} + '@typescript-eslint/type-utils@8.30.1': + resolution: {integrity: sha512-64uBF76bfQiJyHgZISC7vcNz3adqQKIccVoKubyQcOnNcdJBvYOILV1v22Qhsw3tw3VQu5ll8ND6hycgAR5fEA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: 5.8.2 + typescript: 5.8.3 - '@typescript-eslint/types@8.26.1': - resolution: {integrity: sha512-n4THUQW27VmQMx+3P+B0Yptl7ydfceUj4ON/AQILAASwgYdZ/2dhfymRMh5egRUrvK5lSmaOm77Ry+lmXPOgBQ==} + '@typescript-eslint/types@8.30.1': + resolution: {integrity: sha512-81KawPfkuulyWo5QdyG/LOKbspyyiW+p4vpn4bYO7DM/hZImlVnFwrpCTnmNMOt8CvLRr5ojI9nU1Ekpw4RcEw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.26.1': - resolution: {integrity: sha512-yUwPpUHDgdrv1QJ7YQal3cMVBGWfnuCdKbXw1yyjArax3353rEJP1ZA+4F8nOlQ3RfS2hUN/wze3nlY+ZOhvoA==} + '@typescript-eslint/typescript-estree@8.30.1': + resolution: {integrity: sha512-kQQnxymiUy9tTb1F2uep9W6aBiYODgq5EMSk6Nxh4Z+BDUoYUSa029ISs5zTzKBFnexQEh71KqwjKnRz58lusQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: 5.8.2 + typescript: 5.8.3 - '@typescript-eslint/utils@8.26.1': - resolution: {integrity: sha512-V4Urxa/XtSUroUrnI7q6yUTD3hDtfJ2jzVfeT3VK0ciizfK2q/zGC0iDh1lFMUZR8cImRrep6/q0xd/1ZGPQpg==} + '@typescript-eslint/utils@8.30.1': + resolution: {integrity: sha512-T/8q4R9En2tcEsWPQgB5BQ0XJVOtfARcUvOa8yJP3fh9M/mXraLxZrkCfGb6ChrO/V3W+Xbd04RacUEqk1CFEQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: 5.8.2 + typescript: 5.8.3 - '@typescript-eslint/visitor-keys@8.26.1': - resolution: {integrity: sha512-AjOC3zfnxd6S4Eiy3jwktJPclqhFHNyd8L6Gycf9WUPoKZpgM5PjkxY1X7uSy61xVpiJDhhk7XT2NVsN3ALTWg==} + '@typescript-eslint/visitor-keys@8.30.1': + resolution: {integrity: sha512-aEhgas7aJ6vZnNFC7K4/vMGDGyOiqWcYZPpIWrTKuTAlsvDNKy2GFDqh9smL+iq069ZvR0YzEeq0B8NJlLzjFA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@verdaccio/auth@8.0.0-next-8.7': - resolution: {integrity: sha512-CSLBAsCJT1oOpJ4OWnVGmN6o/ZilDNa7Aa5+AU1LI2lbRblqgr4BVRn07GFqimJ//6+tPzl8BHgyiCbBhh1ZiA==} + '@verdaccio/auth@8.0.0-next-8.15': + resolution: {integrity: sha512-vAfzGOHbPcPXMCI90jqm/qSZ1OUBnOGzudZA3+YtherncdwADekvXbdJlZVclcfmZ0sRbfVG5Xpf88aETiwfcw==} engines: {node: '>=18'} '@verdaccio/commons-api@10.2.0': resolution: {integrity: sha512-F/YZANu4DmpcEV0jronzI7v2fGVWkQ5Mwi+bVmV+ACJ+EzR0c9Jbhtbe5QyLUuzR97t8R5E/Xe53O0cc2LukdQ==} engines: {node: '>=8'} - '@verdaccio/config@8.0.0-next-8.7': - resolution: {integrity: sha512-pA0WCWvvWY6vPRav+X0EuFmuK6M08zIpRzTKkqSriCWk6JUCZ07TDnN054AS8TSSOy6EaWgHxnUw3nTd34Z4Sg==} + '@verdaccio/config@8.0.0-next-8.15': + resolution: {integrity: sha512-oEzQB+xeqaFAy54veMshqpt1hlZCYNkqoKuwkt7O8J43Fo/beiLluKUVneXckzi+pg1yvvGT7lNCbvuUQrxxQg==} engines: {node: '>=18'} - '@verdaccio/core@8.0.0-next-8.1': - resolution: {integrity: sha512-kQRCB2wgXEh8H88G51eQgAFK9IxmnBtkQ8sY5FbmB6PbBkyHrbGcCp+2mtRqqo36j0W1VAlfM3XzoknMy6qQnw==} - engines: {node: '>=14'} - - '@verdaccio/core@8.0.0-next-8.7': - resolution: {integrity: sha512-pf8M2Z5EI/5Zdhdcm3aadb9Q9jiDsIredPD3+cIoDum8x3di2AIYvQD7i5BEramfzZlLXVICmFAulU7nUY11qg==} + '@verdaccio/core@8.0.0-next-8.15': + resolution: {integrity: sha512-d5r/ZSkCri7s1hvV35enptquV5LJ81NqMYJnsjuryIUnvwn1yaqLlcdd6zIL08unzCSr7qDdUAdwGRRm6PKzng==} engines: {node: '>=18'} '@verdaccio/file-locking@10.3.1': resolution: {integrity: sha512-oqYLfv3Yg3mAgw9qhASBpjD50osj2AX4IwbkUtyuhhKGyoFU9eZdrbeW6tpnqUnj6yBMtAPm2eGD4BwQuX400g==} engines: {node: '>=12'} - '@verdaccio/file-locking@13.0.0-next-8.2': - resolution: {integrity: sha512-TcHgN3I/N28WBSvtukpGrJhBljl4jyIXq0vEv94vXAG6nUE3saK+vtgo8PfYA3Ueo88v/1zyAbiZM4uxwojCmQ==} + '@verdaccio/file-locking@13.0.0-next-8.3': + resolution: {integrity: sha512-Sugx6XYp8nEJ9SmBoEOExEIQQ0T0q8fcyc/afWdiSNDGWviqqSx2IriCvtMwKZrE4XG0BQo6bXO+A8AOOoo7KQ==} engines: {node: '>=18'} - '@verdaccio/loaders@8.0.0-next-8.4': - resolution: {integrity: sha512-Powlqb4SuMbe6RVgxyyOXaCjuHCcK7oZA+lygaKZDpV9NSHJtbkkV4L+rXyCfTX3b0tKsBh7FzaIdgWc1rDeGQ==} + '@verdaccio/loaders@8.0.0-next-8.6': + resolution: {integrity: sha512-yuqD8uAZJcgzuNHjV6C438UNT5r2Ai9+SnUlO34AHZdWSYcluO3Zj5R3p5uf+C7YPCE31pUD27wBU74xVbUoBw==} engines: {node: '>=18'} '@verdaccio/local-storage-legacy@11.0.2': resolution: {integrity: sha512-7AXG7qlcVFmF+Nue2oKaraprGRtaBvrQIOvc/E89+7hAe399V01KnZI6E/ET56u7U9fq0MSlp92HBcdotlpUXg==} engines: {node: '>=12'} - '@verdaccio/logger-commons@8.0.0-next-8.7': - resolution: {integrity: sha512-sXNx57G1LVp81xF4qHer3AOcMEZ90W4FjxtYF0vmULcVg3ybdtStKAT/9ocZtVMvLWTPAauhqylfnXoRZYf32A==} + '@verdaccio/logger-commons@8.0.0-next-8.15': + resolution: {integrity: sha512-nF7VgBC2cl5ufv+mZEwBHHyZFb1F0+kVkuRMf3Tyk+Qp4lXilC9MRZ0oc+RnzsDbNmJ6IZHgHNbs6aJrNfaRGg==} engines: {node: '>=18'} - '@verdaccio/logger-prettify@8.0.0-next-8.1': - resolution: {integrity: sha512-vLhaGq0q7wtMCcqa0aQY6QOsMNarhTu/l4e6Z8mG/5LUH95GGLsBwpXLnKS94P3deIjsHhc9ycnEmG39txbQ1w==} + '@verdaccio/logger-prettify@8.0.0-next-8.2': + resolution: {integrity: sha512-WMXnZPLw5W7GSIQE8UOTp6kRIwiTmnnoJbMmyMlGiNrsRaFKTqk09R5tKUgOyGgd4Lu6yncLbmdm5UjAuwHf1Q==} engines: {node: '>=18'} - '@verdaccio/logger@8.0.0-next-8.7': - resolution: {integrity: sha512-5EMPdZhz2V08BP2rjhtN/Fz5KxCfPJBkYDitbk/eo+FCZ9nVdMCQE3WRbHEaXyJQcIso/LJ6RnL/zKN20E/rPg==} + '@verdaccio/logger@8.0.0-next-8.15': + resolution: {integrity: sha512-3gjhqvB87JUNDHFMN3YG4IweS9EgbCpAWZatNYzcoIWOoGiEaFQQBSM592CaFiI0yf8acyqWkNa1V95L1NMbRg==} engines: {node: '>=18'} - '@verdaccio/middleware@8.0.0-next-8.7': - resolution: {integrity: sha512-Zad7KcdOsI1DUBt1TjQb08rIi/IFFaJKdPhj7M6oy5BX9l/4OM0TtbBueHFNS1+aU+t5eo8ue7ZHbqmjDY/6VQ==} + '@verdaccio/middleware@8.0.0-next-8.15': + resolution: {integrity: sha512-xsCLGbnhqcYwE8g/u9wxNLfDcESpr9ptEZ8Ce7frVTphU7kYIL48QCDPMzug7U+AguNtCq4v4zcoY1PaOQ8mgw==} engines: {node: '>=18'} - '@verdaccio/search-indexer@8.0.0-next-8.2': - resolution: {integrity: sha512-sWliVN5BkAGbZ3e/GD0CsZMfPJdRMRuN0tEKQFsvEJifxToq5UkfCw6vKaVvhezsTWqb+Rp5y+2d4n5BDOA49w==} + '@verdaccio/search-indexer@8.0.0-next-8.4': + resolution: {integrity: sha512-Oea9m9VDqdlDPyQ9+fpcxZk0sIYH2twVK+YbykHpSYpjZRzz9hJfIr/uUwAgpWq83zAl2YDbz4zR3TjzjrWQig==} engines: {node: '>=18'} - '@verdaccio/signature@8.0.0-next-8.1': - resolution: {integrity: sha512-lHD/Z2FoPQTtDYz6ZlXhj/lrg0SFirHrwCGt/cibl1GlePpx78WPdo03tgAyl0Qf+I35n484/gR1l9eixBQqYw==} + '@verdaccio/signature@8.0.0-next-8.7': + resolution: {integrity: sha512-sqP+tNzUtVIwUtt1ZHwYoxsO3roDLK7GW8c8Hj0SNaON+9ele9z4NBhaor+g95zRuLy6xtw/RgOvpyLon/vPrA==} engines: {node: '>=18'} '@verdaccio/streams@10.2.1': resolution: {integrity: sha512-OojIG/f7UYKxC4dYX8x5ax8QhRx1b8OYUAMz82rUottCuzrssX/4nn5QE7Ank0DUSX3C9l/HPthc4d9uKRJqJQ==} engines: {node: '>=12', npm: '>=5'} - '@verdaccio/tarball@13.0.0-next-8.7': - resolution: {integrity: sha512-EWRuEOLgb3UETxUsYg6+Mml6DDRiwQqKIEsE4Ys6y6rcH2vgW6XMnTt+s/v5pFI+zlbi6fxjOgQB1e6IJAwxVA==} + '@verdaccio/tarball@13.0.0-next-8.15': + resolution: {integrity: sha512-oSNmq7zD/iPIC5HpJbOJjW/lb0JV9k3jLwI6sG7kPgm+UIxVAOV4fKQOAD18HpHl/WjkF247NA6zGlAB94Habw==} engines: {node: '>=18'} - '@verdaccio/ui-theme@8.0.0-next-8.7': - resolution: {integrity: sha512-+7f7XqqIU+TVCHjsP6lWzCdsD4sM7MEhn4cu3mLW1kJZ7eenWKEltoqixQnoXJzaBjCiz+yXW1WkjMyEFLNbpg==} + '@verdaccio/ui-theme@8.0.0-next-8.15': + resolution: {integrity: sha512-k9BAM7rvbUqB2JPReNgXKUVTzBkdmIrNw0f6/7uyO+9cp7eVuarrPBnVF0oMc7jzVNBZRCpUksrhMZ0KwDZTpw==} - '@verdaccio/url@13.0.0-next-8.7': - resolution: {integrity: sha512-biFvwH3zIXYicA+SXNGvjMAe8oIQ5VddsfbO0ZXWlFs0lIz8cgI7QYPeSiCkU2VKpGzZ8pEKgqkxFsfFkU5kGA==} + '@verdaccio/url@13.0.0-next-8.15': + resolution: {integrity: sha512-1N/dGhw7cZMhupf/Xlm73beiL3oCaAiyo9DTumjF3aTcJnipVcT1hoj6CSj9RIX54824rUK9WVmo83dk0KPnjw==} engines: {node: '>=18'} - '@verdaccio/utils@7.0.1-next-8.1': - resolution: {integrity: sha512-cyJdRrVa+8CS7UuIQb3K3IJFjMe64v38tYiBnohSmhRbX7dX9IT3jWbjrwkqWh4KeS1CS6BYENrGG1evJ2ggrQ==} - engines: {node: '>=12'} - - '@verdaccio/utils@8.1.0-next-8.7': - resolution: {integrity: sha512-4eqPCnPAJsL6gdVs0/oqZNgs2PnQW3HHBMgBHyEbb5A/ESI10TvRp+B7MRl9glUmy/aR5B6YSI68rgXvAFjdxA==} - engines: {node: '>=12'} + '@verdaccio/utils@8.1.0-next-8.15': + resolution: {integrity: sha512-efg/bunOUMVXV+MlljJCrpuT+OQRrQS4wJyGL92B3epUGlgZ8DXs+nxN5v59v1a6AocAdSKwHgZS0g9txmBhOg==} + engines: {node: '>=18'} '@vitejs/plugin-basic-ssl@2.0.0': resolution: {integrity: sha512-gc9Tjg8bUxBVSTzeWT3Njc0Cl3PakHFKdNfABnZWiUgbxqmHDEn7uECv3fHVylxoYgNzAcmU7ZrILz+BwSo3sA==} @@ -3211,8 +3018,8 @@ packages: resolution: {integrity: sha512-ypmMG+72ERm+LvP+loj9A64MTXvWMXHUOu773cPO4L1SV/VWg6xA9Pv7vkvkXQX+ItJtCJt+KQ+U6ui2HhSFUw==} engines: {node: '>=18.0.0'} - '@web/config-loader@0.3.2': - resolution: {integrity: sha512-Vrjv/FexBGmAdnCYpJKLHX1dfT1UaUdvHmX1JRaWos9OvDf/tFznYJ5SpJwww3Rl87/ewvLSYG7kfsMqEAsizQ==} + '@web/config-loader@0.3.3': + resolution: {integrity: sha512-ilzeQzrPpPLWZhzFCV+4doxKDGm7oKVfdKpW9wiUNVgive34NSzCw+WzXTvjE4Jgr5CkyTDIObEmMrqQEjhT0g==} engines: {node: '>=18.0.0'} '@web/dev-server-core@0.7.5': @@ -3232,8 +3039,8 @@ packages: resolution: {integrity: sha512-GzfK5disEJ6wEjoPwx8AVNwUe9gYIiwc+x//QYxYDAFKUp4Xb1OJAGLc2l2gVrSQmtPGLKrTRcW90Hv4pEq1qA==} engines: {node: '>=18.0.0'} - '@web/test-runner-chrome@0.18.0': - resolution: {integrity: sha512-EkB70HtHwY36pIbgn9HzqtKAv+i53qa0/UBrs+H0m8j24TxIEH9oWIdF9O/RFxjYpla7fIvZMhOFOjejgrRU5g==} + '@web/test-runner-chrome@0.18.1': + resolution: {integrity: sha512-eO6ctCaqSguGM6G3cFobGHnrEs9wlv9Juj/Akyr4XLjeEMTheNULdvOXw9Bygi+QC/ir/0snMmt+/YKnfy8rYA==} engines: {node: '>=18.0.0'} '@web/test-runner-commands@0.9.0': @@ -3252,8 +3059,8 @@ packages: resolution: {integrity: sha512-ZL9F6FXd0DBQvo/h/+mSfzFTSRVxzV9st/AHhpgABtUtV/AIpVE9to6+xdkpu6827kwjezdpuadPfg+PlrBWqQ==} engines: {node: '>=18.0.0'} - '@web/test-runner@0.20.0': - resolution: {integrity: sha512-xN+4wgEm5xh0VSiC08eUYXW0QDt/NuzZyey4s7Nnjyjs9NkuJHd1jG9aNzfgL1edpJJ/RldHc0KiM2to1h2kxQ==} + '@web/test-runner@0.20.1': + resolution: {integrity: sha512-MTN8D1WCeCdkUWJIeG9yauUbRkk9g0zGFnBbI5smtPE91NpXFMfRd8nShIvxQnHx9fNTmK+OCYKnOSlq5DLLVA==} engines: {node: '>=18.0.0'} hasBin: true @@ -3319,8 +3126,8 @@ packages: resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} hasBin: true - abbrev@3.0.0: - resolution: {integrity: sha512-+/kfrslGQ7TNV2ecmQwMJj/B65g5KVq1/L3SGVZ3tCYGqlzFuFCGBZJtMP99wH3NpEUyAjn0zPdPUg0D+DwrOA==} + abbrev@3.0.1: + resolution: {integrity: sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==} engines: {node: ^18.17.0 || >=20.5.0} abort-controller@3.0.0: @@ -3331,6 +3138,10 @@ packages: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} + accepts@2.0.0: + resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} + engines: {node: '>= 0.6'} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -3473,8 +3284,8 @@ packages: resolution: {integrity: sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==} engines: {node: '>=0.10.0'} - array.prototype.findlastindex@1.2.5: - resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==} + array.prototype.findlastindex@1.2.6: + resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==} engines: {node: '>= 0.4'} array.prototype.flat@1.3.3: @@ -3520,9 +3331,6 @@ packages: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} engines: {node: '>= 0.4'} - async-mutex@0.4.0: - resolution: {integrity: sha512-eJFZ1YhRR8UN8eBLoNzcDPcy/jqjsg6I1AP+KvWQX80BqOSW1oJPJXDylPUEeMr2ZQvHgnQ//Lp6f3RQ1zI7HA==} - async@2.6.4: resolution: {integrity: sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==} @@ -3535,11 +3343,6 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - atob@2.1.2: - resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} - engines: {node: '>= 4.5.0'} - hasBin: true - atomic-sleep@1.0.0: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} engines: {node: '>=8.0.0'} @@ -3571,8 +3374,8 @@ packages: '@babel/core': ^7.12.0 webpack: '>=5.61.0' - babel-plugin-polyfill-corejs2@0.4.12: - resolution: {integrity: sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==} + babel-plugin-polyfill-corejs2@0.4.13: + resolution: {integrity: sha512-3sX/eOms8kd3q2KZ6DAhKPc0dgm525Gqq5NtWKZ7QYYZEv57OQ54KtblzJzH1lQF/eQxO8KjWGIK9IPUJNus5g==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 @@ -3581,8 +3384,8 @@ packages: peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - babel-plugin-polyfill-regenerator@0.6.3: - resolution: {integrity: sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==} + babel-plugin-polyfill-regenerator@0.6.4: + resolution: {integrity: sha512-7gD3pRadPrbjhjLyxebmx/WrFYcuSjZ0XbdUujQMZ/fcE9oeewk2U/7PCvez84UeuK3oSjmPZ0Ch0dlupQvGzw==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 @@ -3592,12 +3395,17 @@ packages: bare-events@2.5.4: resolution: {integrity: sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==} - bare-fs@4.0.1: - resolution: {integrity: sha512-ilQs4fm/l9eMfWY2dY0WCIUplSUp7U0CT1vrqMg1MUdeZl4fypu5UP0XcDBK5WBQPJAKP1b7XEodISmekH/CEg==} - engines: {bare: '>=1.7.0'} + bare-fs@4.1.2: + resolution: {integrity: sha512-8wSeOia5B7LwD4+h465y73KOdj5QHsbbuoUfPBi+pXgFJIPuG7SsiOdJuijWMyfid49eD+WivpfY7KT8gbAzBA==} + engines: {bare: '>=1.16.0'} + peerDependencies: + bare-buffer: '*' + peerDependenciesMeta: + bare-buffer: + optional: true - bare-os@3.6.0: - resolution: {integrity: sha512-BUrFS5TqSBdA0LwHop4OjPJwisqxGy6JsWVqV6qaFoe965qqtaKfDzHY5T2YA1gUL0ZeeQeA+4BBc1FJTcHiPw==} + bare-os@3.6.1: + resolution: {integrity: sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g==} engines: {bare: '>=1.14.0'} bare-path@3.0.0: @@ -3634,8 +3442,8 @@ packages: bcryptjs@2.4.3: resolution: {integrity: sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==} - beasties@0.2.0: - resolution: {integrity: sha512-Ljqskqx/tbZagIglYoJIMzH5zgssyp+in9+9sAyh15N22AornBeIDnb8EZ6Rk+6ShfMxd92uO3gfpT0NtZbpow==} + beasties@0.3.2: + resolution: {integrity: sha512-p4AF8uYzm9Fwu8m/hSVTCPXrRBPmB34hQpHsec2KOaR9CZmgoU8IOv4Cvwq4hgz2p4hLMNbsdNl5XeA6XbAQwA==} engines: {node: '>=14.0.0'} before-after-hook@3.0.2: @@ -3647,8 +3455,8 @@ packages: big.js@6.2.2: resolution: {integrity: sha512-y/ie+Faknx7sZA5MfGA2xKlu0GDv8RWrXGsmlteyJQ2lvoKv9GBK/fpRMc2qlSoBAgNxrixICFCBefIq8WCQpQ==} - bignumber.js@9.1.2: - resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} + bignumber.js@9.2.1: + resolution: {integrity: sha512-+NzaKgOUvInq9TIUZ1+DRspzf/HApkCwD4btfuasFTdrfnOxqx853TgDpMolp+uv4RpRp7bPcEU2zKr9+fRmyw==} binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} @@ -3666,6 +3474,10 @@ packages: resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + body-parser@2.2.0: + resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==} + engines: {node: '>=18'} + bonjour-service@1.3.0: resolution: {integrity: sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==} @@ -3685,15 +3497,15 @@ packages: browser-or-node@3.0.0: resolution: {integrity: sha512-iczIdVJzGEYhP5DqQxYM9Hh7Ztpqqi+CXZpSmX8ALFs9ecXkQIeqRyM6TfxEfMVpwhl3dSuDvxdzzo9sUOIVBQ==} - browser-sync-client@3.0.3: - resolution: {integrity: sha512-TOEXaMgYNjBYIcmX5zDlOdjEqCeCN/d7opf/fuyUD/hhGVCfP54iQIDhENCi012AqzYZm3BvuFl57vbwSTwkSQ==} + browser-sync-client@3.0.4: + resolution: {integrity: sha512-+ew5ubXzGRKVjquBL3u6najS40TG7GxCdyBll0qSRc/n+JRV9gb/yDdRL1IAgRHqjnJTdqeBKKIQabjvjRSYRQ==} engines: {node: '>=8.0.0'} - browser-sync-ui@3.0.3: - resolution: {integrity: sha512-FcGWo5lP5VodPY6O/f4pXQy5FFh4JK0f2/fTBsp0Lx1NtyBWs/IfPPJbW8m1ujTW/2r07oUXKTF2LYZlCZktjw==} + browser-sync-ui@3.0.4: + resolution: {integrity: sha512-5Po3YARCZ/8yQHFzvrSjn8+hBUF7ZWac39SHsy8Tls+7tE62iq6pYWxpVU6aOOMAGD21RwFQhQeqmJPf70kHEQ==} - browser-sync@3.0.3: - resolution: {integrity: sha512-91hoBHKk1C4pGeD+oE9Ld222k2GNQEAsI5AElqR8iLLWNrmZR2LPP8B0h8dpld9u7kro5IEUB3pUb0DJ3n1cRQ==} + browser-sync@3.0.4: + resolution: {integrity: sha512-mcYOIy4BW6sWSEnTSBjQwWsnbx2btZX78ajTTjdNfyC/EqQVcIe0nQR6894RNAMtvlfAnLaH9L2ka97zpvgenA==} engines: {node: '>= 8.0.0'} hasBin: true @@ -3726,10 +3538,6 @@ packages: buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - builtin-modules@3.3.0: - resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} - engines: {node: '>=6'} - bundle-name@4.1.0: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} @@ -3770,8 +3578,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001703: - resolution: {integrity: sha512-kRlAGTRWgPsOj7oARC9m1okJEXdL/8fekFVcxA8Hl7GH4r/sN4OJn/i6Flde373T50KS7Y37oFbMwlE8+F42kQ==} + caniuse-lite@1.0.30001713: + resolution: {integrity: sha512-wCIWIg+A4Xr7NfhTuHdX+/FKh3+Op3LBbSp2N5Pfx6T/LhdQy3GTyoTg48BReaW/MyMNZAkTadsBtai3ldWK0Q==} caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} @@ -3826,8 +3634,8 @@ packages: resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} engines: {node: '>=6.0'} - chromium-bidi@2.1.2: - resolution: {integrity: sha512-vtRWBK2uImo5/W2oG6/cDkkHSm+2t6VHgnj+Rcwhb0pP74OoUb4GipyRX/T/y39gYQPhioP0DPShn+A7P6CHNw==} + chromium-bidi@3.0.0: + resolution: {integrity: sha512-ZOGRDAhBMX1uxL2Cm2TDuhImbrsEz5A/tTcVU6RpXEWaTNUNwsHW6njUXizh51Ir6iqHbKAfhA2XK33uBcLo5A==} peerDependencies: devtools-protocol: '*' @@ -3927,10 +3735,6 @@ packages: resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} engines: {node: '>= 0.6'} - compression@1.7.5: - resolution: {integrity: sha512-bQJ0YRck5ak3LgtnpKkiabX5pNF7tMUh1BSy2ZBOTh0Dim0BUu6aPPwByIns6/A5Prh8PufSPerMDUklpzes2Q==} - engines: {node: '>= 0.8.0'} - compression@1.8.0: resolution: {integrity: sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==} engines: {node: '>= 0.8.0'} @@ -3954,14 +3758,18 @@ packages: resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==} engines: {node: '>= 0.10.0'} - consola@3.4.0: - resolution: {integrity: sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA==} + consola@3.4.2: + resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} engines: {node: ^14.18.0 || >=16.10.0} content-disposition@0.5.4: resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} engines: {node: '>= 0.6'} + content-disposition@1.0.0: + resolution: {integrity: sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==} + engines: {node: '>= 0.6'} + content-type@1.0.5: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} @@ -3975,6 +3783,10 @@ packages: cookie-signature@1.0.6: resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + cookie-signature@1.2.2: + resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} + engines: {node: '>=6.6.0'} + cookie@0.7.1: resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} engines: {node: '>= 0.6'} @@ -3999,8 +3811,8 @@ packages: core-js-compat@3.41.0: resolution: {integrity: sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==} - core-js@3.37.1: - resolution: {integrity: sha512-Xn6qmxrQZyB0FFY8E3bgRXei3lWDJHhvI+u0q9TKIYM49G8pAr0FgnnrFRAmsbptZL1yxRADVXn+x5AGsbBfyw==} + core-js@3.40.0: + resolution: {integrity: sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ==} core-util-is@1.0.2: resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} @@ -4016,7 +3828,7 @@ packages: resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} engines: {node: '>=14'} peerDependencies: - typescript: 5.8.2 + typescript: 5.8.3 peerDependenciesMeta: typescript: optional: true @@ -4146,10 +3958,6 @@ packages: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} - decode-uri-component@0.2.2: - resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} - engines: {node: '>=0.10'} - deep-equal@1.0.1: resolution: {integrity: sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==} @@ -4249,8 +4057,8 @@ packages: devtools-protocol@0.0.1045489: resolution: {integrity: sha512-D+PTmWulkuQW4D1NTiCRCFxF7pQPn0hgp4YyX4wAQ6xYXKOadSWPR3ENGDQ47MW/Ewc9v2rpC/UEEGahgBYpSQ==} - devtools-protocol@0.0.1413902: - resolution: {integrity: sha512-yRtvFD8Oyk7C9Os3GmnFZLu53yAfsnyw1s+mLmHHUK0GQEc9zthHWvS1r67Zqzm5t7v56PILHIVZ7kmFMaL2yQ==} + devtools-protocol@0.0.1425554: + resolution: {integrity: sha512-uRfxR6Nlzdzt0ihVIkV+sLztKgs7rgquY/Mhcv1YNCWDh5IZgl5mnn2aeEnW5stYTE0wwiF4RYVz8eMEpV1SEw==} di@0.0.1: resolution: {integrity: sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==} @@ -4308,8 +4116,8 @@ packages: resolution: {integrity: sha512-8cAwm6md1YTiPpOvDULYJL4ZS6WfM5/cTeVVh4JsvyYZAoqlRVUpHL9Gr5Fy7HA6xcSZicUia3DeAgO3Us8E+Q==} engines: {node: '>= 4.0.0'} - eazy-logger@4.0.1: - resolution: {integrity: sha512-2GSFtnnC6U4IEKhEI7+PvdxrmjJ04mdsj3wHZTFiw0tUtG4HCWzTr13ZYTk8XOGnA1xQMaDljoBOYlk3D/MMSw==} + eazy-logger@4.1.0: + resolution: {integrity: sha512-+mn7lRm+Zf1UT/YaH8WXtpU6PIV2iOjzP6jgKoiaq/VNrjYKp+OHZGe2znaLgDeFkw8cL9ffuaUm+nNnzcYyGw==} engines: {node: '>= 0.8.0'} ecc-jsbn@0.1.2: @@ -4321,8 +4129,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.114: - resolution: {integrity: sha512-DFptFef3iktoKlFQK/afbo274/XNWD00Am0xa7M8FZUepHlHT8PEuiNBoRfFHbH1okqN58AlhbJ4QTkcnXorjA==} + electron-to-chromium@1.5.137: + resolution: {integrity: sha512-/QSJaU2JyIuTbbABAo/crOs+SuAZLS+fVVS10PVrIT9hrRkmZl8Hb0xPSkKRUUWHQtYzXHpQUW3Dy5hwMzGZkA==} emoji-regex@10.4.0: resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} @@ -4374,6 +4182,10 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} + entities@6.0.0: + resolution: {integrity: sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==} + engines: {node: '>=0.12'} + env-paths@2.2.1: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} @@ -4437,13 +4249,13 @@ packages: es6-promisify@5.0.0: resolution: {integrity: sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==} - esbuild-wasm@0.25.1: - resolution: {integrity: sha512-dZxPeDHcDIQ6ilml/NzYxnPbNkoVsHSFH3JGLSobttc5qYYgExMo8lh2XcB+w+AfiqykVDGK5PWanGB0gWaAWw==} + esbuild-wasm@0.25.2: + resolution: {integrity: sha512-vL9PSK1YFGsvrlYPDxfRxpakIDTe1wCS/JO2D45muxwtd7GR/9+fYRU+K8tKs4ZDXaEy5jr6YqrGgDL/iyufyQ==} engines: {node: '>=18'} hasBin: true - esbuild@0.25.1: - resolution: {integrity: sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==} + esbuild@0.25.2: + resolution: {integrity: sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==} engines: {node: '>=18'} hasBin: true @@ -4467,8 +4279,8 @@ packages: engines: {node: '>=6.0'} hasBin: true - eslint-config-prettier@10.1.1: - resolution: {integrity: sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw==} + eslint-config-prettier@10.1.2: + resolution: {integrity: sha512-Epgp/EofAUeEpIdZkW60MHKvPyru1ruQJxPL+WIycnaPApuseK0Zpkrh/FwL9oIpQvIhJwV7ptOy0DWUjTlCiA==} hasBin: true peerDependencies: eslint: '>=7.0.0' @@ -4528,8 +4340,8 @@ packages: resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.22.0: - resolution: {integrity: sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ==} + eslint@9.24.0: + resolution: {integrity: sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -4563,9 +4375,6 @@ packages: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} - estree-walker@1.0.1: - resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==} - estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} @@ -4616,6 +4425,10 @@ packages: resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} engines: {node: '>= 0.10.0'} + express@5.1.0: + resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==} + engines: {node: '>= 18'} + extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} @@ -4655,9 +4468,6 @@ packages: resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} engines: {node: '>=6'} - fast-safe-stringify@2.1.1: - resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} - fast-uri@3.0.6: resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} @@ -4703,6 +4513,10 @@ packages: resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} engines: {node: '>= 0.8'} + finalhandler@2.1.0: + resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==} + engines: {node: '>= 0.8'} + find-cache-dir@3.3.2: resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} engines: {node: '>=8'} @@ -4777,6 +4591,10 @@ packages: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} + fresh@2.0.0: + resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} + engines: {node: '>= 0.8'} + fs-constants@1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} @@ -4995,21 +4813,21 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} - hosted-git-info@8.0.2: - resolution: {integrity: sha512-sYKnA7eGln5ov8T8gnYlkSOxFJvywzEx9BueN6xo/GKO8PGiI6uK6xx+DIGe45T3bdVjLAQDQW1aicT8z8JwQg==} + hosted-git-info@8.1.0: + resolution: {integrity: sha512-Rw/B2DNQaPBICNXEm8balFz9a6WpZrkCGpcWFpy7nCj+NyhSdqXipmfvtmWt9xGfp0wZnBxB+iVpLmQMYt47Tw==} engines: {node: ^18.17.0 || >=20.5.0} hpack.js@2.1.6: resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==} - html-entities@2.5.2: - resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==} + html-entities@2.6.0: + resolution: {integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==} html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - htmlparser2@9.1.0: - resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==} + htmlparser2@10.0.0: + resolution: {integrity: sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==} http-assert@1.5.0: resolution: {integrity: sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==} @@ -5033,8 +4851,8 @@ packages: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} - http-parser-js@0.5.9: - resolution: {integrity: sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw==} + http-parser-js@0.5.10: + resolution: {integrity: sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==} http-proxy-agent@5.0.0: resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} @@ -5044,8 +4862,8 @@ packages: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} - http-proxy-middleware@2.0.7: - resolution: {integrity: sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==} + http-proxy-middleware@2.0.9: + resolution: {integrity: sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==} engines: {node: '>=12.0.0'} peerDependencies: '@types/express': ^4.17.13 @@ -5053,8 +4871,8 @@ packages: '@types/express': optional: true - http-proxy-middleware@3.0.3: - resolution: {integrity: sha512-usY0HG5nyDUwtqpiZdETNbmKtw3QQ1jwYFZ9wi5iHzX2BcILwQKtYDJPo7XHTsu5Z0B2Hj3W9NNnbd+AjFWjqg==} + http-proxy-middleware@3.0.5: + resolution: {integrity: sha512-GLZZm1X38BPY4lkXA01jhwxvDoOkkXqjgVyUzVxiEK4iuRu03PZoYHhHRwxnfhQMDuaxi3vVri0YgSro/1oWqg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} http-proxy@1.18.1: @@ -5137,8 +4955,8 @@ packages: resolution: {integrity: sha512-15gZoQ38eYjEjxkorfbcgBKBL6R7T459OuK+CpcWt7O3KF4uPCx2tD0uFETlUDIyo+1789crbMhTvQBSR5yBMg==} engines: {node: '>=0.10.0'} - immutable@5.0.3: - resolution: {integrity: sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==} + immutable@5.1.1: + resolution: {integrity: sha512-3jatXi9ObIsPGr3N5hGw/vWWcTkq6hUYhpQz4k0wLC+owqWi/LiugIw9x0EdNZ2yGedKN/HzePiBvaJRXa0Ujg==} import-fresh@3.3.1: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} @@ -5223,10 +5041,6 @@ packages: resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} engines: {node: '>= 0.4'} - is-builtin-module@3.2.1: - resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} - engines: {node: '>=6'} - is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} @@ -5350,6 +5164,9 @@ packages: is-promise@2.2.2: resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} + is-promise@4.0.0: + resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + is-reference@1.2.1: resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} @@ -5660,10 +5477,6 @@ packages: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} - kleur@4.1.5: - resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} - engines: {node: '>=6'} - koa-compose@4.1.0: resolution: {integrity: sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==} @@ -5682,8 +5495,8 @@ packages: resolution: {integrity: sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==} engines: {node: '>= 7.6.0'} - koa@2.16.0: - resolution: {integrity: sha512-Afhqq0Vq3W7C+/rW6IqHVBDLzqObwZ07JaUNUEF8yCQ6afiyFE3RAy+i7V0E46XOWlH7vPWn/x0vsZwNy6PWxw==} + koa@2.16.1: + resolution: {integrity: sha512-umfX9d3iuSxTQP4pnzLOz0HKnPg0FaUUIKcye2lOiz3KPu1Y3M3xlz76dISdFPQs37P9eJz1wUpcTS6KDPn9fA==} engines: {node: ^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4} launch-editor@2.10.0: @@ -5702,9 +5515,9 @@ packages: webpack: optional: true - less@4.2.2: - resolution: {integrity: sha512-tkuLHQlvWUTeQ3doAqnHbNn8T6WX1KA8yvbKG9x4VtKtIjHsVKQZCH11zRgAfbDAXC2UNIg/K9BYAAcEzUIrNg==} - engines: {node: '>=6'} + less@4.3.0: + resolution: {integrity: sha512-X9RyH9fvemArzfdP8Pi3irr7lor2Ok4rOttDXBhlwDg+wKQsXOXgHWduAJE1EsF7JJx0w0bcO6BC6tCKKYnXKA==} + engines: {node: '>=14'} hasBin: true levn@0.4.1: @@ -5731,8 +5544,8 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - listr2@8.2.5: - resolution: {integrity: sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==} + listr2@8.3.2: + resolution: {integrity: sha512-vsBzcU4oE+v0lj4FhVLzr9dBTv4/fHIa57l+GCwovP8MoFNZJTOhGU8PXd4v2VJCbECAaijBiHntiekFMLvo0g==} engines: {node: '>=18.0.0'} lmdb@3.2.6: @@ -5860,8 +5673,8 @@ packages: resolution: {integrity: sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==} engines: {node: ^18.17.0 || >=20.5.0} - marky@1.2.5: - resolution: {integrity: sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==} + marky@1.3.0: + resolution: {integrity: sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==} math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} @@ -5871,6 +5684,10 @@ packages: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} + media-typer@1.1.0: + resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} + engines: {node: '>= 0.8'} + memfs@4.17.0: resolution: {integrity: sha512-4eirfZ7thblFmqFjywlTmuWVSvccHAJbn1r8qQLzmTO11qcqpohOjmY2mFce6x7x7WtskzRqApPD0hv+Oa74jg==} engines: {node: '>= 4.0.0'} @@ -5878,6 +5695,10 @@ packages: merge-descriptors@1.0.3: resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + merge-descriptors@2.0.0: + resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} + engines: {node: '>=18'} + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -5897,14 +5718,18 @@ packages: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} - mime-db@1.53.0: - resolution: {integrity: sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==} + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} engines: {node: '>= 0.6'} mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} + mime-types@3.0.1: + resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==} + engines: {node: '>= 0.6'} + mime@1.6.0: resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} engines: {node: '>=4'} @@ -5987,8 +5812,8 @@ packages: resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} engines: {node: '>= 8'} - minizlib@3.0.1: - resolution: {integrity: sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==} + minizlib@3.0.2: + resolution: {integrity: sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==} engines: {node: '>= 18'} mitt@1.2.0: @@ -6049,8 +5874,8 @@ packages: nanocolors@0.2.13: resolution: {integrity: sha512-0n3mSAQLPpGLV9ORXT5+C/D4mwew7Ebws69Hx4E2sgz2ZA5+32Q80B9tL8PbL7XHnRDiAxH/pnrUJ9a4fkTNTA==} - nanoid@3.3.9: - resolution: {integrity: sha512-SppoicMGpZvbF1l3z4x7No3OlIjP7QJvC9XR7AhZr1kL133KHnKPztkKDc+Ir4aJ/1VhTySrtKhrsycmrMQfvg==} + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -6081,15 +5906,15 @@ packages: resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} engines: {node: '>= 0.4.0'} - ng-packagr@20.0.0-next.1: - resolution: {integrity: sha512-6v6t7R9U3UVHx0MywijxWMiQ0OujNCPDaWK/Ih7hUfNmBAIqeF+bdlKc+BnItcHSTyaouethcSQCttxAhpmOXQ==} - engines: {node: ^18.19.1 || >=20.11.1} + ng-packagr@20.0.0-next.6: + resolution: {integrity: sha512-naul5aMAJRla4Mj40bc9ku7FyJu6cZyl+/2D+U8FukorRdwjf2Db4C3RMtjtkKNIBEfHmADOyJmvuevQnxiTKQ==} + engines: {node: ^20.11.1 || >=22.11.0} hasBin: true peerDependencies: '@angular/compiler-cli': ^20.0.0 || ^20.0.0-next.0 tailwindcss: ^2.0.0 || ^3.0.0 || ^4.0.0 tslib: ^2.3.0 - typescript: 5.8.2 + typescript: 5.8.3 peerDependenciesMeta: tailwindcss: optional: true @@ -6106,6 +5931,7 @@ packages: node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'} + deprecated: Use your platform's native DOMException instead node-fetch-native@1.6.6: resolution: {integrity: sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==} @@ -6140,8 +5966,8 @@ packages: resolution: {integrity: sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==} hasBin: true - node-gyp@11.1.0: - resolution: {integrity: sha512-/+7TuHKnBpnMvUQnsYEb0JOozDZqarQbfNuSGLXIjhStMT0fbw7IdSqWgopOP5xhRZE+lsbIvAHcekddruPZgQ==} + node-gyp@11.2.0: + resolution: {integrity: sha512-T0S1zqskVUSxcsSTkAsLc7xCycrRYmtDHadDinzocrThjyQCn5kMlEBSj6H4qDbgsIOSLmmlRIeb0lZXj+UArA==} engines: {node: ^18.17.0 || >=20.5.0} hasBin: true @@ -6197,8 +6023,8 @@ packages: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} - npm@11.2.0: - resolution: {integrity: sha512-PcnFC6gTo9VDkxVaQ1/mZAS3JoWrDjAI+a6e2NgfYQSGDwftJlbdV0jBMi2V8xQPqbGcWaa7p3UP0SKF+Bhm2g==} + npm@11.3.0: + resolution: {integrity: sha512-luthFIP0nFX3+nTfYbWI3p4hP4CiVnKOZ5jdxnF2x7B+Shz8feiSJCLLzgJUNxQ2cDdTaVUiH6RRsMT++vIMZg==} engines: {node: ^20.17.0 || >=22.9.0} hasBin: true bundledDependencies: @@ -6340,8 +6166,8 @@ packages: only@0.0.2: resolution: {integrity: sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==} - open@10.1.0: - resolution: {integrity: sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==} + open@10.1.1: + resolution: {integrity: sha512-zy1wx4+P3PfhXSEPJNtZmJXfhkkIaxU1VauWIrDZw1O7uJRDRJtKr9n3Ic4NgbA16KyOxOXO2ng9gYwCdXuSXA==} engines: {node: '>=18'} open@8.4.2: @@ -6494,6 +6320,10 @@ packages: path-to-regexp@0.1.12: resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} + path-to-regexp@8.2.0: + resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==} + engines: {node: '>=16'} + path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -6550,12 +6380,12 @@ packages: pino-std-serializers@7.0.0: resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} - pino@9.5.0: - resolution: {integrity: sha512-xSEmD4pLnV54t0NOUN16yCl7RIB1c5UUOse5HSyEXtBp+FgFQyPeDutc+Q2ZO7/22vImV7VfEjH/1zV2QuqvYw==} + pino@9.6.0: + resolution: {integrity: sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg==} hasBin: true - piscina@4.8.0: - resolution: {integrity: sha512-EZJb+ZxDrQf3dihsUL7p42pjNyrNIFJCrRHPMgxu/svsj+P3xS3fuEWp7k2+rfsavfl1N0G29b1HGs7J0m8rZA==} + piscina@4.9.2: + resolution: {integrity: sha512-Fq0FERJWFEUpB4eSY59wSNwXD4RYqR+nR/WiEVcZW8IWfVBxJJafcgTEZDQo8k3w0sUarJ8RyVbbUF4GQ2LGbQ==} pkg-dir@4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} @@ -6569,9 +6399,9 @@ packages: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} - portfinder@1.0.33: - resolution: {integrity: sha512-+2jndHT63cL5MdQOwDm9OT2dIe11zVpjV+0GGRXdtO1wpPxv260NfVqoEXtYAi/shanmm3W4+yLduIe55ektTw==} - engines: {node: '>= 0.12.0'} + portfinder@1.0.36: + resolution: {integrity: sha512-gMKUzCoP+feA7t45moaSx7UniU7PgGN3hA8acAB+3Qn7/js0/lJ07fYZlxt9riE9S3myyxDCyAFzSrLlta0c9g==} + engines: {node: '>= 10.12'} portscanner@2.2.0: resolution: {integrity: sha512-IFroCz/59Lqa2uBvzK3bKDbDDIEaAY8XJ1jFxcLWTqosrsc32//P4VuSB2vZXoHiHqOmx8B5L5hnKOxL/7FlPw==} @@ -6717,8 +6547,8 @@ packages: resolution: {integrity: sha512-MRtTAZfQTluz3U2oU/X2VqVWPcR1+94nbA2V6ZrSZRVEwLqZ8eclZ551qGFQD/vD2PYqHJwWOW/fpC721uznVw==} engines: {node: '>=14.1.0'} - puppeteer-core@24.4.0: - resolution: {integrity: sha512-eFw66gCnWo0X8Hyf9KxxJtms7a61NJVMiSaWfItsFPzFBsjsWdmcNlBdsA1WVwln6neoHhsG+uTVesKmTREn/g==} + puppeteer-core@24.6.1: + resolution: {integrity: sha512-sMCxsY+OPWO2fecBrhIeCeJbWWXJ6UaN997sTid6whY0YT9XM0RnxEwLeUibluIS5/fRmuxe1efjb5RMBsky7g==} engines: {node: '>=18'} puppeteer@18.2.1: @@ -6742,10 +6572,6 @@ packages: resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} engines: {node: '>=0.6'} - qs@6.13.1: - resolution: {integrity: sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==} - engines: {node: '>=0.6'} - qs@6.14.0: resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} engines: {node: '>=0.6'} @@ -6774,6 +6600,10 @@ packages: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} + raw-body@3.0.0: + resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==} + engines: {node: '>= 0.8'} + readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} @@ -6920,29 +6750,36 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true - rimraf@5.0.10: - resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} - hasBin: true - rollup-license-plugin@3.0.2: resolution: {integrity: sha512-68LWDlUKxqLO4Si3Extca4X7P99tU7s0KLnVUzN6h6SDihGAWYMQ0q73XLnHbUmG0IFgvC0AzuYvbogceQ9Hcw==} engines: {node: '>=18.0.0'} - rollup-plugin-sourcemaps@0.6.3: - resolution: {integrity: sha512-paFu+nT1xvuO1tPFYXGe+XnQvg4Hjqv/eIhG8i5EspfYYPBKL57X7iVbfv55aNVASg3dzWvES9dmWsL2KhfByw==} - engines: {node: '>=10.0.0'} + rollup-plugin-dts@6.2.1: + resolution: {integrity: sha512-sR3CxYUl7i2CHa0O7bA45mCrgADyAQ0tVtGSqi3yvH28M+eg1+g5d7kQ9hLvEz5dorK3XVsH5L2jwHLQf72DzA==} + engines: {node: '>=16'} peerDependencies: - '@types/node': '>=10.0.0' - rollup: '>=0.31.2' + rollup: ^3.29.4 || ^4 + typescript: 5.8.3 + + rollup-plugin-sourcemaps2@0.5.0: + resolution: {integrity: sha512-ozRq2fRuJYkA2cRT1CxaWNovtdBbrlXMK/vKIm5Q7rLUHx4jF21jZu1plO+VNOWPDAn+q1CaIAWKQL5QGej6Bw==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@types/node': '>=18.0.0' + rollup: '>=4' peerDependenciesMeta: '@types/node': optional: true - rollup@4.35.0: - resolution: {integrity: sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg==} + rollup@4.40.0: + resolution: {integrity: sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + router@2.2.0: + resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} + engines: {node: '>= 18'} + run-applescript@7.0.0: resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} engines: {node: '>=18'} @@ -7002,8 +6839,8 @@ packages: webpack: optional: true - sass@1.85.1: - resolution: {integrity: sha512-Uk8WpxM5v+0cMR0XjX9KfRIacmSG86RH4DCCZjLU2rFh5tyutt9siAXJ7G+YfxQ99Q6wrRMbMlVl6KqUms71ag==} + sass@1.86.3: + resolution: {integrity: sha512-iGtg8kus4GrsGLRDLRBRHY9dNVA78ZaS7xr01cWnS7PEMQyFtTqBiyCrfpTYTZXRWM94akzckYjh8oADfFNTzw==} engines: {node: '>=14.0.0'} hasBin: true @@ -7054,6 +6891,10 @@ packages: resolution: {integrity: sha512-p4rRk4f23ynFEfcD9LA0xRYngj+IyGiEYyqqOak8kaN0TvNmuxC2dcVeBn62GpCeR2CpWqyHCNScTP91QbAVFg==} engines: {node: '>= 0.8.0'} + send@1.2.0: + resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==} + engines: {node: '>= 18'} + serialize-javascript@6.0.2: resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} @@ -7065,6 +6906,10 @@ packages: resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} engines: {node: '>= 0.8.0'} + serve-static@2.2.0: + resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==} + engines: {node: '>= 18'} + server-destroy@1.0.1: resolution: {integrity: sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==} @@ -7116,8 +6961,8 @@ packages: resolution: {integrity: sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==} engines: {node: '>= 0.4'} - shelljs@0.9.1: - resolution: {integrity: sha512-ngPynK9u9OmsL2DttaTOhEPahyAjVbjIwCK3R+2V9YDq0/equpq7hVz3XrnfIjAk1thN5ET5mEIzAmocmV6i+Q==} + shelljs@0.9.2: + resolution: {integrity: sha512-S3I64fEiKgTZzKCC46zT/Ib9meqofLrQVbpSswtjFfAVDW+AZ54WTnAM/3/yENoxz/V1Cy6u3kiiEbQ4DNphvw==} engines: {node: '>=18'} hasBin: true @@ -7210,10 +7055,6 @@ packages: peerDependencies: webpack: ^5.72.1 - source-map-resolve@0.6.0: - resolution: {integrity: sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==} - deprecated: See https://github.com/lydell/source-map-resolve#deprecated - source-map-support@0.4.18: resolution: {integrity: sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==} @@ -7393,10 +7234,6 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - symbol-observable@4.0.0: - resolution: {integrity: sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==} - engines: {node: '>=0.10'} - table-layout@4.1.1: resolution: {integrity: sha512-iK5/YhZxq5GO5z8wb0bY1317uDF3Zjpha0QFFLA8/trAoiLbQD0HUbMesEaxyzUgDxi2QlcbM8IvqOlEjgoXBA==} engines: {node: '>=12.17'} @@ -7482,11 +7319,11 @@ packages: resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} engines: {node: '>=12.0.0'} - tldts-core@6.1.84: - resolution: {integrity: sha512-NaQa1W76W2aCGjXybvnMYzGSM4x8fvG2AN/pla7qxcg0ZHbooOPhA8kctmOZUDfZyhDL27OGNbwAeig8P4p1vg==} + tldts-core@6.1.86: + resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} - tldts@6.1.84: - resolution: {integrity: sha512-aRGIbCIF3teodtUFAYSdQONVmDRy21REM3o6JnqWn5ZkQBJJ4gHxhw6OfwQ+WkSAi3ASamrS4N4nyazWx6uTYg==} + tldts@6.1.86: + resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} hasBin: true tmp@0.0.30: @@ -7520,8 +7357,8 @@ packages: tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - tr46@5.0.0: - resolution: {integrity: sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==} + tr46@5.1.0: + resolution: {integrity: sha512-IUWnUK7ADYR5Sl1fZlO1INDUhVhatWl7BtJWsIhwJ0UAK7ilzzIa8uIqOO/aYVWHZPJkKbEL+362wrzoeRF7bw==} engines: {node: '>=18'} tree-dump@1.0.2: @@ -7534,11 +7371,11 @@ packages: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true - ts-api-utils@2.0.1: - resolution: {integrity: sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==} + ts-api-utils@2.1.0: + resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} engines: {node: '>=18.12'} peerDependencies: - typescript: 5.8.2 + typescript: 5.8.3 ts-node@10.9.2: resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} @@ -7547,7 +7384,7 @@ packages: '@swc/core': '>=1.2.50' '@swc/wasm': '>=1.2.50' '@types/node': '*' - typescript: 5.8.2 + typescript: 5.8.3 peerDependenciesMeta: '@swc/core': optional: true @@ -7589,6 +7426,10 @@ packages: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} + type-is@2.0.1: + resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==} + engines: {node: '>= 0.6'} + typed-array-buffer@1.0.3: resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} engines: {node: '>= 0.4'} @@ -7614,8 +7455,8 @@ packages: typed-query-selector@2.12.0: resolution: {integrity: sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==} - typescript@5.8.2: - resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} + typescript@5.8.3: + resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} engines: {node: '>=14.17'} hasBin: true @@ -7650,8 +7491,8 @@ packages: undici-types@6.19.8: resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} - undici@7.5.0: - resolution: {integrity: sha512-NFQG741e8mJ0fLQk90xKxFdaSM7z4+IQpAgsFI36bCDY9Z2+aXXZjVy2uUksMouWfMI9+w5ejOq5zYYTBCQJDQ==} + undici@7.8.0: + resolution: {integrity: sha512-vFv1GA99b7eKO1HG/4RPu2Is3FBTWBrmzqzO0mz+rLxN3yXkE4mqRcb8g8fHxzX4blEysrNZLqg5RbJLqX5buA==} engines: {node: '>=20.18.1'} unenv@1.10.0: @@ -7755,20 +7596,20 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} - verdaccio-audit@13.0.0-next-8.7: - resolution: {integrity: sha512-kd6YdrDztkP1/GDZT7Ue2u41iGPvM9y+5aaUbIBUPvTY/YVv57K6MaCMfn9C/I+ZL4R7XOTSxTtWvz3JK4QrNg==} + verdaccio-audit@13.0.0-next-8.15: + resolution: {integrity: sha512-Aeau0u0fi5l4PoSDyOV6glz2FDO9+ofvogJIELV4H6fhDXhgPc2MnoKuaUgOT//khESLle/a6YfcLY2/KNLs6g==} engines: {node: '>=18'} verdaccio-auth-memory@10.2.2: resolution: {integrity: sha512-JCAnSqwq2l1UPt0hQcPn1B3X9mYpJ5zMsDvuDdmnlWLkrIDx2Wev5fluW0HC9hcFMITFl/DJj/DyzYOOqwhFSQ==} engines: {node: '>=8'} - verdaccio-htpasswd@13.0.0-next-8.7: - resolution: {integrity: sha512-znyFnwt59mLKTAu6eHJrfWP07iaHUlYiQN7QoBo8KMAOT1AecUYreBqs93oKHdIOzjTI8j6tQLg57DpeVS5vgg==} + verdaccio-htpasswd@13.0.0-next-8.15: + resolution: {integrity: sha512-rQg5oZ/rReDAM4g4W68hvtzReTbM6vduvVtobHsQxhbtbotEuUjP6O8uaROYtgZ60giGva5Tub2SOm2T9Ln9Dw==} engines: {node: '>=18'} - verdaccio@6.0.5: - resolution: {integrity: sha512-hv+v4mtG/rcNidGUHXAtNuVySiPE3/PM+7dYye5jCDrhCUmRJYOtnvDe/Ym1ZE/twti39g6izVRxEkjnSp52gA==} + verdaccio@6.1.2: + resolution: {integrity: sha512-HQCquycSQkA+tKRVqMjIVRzmhzTciLfScvKIhhiwZZ9Qd13e2KJQTOdB7QrSacfJuPpl94TA5EZ7XmVRQKk3ag==} engines: {node: '>=18'} hasBin: true @@ -7776,8 +7617,8 @@ packages: resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} engines: {'0': node >=0.6.0} - vite@6.2.1: - resolution: {integrity: sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q==} + vite@6.2.6: + resolution: {integrity: sha512-9xpjNl3kR4rVDZgPNdTL0/c6ao4km69a/2ihNQbcANz8RuCOK3hQBmLSJf3bRKVQjVMda+YvizNE8AwvogcPbw==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -7862,8 +7703,8 @@ packages: webpack: optional: true - webpack-dev-server@5.2.0: - resolution: {integrity: sha512-90SqqYXA2SK36KcT6o1bvwvZfJFcmoamqeJY7+boioffX9g9C0wjjJRGUrQIuh43pb0ttX7+ssavmj/WN2RHtA==} + webpack-dev-server@5.2.1: + resolution: {integrity: sha512-ml/0HIj9NLpVKOMq+SuBPLHcmbG+TGIjXRHsYfZwocUBIqEvws8NnS/V9AFQ5FKP+tgn5adwVwRrTEpGL33QFQ==} engines: {node: '>= 18.12.0'} hasBin: true peerDependencies: @@ -7893,8 +7734,8 @@ packages: html-webpack-plugin: optional: true - webpack@5.98.0: - resolution: {integrity: sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA==} + webpack@5.99.5: + resolution: {integrity: sha512-q+vHBa6H9qwBLUlHL4Y7L0L1/LlyBKZtS9FHNCQmtayxjI5RKC9yD8gpvLeqGv5lCQp1Re04yi0MF40pf30Pvg==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -7911,8 +7752,8 @@ packages: resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} engines: {node: '>=0.8.0'} - whatwg-url@14.1.1: - resolution: {integrity: sha512-mDGf9diDad/giZ/Sm9Xi2YcyzaFpbdLpJPr+E9fSkyQ7KpQD4SdFcugkRQYzhmfI4KeV4Qpnn2sKPdo+kmsgRQ==} + whatwg-url@14.2.0: + resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} engines: {node: '>=18'} whatwg-url@5.0.0: @@ -8069,8 +7910,8 @@ packages: resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} engines: {node: '>=18'} - yaml@2.7.0: - resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==} + yaml@2.7.1: + resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==} engines: {node: '>= 14'} hasBin: true @@ -8130,138 +7971,128 @@ snapshots: '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 - '@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2)': + '@angular/animations@20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))': dependencies: - '@angular/core': 20.0.0-next.2(@angular/compiler@20.0.0-next.2)(rxjs@7.8.2)(zone.js@0.15.0) + '@angular/common': 20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + '@angular/core': 20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0) tslib: 2.8.1 - '@angular/cdk@20.0.0-next.1(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2)(rxjs@7.8.2)': + '@angular/cdk@20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2)': dependencies: - '@angular/common': 20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2) - '@angular/core': 20.0.0-next.2(@angular/compiler@20.0.0-next.2)(rxjs@7.8.2)(zone.js@0.15.0) + '@angular/common': 20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + '@angular/core': 20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0) + parse5: 7.2.1 rxjs: 7.8.2 tslib: 2.8.1 - optionalDependencies: - parse5: 7.2.1 - '@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2)': + '@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2)': dependencies: - '@angular/core': 20.0.0-next.2(@angular/compiler@20.0.0-next.2)(rxjs@7.8.2)(zone.js@0.15.0) + '@angular/core': 20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0) rxjs: 7.8.2 tslib: 2.8.1 - '@angular/compiler-cli@20.0.0-next.2(@angular/compiler@20.0.0-next.2)(typescript@5.8.2)': + '@angular/compiler-cli@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(typescript@5.8.3)': dependencies: - '@angular/compiler': 20.0.0-next.2(@angular/core@20.0.0-next.2) - '@babel/core': 7.26.9 + '@angular/compiler': 20.0.0-next.7 + '@babel/core': 7.26.10 '@jridgewell/sourcemap-codec': 1.5.0 chokidar: 4.0.3 convert-source-map: 1.9.0 reflect-metadata: 0.2.2 semver: 7.7.1 tslib: 2.8.1 - typescript: 5.8.2 + typescript: 5.8.3 yargs: 17.7.2 transitivePeerDependencies: - supports-color - '@angular/compiler@20.0.0-next.2(@angular/core@20.0.0-next.2)': + '@angular/compiler@20.0.0-next.7': dependencies: tslib: 2.8.1 - optionalDependencies: - '@angular/core': 20.0.0-next.2(@angular/compiler@20.0.0-next.2)(rxjs@7.8.2)(zone.js@0.15.0) - '@angular/core@20.0.0-next.2(@angular/compiler@20.0.0-next.2)(rxjs@7.8.2)(zone.js@0.15.0)': + '@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)': dependencies: rxjs: 7.8.2 tslib: 2.8.1 zone.js: 0.15.0 optionalDependencies: - '@angular/compiler': 20.0.0-next.2(@angular/core@20.0.0-next.2) + '@angular/compiler': 20.0.0-next.7 - '@angular/forms@20.0.0-next.2(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2)(@angular/platform-browser@20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2))(rxjs@7.8.2)': + '@angular/forms@20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.0.0-next.7(@angular/animations@20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2)': dependencies: - '@angular/common': 20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2) - '@angular/core': 20.0.0-next.2(@angular/compiler@20.0.0-next.2)(rxjs@7.8.2)(zone.js@0.15.0) - '@angular/platform-browser': 20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2) + '@angular/common': 20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + '@angular/core': 20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0) + '@angular/platform-browser': 20.0.0-next.7(@angular/animations@20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)) rxjs: 7.8.2 tslib: 2.8.1 - '@angular/localize@20.0.0-next.2(@angular/compiler-cli@20.0.0-next.2(@angular/compiler@20.0.0-next.2)(typescript@5.8.2))(@angular/compiler@20.0.0-next.2)': + '@angular/localize@20.0.0-next.7(@angular/compiler-cli@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(typescript@5.8.3))(@angular/compiler@20.0.0-next.7)': dependencies: - '@angular/compiler': 20.0.0-next.2(@angular/core@20.0.0-next.2) - '@angular/compiler-cli': 20.0.0-next.2(@angular/compiler@20.0.0-next.2)(typescript@5.8.2) - '@babel/core': 7.26.9 + '@angular/compiler': 20.0.0-next.7 + '@angular/compiler-cli': 20.0.0-next.7(@angular/compiler@20.0.0-next.7)(typescript@5.8.3) + '@babel/core': 7.26.10 '@types/babel__core': 7.20.5 tinyglobby: 0.2.12 yargs: 17.7.2 transitivePeerDependencies: - supports-color - '@angular/material@20.0.0-next.1(@angular/cdk@20.0.0-next.1(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2)(@angular/forms@20.0.0-next.2(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2)(@angular/platform-browser@20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2))(rxjs@7.8.2))(@angular/platform-browser@20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2))(rxjs@7.8.2)': + '@angular/material@20.0.0-next.7(ozjl26epfqhdomh6tzbizc4svy)': dependencies: - '@angular/cdk': 20.0.0-next.1(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2)(rxjs@7.8.2) - '@angular/common': 20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2) - '@angular/core': 20.0.0-next.2(@angular/compiler@20.0.0-next.2)(rxjs@7.8.2)(zone.js@0.15.0) - '@angular/forms': 20.0.0-next.2(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2)(@angular/platform-browser@20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2))(rxjs@7.8.2) - '@angular/platform-browser': 20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2) + '@angular/cdk': 20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + '@angular/common': 20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + '@angular/core': 20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0) + '@angular/forms': 20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.0.0-next.7(@angular/animations@20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2) + '@angular/platform-browser': 20.0.0-next.7(@angular/animations@20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)) rxjs: 7.8.2 tslib: 2.8.1 - '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/9fd3adb2e8b9a0fef1ba5bc905a900e018445e05(encoding@0.1.13)': + '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/94729f43b53fb611c71c695733d2fb3d873cd25d(encoding@0.1.13)': dependencies: - '@google-cloud/spanner': 7.19.0(encoding@0.1.13)(supports-color@10.0.0) + '@google-cloud/spanner': 7.19.1(encoding@0.1.13)(supports-color@10.0.0) '@octokit/rest': 21.1.1 - '@types/semver': 7.5.8 + '@types/semver': 7.7.0 '@types/supports-color': 10.0.0 '@yarnpkg/lockfile': 1.1.0 chalk: 5.4.1 semver: 7.7.1 supports-color: 10.0.0 typed-graphqlify: 3.1.6 - typescript: 5.8.2 + typescript: 5.8.3 which: 5.0.0 - yaml: 2.7.0 + yaml: 2.7.1 transitivePeerDependencies: - encoding - '@angular/platform-browser-dynamic@20.0.0-next.2(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/compiler@20.0.0-next.2)(@angular/core@20.0.0-next.2)(@angular/platform-browser@20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2))': + '@angular/platform-browser@20.0.0-next.7(@angular/animations@20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))': dependencies: - '@angular/common': 20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2) - '@angular/compiler': 20.0.0-next.2(@angular/core@20.0.0-next.2) - '@angular/core': 20.0.0-next.2(@angular/compiler@20.0.0-next.2)(rxjs@7.8.2)(zone.js@0.15.0) - '@angular/platform-browser': 20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2) - tslib: 2.8.1 - - '@angular/platform-browser@20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2)': - dependencies: - '@angular/common': 20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2) - '@angular/core': 20.0.0-next.2(@angular/compiler@20.0.0-next.2)(rxjs@7.8.2)(zone.js@0.15.0) + '@angular/common': 20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + '@angular/core': 20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0) tslib: 2.8.1 optionalDependencies: - '@angular/animations': 20.0.0-next.2(@angular/core@20.0.0-next.2) + '@angular/animations': 20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)) - '@angular/platform-server@20.0.0-next.2(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/compiler@20.0.0-next.2)(@angular/core@20.0.0-next.2)(@angular/platform-browser@20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2))(rxjs@7.8.2)': + '@angular/platform-server@20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/compiler@20.0.0-next.7)(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.0.0-next.7(@angular/animations@20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2)': dependencies: - '@angular/common': 20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2) - '@angular/compiler': 20.0.0-next.2(@angular/core@20.0.0-next.2) - '@angular/core': 20.0.0-next.2(@angular/compiler@20.0.0-next.2)(rxjs@7.8.2)(zone.js@0.15.0) - '@angular/platform-browser': 20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2) + '@angular/common': 20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + '@angular/compiler': 20.0.0-next.7 + '@angular/core': 20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0) + '@angular/platform-browser': 20.0.0-next.7(@angular/animations@20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)) rxjs: 7.8.2 tslib: 2.8.1 xhr2: 0.2.1 - '@angular/router@20.0.0-next.2(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2)(@angular/platform-browser@20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2))(rxjs@7.8.2)': + '@angular/router@20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.0.0-next.7(@angular/animations@20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2)': dependencies: - '@angular/common': 20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2) - '@angular/core': 20.0.0-next.2(@angular/compiler@20.0.0-next.2)(rxjs@7.8.2)(zone.js@0.15.0) - '@angular/platform-browser': 20.0.0-next.2(@angular/animations@20.0.0-next.2(@angular/core@20.0.0-next.2))(@angular/common@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2))(@angular/core@20.0.0-next.2) + '@angular/common': 20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + '@angular/core': 20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0) + '@angular/platform-browser': 20.0.0-next.7(@angular/animations@20.0.0-next.7(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0)) rxjs: 7.8.2 tslib: 2.8.1 - '@angular/service-worker@20.0.0-next.2(@angular/core@20.0.0-next.2)(rxjs@7.8.2)': + '@angular/service-worker@20.0.0-next.7(@angular/core@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2)': dependencies: - '@angular/core': 20.0.0-next.2(@angular/compiler@20.0.0-next.2)(rxjs@7.8.2)(zone.js@0.15.0) + '@angular/core': 20.0.0-next.7(@angular/compiler@20.0.0-next.7)(rxjs@7.8.2)(zone.js@0.15.0) rxjs: 7.8.2 tslib: 2.8.1 @@ -8277,34 +8108,14 @@ snapshots: dependencies: '@ampproject/remapping': 2.3.0 '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.10 - '@babel/helper-compilation-targets': 7.26.5 + '@babel/generator': 7.27.0 + '@babel/helper-compilation-targets': 7.27.0 '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10) - '@babel/helpers': 7.26.10 - '@babel/parser': 7.26.10 - '@babel/template': 7.26.9 - '@babel/traverse': 7.26.10 - '@babel/types': 7.26.10 - convert-source-map: 2.0.0 - debug: 4.4.0(supports-color@10.0.0) - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - '@babel/core@7.26.9': - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.10 - '@babel/helper-compilation-targets': 7.26.5 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) - '@babel/helpers': 7.26.10 - '@babel/parser': 7.26.10 - '@babel/template': 7.26.9 - '@babel/traverse': 7.26.10 - '@babel/types': 7.26.10 + '@babel/helpers': 7.27.0 + '@babel/parser': 7.27.0 + '@babel/template': 7.27.0 + '@babel/traverse': 7.27.0 + '@babel/types': 7.27.0 convert-source-map: 2.0.0 debug: 4.4.0(supports-color@10.0.0) gensync: 1.0.0-beta.2 @@ -8313,19 +8124,19 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.26.10': + '@babel/generator@7.27.0': dependencies: - '@babel/parser': 7.26.10 - '@babel/types': 7.26.10 + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 jsesc: 3.1.0 '@babel/helper-annotate-as-pure@7.25.9': dependencies: - '@babel/types': 7.26.9 + '@babel/types': 7.27.0 - '@babel/helper-compilation-targets@7.26.5': + '@babel/helper-compilation-targets@7.27.0': dependencies: '@babel/compat-data': 7.26.8 '@babel/helper-validator-option': 7.25.9 @@ -8333,7 +8144,7 @@ snapshots: lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-create-class-features-plugin@7.26.9(@babel/core@7.26.10)': + '@babel/helper-create-class-features-plugin@7.27.0(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 '@babel/helper-annotate-as-pure': 7.25.9 @@ -8341,22 +8152,22 @@ snapshots: '@babel/helper-optimise-call-expression': 7.25.9 '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.10) '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 - '@babel/traverse': 7.26.10 + '@babel/traverse': 7.27.0 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/helper-create-regexp-features-plugin@7.26.3(@babel/core@7.26.10)': + '@babel/helper-create-regexp-features-plugin@7.27.0(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 '@babel/helper-annotate-as-pure': 7.25.9 regexpu-core: 6.2.0 semver: 6.3.1 - '@babel/helper-define-polyfill-provider@0.6.3(@babel/core@7.26.10)': + '@babel/helper-define-polyfill-provider@0.6.4(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 - '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-compilation-targets': 7.27.0 '@babel/helper-plugin-utils': 7.26.5 debug: 4.4.0(supports-color@10.0.0) lodash.debounce: 4.0.8 @@ -8366,15 +8177,15 @@ snapshots: '@babel/helper-member-expression-to-functions@7.25.9': dependencies: - '@babel/traverse': 7.26.10 - '@babel/types': 7.26.10 + '@babel/traverse': 7.27.0 + '@babel/types': 7.27.0 transitivePeerDependencies: - supports-color '@babel/helper-module-imports@7.25.9': dependencies: - '@babel/traverse': 7.26.9 - '@babel/types': 7.26.9 + '@babel/traverse': 7.27.0 + '@babel/types': 7.27.0 transitivePeerDependencies: - supports-color @@ -8383,22 +8194,13 @@ snapshots: '@babel/core': 7.26.10 '@babel/helper-module-imports': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 - '@babel/traverse': 7.26.10 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.9)': - dependencies: - '@babel/core': 7.26.9 - '@babel/helper-module-imports': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - '@babel/traverse': 7.26.10 + '@babel/traverse': 7.27.0 transitivePeerDependencies: - supports-color '@babel/helper-optimise-call-expression@7.25.9': dependencies: - '@babel/types': 7.26.10 + '@babel/types': 7.27.0 '@babel/helper-plugin-utils@7.26.5': {} @@ -8407,7 +8209,7 @@ snapshots: '@babel/core': 7.26.10 '@babel/helper-annotate-as-pure': 7.25.9 '@babel/helper-wrap-function': 7.25.9 - '@babel/traverse': 7.26.9 + '@babel/traverse': 7.27.0 transitivePeerDependencies: - supports-color @@ -8416,20 +8218,20 @@ snapshots: '@babel/core': 7.26.10 '@babel/helper-member-expression-to-functions': 7.25.9 '@babel/helper-optimise-call-expression': 7.25.9 - '@babel/traverse': 7.26.10 + '@babel/traverse': 7.27.0 transitivePeerDependencies: - supports-color '@babel/helper-skip-transparent-expression-wrappers@7.25.9': dependencies: - '@babel/traverse': 7.26.10 - '@babel/types': 7.26.10 + '@babel/traverse': 7.27.0 + '@babel/types': 7.27.0 transitivePeerDependencies: - supports-color '@babel/helper-split-export-declaration@7.24.7': dependencies: - '@babel/types': 7.26.9 + '@babel/types': 7.27.0 '@babel/helper-string-parser@7.25.9': {} @@ -8439,30 +8241,26 @@ snapshots: '@babel/helper-wrap-function@7.25.9': dependencies: - '@babel/template': 7.26.9 - '@babel/traverse': 7.26.9 - '@babel/types': 7.26.9 + '@babel/template': 7.27.0 + '@babel/traverse': 7.27.0 + '@babel/types': 7.27.0 transitivePeerDependencies: - supports-color - '@babel/helpers@7.26.10': + '@babel/helpers@7.27.0': dependencies: - '@babel/template': 7.26.9 - '@babel/types': 7.26.10 + '@babel/template': 7.27.0 + '@babel/types': 7.27.0 - '@babel/parser@7.26.10': + '@babel/parser@7.27.0': dependencies: - '@babel/types': 7.26.10 - - '@babel/parser@7.26.9': - dependencies: - '@babel/types': 7.26.9 + '@babel/types': 7.27.0 '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 '@babel/helper-plugin-utils': 7.26.5 - '@babel/traverse': 7.26.9 + '@babel/traverse': 7.27.0 transitivePeerDependencies: - supports-color @@ -8489,7 +8287,7 @@ snapshots: dependencies: '@babel/core': 7.26.10 '@babel/helper-plugin-utils': 7.26.5 - '@babel/traverse': 7.26.9 + '@babel/traverse': 7.27.0 transitivePeerDependencies: - supports-color @@ -8510,7 +8308,7 @@ snapshots: '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 - '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.10) + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-arrow-functions@7.25.9(@babel/core@7.26.10)': @@ -8523,7 +8321,7 @@ snapshots: '@babel/core': 7.26.10 '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.10) - '@babel/traverse': 7.26.9 + '@babel/traverse': 7.27.0 transitivePeerDependencies: - supports-color @@ -8541,7 +8339,7 @@ snapshots: '@babel/core': 7.26.10 '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-block-scoping@7.25.9(@babel/core@7.26.10)': + '@babel/plugin-transform-block-scoping@7.27.0(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 '@babel/helper-plugin-utils': 7.26.5 @@ -8549,7 +8347,7 @@ snapshots: '@babel/plugin-transform-class-properties@7.25.9(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 - '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.10) + '@babel/helper-create-class-features-plugin': 7.27.0(@babel/core@7.26.10) '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color @@ -8557,7 +8355,7 @@ snapshots: '@babel/plugin-transform-class-static-block@7.26.0(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 - '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.10) + '@babel/helper-create-class-features-plugin': 7.27.0(@babel/core@7.26.10) '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color @@ -8566,10 +8364,10 @@ snapshots: dependencies: '@babel/core': 7.26.10 '@babel/helper-annotate-as-pure': 7.25.9 - '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-compilation-targets': 7.27.0 '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.10) - '@babel/traverse': 7.26.9 + '@babel/traverse': 7.27.0 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -8578,7 +8376,7 @@ snapshots: dependencies: '@babel/core': 7.26.10 '@babel/helper-plugin-utils': 7.26.5 - '@babel/template': 7.26.9 + '@babel/template': 7.27.0 '@babel/plugin-transform-destructuring@7.25.9(@babel/core@7.26.10)': dependencies: @@ -8588,7 +8386,7 @@ snapshots: '@babel/plugin-transform-dotall-regex@7.25.9(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 - '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.10) + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-duplicate-keys@7.25.9(@babel/core@7.26.10)': @@ -8599,7 +8397,7 @@ snapshots: '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 - '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.10) + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-dynamic-import@7.25.9(@babel/core@7.26.10)': @@ -8628,9 +8426,9 @@ snapshots: '@babel/plugin-transform-function-name@7.25.9(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 - '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-compilation-targets': 7.27.0 '@babel/helper-plugin-utils': 7.26.5 - '@babel/traverse': 7.26.9 + '@babel/traverse': 7.27.0 transitivePeerDependencies: - supports-color @@ -8676,7 +8474,7 @@ snapshots: '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10) '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-validator-identifier': 7.25.9 - '@babel/traverse': 7.26.9 + '@babel/traverse': 7.27.0 transitivePeerDependencies: - supports-color @@ -8691,7 +8489,7 @@ snapshots: '@babel/plugin-transform-named-capturing-groups-regex@7.25.9(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 - '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.10) + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-new-target@7.25.9(@babel/core@7.26.10)': @@ -8712,7 +8510,7 @@ snapshots: '@babel/plugin-transform-object-rest-spread@7.25.9(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 - '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-compilation-targets': 7.27.0 '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.10) @@ -8745,7 +8543,7 @@ snapshots: '@babel/plugin-transform-private-methods@7.25.9(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 - '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.10) + '@babel/helper-create-class-features-plugin': 7.27.0(@babel/core@7.26.10) '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color @@ -8754,7 +8552,7 @@ snapshots: dependencies: '@babel/core': 7.26.10 '@babel/helper-annotate-as-pure': 7.25.9 - '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.10) + '@babel/helper-create-class-features-plugin': 7.27.0(@babel/core@7.26.10) '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color @@ -8764,7 +8562,7 @@ snapshots: '@babel/core': 7.26.10 '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-regenerator@7.25.9(@babel/core@7.26.10)': + '@babel/plugin-transform-regenerator@7.27.0(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 '@babel/helper-plugin-utils': 7.26.5 @@ -8773,7 +8571,7 @@ snapshots: '@babel/plugin-transform-regexp-modifiers@7.26.0(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 - '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.10) + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-reserved-words@7.25.9(@babel/core@7.26.10)': @@ -8786,9 +8584,9 @@ snapshots: '@babel/core': 7.26.10 '@babel/helper-module-imports': 7.25.9 '@babel/helper-plugin-utils': 7.26.5 - babel-plugin-polyfill-corejs2: 0.4.12(@babel/core@7.26.10) + babel-plugin-polyfill-corejs2: 0.4.13(@babel/core@7.26.10) babel-plugin-polyfill-corejs3: 0.11.1(@babel/core@7.26.10) - babel-plugin-polyfill-regenerator: 0.6.3(@babel/core@7.26.10) + babel-plugin-polyfill-regenerator: 0.6.4(@babel/core@7.26.10) semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -8816,7 +8614,7 @@ snapshots: '@babel/core': 7.26.10 '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-typeof-symbol@7.26.7(@babel/core@7.26.10)': + '@babel/plugin-transform-typeof-symbol@7.27.0(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 '@babel/helper-plugin-utils': 7.26.5 @@ -8829,26 +8627,26 @@ snapshots: '@babel/plugin-transform-unicode-property-regex@7.25.9(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 - '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.10) + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-unicode-regex@7.25.9(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 - '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.10) + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-unicode-sets-regex@7.25.9(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 - '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.10) + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) '@babel/helper-plugin-utils': 7.26.5 '@babel/preset-env@7.26.9(@babel/core@7.26.10)': dependencies: '@babel/compat-data': 7.26.8 '@babel/core': 7.26.10 - '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-compilation-targets': 7.27.0 '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-validator-option': 7.25.9 '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.25.9(@babel/core@7.26.10) @@ -8864,7 +8662,7 @@ snapshots: '@babel/plugin-transform-async-generator-functions': 7.26.8(@babel/core@7.26.10) '@babel/plugin-transform-async-to-generator': 7.25.9(@babel/core@7.26.10) '@babel/plugin-transform-block-scoped-functions': 7.26.5(@babel/core@7.26.10) - '@babel/plugin-transform-block-scoping': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-block-scoping': 7.27.0(@babel/core@7.26.10) '@babel/plugin-transform-class-properties': 7.25.9(@babel/core@7.26.10) '@babel/plugin-transform-class-static-block': 7.26.0(@babel/core@7.26.10) '@babel/plugin-transform-classes': 7.25.9(@babel/core@7.26.10) @@ -8898,22 +8696,22 @@ snapshots: '@babel/plugin-transform-private-methods': 7.25.9(@babel/core@7.26.10) '@babel/plugin-transform-private-property-in-object': 7.25.9(@babel/core@7.26.10) '@babel/plugin-transform-property-literals': 7.25.9(@babel/core@7.26.10) - '@babel/plugin-transform-regenerator': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-regenerator': 7.27.0(@babel/core@7.26.10) '@babel/plugin-transform-regexp-modifiers': 7.26.0(@babel/core@7.26.10) '@babel/plugin-transform-reserved-words': 7.25.9(@babel/core@7.26.10) '@babel/plugin-transform-shorthand-properties': 7.25.9(@babel/core@7.26.10) '@babel/plugin-transform-spread': 7.25.9(@babel/core@7.26.10) '@babel/plugin-transform-sticky-regex': 7.25.9(@babel/core@7.26.10) '@babel/plugin-transform-template-literals': 7.26.8(@babel/core@7.26.10) - '@babel/plugin-transform-typeof-symbol': 7.26.7(@babel/core@7.26.10) + '@babel/plugin-transform-typeof-symbol': 7.27.0(@babel/core@7.26.10) '@babel/plugin-transform-unicode-escapes': 7.25.9(@babel/core@7.26.10) '@babel/plugin-transform-unicode-property-regex': 7.25.9(@babel/core@7.26.10) '@babel/plugin-transform-unicode-regex': 7.25.9(@babel/core@7.26.10) '@babel/plugin-transform-unicode-sets-regex': 7.25.9(@babel/core@7.26.10) '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.26.10) - babel-plugin-polyfill-corejs2: 0.4.12(@babel/core@7.26.10) + babel-plugin-polyfill-corejs2: 0.4.13(@babel/core@7.26.10) babel-plugin-polyfill-corejs3: 0.11.1(@babel/core@7.26.10) - babel-plugin-polyfill-regenerator: 0.6.3(@babel/core@7.26.10) + babel-plugin-polyfill-regenerator: 0.6.4(@babel/core@7.26.10) core-js-compat: 3.41.0 semver: 6.3.1 transitivePeerDependencies: @@ -8923,54 +8721,37 @@ snapshots: dependencies: '@babel/core': 7.26.10 '@babel/helper-plugin-utils': 7.26.5 - '@babel/types': 7.26.9 + '@babel/types': 7.27.0 esutils: 2.0.3 - '@babel/runtime@7.26.10': + '@babel/runtime@7.27.0': dependencies: regenerator-runtime: 0.14.1 - '@babel/template@7.26.9': - dependencies: - '@babel/code-frame': 7.26.2 - '@babel/parser': 7.26.10 - '@babel/types': 7.26.10 - - '@babel/traverse@7.26.10': + '@babel/template@7.27.0': dependencies: '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.10 - '@babel/parser': 7.26.10 - '@babel/template': 7.26.9 - '@babel/types': 7.26.10 - debug: 4.4.0(supports-color@10.0.0) - globals: 11.12.0 - transitivePeerDependencies: - - supports-color + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 - '@babel/traverse@7.26.9': + '@babel/traverse@7.27.0': dependencies: '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.10 - '@babel/parser': 7.26.9 - '@babel/template': 7.26.9 - '@babel/types': 7.26.9 + '@babel/generator': 7.27.0 + '@babel/parser': 7.27.0 + '@babel/template': 7.27.0 + '@babel/types': 7.27.0 debug: 4.4.0(supports-color@10.0.0) globals: 11.12.0 transitivePeerDependencies: - supports-color - '@babel/types@7.26.10': - dependencies: - '@babel/helper-string-parser': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - - '@babel/types@7.26.9': + '@babel/types@7.27.0': dependencies: '@babel/helper-string-parser': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 - '@bazel/bazelisk@1.25.0': {} + '@bazel/bazelisk@1.26.0': {} '@bazel/buildifier@8.0.3': {} @@ -8980,7 +8761,7 @@ snapshots: dependencies: '@jridgewell/trace-mapping': 0.3.9 - '@cypress/request@3.0.7': + '@cypress/request@3.0.8': dependencies: aws-sign2: 0.7.0 aws4: 1.13.2 @@ -8995,7 +8776,7 @@ snapshots: json-stringify-safe: 5.0.1 mime-types: 2.1.35 performance-now: 2.1.0 - qs: 6.13.1 + qs: 6.14.0 safe-buffer: 5.2.1 tough-cookie: 5.1.2 tunnel-agent: 0.6.0 @@ -9003,93 +8784,93 @@ snapshots: '@discoveryjs/json-ext@0.6.3': {} - '@esbuild/aix-ppc64@0.25.1': + '@esbuild/aix-ppc64@0.25.2': optional: true - '@esbuild/android-arm64@0.25.1': + '@esbuild/android-arm64@0.25.2': optional: true - '@esbuild/android-arm@0.25.1': + '@esbuild/android-arm@0.25.2': optional: true - '@esbuild/android-x64@0.25.1': + '@esbuild/android-x64@0.25.2': optional: true - '@esbuild/darwin-arm64@0.25.1': + '@esbuild/darwin-arm64@0.25.2': optional: true - '@esbuild/darwin-x64@0.25.1': + '@esbuild/darwin-x64@0.25.2': optional: true - '@esbuild/freebsd-arm64@0.25.1': + '@esbuild/freebsd-arm64@0.25.2': optional: true - '@esbuild/freebsd-x64@0.25.1': + '@esbuild/freebsd-x64@0.25.2': optional: true - '@esbuild/linux-arm64@0.25.1': + '@esbuild/linux-arm64@0.25.2': optional: true - '@esbuild/linux-arm@0.25.1': + '@esbuild/linux-arm@0.25.2': optional: true - '@esbuild/linux-ia32@0.25.1': + '@esbuild/linux-ia32@0.25.2': optional: true - '@esbuild/linux-loong64@0.25.1': + '@esbuild/linux-loong64@0.25.2': optional: true - '@esbuild/linux-mips64el@0.25.1': + '@esbuild/linux-mips64el@0.25.2': optional: true - '@esbuild/linux-ppc64@0.25.1': + '@esbuild/linux-ppc64@0.25.2': optional: true - '@esbuild/linux-riscv64@0.25.1': + '@esbuild/linux-riscv64@0.25.2': optional: true - '@esbuild/linux-s390x@0.25.1': + '@esbuild/linux-s390x@0.25.2': optional: true - '@esbuild/linux-x64@0.25.1': + '@esbuild/linux-x64@0.25.2': optional: true - '@esbuild/netbsd-arm64@0.25.1': + '@esbuild/netbsd-arm64@0.25.2': optional: true - '@esbuild/netbsd-x64@0.25.1': + '@esbuild/netbsd-x64@0.25.2': optional: true - '@esbuild/openbsd-arm64@0.25.1': + '@esbuild/openbsd-arm64@0.25.2': optional: true - '@esbuild/openbsd-x64@0.25.1': + '@esbuild/openbsd-x64@0.25.2': optional: true - '@esbuild/sunos-x64@0.25.1': + '@esbuild/sunos-x64@0.25.2': optional: true - '@esbuild/win32-arm64@0.25.1': + '@esbuild/win32-arm64@0.25.2': optional: true - '@esbuild/win32-ia32@0.25.1': + '@esbuild/win32-ia32@0.25.2': optional: true - '@esbuild/win32-x64@0.25.1': + '@esbuild/win32-x64@0.25.2': optional: true - '@eslint-community/eslint-utils@4.5.0(eslint@9.22.0(jiti@1.21.7))': + '@eslint-community/eslint-utils@4.6.0(eslint@9.24.0(jiti@1.21.7))': dependencies: - eslint: 9.22.0(jiti@1.21.7) + eslint: 9.24.0(jiti@1.21.7) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} - '@eslint/compat@1.2.7(eslint@9.22.0(jiti@1.21.7))': + '@eslint/compat@1.2.8(eslint@9.24.0(jiti@1.21.7))': optionalDependencies: - eslint: 9.22.0(jiti@1.21.7) + eslint: 9.24.0(jiti@1.21.7) - '@eslint/config-array@0.19.2': + '@eslint/config-array@0.20.0': dependencies: '@eslint/object-schema': 2.1.6 debug: 4.4.0(supports-color@10.0.0) @@ -9097,13 +8878,17 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.1.0': {} + '@eslint/config-helpers@0.2.1': {} '@eslint/core@0.12.0': dependencies: '@types/json-schema': 7.0.15 - '@eslint/eslintrc@3.3.0': + '@eslint/core@0.13.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.1': dependencies: ajv: 6.12.6 debug: 4.4.0(supports-color@10.0.0) @@ -9117,13 +8902,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.22.0': {} + '@eslint/js@9.24.0': {} '@eslint/object-schema@2.1.6': {} - '@eslint/plugin-kit@0.2.7': + '@eslint/plugin-kit@0.2.8': dependencies: - '@eslint/core': 0.12.0 + '@eslint/core': 0.13.0 levn: 0.4.1 '@glideapps/ts-necessities@2.2.3': {} @@ -9136,7 +8921,7 @@ snapshots: duplexify: 4.1.3 extend: 3.0.2 google-auth-library: 9.15.1(encoding@0.1.13)(supports-color@10.0.0) - html-entities: 2.5.2 + html-entities: 2.6.0 retry-request: 7.0.2(encoding@0.1.13)(supports-color@10.0.0) teeny-request: 9.0.0(encoding@0.1.13)(supports-color@10.0.0) transitivePeerDependencies: @@ -9149,7 +8934,7 @@ snapshots: '@google-cloud/promisify@4.0.0': {} - '@google-cloud/spanner@7.19.0(encoding@0.1.13)(supports-color@10.0.0)': + '@google-cloud/spanner@7.19.1(encoding@0.1.13)(supports-color@10.0.0)': dependencies: '@google-cloud/common': 5.0.2(encoding@0.1.13)(supports-color@10.0.0) '@google-cloud/precise-date': 4.0.0 @@ -9159,7 +8944,7 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/context-async-hooks': 1.30.1(@opentelemetry/api@1.9.0) '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.30.0 + '@opentelemetry/semantic-conventions': 1.32.0 '@types/big.js': 6.2.2 '@types/stack-trace': 0.0.33 arrify: 2.0.1 @@ -9186,7 +8971,7 @@ snapshots: - encoding - supports-color - '@grpc/grpc-js@1.12.6': + '@grpc/grpc-js@1.13.3': dependencies: '@grpc/proto-loader': 0.7.13 '@js-sdsl/ordered-map': 4.4.2 @@ -9213,27 +8998,27 @@ snapshots: '@humanwhocodes/retry@0.4.2': {} - '@inquirer/checkbox@4.1.3(@types/node@20.17.24)': + '@inquirer/checkbox@4.1.5(@types/node@20.17.30)': dependencies: - '@inquirer/core': 10.1.8(@types/node@20.17.24) + '@inquirer/core': 10.1.10(@types/node@20.17.30) '@inquirer/figures': 1.0.11 - '@inquirer/type': 3.0.5(@types/node@20.17.24) + '@inquirer/type': 3.0.6(@types/node@20.17.30) ansi-escapes: 4.3.2 yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 - '@inquirer/confirm@5.1.7(@types/node@20.17.24)': + '@inquirer/confirm@5.1.9(@types/node@20.17.30)': dependencies: - '@inquirer/core': 10.1.8(@types/node@20.17.24) - '@inquirer/type': 3.0.5(@types/node@20.17.24) + '@inquirer/core': 10.1.10(@types/node@20.17.30) + '@inquirer/type': 3.0.6(@types/node@20.17.30) optionalDependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 - '@inquirer/core@10.1.8(@types/node@20.17.24)': + '@inquirer/core@10.1.10(@types/node@20.17.30)': dependencies: '@inquirer/figures': 1.0.11 - '@inquirer/type': 3.0.5(@types/node@20.17.24) + '@inquirer/type': 3.0.6(@types/node@20.17.30) ansi-escapes: 4.3.2 cli-width: 4.1.0 mute-stream: 2.0.0 @@ -9241,97 +9026,97 @@ snapshots: wrap-ansi: 6.2.0 yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 - '@inquirer/editor@4.2.8(@types/node@20.17.24)': + '@inquirer/editor@4.2.10(@types/node@20.17.30)': dependencies: - '@inquirer/core': 10.1.8(@types/node@20.17.24) - '@inquirer/type': 3.0.5(@types/node@20.17.24) + '@inquirer/core': 10.1.10(@types/node@20.17.30) + '@inquirer/type': 3.0.6(@types/node@20.17.30) external-editor: 3.1.0 optionalDependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 - '@inquirer/expand@4.0.10(@types/node@20.17.24)': + '@inquirer/expand@4.0.12(@types/node@20.17.30)': dependencies: - '@inquirer/core': 10.1.8(@types/node@20.17.24) - '@inquirer/type': 3.0.5(@types/node@20.17.24) + '@inquirer/core': 10.1.10(@types/node@20.17.30) + '@inquirer/type': 3.0.6(@types/node@20.17.30) yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@inquirer/figures@1.0.11': {} - '@inquirer/input@4.1.7(@types/node@20.17.24)': + '@inquirer/input@4.1.9(@types/node@20.17.30)': dependencies: - '@inquirer/core': 10.1.8(@types/node@20.17.24) - '@inquirer/type': 3.0.5(@types/node@20.17.24) + '@inquirer/core': 10.1.10(@types/node@20.17.30) + '@inquirer/type': 3.0.6(@types/node@20.17.30) optionalDependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 - '@inquirer/number@3.0.10(@types/node@20.17.24)': + '@inquirer/number@3.0.12(@types/node@20.17.30)': dependencies: - '@inquirer/core': 10.1.8(@types/node@20.17.24) - '@inquirer/type': 3.0.5(@types/node@20.17.24) + '@inquirer/core': 10.1.10(@types/node@20.17.30) + '@inquirer/type': 3.0.6(@types/node@20.17.30) optionalDependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 - '@inquirer/password@4.0.10(@types/node@20.17.24)': + '@inquirer/password@4.0.12(@types/node@20.17.30)': dependencies: - '@inquirer/core': 10.1.8(@types/node@20.17.24) - '@inquirer/type': 3.0.5(@types/node@20.17.24) + '@inquirer/core': 10.1.10(@types/node@20.17.30) + '@inquirer/type': 3.0.6(@types/node@20.17.30) ansi-escapes: 4.3.2 optionalDependencies: - '@types/node': 20.17.24 - - '@inquirer/prompts@7.3.3(@types/node@20.17.24)': - dependencies: - '@inquirer/checkbox': 4.1.3(@types/node@20.17.24) - '@inquirer/confirm': 5.1.7(@types/node@20.17.24) - '@inquirer/editor': 4.2.8(@types/node@20.17.24) - '@inquirer/expand': 4.0.10(@types/node@20.17.24) - '@inquirer/input': 4.1.7(@types/node@20.17.24) - '@inquirer/number': 3.0.10(@types/node@20.17.24) - '@inquirer/password': 4.0.10(@types/node@20.17.24) - '@inquirer/rawlist': 4.0.10(@types/node@20.17.24) - '@inquirer/search': 3.0.10(@types/node@20.17.24) - '@inquirer/select': 4.0.10(@types/node@20.17.24) + '@types/node': 20.17.30 + + '@inquirer/prompts@7.4.1(@types/node@20.17.30)': + dependencies: + '@inquirer/checkbox': 4.1.5(@types/node@20.17.30) + '@inquirer/confirm': 5.1.9(@types/node@20.17.30) + '@inquirer/editor': 4.2.10(@types/node@20.17.30) + '@inquirer/expand': 4.0.12(@types/node@20.17.30) + '@inquirer/input': 4.1.9(@types/node@20.17.30) + '@inquirer/number': 3.0.12(@types/node@20.17.30) + '@inquirer/password': 4.0.12(@types/node@20.17.30) + '@inquirer/rawlist': 4.0.12(@types/node@20.17.30) + '@inquirer/search': 3.0.12(@types/node@20.17.30) + '@inquirer/select': 4.1.1(@types/node@20.17.30) optionalDependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 - '@inquirer/rawlist@4.0.10(@types/node@20.17.24)': + '@inquirer/rawlist@4.0.12(@types/node@20.17.30)': dependencies: - '@inquirer/core': 10.1.8(@types/node@20.17.24) - '@inquirer/type': 3.0.5(@types/node@20.17.24) + '@inquirer/core': 10.1.10(@types/node@20.17.30) + '@inquirer/type': 3.0.6(@types/node@20.17.30) yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 - '@inquirer/search@3.0.10(@types/node@20.17.24)': + '@inquirer/search@3.0.12(@types/node@20.17.30)': dependencies: - '@inquirer/core': 10.1.8(@types/node@20.17.24) + '@inquirer/core': 10.1.10(@types/node@20.17.30) '@inquirer/figures': 1.0.11 - '@inquirer/type': 3.0.5(@types/node@20.17.24) + '@inquirer/type': 3.0.6(@types/node@20.17.30) yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 - '@inquirer/select@4.0.10(@types/node@20.17.24)': + '@inquirer/select@4.1.1(@types/node@20.17.30)': dependencies: - '@inquirer/core': 10.1.8(@types/node@20.17.24) + '@inquirer/core': 10.1.10(@types/node@20.17.30) '@inquirer/figures': 1.0.11 - '@inquirer/type': 3.0.5(@types/node@20.17.24) + '@inquirer/type': 3.0.6(@types/node@20.17.30) ansi-escapes: 4.3.2 yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@inquirer/type@1.5.5': dependencies: mute-stream: 1.0.0 - '@inquirer/type@3.0.5(@types/node@20.17.24)': + '@inquirer/type@3.0.6(@types/node@20.17.30)': optionalDependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@isaacs/cliui@8.0.2': dependencies: @@ -9395,9 +9180,9 @@ snapshots: '@leichtgewicht/ip-codec@2.0.5': {} - '@listr2/prompt-adapter-inquirer@2.0.18(@inquirer/prompts@7.3.3(@types/node@20.17.24))': + '@listr2/prompt-adapter-inquirer@2.0.21(@inquirer/prompts@7.4.1(@types/node@20.17.30))': dependencies: - '@inquirer/prompts': 7.3.3(@types/node@20.17.24) + '@inquirer/prompts': 7.4.1(@types/node@20.17.30) '@inquirer/type': 1.5.5 '@lmdb/lmdb-darwin-arm64@3.2.6': @@ -9552,7 +9337,7 @@ snapshots: dependencies: '@npmcli/git': 6.0.3 glob: 10.4.5 - hosted-git-info: 8.0.2 + hosted-git-info: 8.1.0 json-parse-even-better-errors: 4.0.0 proc-log: 5.0.0 semver: 7.7.1 @@ -9569,7 +9354,7 @@ snapshots: '@npmcli/node-gyp': 4.0.0 '@npmcli/package-json': 6.1.1 '@npmcli/promise-spawn': 8.0.2 - node-gyp: 11.1.0 + node-gyp: 11.2.0 proc-log: 5.0.0 which: 5.0.0 transitivePeerDependencies: @@ -9577,65 +9362,71 @@ snapshots: '@octokit/auth-token@5.1.2': {} - '@octokit/core@6.1.4': + '@octokit/core@6.1.5': dependencies: '@octokit/auth-token': 5.1.2 - '@octokit/graphql': 8.2.1 - '@octokit/request': 9.2.2 - '@octokit/request-error': 6.1.7 - '@octokit/types': 13.8.0 + '@octokit/graphql': 8.2.2 + '@octokit/request': 9.2.3 + '@octokit/request-error': 6.1.8 + '@octokit/types': 14.0.0 before-after-hook: 3.0.2 universal-user-agent: 7.0.2 - '@octokit/endpoint@10.1.3': + '@octokit/endpoint@10.1.4': dependencies: - '@octokit/types': 13.8.0 + '@octokit/types': 14.0.0 universal-user-agent: 7.0.2 - '@octokit/graphql@8.2.1': + '@octokit/graphql@8.2.2': dependencies: - '@octokit/request': 9.2.2 - '@octokit/types': 13.8.0 + '@octokit/request': 9.2.3 + '@octokit/types': 14.0.0 universal-user-agent: 7.0.2 - '@octokit/openapi-types@23.0.1': {} + '@octokit/openapi-types@24.2.0': {} - '@octokit/plugin-paginate-rest@11.4.3(@octokit/core@6.1.4)': + '@octokit/openapi-types@25.0.0': {} + + '@octokit/plugin-paginate-rest@11.6.0(@octokit/core@6.1.5)': dependencies: - '@octokit/core': 6.1.4 - '@octokit/types': 13.8.0 + '@octokit/core': 6.1.5 + '@octokit/types': 13.10.0 - '@octokit/plugin-request-log@5.3.1(@octokit/core@6.1.4)': + '@octokit/plugin-request-log@5.3.1(@octokit/core@6.1.5)': dependencies: - '@octokit/core': 6.1.4 + '@octokit/core': 6.1.5 - '@octokit/plugin-rest-endpoint-methods@13.3.1(@octokit/core@6.1.4)': + '@octokit/plugin-rest-endpoint-methods@13.5.0(@octokit/core@6.1.5)': dependencies: - '@octokit/core': 6.1.4 - '@octokit/types': 13.8.0 + '@octokit/core': 6.1.5 + '@octokit/types': 13.10.0 - '@octokit/request-error@6.1.7': + '@octokit/request-error@6.1.8': dependencies: - '@octokit/types': 13.8.0 + '@octokit/types': 14.0.0 - '@octokit/request@9.2.2': + '@octokit/request@9.2.3': dependencies: - '@octokit/endpoint': 10.1.3 - '@octokit/request-error': 6.1.7 - '@octokit/types': 13.8.0 + '@octokit/endpoint': 10.1.4 + '@octokit/request-error': 6.1.8 + '@octokit/types': 14.0.0 fast-content-type-parse: 2.0.1 universal-user-agent: 7.0.2 '@octokit/rest@21.1.1': dependencies: - '@octokit/core': 6.1.4 - '@octokit/plugin-paginate-rest': 11.4.3(@octokit/core@6.1.4) - '@octokit/plugin-request-log': 5.3.1(@octokit/core@6.1.4) - '@octokit/plugin-rest-endpoint-methods': 13.3.1(@octokit/core@6.1.4) + '@octokit/core': 6.1.5 + '@octokit/plugin-paginate-rest': 11.6.0(@octokit/core@6.1.5) + '@octokit/plugin-request-log': 5.3.1(@octokit/core@6.1.5) + '@octokit/plugin-rest-endpoint-methods': 13.5.0(@octokit/core@6.1.5) + + '@octokit/types@13.10.0': + dependencies: + '@octokit/openapi-types': 24.2.0 - '@octokit/types@13.8.0': + '@octokit/types@14.0.0': dependencies: - '@octokit/openapi-types': 23.0.1 + '@octokit/openapi-types': 25.0.0 '@opentelemetry/api@1.9.0': {} @@ -9650,7 +9441,7 @@ snapshots: '@opentelemetry/semantic-conventions@1.28.0': {} - '@opentelemetry/semantic-conventions@1.30.0': {} + '@opentelemetry/semantic-conventions@1.32.0': {} '@parcel/watcher-android-arm64@2.5.1': optional: true @@ -9739,7 +9530,7 @@ snapshots: '@protobufjs/utf8@1.1.0': {} - '@puppeteer/browsers@2.8.0': + '@puppeteer/browsers@2.10.0': dependencies: debug: 4.4.0(supports-color@10.0.0) extract-zip: 2.0.1 @@ -9752,13 +9543,13 @@ snapshots: - bare-buffer - supports-color - '@rollup/plugin-alias@5.1.1(rollup@4.35.0)': + '@rollup/plugin-alias@5.1.1(rollup@4.40.0)': optionalDependencies: - rollup: 4.35.0 + rollup: 4.40.0 - '@rollup/plugin-commonjs@28.0.3(rollup@4.35.0)': + '@rollup/plugin-commonjs@28.0.3(rollup@4.40.0)': dependencies: - '@rollup/pluginutils': 5.1.4(rollup@4.35.0) + '@rollup/pluginutils': 5.1.4(rollup@4.40.0) commondir: 1.0.1 estree-walker: 2.0.2 fdir: 6.4.3(picomatch@4.0.2) @@ -9766,109 +9557,105 @@ snapshots: magic-string: 0.30.17 picomatch: 4.0.2 optionalDependencies: - rollup: 4.35.0 + rollup: 4.40.0 - '@rollup/plugin-json@6.1.0(rollup@4.35.0)': + '@rollup/plugin-json@6.1.0(rollup@4.40.0)': dependencies: - '@rollup/pluginutils': 5.1.4(rollup@4.35.0) + '@rollup/pluginutils': 5.1.4(rollup@4.40.0) optionalDependencies: - rollup: 4.35.0 + rollup: 4.40.0 - '@rollup/plugin-node-resolve@13.3.0(rollup@4.35.0)': + '@rollup/plugin-node-resolve@15.3.1(rollup@4.40.0)': dependencies: - '@rollup/pluginutils': 3.1.0(rollup@4.35.0) - '@types/resolve': 1.17.1 + '@rollup/pluginutils': 5.1.4(rollup@4.40.0) + '@types/resolve': 1.20.2 deepmerge: 4.3.1 - is-builtin-module: 3.2.1 is-module: 1.0.0 resolve: 1.22.10 - rollup: 4.35.0 + optionalDependencies: + rollup: 4.40.0 - '@rollup/plugin-node-resolve@15.3.1(rollup@4.35.0)': + '@rollup/plugin-node-resolve@16.0.1(rollup@4.40.0)': dependencies: - '@rollup/pluginutils': 5.1.4(rollup@4.35.0) + '@rollup/pluginutils': 5.1.4(rollup@4.40.0) '@types/resolve': 1.20.2 deepmerge: 4.3.1 is-module: 1.0.0 resolve: 1.22.10 optionalDependencies: - rollup: 4.35.0 - - '@rollup/pluginutils@3.1.0(rollup@4.35.0)': - dependencies: - '@types/estree': 0.0.39 - estree-walker: 1.0.1 - picomatch: 2.3.1 - rollup: 4.35.0 + rollup: 4.40.0 - '@rollup/pluginutils@5.1.4(rollup@4.35.0)': + '@rollup/pluginutils@5.1.4(rollup@4.40.0)': dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 estree-walker: 2.0.2 picomatch: 4.0.2 optionalDependencies: - rollup: 4.35.0 + rollup: 4.40.0 + + '@rollup/rollup-android-arm-eabi@4.40.0': + optional: true - '@rollup/rollup-android-arm-eabi@4.35.0': + '@rollup/rollup-android-arm64@4.40.0': optional: true - '@rollup/rollup-android-arm64@4.35.0': + '@rollup/rollup-darwin-arm64@4.40.0': optional: true - '@rollup/rollup-darwin-arm64@4.35.0': + '@rollup/rollup-darwin-x64@4.40.0': optional: true - '@rollup/rollup-darwin-x64@4.35.0': + '@rollup/rollup-freebsd-arm64@4.40.0': optional: true - '@rollup/rollup-freebsd-arm64@4.35.0': + '@rollup/rollup-freebsd-x64@4.40.0': optional: true - '@rollup/rollup-freebsd-x64@4.35.0': + '@rollup/rollup-linux-arm-gnueabihf@4.40.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.35.0': + '@rollup/rollup-linux-arm-musleabihf@4.40.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.35.0': + '@rollup/rollup-linux-arm64-gnu@4.40.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.35.0': + '@rollup/rollup-linux-arm64-musl@4.40.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.35.0': + '@rollup/rollup-linux-loongarch64-gnu@4.40.0': optional: true - '@rollup/rollup-linux-loongarch64-gnu@4.35.0': + '@rollup/rollup-linux-powerpc64le-gnu@4.40.0': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.35.0': + '@rollup/rollup-linux-riscv64-gnu@4.40.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.35.0': + '@rollup/rollup-linux-riscv64-musl@4.40.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.35.0': + '@rollup/rollup-linux-s390x-gnu@4.40.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.35.0': + '@rollup/rollup-linux-x64-gnu@4.40.0': optional: true - '@rollup/rollup-linux-x64-musl@4.35.0': + '@rollup/rollup-linux-x64-musl@4.40.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.35.0': + '@rollup/rollup-win32-arm64-msvc@4.40.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.35.0': + '@rollup/rollup-win32-ia32-msvc@4.40.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.35.0': + '@rollup/rollup-win32-x64-msvc@4.40.0': optional: true - '@rollup/wasm-node@4.35.0': + '@rollup/wasm-node@4.40.0': dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 optionalDependencies: fsevents: 2.3.3 @@ -9876,17 +9663,17 @@ snapshots: '@sigstore/bundle@3.1.0': dependencies: - '@sigstore/protobuf-specs': 0.4.0 + '@sigstore/protobuf-specs': 0.4.1 '@sigstore/core@2.0.0': {} - '@sigstore/protobuf-specs@0.4.0': {} + '@sigstore/protobuf-specs@0.4.1': {} '@sigstore/sign@3.1.0': dependencies: '@sigstore/bundle': 3.1.0 '@sigstore/core': 2.0.0 - '@sigstore/protobuf-specs': 0.4.0 + '@sigstore/protobuf-specs': 0.4.1 make-fetch-happen: 14.0.3 proc-log: 5.0.0 promise-retry: 2.0.1 @@ -9895,7 +9682,7 @@ snapshots: '@sigstore/tuf@3.1.0': dependencies: - '@sigstore/protobuf-specs': 0.4.0 + '@sigstore/protobuf-specs': 0.4.1 tuf-js: 3.0.1 transitivePeerDependencies: - supports-color @@ -9904,14 +9691,14 @@ snapshots: dependencies: '@sigstore/bundle': 3.1.0 '@sigstore/core': 2.0.0 - '@sigstore/protobuf-specs': 0.4.0 + '@sigstore/protobuf-specs': 0.4.1 '@socket.io/component-emitter@3.1.2': {} - '@stylistic/eslint-plugin@4.2.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.8.2)': + '@stylistic/eslint-plugin@4.2.0(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3)': dependencies: - '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.8.2) - eslint: 9.22.0(jiti@1.21.7) + '@typescript-eslint/utils': 8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3) + eslint: 9.24.0(jiti@1.21.7) eslint-visitor-keys: 4.2.0 espree: 10.3.0 estraverse: 5.3.0 @@ -9941,46 +9728,46 @@ snapshots: '@types/accepts@1.3.7': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/babel__code-frame@7.0.6': {} '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.26.9 - '@babel/types': 7.26.9 - '@types/babel__generator': 7.6.8 + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 + '@types/babel__generator': 7.27.0 '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.20.6 + '@types/babel__traverse': 7.20.7 - '@types/babel__generator@7.6.8': + '@types/babel__generator@7.27.0': dependencies: - '@babel/types': 7.26.9 + '@babel/types': 7.27.0 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.26.9 - '@babel/types': 7.26.9 + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 - '@types/babel__traverse@7.20.6': + '@types/babel__traverse@7.20.7': dependencies: - '@babel/types': 7.26.9 + '@babel/types': 7.27.0 '@types/big.js@6.2.2': {} '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.38 - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/bonjour@3.5.13': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/browser-sync@2.29.0': dependencies: '@types/micromatch': 2.3.35 - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/serve-static': 1.15.7 chokidar: 3.6.0 @@ -9988,19 +9775,19 @@ snapshots: '@types/co-body@6.1.3': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/qs': 6.9.18 '@types/command-line-args@5.2.3': {} '@types/connect-history-api-fallback@1.5.4': dependencies: - '@types/express-serve-static-core': 5.0.6 - '@types/node': 20.17.24 + '@types/express-serve-static-core': 4.19.6 + '@types/node': 20.17.30 '@types/connect@3.4.38': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/content-disposition@0.5.8': {} @@ -10009,44 +9796,42 @@ snapshots: '@types/cookies@0.9.0': dependencies: '@types/connect': 3.4.38 - '@types/express': 4.17.21 + '@types/express': 5.0.1 '@types/keygrip': 1.0.6 - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/cors@2.8.17': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/debounce@1.2.4': {} '@types/duplexify@3.6.4': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/eslint-scope@3.7.7': dependencies: '@types/eslint': 9.6.1 - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 '@types/eslint@9.6.1': dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 '@types/json-schema': 7.0.15 - '@types/estree@0.0.39': {} - - '@types/estree@1.0.6': {} + '@types/estree@1.0.7': {} '@types/express-serve-static-core@4.19.6': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/qs': 6.9.18 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 '@types/express-serve-static-core@5.0.6': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/qs': 6.9.18 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -10058,14 +9843,20 @@ snapshots: '@types/qs': 6.9.18 '@types/serve-static': 1.15.7 + '@types/express@5.0.1': + dependencies: + '@types/body-parser': 1.19.5 + '@types/express-serve-static-core': 5.0.6 + '@types/serve-static': 1.15.7 + '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/http-assert@1.5.6': {} @@ -10073,7 +9864,7 @@ snapshots: '@types/http-proxy@1.17.16': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/ini@4.1.1': {} @@ -10099,7 +9890,7 @@ snapshots: '@types/karma@6.3.9': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 log4js: 6.9.1 transitivePeerDependencies: - supports-color @@ -10119,13 +9910,13 @@ snapshots: '@types/http-errors': 2.0.4 '@types/keygrip': 1.0.6 '@types/koa-compose': 3.2.8 - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/less@3.0.8': {} '@types/loader-utils@2.0.6': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/webpack': 4.41.40 '@types/lodash@4.17.16': {} @@ -10142,14 +9933,14 @@ snapshots: '@types/node-fetch@2.6.12': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 form-data: 4.0.2 '@types/node-forge@1.3.11': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 - '@types/node@20.17.24': + '@types/node@20.17.30': dependencies: undici-types: 6.19.8 @@ -10157,7 +9948,7 @@ snapshots: '@types/npm-registry-fetch@8.0.7': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/node-fetch': 2.6.12 '@types/npm-package-arg': 6.1.4 '@types/npmlog': 7.0.0 @@ -10165,11 +9956,11 @@ snapshots: '@types/npmlog@7.0.0': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/pacote@11.1.8': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/npm-registry-fetch': 8.0.7 '@types/npmlog': 7.0.0 '@types/ssri': 7.1.5 @@ -10178,16 +9969,16 @@ snapshots: '@types/parse5@6.0.3': {} - '@types/picomatch@3.0.2': {} + '@types/picomatch@4.0.0': {} '@types/progress@2.0.7': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/pumpify@1.4.4': dependencies: '@types/duplexify': 3.6.4 - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/q@0.0.32': {} @@ -10198,14 +9989,10 @@ snapshots: '@types/request@2.48.12': dependencies: '@types/caseless': 0.12.5 - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/tough-cookie': 4.0.5 form-data: 2.5.3 - '@types/resolve@1.17.1': - dependencies: - '@types/node': 20.17.24 - '@types/resolve@1.20.2': {} '@types/resolve@1.20.6': {} @@ -10214,37 +10001,37 @@ snapshots: '@types/selenium-webdriver@3.0.26': {} - '@types/semver@7.5.8': {} + '@types/semver@7.7.0': {} '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/serve-index@1.9.4': dependencies: - '@types/express': 4.17.21 + '@types/express': 5.0.1 '@types/serve-static@1.15.7': dependencies: '@types/http-errors': 2.0.4 - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/send': 0.17.4 '@types/shelljs@0.8.15': dependencies: '@types/glob': 7.2.0 - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/sockjs@0.3.36': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/source-list-map@0.1.6': {} '@types/ssri@7.1.5': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/stack-trace@0.0.33': {} @@ -10263,17 +10050,17 @@ snapshots: '@types/watchpack@2.4.4': dependencies: '@types/graceful-fs': 4.1.9 - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/webpack-sources@3.2.3': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/source-list-map': 0.1.6 source-map: 0.7.4 '@types/webpack@4.41.40': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/tapable': 1.0.12 '@types/uglify-js': 3.17.5 '@types/webpack-sources': 3.2.3 @@ -10282,11 +10069,11 @@ snapshots: '@types/ws@7.4.7': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 - '@types/ws@8.18.0': + '@types/ws@8.18.1': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 '@types/yargs-parser@21.0.3': {} @@ -10298,96 +10085,96 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 optional: true - '@typescript-eslint/eslint-plugin@8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.8.2))(eslint@9.22.0(jiti@1.21.7))(typescript@5.8.2)': + '@typescript-eslint/eslint-plugin@8.30.1(@typescript-eslint/parser@8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.8.2) - '@typescript-eslint/scope-manager': 8.26.1 - '@typescript-eslint/type-utils': 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.8.2) - '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.8.2) - '@typescript-eslint/visitor-keys': 8.26.1 - eslint: 9.22.0(jiti@1.21.7) + '@typescript-eslint/parser': 8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/scope-manager': 8.30.1 + '@typescript-eslint/type-utils': 8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/utils': 8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.30.1 + eslint: 9.24.0(jiti@1.21.7) graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 - ts-api-utils: 2.0.1(typescript@5.8.2) - typescript: 5.8.2 + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.8.2)': + '@typescript-eslint/parser@8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3)': dependencies: - '@typescript-eslint/scope-manager': 8.26.1 - '@typescript-eslint/types': 8.26.1 - '@typescript-eslint/typescript-estree': 8.26.1(typescript@5.8.2) - '@typescript-eslint/visitor-keys': 8.26.1 + '@typescript-eslint/scope-manager': 8.30.1 + '@typescript-eslint/types': 8.30.1 + '@typescript-eslint/typescript-estree': 8.30.1(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.30.1 debug: 4.4.0(supports-color@10.0.0) - eslint: 9.22.0(jiti@1.21.7) - typescript: 5.8.2 + eslint: 9.24.0(jiti@1.21.7) + typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.26.1': + '@typescript-eslint/scope-manager@8.30.1': dependencies: - '@typescript-eslint/types': 8.26.1 - '@typescript-eslint/visitor-keys': 8.26.1 + '@typescript-eslint/types': 8.30.1 + '@typescript-eslint/visitor-keys': 8.30.1 - '@typescript-eslint/type-utils@8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.8.2)': + '@typescript-eslint/type-utils@8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3)': dependencies: - '@typescript-eslint/typescript-estree': 8.26.1(typescript@5.8.2) - '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.8.2) + '@typescript-eslint/typescript-estree': 8.30.1(typescript@5.8.3) + '@typescript-eslint/utils': 8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3) debug: 4.4.0(supports-color@10.0.0) - eslint: 9.22.0(jiti@1.21.7) - ts-api-utils: 2.0.1(typescript@5.8.2) - typescript: 5.8.2 + eslint: 9.24.0(jiti@1.21.7) + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.26.1': {} + '@typescript-eslint/types@8.30.1': {} - '@typescript-eslint/typescript-estree@8.26.1(typescript@5.8.2)': + '@typescript-eslint/typescript-estree@8.30.1(typescript@5.8.3)': dependencies: - '@typescript-eslint/types': 8.26.1 - '@typescript-eslint/visitor-keys': 8.26.1 + '@typescript-eslint/types': 8.30.1 + '@typescript-eslint/visitor-keys': 8.30.1 debug: 4.4.0(supports-color@10.0.0) fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.7.1 - ts-api-utils: 2.0.1(typescript@5.8.2) - typescript: 5.8.2 + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.8.2)': + '@typescript-eslint/utils@8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3)': dependencies: - '@eslint-community/eslint-utils': 4.5.0(eslint@9.22.0(jiti@1.21.7)) - '@typescript-eslint/scope-manager': 8.26.1 - '@typescript-eslint/types': 8.26.1 - '@typescript-eslint/typescript-estree': 8.26.1(typescript@5.8.2) - eslint: 9.22.0(jiti@1.21.7) - typescript: 5.8.2 + '@eslint-community/eslint-utils': 4.6.0(eslint@9.24.0(jiti@1.21.7)) + '@typescript-eslint/scope-manager': 8.30.1 + '@typescript-eslint/types': 8.30.1 + '@typescript-eslint/typescript-estree': 8.30.1(typescript@5.8.3) + eslint: 9.24.0(jiti@1.21.7) + typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.26.1': + '@typescript-eslint/visitor-keys@8.30.1': dependencies: - '@typescript-eslint/types': 8.26.1 + '@typescript-eslint/types': 8.30.1 eslint-visitor-keys: 4.2.0 - '@verdaccio/auth@8.0.0-next-8.7': + '@verdaccio/auth@8.0.0-next-8.15': dependencies: - '@verdaccio/config': 8.0.0-next-8.7 - '@verdaccio/core': 8.0.0-next-8.7 - '@verdaccio/loaders': 8.0.0-next-8.4 - '@verdaccio/signature': 8.0.0-next-8.1 - '@verdaccio/utils': 8.1.0-next-8.7 + '@verdaccio/config': 8.0.0-next-8.15 + '@verdaccio/core': 8.0.0-next-8.15 + '@verdaccio/loaders': 8.0.0-next-8.6 + '@verdaccio/signature': 8.0.0-next-8.7 + '@verdaccio/utils': 8.1.0-next-8.15 debug: 4.4.0(supports-color@10.0.0) lodash: 4.17.21 - verdaccio-htpasswd: 13.0.0-next-8.7 + verdaccio-htpasswd: 13.0.0-next-8.15 transitivePeerDependencies: - supports-color @@ -10396,10 +10183,10 @@ snapshots: http-errors: 2.0.0 http-status-codes: 2.2.0 - '@verdaccio/config@8.0.0-next-8.7': + '@verdaccio/config@8.0.0-next-8.15': dependencies: - '@verdaccio/core': 8.0.0-next-8.7 - '@verdaccio/utils': 8.1.0-next-8.7 + '@verdaccio/core': 8.0.0-next-8.15 + '@verdaccio/utils': 8.1.0-next-8.15 debug: 4.4.0(supports-color@10.0.0) js-yaml: 4.1.0 lodash: 4.17.21 @@ -10407,35 +10194,26 @@ snapshots: transitivePeerDependencies: - supports-color - '@verdaccio/core@8.0.0-next-8.1': - dependencies: - ajv: 8.17.1 - core-js: 3.37.1 - http-errors: 2.0.0 - http-status-codes: 2.3.0 - process-warning: 1.0.0 - semver: 7.6.3 - - '@verdaccio/core@8.0.0-next-8.7': + '@verdaccio/core@8.0.0-next-8.15': dependencies: ajv: 8.17.1 - core-js: 3.37.1 + core-js: 3.40.0 http-errors: 2.0.0 http-status-codes: 2.3.0 process-warning: 1.0.0 - semver: 7.6.3 + semver: 7.7.1 '@verdaccio/file-locking@10.3.1': dependencies: lockfile: 1.0.4 - '@verdaccio/file-locking@13.0.0-next-8.2': + '@verdaccio/file-locking@13.0.0-next-8.3': dependencies: lockfile: 1.0.4 - '@verdaccio/loaders@8.0.0-next-8.4': + '@verdaccio/loaders@8.0.0-next-8.6': dependencies: - debug: 4.3.7 + debug: 4.4.0(supports-color@10.0.0) lodash: 4.17.21 transitivePeerDependencies: - supports-color @@ -10453,16 +10231,16 @@ snapshots: transitivePeerDependencies: - supports-color - '@verdaccio/logger-commons@8.0.0-next-8.7': + '@verdaccio/logger-commons@8.0.0-next-8.15': dependencies: - '@verdaccio/core': 8.0.0-next-8.7 - '@verdaccio/logger-prettify': 8.0.0-next-8.1 + '@verdaccio/core': 8.0.0-next-8.15 + '@verdaccio/logger-prettify': 8.0.0-next-8.2 colorette: 2.0.20 debug: 4.4.0(supports-color@10.0.0) transitivePeerDependencies: - supports-color - '@verdaccio/logger-prettify@8.0.0-next-8.1': + '@verdaccio/logger-prettify@8.0.0-next-8.2': dependencies: colorette: 2.0.20 dayjs: 1.11.13 @@ -10470,19 +10248,19 @@ snapshots: pino-abstract-transport: 1.2.0 sonic-boom: 3.8.1 - '@verdaccio/logger@8.0.0-next-8.7': + '@verdaccio/logger@8.0.0-next-8.15': dependencies: - '@verdaccio/logger-commons': 8.0.0-next-8.7 - pino: 9.5.0 + '@verdaccio/logger-commons': 8.0.0-next-8.15 + pino: 9.6.0 transitivePeerDependencies: - supports-color - '@verdaccio/middleware@8.0.0-next-8.7': + '@verdaccio/middleware@8.0.0-next-8.15': dependencies: - '@verdaccio/config': 8.0.0-next-8.7 - '@verdaccio/core': 8.0.0-next-8.7 - '@verdaccio/url': 13.0.0-next-8.7 - '@verdaccio/utils': 8.1.0-next-8.7 + '@verdaccio/config': 8.0.0-next-8.15 + '@verdaccio/core': 8.0.0-next-8.15 + '@verdaccio/url': 13.0.0-next-8.15 + '@verdaccio/utils': 8.1.0-next-8.15 debug: 4.4.0(supports-color@10.0.0) express: 4.21.2 express-rate-limit: 5.5.1 @@ -10492,22 +10270,23 @@ snapshots: transitivePeerDependencies: - supports-color - '@verdaccio/search-indexer@8.0.0-next-8.2': {} + '@verdaccio/search-indexer@8.0.0-next-8.4': {} - '@verdaccio/signature@8.0.0-next-8.1': + '@verdaccio/signature@8.0.0-next-8.7': dependencies: - debug: 4.3.7 + '@verdaccio/config': 8.0.0-next-8.15 + debug: 4.4.0(supports-color@10.0.0) jsonwebtoken: 9.0.2 transitivePeerDependencies: - supports-color '@verdaccio/streams@10.2.1': {} - '@verdaccio/tarball@13.0.0-next-8.7': + '@verdaccio/tarball@13.0.0-next-8.15': dependencies: - '@verdaccio/core': 8.0.0-next-8.7 - '@verdaccio/url': 13.0.0-next-8.7 - '@verdaccio/utils': 8.1.0-next-8.7 + '@verdaccio/core': 8.0.0-next-8.15 + '@verdaccio/url': 13.0.0-next-8.15 + '@verdaccio/utils': 8.1.0-next-8.15 debug: 4.4.0(supports-color@10.0.0) gunzip-maybe: 1.4.2 lodash: 4.17.21 @@ -10515,40 +10294,33 @@ snapshots: transitivePeerDependencies: - supports-color - '@verdaccio/ui-theme@8.0.0-next-8.7': {} + '@verdaccio/ui-theme@8.0.0-next-8.15': {} - '@verdaccio/url@13.0.0-next-8.7': + '@verdaccio/url@13.0.0-next-8.15': dependencies: - '@verdaccio/core': 8.0.0-next-8.7 + '@verdaccio/core': 8.0.0-next-8.15 debug: 4.4.0(supports-color@10.0.0) lodash: 4.17.21 validator: 13.12.0 transitivePeerDependencies: - supports-color - '@verdaccio/utils@7.0.1-next-8.1': - dependencies: - '@verdaccio/core': 8.0.0-next-8.1 - lodash: 4.17.21 - minimatch: 7.4.6 - semver: 7.6.3 - - '@verdaccio/utils@8.1.0-next-8.7': + '@verdaccio/utils@8.1.0-next-8.15': dependencies: - '@verdaccio/core': 8.0.0-next-8.7 + '@verdaccio/core': 8.0.0-next-8.15 lodash: 4.17.21 minimatch: 7.4.6 - semver: 7.6.3 + semver: 7.7.1 - '@vitejs/plugin-basic-ssl@2.0.0(vite@6.2.1(@types/node@20.17.24)(jiti@1.21.7)(less@4.2.2)(sass@1.85.1)(terser@5.39.0)(yaml@2.7.0))': + '@vitejs/plugin-basic-ssl@2.0.0(vite@6.2.6(@types/node@20.17.30)(jiti@1.21.7)(less@4.3.0)(sass@1.86.3)(terser@5.39.0)(yaml@2.7.1))': dependencies: - vite: 6.2.1(@types/node@20.17.24)(jiti@1.21.7)(less@4.2.2)(sass@1.85.1)(terser@5.39.0)(yaml@2.7.0) + vite: 6.2.6(@types/node@20.17.30)(jiti@1.21.7)(less@4.3.0)(sass@1.86.3)(terser@5.39.0)(yaml@2.7.1) '@web/browser-logs@0.4.1': dependencies: errorstacks: 2.4.1 - '@web/config-loader@0.3.2': {} + '@web/config-loader@0.3.3': {} '@web/dev-server-core@0.7.5': dependencies: @@ -10561,7 +10333,7 @@ snapshots: get-stream: 6.0.1 is-stream: 2.0.1 isbinaryfile: 5.0.4 - koa: 2.16.0 + koa: 2.16.1 koa-etag: 4.0.0 koa-send: 5.0.1 koa-static: 5.0.0 @@ -10577,12 +10349,12 @@ snapshots: '@web/dev-server-rollup@0.6.4': dependencies: - '@rollup/plugin-node-resolve': 15.3.1(rollup@4.35.0) + '@rollup/plugin-node-resolve': 15.3.1(rollup@4.40.0) '@web/dev-server-core': 0.7.5 nanocolors: 0.2.13 parse5: 6.0.1 - rollup: 4.35.0 - whatwg-url: 14.1.1 + rollup: 4.40.0 + whatwg-url: 14.2.0 transitivePeerDependencies: - bufferutil - supports-color @@ -10592,7 +10364,7 @@ snapshots: dependencies: '@babel/code-frame': 7.26.2 '@types/command-line-args': 5.2.3 - '@web/config-loader': 0.3.2 + '@web/config-loader': 0.3.3 '@web/dev-server-core': 0.7.5 '@web/dev-server-rollup': 0.6.4 camelcase: 6.3.0 @@ -10603,7 +10375,7 @@ snapshots: internal-ip: 6.2.0 nanocolors: 0.2.13 open: 8.4.2 - portfinder: 1.0.33 + portfinder: 1.0.36 transitivePeerDependencies: - bufferutil - supports-color @@ -10614,13 +10386,12 @@ snapshots: '@types/parse5': 6.0.3 parse5: 6.0.1 - '@web/test-runner-chrome@0.18.0': + '@web/test-runner-chrome@0.18.1': dependencies: '@web/test-runner-core': 0.13.4 '@web/test-runner-coverage-v8': 0.8.0 - async-mutex: 0.4.0 chrome-launcher: 0.15.2 - puppeteer-core: 24.4.0 + puppeteer-core: 24.6.1 transitivePeerDependencies: - bare-buffer - bufferutil @@ -10660,7 +10431,7 @@ snapshots: istanbul-reports: 3.1.7 log-update: 4.0.0 nanocolors: 0.2.13 - nanoid: 3.3.9 + nanoid: 3.3.11 open: 8.4.2 picomatch: 2.3.1 source-map: 0.7.4 @@ -10689,12 +10460,12 @@ snapshots: - supports-color - utf-8-validate - '@web/test-runner@0.20.0': + '@web/test-runner@0.20.1': dependencies: '@web/browser-logs': 0.4.1 - '@web/config-loader': 0.3.2 + '@web/config-loader': 0.3.3 '@web/dev-server': 0.4.6 - '@web/test-runner-chrome': 0.18.0 + '@web/test-runner-chrome': 0.18.1 '@web/test-runner-commands': 0.9.0 '@web/test-runner-core': 0.13.4 '@web/test-runner-mocha': 0.9.0 @@ -10705,7 +10476,7 @@ snapshots: diff: 5.2.0 globby: 11.1.0 nanocolors: 0.2.13 - portfinder: 1.0.33 + portfinder: 1.0.36 source-map: 0.7.4 transitivePeerDependencies: - bare-buffer @@ -10802,7 +10573,7 @@ snapshots: jsonparse: 1.3.1 through: 2.3.8 - abbrev@3.0.0: {} + abbrev@3.0.1: {} abort-controller@3.0.0: dependencies: @@ -10813,6 +10584,11 @@ snapshots: mime-types: 2.1.35 negotiator: 0.6.3 + accepts@2.0.0: + dependencies: + mime-types: 3.0.1 + negotiator: 1.0.0 + acorn-jsx@5.3.2(acorn@8.14.1): dependencies: acorn: 8.14.1 @@ -10934,9 +10710,10 @@ snapshots: array-uniq@1.0.3: {} - array.prototype.findlastindex@1.2.5: + array.prototype.findlastindex@1.2.6: dependencies: call-bind: 1.0.8 + call-bound: 1.0.4 define-properties: 1.2.1 es-abstract: 1.23.9 es-errors: 1.3.0 @@ -10987,10 +10764,6 @@ snapshots: async-function@1.0.0: {} - async-mutex@0.4.0: - dependencies: - tslib: 2.8.1 - async@2.6.4: dependencies: lodash: 4.17.21 @@ -11001,14 +10774,12 @@ snapshots: asynckit@0.4.0: {} - atob@2.1.2: {} - atomic-sleep@1.0.0: {} autoprefixer@10.4.21(postcss@8.5.3): dependencies: browserslist: 4.24.4 - caniuse-lite: 1.0.30001703 + caniuse-lite: 1.0.30001713 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.1.1 @@ -11025,17 +10796,17 @@ snapshots: b4a@1.6.7: {} - babel-loader@10.0.0(@babel/core@7.26.10)(webpack@5.98.0(esbuild@0.25.1)): + babel-loader@10.0.0(@babel/core@7.26.10)(webpack@5.99.5(esbuild@0.25.2)): dependencies: '@babel/core': 7.26.10 find-up: 5.0.0 - webpack: 5.98.0(esbuild@0.25.1) + webpack: 5.99.5(esbuild@0.25.2) - babel-plugin-polyfill-corejs2@0.4.12(@babel/core@7.26.10): + babel-plugin-polyfill-corejs2@0.4.13(@babel/core@7.26.10): dependencies: '@babel/compat-data': 7.26.8 '@babel/core': 7.26.10 - '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.10) + '@babel/helper-define-polyfill-provider': 0.6.4(@babel/core@7.26.10) semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -11043,15 +10814,15 @@ snapshots: babel-plugin-polyfill-corejs3@0.11.1(@babel/core@7.26.10): dependencies: '@babel/core': 7.26.10 - '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.10) + '@babel/helper-define-polyfill-provider': 0.6.4(@babel/core@7.26.10) core-js-compat: 3.41.0 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-regenerator@0.6.3(@babel/core@7.26.10): + babel-plugin-polyfill-regenerator@0.6.4(@babel/core@7.26.10): dependencies: '@babel/core': 7.26.10 - '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.10) + '@babel/helper-define-polyfill-provider': 0.6.4(@babel/core@7.26.10) transitivePeerDependencies: - supports-color @@ -11060,21 +10831,19 @@ snapshots: bare-events@2.5.4: optional: true - bare-fs@4.0.1: + bare-fs@4.1.2: dependencies: bare-events: 2.5.4 bare-path: 3.0.0 bare-stream: 2.6.5(bare-events@2.5.4) - transitivePeerDependencies: - - bare-buffer optional: true - bare-os@3.6.0: + bare-os@3.6.1: optional: true bare-path@3.0.0: dependencies: - bare-os: 3.6.0 + bare-os: 3.6.1 optional: true bare-stream@2.6.5(bare-events@2.5.4): @@ -11098,13 +10867,13 @@ snapshots: bcryptjs@2.4.3: {} - beasties@0.2.0: + beasties@0.3.2: dependencies: css-select: 5.1.0 css-what: 6.1.0 dom-serializer: 2.0.0 domhandler: 5.0.3 - htmlparser2: 9.1.0 + htmlparser2: 10.0.0 picocolors: 1.1.1 postcss: 8.5.3 postcss-media-query-parser: 0.2.3 @@ -11115,7 +10884,7 @@ snapshots: big.js@6.2.2: {} - bignumber.js@9.1.2: {} + bignumber.js@9.2.1: {} binary-extensions@2.3.0: {} @@ -11146,6 +10915,20 @@ snapshots: transitivePeerDependencies: - supports-color + body-parser@2.2.0: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 4.4.0(supports-color@10.0.0) + http-errors: 2.0.0 + iconv-lite: 0.6.3 + on-finished: 2.4.1 + qs: 6.14.0 + raw-body: 3.0.0 + type-is: 2.0.1 + transitivePeerDependencies: + - supports-color + bonjour-service@1.3.0: dependencies: fast-deep-equal: 3.1.3 @@ -11168,13 +10951,13 @@ snapshots: browser-or-node@3.0.0: {} - browser-sync-client@3.0.3: + browser-sync-client@3.0.4: dependencies: etag: 1.8.1 fresh: 0.5.2 mitt: 1.2.0 - browser-sync-ui@3.0.3: + browser-sync-ui@3.0.4: dependencies: async-each-series: 0.1.1 chalk: 4.1.2 @@ -11188,10 +10971,10 @@ snapshots: - supports-color - utf-8-validate - browser-sync@3.0.3(debug@4.4.0): + browser-sync@3.0.4: dependencies: - browser-sync-client: 3.0.3 - browser-sync-ui: 3.0.3 + browser-sync-client: 3.0.4 + browser-sync-ui: 3.0.4 bs-recipes: 1.3.4 chalk: 4.1.2 chokidar: 3.6.0 @@ -11199,7 +10982,7 @@ snapshots: connect-history-api-fallback: 1.6.0 dev-ip: 1.0.1 easy-extender: 2.3.4 - eazy-logger: 4.0.1 + eazy-logger: 4.1.0 etag: 1.8.1 fresh: 0.5.2 fs-extra: 3.0.1 @@ -11230,8 +11013,8 @@ snapshots: browserslist@4.24.4: dependencies: - caniuse-lite: 1.0.30001703 - electron-to-chromium: 1.5.114 + caniuse-lite: 1.0.30001713 + electron-to-chromium: 1.5.137 node-releases: 2.0.19 update-browserslist-db: 1.1.3(browserslist@4.24.4) @@ -11259,8 +11042,6 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 - builtin-modules@3.3.0: {} - bundle-name@4.1.0: dependencies: run-applescript: 7.0.0 @@ -11310,7 +11091,7 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001703: {} + caniuse-lite@1.0.30001713: {} caseless@0.12.0: {} @@ -11367,7 +11148,7 @@ snapshots: chrome-launcher@0.15.2: dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 1.4.2 @@ -11376,9 +11157,9 @@ snapshots: chrome-trace-event@1.0.4: {} - chromium-bidi@2.1.2(devtools-protocol@0.0.1413902): + chromium-bidi@3.0.0(devtools-protocol@0.0.1425554): dependencies: - devtools-protocol: 0.0.1413902 + devtools-protocol: 0.0.1425554 mitt: 3.0.1 zod: 3.24.2 @@ -11479,19 +11260,7 @@ snapshots: compressible@2.0.18: dependencies: - mime-db: 1.53.0 - - compression@1.7.5: - dependencies: - bytes: 3.1.2 - compressible: 2.0.18 - debug: 2.6.9 - negotiator: 0.6.4 - on-headers: 1.0.2 - safe-buffer: 5.2.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color + mime-db: 1.54.0 compression@1.8.0: dependencies: @@ -11529,12 +11298,16 @@ snapshots: transitivePeerDependencies: - supports-color - consola@3.4.0: {} + consola@3.4.2: {} content-disposition@0.5.4: dependencies: safe-buffer: 5.2.1 + content-disposition@1.0.0: + dependencies: + safe-buffer: 5.2.1 + content-type@1.0.5: {} convert-source-map@1.9.0: {} @@ -11543,6 +11316,8 @@ snapshots: cookie-signature@1.0.6: {} + cookie-signature@1.2.2: {} + cookie@0.7.1: {} cookie@0.7.2: {} @@ -11556,20 +11331,20 @@ snapshots: dependencies: is-what: 3.14.1 - copy-webpack-plugin@13.0.0(webpack@5.98.0(esbuild@0.25.1)): + copy-webpack-plugin@13.0.0(webpack@5.99.5(esbuild@0.25.2)): dependencies: glob-parent: 6.0.2 normalize-path: 3.0.0 schema-utils: 4.3.0 serialize-javascript: 6.0.2 tinyglobby: 0.2.12 - webpack: 5.98.0(esbuild@0.25.1) + webpack: 5.99.5(esbuild@0.25.2) core-js-compat@3.41.0: dependencies: browserslist: 4.24.4 - core-js@3.37.1: {} + core-js@3.40.0: {} core-util-is@1.0.2: {} @@ -11580,14 +11355,14 @@ snapshots: object-assign: 4.1.1 vary: 1.1.2 - cosmiconfig@9.0.0(typescript@5.8.2): + cosmiconfig@9.0.0(typescript@5.8.3): dependencies: env-paths: 2.2.1 import-fresh: 3.3.1 js-yaml: 4.1.0 parse-json: 5.2.0 optionalDependencies: - typescript: 5.8.2 + typescript: 5.8.3 create-require@1.1.1: {} @@ -11617,7 +11392,7 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - css-loader@7.1.2(webpack@5.98.0(esbuild@0.25.1)): + css-loader@7.1.2(webpack@5.99.5(esbuild@0.25.2)): dependencies: icss-utils: 5.1.0(postcss@8.5.3) postcss: 8.5.3 @@ -11628,7 +11403,7 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.7.1 optionalDependencies: - webpack: 5.98.0(esbuild@0.25.1) + webpack: 5.99.5(esbuild@0.25.2) css-select@5.1.0: dependencies: @@ -11700,8 +11475,6 @@ snapshots: decamelize@1.2.0: {} - decode-uri-component@0.2.2: {} - deep-equal@1.0.1: {} deep-is@0.1.4: {} @@ -11774,7 +11547,8 @@ snapshots: detect-libc@1.0.3: optional: true - detect-libc@2.0.3: {} + detect-libc@2.0.3: + optional: true detect-node@2.1.0: {} @@ -11782,7 +11556,7 @@ snapshots: devtools-protocol@0.0.1045489: {} - devtools-protocol@0.0.1413902: {} + devtools-protocol@0.0.1425554: {} di@0.0.1: {} @@ -11853,7 +11627,7 @@ snapshots: dependencies: lodash: 4.17.21 - eazy-logger@4.0.1: + eazy-logger@4.1.0: dependencies: chalk: 4.1.2 @@ -11868,7 +11642,7 @@ snapshots: ee-first@1.1.1: {} - electron-to-chromium@1.5.114: {} + electron-to-chromium@1.5.137: {} emoji-regex@10.4.0: {} @@ -11908,7 +11682,7 @@ snapshots: engine.io@6.6.4: dependencies: '@types/cors': 2.8.17 - '@types/node': 20.17.24 + '@types/node': 20.17.30 accepts: 1.3.8 base64id: 2.0.0 cookie: 0.7.2 @@ -11935,6 +11709,8 @@ snapshots: entities@4.5.0: {} + entities@6.0.0: {} + env-paths@2.2.1: {} envinfo@7.14.0: {} @@ -12041,35 +11817,35 @@ snapshots: dependencies: es6-promise: 4.2.8 - esbuild-wasm@0.25.1: {} + esbuild-wasm@0.25.2: {} - esbuild@0.25.1: + esbuild@0.25.2: optionalDependencies: - '@esbuild/aix-ppc64': 0.25.1 - '@esbuild/android-arm': 0.25.1 - '@esbuild/android-arm64': 0.25.1 - '@esbuild/android-x64': 0.25.1 - '@esbuild/darwin-arm64': 0.25.1 - '@esbuild/darwin-x64': 0.25.1 - '@esbuild/freebsd-arm64': 0.25.1 - '@esbuild/freebsd-x64': 0.25.1 - '@esbuild/linux-arm': 0.25.1 - '@esbuild/linux-arm64': 0.25.1 - '@esbuild/linux-ia32': 0.25.1 - '@esbuild/linux-loong64': 0.25.1 - '@esbuild/linux-mips64el': 0.25.1 - '@esbuild/linux-ppc64': 0.25.1 - '@esbuild/linux-riscv64': 0.25.1 - '@esbuild/linux-s390x': 0.25.1 - '@esbuild/linux-x64': 0.25.1 - '@esbuild/netbsd-arm64': 0.25.1 - '@esbuild/netbsd-x64': 0.25.1 - '@esbuild/openbsd-arm64': 0.25.1 - '@esbuild/openbsd-x64': 0.25.1 - '@esbuild/sunos-x64': 0.25.1 - '@esbuild/win32-arm64': 0.25.1 - '@esbuild/win32-ia32': 0.25.1 - '@esbuild/win32-x64': 0.25.1 + '@esbuild/aix-ppc64': 0.25.2 + '@esbuild/android-arm': 0.25.2 + '@esbuild/android-arm64': 0.25.2 + '@esbuild/android-x64': 0.25.2 + '@esbuild/darwin-arm64': 0.25.2 + '@esbuild/darwin-x64': 0.25.2 + '@esbuild/freebsd-arm64': 0.25.2 + '@esbuild/freebsd-x64': 0.25.2 + '@esbuild/linux-arm': 0.25.2 + '@esbuild/linux-arm64': 0.25.2 + '@esbuild/linux-ia32': 0.25.2 + '@esbuild/linux-loong64': 0.25.2 + '@esbuild/linux-mips64el': 0.25.2 + '@esbuild/linux-ppc64': 0.25.2 + '@esbuild/linux-riscv64': 0.25.2 + '@esbuild/linux-s390x': 0.25.2 + '@esbuild/linux-x64': 0.25.2 + '@esbuild/netbsd-arm64': 0.25.2 + '@esbuild/netbsd-x64': 0.25.2 + '@esbuild/openbsd-arm64': 0.25.2 + '@esbuild/openbsd-x64': 0.25.2 + '@esbuild/sunos-x64': 0.25.2 + '@esbuild/win32-arm64': 0.25.2 + '@esbuild/win32-ia32': 0.25.2 + '@esbuild/win32-x64': 0.25.2 escalade@3.2.0: {} @@ -12087,9 +11863,9 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-config-prettier@10.1.1(eslint@9.22.0(jiti@1.21.7)): + eslint-config-prettier@10.1.2(eslint@9.24.0(jiti@1.21.7)): dependencies: - eslint: 9.22.0(jiti@1.21.7) + eslint: 9.24.0(jiti@1.21.7) eslint-import-resolver-node@0.3.9: dependencies: @@ -12099,32 +11875,32 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint@9.22.0(jiti@1.21.7)): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.24.0(jiti@1.21.7)): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.8.2) - eslint: 9.22.0(jiti@1.21.7) + '@typescript-eslint/parser': 8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3) + eslint: 9.24.0(jiti@1.21.7) eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-plugin-header@3.1.1(eslint@9.22.0(jiti@1.21.7)): + eslint-plugin-header@3.1.1(eslint@9.24.0(jiti@1.21.7)): dependencies: - eslint: 9.22.0(jiti@1.21.7) + eslint: 9.24.0(jiti@1.21.7) - eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.8.2))(eslint@9.22.0(jiti@1.21.7)): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.24.0(jiti@1.21.7)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 - array.prototype.findlastindex: 1.2.5 + array.prototype.findlastindex: 1.2.6 array.prototype.flat: 1.3.3 array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.22.0(jiti@1.21.7) + eslint: 9.24.0(jiti@1.21.7) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint@9.22.0(jiti@1.21.7)) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.24.0(jiti@1.21.7)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -12136,7 +11912,7 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.8.2) + '@typescript-eslint/parser': 8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -12156,20 +11932,20 @@ snapshots: eslint-visitor-keys@4.2.0: {} - eslint@9.22.0(jiti@1.21.7): + eslint@9.24.0(jiti@1.21.7): dependencies: - '@eslint-community/eslint-utils': 4.5.0(eslint@9.22.0(jiti@1.21.7)) + '@eslint-community/eslint-utils': 4.6.0(eslint@9.24.0(jiti@1.21.7)) '@eslint-community/regexpp': 4.12.1 - '@eslint/config-array': 0.19.2 - '@eslint/config-helpers': 0.1.0 + '@eslint/config-array': 0.20.0 + '@eslint/config-helpers': 0.2.1 '@eslint/core': 0.12.0 - '@eslint/eslintrc': 3.3.0 - '@eslint/js': 9.22.0 - '@eslint/plugin-kit': 0.2.7 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.24.0 + '@eslint/plugin-kit': 0.2.8 '@humanfs/node': 0.16.6 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.2 - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 '@types/json-schema': 7.0.15 ajv: 6.12.6 chalk: 4.1.2 @@ -12218,8 +11994,6 @@ snapshots: estraverse@5.3.0: {} - estree-walker@1.0.1: {} - estree-walker@2.0.2: {} esutils@2.0.3: {} @@ -12300,6 +12074,38 @@ snapshots: transitivePeerDependencies: - supports-color + express@5.1.0: + dependencies: + accepts: 2.0.0 + body-parser: 2.2.0 + content-disposition: 1.0.0 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.2.2 + debug: 4.4.0(supports-color@10.0.0) + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 2.1.0 + fresh: 2.0.0 + http-errors: 2.0.0 + merge-descriptors: 2.0.0 + mime-types: 3.0.1 + on-finished: 2.4.1 + once: 1.4.0 + parseurl: 1.3.3 + proxy-addr: 2.0.7 + qs: 6.14.0 + range-parser: 1.2.1 + router: 2.2.0 + send: 1.2.0 + serve-static: 2.2.0 + statuses: 2.0.1 + type-is: 2.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + extend@3.0.2: {} external-editor@3.1.0: @@ -12310,7 +12116,7 @@ snapshots: extract-zip@2.0.1: dependencies: - debug: 4.4.0(supports-color@10.0.0) + debug: 4.3.4 get-stream: 5.2.0 yauzl: 2.10.0 optionalDependencies: @@ -12340,8 +12146,6 @@ snapshots: fast-redact@3.5.0: {} - fast-safe-stringify@2.1.1: {} - fast-uri@3.0.6: {} fastq@1.19.1: @@ -12409,6 +12213,17 @@ snapshots: transitivePeerDependencies: - supports-color + finalhandler@2.1.0: + dependencies: + debug: 4.4.0(supports-color@10.0.0) + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + find-cache-dir@3.3.2: dependencies: commondir: 1.0.1 @@ -12484,6 +12299,8 @@ snapshots: fresh@0.5.2: {} + fresh@2.0.0: {} + fs-constants@1.0.0: {} fs-extra@3.0.1: @@ -12669,7 +12486,7 @@ snapshots: google-gax@4.4.1(encoding@0.1.13)(supports-color@10.0.0): dependencies: - '@grpc/grpc-js': 1.12.6 + '@grpc/grpc-js': 1.13.3 '@grpc/proto-loader': 0.7.13 '@types/long': 4.0.2 abort-controller: 3.0.0 @@ -12695,7 +12512,7 @@ snapshots: grpc-gcp@1.0.1(protobufjs@7.4.0): dependencies: - '@grpc/grpc-js': 1.12.6 + '@grpc/grpc-js': 1.13.3 protobufjs: 7.4.0 gtoken@7.1.0(encoding@0.1.13)(supports-color@10.0.0): @@ -12759,7 +12576,7 @@ snapshots: dependencies: function-bind: 1.1.2 - hosted-git-info@8.0.2: + hosted-git-info@8.1.0: dependencies: lru-cache: 10.4.3 @@ -12770,16 +12587,16 @@ snapshots: readable-stream: 2.3.8 wbuf: 1.7.3 - html-entities@2.5.2: {} + html-entities@2.6.0: {} html-escaper@2.0.2: {} - htmlparser2@9.1.0: + htmlparser2@10.0.0: dependencies: domelementtype: 2.3.0 domhandler: 5.0.3 domutils: 3.2.2 - entities: 4.5.0 + entities: 6.0.0 http-assert@1.5.0: dependencies: @@ -12813,7 +12630,7 @@ snapshots: statuses: 2.0.1 toidentifier: 1.0.1 - http-parser-js@0.5.9: {} + http-parser-js@0.5.10: {} http-proxy-agent@5.0.0(supports-color@10.0.0): dependencies: @@ -12830,7 +12647,7 @@ snapshots: transitivePeerDependencies: - supports-color - http-proxy-middleware@2.0.7(@types/express@4.17.21)(debug@4.4.0): + http-proxy-middleware@2.0.9(@types/express@4.17.21): dependencies: '@types/http-proxy': 1.17.16 http-proxy: 1.18.1(debug@4.4.0) @@ -12842,7 +12659,7 @@ snapshots: transitivePeerDependencies: - debug - http-proxy-middleware@3.0.3: + http-proxy-middleware@3.0.5: dependencies: '@types/http-proxy': 1.17.16 debug: 4.4.0(supports-color@10.0.0) @@ -12931,7 +12748,7 @@ snapshots: immutable@3.8.2: {} - immutable@5.0.3: {} + immutable@5.1.1: {} import-fresh@3.3.1: dependencies: @@ -13014,10 +12831,6 @@ snapshots: call-bound: 1.0.4 has-tostringtag: 1.0.2 - is-builtin-module@3.2.1: - dependencies: - builtin-modules: 3.3.0 - is-callable@1.2.7: {} is-core-module@2.16.1: @@ -13115,9 +12928,11 @@ snapshots: is-promise@2.2.2: {} + is-promise@4.0.0: {} + is-reference@1.2.1: dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 is-regex@1.2.1: dependencies: @@ -13205,7 +13020,7 @@ snapshots: istanbul-lib-instrument@5.2.1: dependencies: '@babel/core': 7.26.10 - '@babel/parser': 7.26.9 + '@babel/parser': 7.27.0 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 6.3.1 @@ -13215,7 +13030,7 @@ snapshots: istanbul-lib-instrument@6.0.3: dependencies: '@babel/core': 7.26.10 - '@babel/parser': 7.26.9 + '@babel/parser': 7.27.0 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 7.7.1 @@ -13277,7 +13092,7 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -13301,7 +13116,7 @@ snapshots: json-bigint@1.0.0: dependencies: - bignumber.js: 9.1.2 + bignumber.js: 9.2.1 json-buffer@3.0.1: {} @@ -13408,22 +13223,22 @@ snapshots: transitivePeerDependencies: - supports-color - karma-jasmine-html-reporter@2.1.0(jasmine-core@5.6.0)(karma-jasmine@5.1.0(karma@6.4.4(debug@4.4.0)))(karma@6.4.4(debug@4.4.0)): + karma-jasmine-html-reporter@2.1.0(jasmine-core@5.6.0)(karma-jasmine@5.1.0(karma@6.4.4))(karma@6.4.4): dependencies: jasmine-core: 5.6.0 - karma: 6.4.4(debug@4.4.0) - karma-jasmine: 5.1.0(karma@6.4.4(debug@4.4.0)) + karma: 6.4.4 + karma-jasmine: 5.1.0(karma@6.4.4) - karma-jasmine@5.1.0(karma@6.4.4(debug@4.4.0)): + karma-jasmine@5.1.0(karma@6.4.4): dependencies: jasmine-core: 4.6.1 - karma: 6.4.4(debug@4.4.0) + karma: 6.4.4 karma-source-map-support@1.4.0: dependencies: source-map-support: 0.5.21 - karma@6.4.4(debug@4.4.0): + karma@6.4.4: dependencies: '@colors/colors': 1.5.0 body-parser: 1.20.3 @@ -13465,8 +13280,6 @@ snapshots: kind-of@6.0.3: {} - kleur@4.1.5: {} - koa-compose@4.1.0: {} koa-convert@2.0.0: @@ -13493,7 +13306,7 @@ snapshots: transitivePeerDependencies: - supports-color - koa@2.16.0: + koa@2.16.1: dependencies: accepts: 1.3.8 cache-content-type: 1.0.1 @@ -13526,13 +13339,13 @@ snapshots: picocolors: 1.1.1 shell-quote: 1.8.2 - less-loader@12.2.0(less@4.2.2)(webpack@5.98.0(esbuild@0.25.1)): + less-loader@12.2.0(less@4.3.0)(webpack@5.99.5(esbuild@0.25.2)): dependencies: - less: 4.2.2 + less: 4.3.0 optionalDependencies: - webpack: 5.98.0(esbuild@0.25.1) + webpack: 5.99.5(esbuild@0.25.2) - less@4.2.2: + less@4.3.0: dependencies: copy-anything: 2.0.6 parse-node-version: 1.0.1 @@ -13551,11 +13364,11 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - license-webpack-plugin@4.0.2(webpack@5.98.0(esbuild@0.25.1)): + license-webpack-plugin@4.0.2(webpack@5.99.5(esbuild@0.25.2)): dependencies: webpack-sources: 3.2.3 optionalDependencies: - webpack: 5.98.0(esbuild@0.25.1) + webpack: 5.99.5(esbuild@0.25.2) lie@3.3.0: dependencies: @@ -13564,7 +13377,7 @@ snapshots: lighthouse-logger@1.4.2: dependencies: debug: 2.6.9 - marky: 1.2.5 + marky: 1.3.0 transitivePeerDependencies: - supports-color @@ -13572,7 +13385,7 @@ snapshots: lines-and-columns@1.2.4: {} - listr2@8.2.5: + listr2@8.3.2: dependencies: cli-truncate: 4.0.0 colorette: 2.0.20 @@ -13595,6 +13408,7 @@ snapshots: '@lmdb/lmdb-linux-arm64': 3.2.6 '@lmdb/lmdb-linux-x64': 3.2.6 '@lmdb/lmdb-win32-x64': 3.2.6 + optional: true loader-runner@4.3.0: {} @@ -13730,12 +13544,14 @@ snapshots: transitivePeerDependencies: - supports-color - marky@1.2.5: {} + marky@1.3.0: {} math-intrinsics@1.1.0: {} media-typer@0.3.0: {} + media-typer@1.1.0: {} + memfs@4.17.0: dependencies: '@jsonjoy.com/json-pack': 1.2.0(tslib@2.8.1) @@ -13745,6 +13561,8 @@ snapshots: merge-descriptors@1.0.3: {} + merge-descriptors@2.0.0: {} + merge-stream@2.0.0: {} merge2@1.4.1: {} @@ -13758,12 +13576,16 @@ snapshots: mime-db@1.52.0: {} - mime-db@1.53.0: {} + mime-db@1.54.0: {} mime-types@2.1.35: dependencies: mime-db: 1.52.0 + mime-types@3.0.1: + dependencies: + mime-db: 1.54.0 + mime@1.6.0: {} mime@2.6.0: {} @@ -13774,11 +13596,11 @@ snapshots: mimic-function@5.0.1: {} - mini-css-extract-plugin@2.9.2(webpack@5.98.0(esbuild@0.25.1)): + mini-css-extract-plugin@2.9.2(webpack@5.99.5(esbuild@0.25.2)): dependencies: schema-utils: 4.3.0 tapable: 2.2.1 - webpack: 5.98.0(esbuild@0.25.1) + webpack: 5.99.5(esbuild@0.25.2) minimalistic-assert@1.0.1: {} @@ -13804,7 +13626,7 @@ snapshots: dependencies: minipass: 7.1.2 minipass-sized: 1.0.3 - minizlib: 3.0.1 + minizlib: 3.0.2 optionalDependencies: encoding: 0.1.13 @@ -13833,10 +13655,9 @@ snapshots: minipass: 3.3.6 yallist: 4.0.0 - minizlib@3.0.1: + minizlib@3.0.2: dependencies: minipass: 7.1.2 - rimraf: 5.0.10 mitt@1.2.0: {} @@ -13875,6 +13696,7 @@ snapshots: msgpackr@1.11.2: optionalDependencies: msgpackr-extract: 3.0.3 + optional: true multicast-dns@7.2.5: dependencies: @@ -13887,7 +13709,7 @@ snapshots: nanocolors@0.2.13: {} - nanoid@3.3.9: {} + nanoid@3.3.11: {} natural-compare@1.4.0: {} @@ -13907,37 +13729,39 @@ snapshots: netmask@2.0.2: {} - ng-packagr@20.0.0-next.1(@angular/compiler-cli@20.0.0-next.2(@angular/compiler@20.0.0-next.2)(typescript@5.8.2))(tslib@2.8.1)(typescript@5.8.2): + ng-packagr@20.0.0-next.6(@angular/compiler-cli@20.0.0-next.7(@angular/compiler@20.0.0-next.7)(typescript@5.8.3))(tslib@2.8.1)(typescript@5.8.3): dependencies: - '@angular/compiler-cli': 20.0.0-next.2(@angular/compiler@20.0.0-next.2)(typescript@5.8.2) - '@rollup/plugin-json': 6.1.0(rollup@4.35.0) - '@rollup/wasm-node': 4.35.0 + '@ampproject/remapping': 2.3.0 + '@angular/compiler-cli': 20.0.0-next.7(@angular/compiler@20.0.0-next.7)(typescript@5.8.3) + '@rollup/plugin-json': 6.1.0(rollup@4.40.0) + '@rollup/wasm-node': 4.40.0 ajv: 8.17.1 ansi-colors: 4.1.3 browserslist: 4.24.4 chokidar: 4.0.3 commander: 13.1.0 - convert-source-map: 2.0.0 dependency-graph: 1.0.0 - esbuild: 0.25.1 + esbuild: 0.25.2 find-cache-dir: 3.3.2 injection-js: 2.4.0 jsonc-parser: 3.3.1 - less: 4.2.2 + less: 4.3.0 ora: 5.4.1 - piscina: 4.8.0 + piscina: 4.9.2 postcss: 8.5.3 + rollup-plugin-dts: 6.2.1(rollup@4.40.0)(typescript@5.8.3) rxjs: 7.8.2 - sass: 1.85.1 + sass: 1.86.3 tinyglobby: 0.2.12 tslib: 2.8.1 - typescript: 5.8.2 + typescript: 5.8.3 optionalDependencies: - rollup: 4.35.0 + rollup: 4.40.0 nice-try@1.0.5: {} - node-addon-api@6.1.0: {} + node-addon-api@6.1.0: + optional: true node-addon-api@7.1.1: optional: true @@ -13969,18 +13793,19 @@ snapshots: node-gyp-build-optional-packages@5.2.2: dependencies: detect-libc: 2.0.3 + optional: true - node-gyp@11.1.0: + node-gyp@11.2.0: dependencies: env-paths: 2.2.1 exponential-backoff: 3.1.2 - glob: 10.4.5 graceful-fs: 4.2.11 make-fetch-happen: 14.0.3 nopt: 8.1.0 proc-log: 5.0.0 semver: 7.7.1 tar: 7.4.3 + tinyglobby: 0.2.12 which: 5.0.0 transitivePeerDependencies: - supports-color @@ -13989,7 +13814,7 @@ snapshots: nopt@8.1.0: dependencies: - abbrev: 3.0.0 + abbrev: 3.0.1 normalize-path@3.0.0: {} @@ -14007,7 +13832,7 @@ snapshots: npm-package-arg@12.0.2: dependencies: - hosted-git-info: 8.0.2 + hosted-git-info: 8.1.0 proc-log: 5.0.0 semver: 7.7.1 validate-npm-package-name: 6.0.0 @@ -14030,7 +13855,7 @@ snapshots: make-fetch-happen: 14.0.3 minipass: 7.1.2 minipass-fetch: 4.0.1 - minizlib: 3.0.1 + minizlib: 3.0.2 npm-package-arg: 12.0.2 proc-log: 5.0.0 transitivePeerDependencies: @@ -14044,7 +13869,7 @@ snapshots: dependencies: path-key: 3.1.1 - npm@11.2.0: {} + npm@11.3.0: {} nth-check@2.1.1: dependencies: @@ -14117,7 +13942,7 @@ snapshots: only@0.0.2: {} - open@10.1.0: + open@10.1.1: dependencies: default-browser: 5.2.1 define-lazy-prop: 3.0.0 @@ -14155,7 +13980,8 @@ snapshots: strip-ansi: 6.0.1 wcwidth: 1.0.1 - ordered-binary@1.5.3: {} + ordered-binary@1.5.3: + optional: true os-tmpdir@1.0.2: {} @@ -14302,6 +14128,8 @@ snapshots: path-to-regexp@0.1.12: {} + path-to-regexp@8.2.0: {} + path-type@4.0.0: {} pathe@1.1.2: {} @@ -14346,7 +14174,7 @@ snapshots: pino-std-serializers@7.0.0: {} - pino@9.5.0: + pino@9.6.0: dependencies: atomic-sleep: 1.0.0 fast-redact: 3.5.0 @@ -14360,7 +14188,7 @@ snapshots: sonic-boom: 4.2.0 thread-stream: 3.1.0 - piscina@4.8.0: + piscina@4.9.2: optionalDependencies: '@napi-rs/nice': 1.0.1 @@ -14372,11 +14200,10 @@ snapshots: pluralize@8.0.0: {} - portfinder@1.0.33: + portfinder@1.0.36: dependencies: - async: 2.6.4 - debug: 3.2.7 - mkdirp: 0.5.6 + async: 3.2.6 + debug: 4.4.0(supports-color@10.0.0) transitivePeerDependencies: - supports-color @@ -14387,14 +14214,14 @@ snapshots: possible-typed-array-names@1.1.0: {} - postcss-loader@8.1.1(postcss@8.5.3)(typescript@5.8.2)(webpack@5.98.0(esbuild@0.25.1)): + postcss-loader@8.1.1(postcss@8.5.3)(typescript@5.8.3)(webpack@5.99.5(esbuild@0.25.2)): dependencies: - cosmiconfig: 9.0.0(typescript@5.8.2) + cosmiconfig: 9.0.0(typescript@5.8.3) jiti: 1.21.7 postcss: 8.5.3 semver: 7.7.1 optionalDependencies: - webpack: 5.98.0(esbuild@0.25.1) + webpack: 5.99.5(esbuild@0.25.2) transitivePeerDependencies: - typescript @@ -14430,7 +14257,7 @@ snapshots: postcss@8.5.3: dependencies: - nanoid: 3.3.9 + nanoid: 3.3.11 picocolors: 1.1.1 source-map-js: 1.2.1 @@ -14471,7 +14298,7 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 20.17.24 + '@types/node': 20.17.30 long: 5.3.1 protractor@7.0.0: @@ -14559,12 +14386,12 @@ snapshots: - supports-color - utf-8-validate - puppeteer-core@24.4.0: + puppeteer-core@24.6.1: dependencies: - '@puppeteer/browsers': 2.8.0 - chromium-bidi: 2.1.2(devtools-protocol@0.0.1413902) + '@puppeteer/browsers': 2.10.0 + chromium-bidi: 3.0.0(devtools-protocol@0.0.1425554) debug: 4.4.0(supports-color@10.0.0) - devtools-protocol: 0.0.1413902 + devtools-protocol: 0.0.1425554 typed-query-selector: 2.12.0 ws: 8.18.1 transitivePeerDependencies: @@ -14593,10 +14420,6 @@ snapshots: dependencies: side-channel: 1.1.0 - qs@6.13.1: - dependencies: - side-channel: 1.1.0 - qs@6.14.0: dependencies: side-channel: 1.1.0 @@ -14622,7 +14445,7 @@ snapshots: unicode-properties: 1.4.1 urijs: 1.19.11 wordwrap: 1.0.0 - yaml: 2.7.0 + yaml: 2.7.1 transitivePeerDependencies: - encoding @@ -14639,6 +14462,13 @@ snapshots: iconv-lite: 0.4.24 unpipe: 1.0.0 + raw-body@3.0.0: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.6.3 + unpipe: 1.0.0 + readable-stream@2.3.8: dependencies: core-util-is: 1.0.3 @@ -14706,7 +14536,7 @@ snapshots: regenerator-transform@0.15.2: dependencies: - '@babel/runtime': 7.26.10 + '@babel/runtime': 7.27.0 regex-parser@2.3.1: {} @@ -14828,49 +14658,63 @@ snapshots: dependencies: glob: 7.2.3 - rimraf@5.0.10: - dependencies: - glob: 10.4.5 - rollup-license-plugin@3.0.2: dependencies: get-npm-tarball-url: 2.1.0 node-fetch: 3.3.2 spdx-expression-validate: 2.0.0 - rollup-plugin-sourcemaps@0.6.3(@types/node@20.17.24)(rollup@4.35.0): + rollup-plugin-dts@6.2.1(rollup@4.40.0)(typescript@5.8.3): + dependencies: + magic-string: 0.30.17 + rollup: 4.40.0 + typescript: 5.8.3 + optionalDependencies: + '@babel/code-frame': 7.26.2 + + rollup-plugin-sourcemaps2@0.5.0(@types/node@20.17.30)(rollup@4.40.0): dependencies: - '@rollup/pluginutils': 3.1.0(rollup@4.35.0) - rollup: 4.35.0 - source-map-resolve: 0.6.0 + '@rollup/pluginutils': 5.1.4(rollup@4.40.0) + rollup: 4.40.0 optionalDependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 - rollup@4.35.0: + rollup@4.40.0: dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.35.0 - '@rollup/rollup-android-arm64': 4.35.0 - '@rollup/rollup-darwin-arm64': 4.35.0 - '@rollup/rollup-darwin-x64': 4.35.0 - '@rollup/rollup-freebsd-arm64': 4.35.0 - '@rollup/rollup-freebsd-x64': 4.35.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.35.0 - '@rollup/rollup-linux-arm-musleabihf': 4.35.0 - '@rollup/rollup-linux-arm64-gnu': 4.35.0 - '@rollup/rollup-linux-arm64-musl': 4.35.0 - '@rollup/rollup-linux-loongarch64-gnu': 4.35.0 - '@rollup/rollup-linux-powerpc64le-gnu': 4.35.0 - '@rollup/rollup-linux-riscv64-gnu': 4.35.0 - '@rollup/rollup-linux-s390x-gnu': 4.35.0 - '@rollup/rollup-linux-x64-gnu': 4.35.0 - '@rollup/rollup-linux-x64-musl': 4.35.0 - '@rollup/rollup-win32-arm64-msvc': 4.35.0 - '@rollup/rollup-win32-ia32-msvc': 4.35.0 - '@rollup/rollup-win32-x64-msvc': 4.35.0 + '@rollup/rollup-android-arm-eabi': 4.40.0 + '@rollup/rollup-android-arm64': 4.40.0 + '@rollup/rollup-darwin-arm64': 4.40.0 + '@rollup/rollup-darwin-x64': 4.40.0 + '@rollup/rollup-freebsd-arm64': 4.40.0 + '@rollup/rollup-freebsd-x64': 4.40.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.40.0 + '@rollup/rollup-linux-arm-musleabihf': 4.40.0 + '@rollup/rollup-linux-arm64-gnu': 4.40.0 + '@rollup/rollup-linux-arm64-musl': 4.40.0 + '@rollup/rollup-linux-loongarch64-gnu': 4.40.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.40.0 + '@rollup/rollup-linux-riscv64-gnu': 4.40.0 + '@rollup/rollup-linux-riscv64-musl': 4.40.0 + '@rollup/rollup-linux-s390x-gnu': 4.40.0 + '@rollup/rollup-linux-x64-gnu': 4.40.0 + '@rollup/rollup-linux-x64-musl': 4.40.0 + '@rollup/rollup-win32-arm64-msvc': 4.40.0 + '@rollup/rollup-win32-ia32-msvc': 4.40.0 + '@rollup/rollup-win32-x64-msvc': 4.40.0 fsevents: 2.3.3 + router@2.2.0: + dependencies: + debug: 4.4.0(supports-color@10.0.0) + depd: 2.0.0 + is-promise: 4.0.0 + parseurl: 1.3.3 + path-to-regexp: 8.2.0 + transitivePeerDependencies: + - supports-color + run-applescript@7.0.0: {} run-parallel@1.2.0: @@ -14910,17 +14754,17 @@ snapshots: safer-buffer@2.1.2: {} - sass-loader@16.0.5(sass@1.85.1)(webpack@5.98.0(esbuild@0.25.1)): + sass-loader@16.0.5(sass@1.86.3)(webpack@5.99.5(esbuild@0.25.2)): dependencies: neo-async: 2.6.2 optionalDependencies: - sass: 1.85.1 - webpack: 5.98.0(esbuild@0.25.1) + sass: 1.86.3 + webpack: 5.99.5(esbuild@0.25.2) - sass@1.85.1: + sass@1.86.3: dependencies: chokidar: 4.0.3 - immutable: 5.0.3 + immutable: 5.1.1 source-map-js: 1.2.1 optionalDependencies: '@parcel/watcher': 2.5.1 @@ -14998,6 +14842,22 @@ snapshots: transitivePeerDependencies: - supports-color + send@1.2.0: + dependencies: + debug: 4.4.0(supports-color@10.0.0) + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 2.0.0 + http-errors: 2.0.0 + mime-types: 3.0.1 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + serialize-javascript@6.0.2: dependencies: randombytes: 2.1.0 @@ -15023,6 +14883,15 @@ snapshots: transitivePeerDependencies: - supports-color + serve-static@2.2.0: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 1.2.0 + transitivePeerDependencies: + - supports-color + server-destroy@1.0.1: {} set-blocking@2.0.0: {} @@ -15073,7 +14942,7 @@ snapshots: shell-quote@1.8.2: {} - shelljs@0.9.1: + shelljs@0.9.2: dependencies: execa: 1.0.0 fast-glob: 3.3.3 @@ -15116,7 +14985,7 @@ snapshots: dependencies: '@sigstore/bundle': 3.1.0 '@sigstore/core': 2.0.0 - '@sigstore/protobuf-specs': 0.4.0 + '@sigstore/protobuf-specs': 0.4.1 '@sigstore/sign': 3.1.0 '@sigstore/tuf': 3.1.0 '@sigstore/verify': 2.1.0 @@ -15213,16 +15082,11 @@ snapshots: source-map-js@1.2.1: {} - source-map-loader@5.0.0(webpack@5.98.0(esbuild@0.25.1)): + source-map-loader@5.0.0(webpack@5.99.5(esbuild@0.25.2)): dependencies: iconv-lite: 0.6.3 source-map-js: 1.2.1 - webpack: 5.98.0(esbuild@0.25.1) - - source-map-resolve@0.6.0: - dependencies: - atob: 2.1.2 - decode-uri-component: 0.2.2 + webpack: 5.99.5(esbuild@0.25.2) source-map-support@0.4.18: dependencies: @@ -15430,8 +15294,6 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - symbol-observable@4.0.0: {} - table-layout@4.1.1: dependencies: array-back: 6.2.2 @@ -15451,7 +15313,7 @@ snapshots: pump: 3.0.2 tar-stream: 3.1.7 optionalDependencies: - bare-fs: 4.0.1 + bare-fs: 4.1.2 bare-path: 3.0.0 transitivePeerDependencies: - bare-buffer @@ -15484,7 +15346,7 @@ snapshots: '@isaacs/fs-minipass': 4.0.1 chownr: 3.0.0 minipass: 7.1.2 - minizlib: 3.0.1 + minizlib: 3.0.2 mkdirp: 3.0.1 yallist: 5.0.0 @@ -15499,16 +15361,16 @@ snapshots: - encoding - supports-color - terser-webpack-plugin@5.3.14(esbuild@0.25.1)(webpack@5.98.0(esbuild@0.25.1)): + terser-webpack-plugin@5.3.14(esbuild@0.25.2)(webpack@5.99.5(esbuild@0.25.2)): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 4.3.0 serialize-javascript: 6.0.2 terser: 5.39.0 - webpack: 5.98.0(esbuild@0.25.1) + webpack: 5.99.5(esbuild@0.25.2) optionalDependencies: - esbuild: 0.25.1 + esbuild: 0.25.2 terser@5.39.0: dependencies: @@ -15549,11 +15411,11 @@ snapshots: fdir: 6.4.3(picomatch@4.0.2) picomatch: 4.0.2 - tldts-core@6.1.84: {} + tldts-core@6.1.86: {} - tldts@6.1.84: + tldts@6.1.86: dependencies: - tldts-core: 6.1.84 + tldts-core: 6.1.86 tmp@0.0.30: dependencies: @@ -15578,11 +15440,11 @@ snapshots: tough-cookie@5.1.2: dependencies: - tldts: 6.1.84 + tldts: 6.1.86 tr46@0.0.3: {} - tr46@5.0.0: + tr46@5.1.0: dependencies: punycode: 2.3.1 @@ -15592,25 +15454,25 @@ snapshots: tree-kill@1.2.2: {} - ts-api-utils@2.0.1(typescript@5.8.2): + ts-api-utils@2.1.0(typescript@5.8.3): dependencies: - typescript: 5.8.2 + typescript: 5.8.3 - ts-node@10.9.2(@types/node@20.17.24)(typescript@5.8.2): + ts-node@10.9.2(@types/node@20.17.30)(typescript@5.8.3): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.17.24 + '@types/node': 20.17.30 acorn: 8.14.1 acorn-walk: 8.3.4 arg: 4.1.3 create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 - typescript: 5.8.2 + typescript: 5.8.3 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 @@ -15652,6 +15514,12 @@ snapshots: media-typer: 0.3.0 mime-types: 2.1.35 + type-is@2.0.1: + dependencies: + content-type: 1.0.5 + media-typer: 1.1.0 + mime-types: 3.0.1 + typed-array-buffer@1.0.3: dependencies: call-bound: 1.0.4 @@ -15691,7 +15559,7 @@ snapshots: typed-query-selector@2.12.0: {} - typescript@5.8.2: {} + typescript@5.8.3: {} typical@4.0.0: {} @@ -15718,11 +15586,11 @@ snapshots: undici-types@6.19.8: {} - undici@7.5.0: {} + undici@7.8.0: {} unenv@1.10.0: dependencies: - consola: 3.4.0 + consola: 3.4.2 defu: 6.1.4 mime: 3.0.0 node-fetch-native: 1.6.6 @@ -15806,10 +15674,10 @@ snapshots: vary@1.1.2: {} - verdaccio-audit@13.0.0-next-8.7(encoding@0.1.13): + verdaccio-audit@13.0.0-next-8.15(encoding@0.1.13): dependencies: - '@verdaccio/config': 8.0.0-next-8.7 - '@verdaccio/core': 8.0.0-next-8.7 + '@verdaccio/config': 8.0.0-next-8.15 + '@verdaccio/core': 8.0.0-next-8.15 express: 4.21.2 https-proxy-agent: 5.0.1(supports-color@10.0.0) node-fetch: 2.6.7(encoding@0.1.13) @@ -15821,58 +15689,53 @@ snapshots: dependencies: '@verdaccio/commons-api': 10.2.0 - verdaccio-htpasswd@13.0.0-next-8.7: + verdaccio-htpasswd@13.0.0-next-8.15: dependencies: - '@verdaccio/core': 8.0.0-next-8.7 - '@verdaccio/file-locking': 13.0.0-next-8.2 + '@verdaccio/core': 8.0.0-next-8.15 + '@verdaccio/file-locking': 13.0.0-next-8.3 apache-md5: 1.1.8 bcryptjs: 2.4.3 - core-js: 3.37.1 + core-js: 3.40.0 debug: 4.4.0(supports-color@10.0.0) http-errors: 2.0.0 unix-crypt-td-js: 1.1.4 transitivePeerDependencies: - supports-color - verdaccio@6.0.5(encoding@0.1.13): + verdaccio@6.1.2(encoding@0.1.13): dependencies: - '@cypress/request': 3.0.7 - '@verdaccio/auth': 8.0.0-next-8.7 - '@verdaccio/config': 8.0.0-next-8.7 - '@verdaccio/core': 8.0.0-next-8.7 + '@cypress/request': 3.0.8 + '@verdaccio/auth': 8.0.0-next-8.15 + '@verdaccio/config': 8.0.0-next-8.15 + '@verdaccio/core': 8.0.0-next-8.15 + '@verdaccio/loaders': 8.0.0-next-8.6 '@verdaccio/local-storage-legacy': 11.0.2 - '@verdaccio/logger': 8.0.0-next-8.7 - '@verdaccio/middleware': 8.0.0-next-8.7 - '@verdaccio/search-indexer': 8.0.0-next-8.2 - '@verdaccio/signature': 8.0.0-next-8.1 + '@verdaccio/logger': 8.0.0-next-8.15 + '@verdaccio/middleware': 8.0.0-next-8.15 + '@verdaccio/search-indexer': 8.0.0-next-8.4 + '@verdaccio/signature': 8.0.0-next-8.7 '@verdaccio/streams': 10.2.1 - '@verdaccio/tarball': 13.0.0-next-8.7 - '@verdaccio/ui-theme': 8.0.0-next-8.7 - '@verdaccio/url': 13.0.0-next-8.7 - '@verdaccio/utils': 7.0.1-next-8.1 + '@verdaccio/tarball': 13.0.0-next-8.15 + '@verdaccio/ui-theme': 8.0.0-next-8.15 + '@verdaccio/url': 13.0.0-next-8.15 + '@verdaccio/utils': 8.1.0-next-8.15 JSONStream: 1.3.5 async: 3.2.6 clipanion: 4.0.0-rc.4 - compression: 1.7.5 + compression: 1.8.0 cors: 2.8.5 debug: 4.4.0(supports-color@10.0.0) envinfo: 7.14.0 express: 4.21.2 - express-rate-limit: 5.5.1 - fast-safe-stringify: 2.1.1 handlebars: 4.7.8 - js-yaml: 4.1.0 - jsonwebtoken: 9.0.2 - kleur: 4.1.5 lodash: 4.17.21 lru-cache: 7.18.3 mime: 3.0.0 mkdirp: 1.0.4 pkginfo: 0.4.1 semver: 7.6.3 - validator: 13.12.0 - verdaccio-audit: 13.0.0-next-8.7(encoding@0.1.13) - verdaccio-htpasswd: 13.0.0-next-8.7 + verdaccio-audit: 13.0.0-next-8.15(encoding@0.1.13) + verdaccio-htpasswd: 13.0.0-next-8.15 transitivePeerDependencies: - encoding - supports-color @@ -15883,19 +15746,19 @@ snapshots: core-util-is: 1.0.2 extsprintf: 1.3.0 - vite@6.2.1(@types/node@20.17.24)(jiti@1.21.7)(less@4.2.2)(sass@1.85.1)(terser@5.39.0)(yaml@2.7.0): + vite@6.2.6(@types/node@20.17.30)(jiti@1.21.7)(less@4.3.0)(sass@1.86.3)(terser@5.39.0)(yaml@2.7.1): dependencies: - esbuild: 0.25.1 + esbuild: 0.25.2 postcss: 8.5.3 - rollup: 4.35.0 + rollup: 4.40.0 optionalDependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.30 fsevents: 2.3.3 jiti: 1.21.7 - less: 4.2.2 - sass: 1.85.1 + less: 4.3.0 + sass: 1.86.3 terser: 5.39.0 - yaml: 2.7.0 + yaml: 2.7.1 void-elements@2.0.1: {} @@ -15912,7 +15775,8 @@ snapshots: dependencies: defaults: 1.0.4 - weak-lru-cache@1.2.2: {} + weak-lru-cache@1.2.2: + optional: true web-streams-polyfill@3.3.3: {} @@ -15939,7 +15803,7 @@ snapshots: webidl-conversions@7.0.0: {} - webpack-dev-middleware@7.4.2(webpack@5.98.0(esbuild@0.25.1)): + webpack-dev-middleware@7.4.2(webpack@5.99.5(esbuild@0.25.2)): dependencies: colorette: 2.0.20 memfs: 4.17.0 @@ -15948,17 +15812,18 @@ snapshots: range-parser: 1.2.1 schema-utils: 4.3.0 optionalDependencies: - webpack: 5.98.0(esbuild@0.25.1) + webpack: 5.99.5(esbuild@0.25.2) - webpack-dev-server@5.2.0(debug@4.4.0)(webpack@5.98.0(esbuild@0.25.1)): + webpack-dev-server@5.2.1(webpack@5.99.5(esbuild@0.25.2)): dependencies: '@types/bonjour': 3.5.13 '@types/connect-history-api-fallback': 1.5.4 '@types/express': 4.17.21 + '@types/express-serve-static-core': 4.19.6 '@types/serve-index': 1.9.4 '@types/serve-static': 1.15.7 '@types/sockjs': 0.3.36 - '@types/ws': 8.18.0 + '@types/ws': 8.18.1 ansi-html-community: 0.0.8 bonjour-service: 1.3.0 chokidar: 3.6.0 @@ -15967,20 +15832,20 @@ snapshots: connect-history-api-fallback: 2.0.0 express: 4.21.2 graceful-fs: 4.2.11 - http-proxy-middleware: 2.0.7(@types/express@4.17.21)(debug@4.4.0) + http-proxy-middleware: 2.0.9(@types/express@4.17.21) ipaddr.js: 2.2.0 launch-editor: 2.10.0 - open: 10.1.0 + open: 10.1.1 p-retry: 6.2.1 schema-utils: 4.3.0 selfsigned: 2.4.1 serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack-dev-middleware: 7.4.2(webpack@5.98.0(esbuild@0.25.1)) + webpack-dev-middleware: 7.4.2(webpack@5.99.5(esbuild@0.25.2)) ws: 8.18.1 optionalDependencies: - webpack: 5.98.0(esbuild@0.25.1) + webpack: 5.99.5(esbuild@0.25.2) transitivePeerDependencies: - bufferutil - debug @@ -15995,15 +15860,15 @@ snapshots: webpack-sources@3.2.3: {} - webpack-subresource-integrity@5.1.0(webpack@5.98.0(esbuild@0.25.1)): + webpack-subresource-integrity@5.1.0(webpack@5.99.5(esbuild@0.25.2)): dependencies: typed-assert: 1.0.9 - webpack: 5.98.0(esbuild@0.25.1) + webpack: 5.99.5(esbuild@0.25.2) - webpack@5.98.0(esbuild@0.25.1): + webpack@5.99.5(esbuild@0.25.2): dependencies: '@types/eslint-scope': 3.7.7 - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 '@webassemblyjs/ast': 1.14.1 '@webassemblyjs/wasm-edit': 1.14.1 '@webassemblyjs/wasm-parser': 1.14.1 @@ -16022,7 +15887,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 4.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.14(esbuild@0.25.1)(webpack@5.98.0(esbuild@0.25.1)) + terser-webpack-plugin: 5.3.14(esbuild@0.25.2)(webpack@5.99.5(esbuild@0.25.2)) watchpack: 2.4.2 webpack-sources: 3.2.3 transitivePeerDependencies: @@ -16032,15 +15897,15 @@ snapshots: websocket-driver@0.7.4: dependencies: - http-parser-js: 0.5.9 + http-parser-js: 0.5.10 safe-buffer: 5.2.1 websocket-extensions: 0.1.4 websocket-extensions@0.1.4: {} - whatwg-url@14.1.1: + whatwg-url@14.2.0: dependencies: - tr46: 5.0.0 + tr46: 5.1.0 webidl-conversions: 7.0.0 whatwg-url@5.0.0: @@ -16168,7 +16033,7 @@ snapshots: yallist@5.0.0: {} - yaml@2.7.0: {} + yaml@2.7.1: {} yargs-parser@18.1.3: dependencies: diff --git a/renovate.json b/renovate.json index 7fca84fadc0e..46266084e448 100644 --- a/renovate.json +++ b/renovate.json @@ -14,15 +14,25 @@ "dependencyDashboard": true, "schedule": ["after 10:00pm every weekday", "before 4:00am every weekday", "every weekend"], "baseBranches": ["main"], - "ignoreDeps": ["@types/node", "@types/express", "build_bazel_rules_nodejs", "rules_pkg", "yarn"], + "ignoreDeps": ["@types/node", "build_bazel_rules_nodejs", "rules_pkg", "yarn"], "includePaths": [ "WORKSPACE", "package.json", - "packages/**/package.json", - "tests/legacy-cli/e2e/ng-snapshot/package.json", - ".github/workflows/**/*.yml" + "**/package.json", + ".github/workflows/**/*.yml", + ".nvmrc" ], + "ignorePaths": ["tests/legacy-cli/e2e/assets/**", "tests/schematics/update/packages/**"], "packageRules": [ + { + "matchDepNames": ["node"], + "matchUpdateTypes": ["minor", "patch"] + }, + { + "enabled": false, + "matchDepNames": ["node"], + "matchUpdateTypes": ["major"] + }, { "matchPackageNames": ["quicktype-core"], "schedule": ["before 4:00am on the first day of the month"] diff --git a/scripts/build-packages-dist.mts b/scripts/build-packages-dist.mts index 5bdd7b907048..441a3a2a021a 100644 --- a/scripts/build-packages-dist.mts +++ b/scripts/build-packages-dist.mts @@ -16,14 +16,13 @@ import { BuiltPackage } from '@angular/ng-dev'; import { execSync } from 'node:child_process'; import { chmodSync, copyFileSync, mkdirSync, rmSync } from 'node:fs'; import { dirname, join } from 'node:path'; -import { fileURLToPath } from 'node:url'; import sh from 'shelljs'; /** Name of the Bazel tag that will be used to find release package targets. */ const releaseTargetTag = 'release-package'; /** Path to the project directory. */ -const projectDir = join(dirname(fileURLToPath(import.meta.url)), '../'); +const projectDir = join(import.meta.dirname, '../'); /** Command that runs Bazel. */ const bazelCmd = process.env.BAZEL || `pnpm -s bazel`; diff --git a/scripts/build-schema.mts b/scripts/build-schema.mts index 2f7553e24f51..ffc042af9630 100644 --- a/scripts/build-schema.mts +++ b/scripts/build-schema.mts @@ -8,10 +8,9 @@ import { spawn } from 'node:child_process'; import { rm } from 'node:fs/promises'; -import { dirname, join, resolve } from 'node:path'; -import { fileURLToPath } from 'node:url'; +import { join, resolve } from 'node:path'; -const __dirname = dirname(fileURLToPath(import.meta.url)); +const __dirname = import.meta.dirname; const baseDir = resolve(`${__dirname}/..`); const bazelCmd = process.env.BAZEL ?? `pnpm -s bazel`; const distRoot = join(baseDir, '/dist-schema/'); diff --git a/scripts/build.mts b/scripts/build.mts index 1b15c026d480..b78df0d6b904 100644 --- a/scripts/build.mts +++ b/scripts/build.mts @@ -9,10 +9,9 @@ import { spawn } from 'node:child_process'; import { COPYFILE_FICLONE } from 'node:constants'; import fs from 'node:fs'; -import path, { dirname, join, relative, resolve } from 'node:path'; -import { fileURLToPath } from 'node:url'; +import { dirname, join, relative, resolve } from 'node:path'; -const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const __dirname = import.meta.dirname; const baseDir = resolve(`${__dirname}/..`); const bazelCmd = process.env.BAZEL ?? `pnpm -s bazel`; const distRoot = join(baseDir, '/dist'); diff --git a/scripts/create.mts b/scripts/create.mts index 7b4a78f39f63..9ed02a64b316 100644 --- a/scripts/create.mts +++ b/scripts/create.mts @@ -10,7 +10,7 @@ import assert from 'node:assert'; import * as child_process from 'node:child_process'; import { copyFile, readFile, rm, writeFile } from 'node:fs/promises'; import * as path from 'node:path'; -import { fileURLToPath, pathToFileURL } from 'node:url'; +import { pathToFileURL } from 'node:url'; import build from './build.mjs'; import { packages } from './packages.mjs'; @@ -18,7 +18,7 @@ export interface CreateOptions extends Record { _: string[]; } -const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const __dirname = import.meta.dirname; async function _exec(command: string, args: string[], opts: { cwd?: string }) { const { status, error, stderr, stdout } = child_process.spawnSync(command, args, { ...opts }); diff --git a/scripts/devkit-admin.mts b/scripts/devkit-admin.mts index 74a9e176db6b..3240759f3b54 100644 --- a/scripts/devkit-admin.mts +++ b/scripts/devkit-admin.mts @@ -8,8 +8,7 @@ */ import colors from 'ansi-colors'; -import path, { dirname } from 'node:path'; -import { fileURLToPath } from 'node:url'; +import path from 'node:path'; import yargsParser from 'yargs-parser'; const args = yargsParser(process.argv.slice(2), { @@ -21,7 +20,7 @@ const args = yargsParser(process.argv.slice(2), { const scriptName = args._.shift(); const cwd = process.cwd(); -const scriptDir = dirname(fileURLToPath(import.meta.url)); +const scriptDir = import.meta.dirname; process.chdir(path.join(scriptDir, '..')); const originalConsole = { ...console }; diff --git a/scripts/json-help.mts b/scripts/json-help.mts index c0b62162d875..34271a8925bc 100644 --- a/scripts/json-help.mts +++ b/scripts/json-help.mts @@ -10,10 +10,9 @@ import { spawnSync } from 'node:child_process'; import { promises as fs } from 'node:fs'; import * as os from 'node:os'; import * as path from 'node:path'; -import { fileURLToPath } from 'node:url'; import create from './create.mjs'; -const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const __dirname = import.meta.dirname; export async function createTemporaryProject(): Promise { console.info('Creating temporary project...'); diff --git a/scripts/snapshots.mts b/scripts/snapshots.mts index 6f29e6ef80c3..1e7a751aeab2 100644 --- a/scripts/snapshots.mts +++ b/scripts/snapshots.mts @@ -10,12 +10,11 @@ import { execSync, spawnSync } from 'node:child_process'; import * as fs from 'node:fs'; import * as os from 'node:os'; import * as path from 'node:path'; -import { fileURLToPath } from 'node:url'; import build from './build.mjs'; import jsonHelp, { createTemporaryProject } from './json-help.mjs'; import { PackageInfo, packages } from './packages.mjs'; -const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const __dirname = import.meta.dirname; // Added to the README.md of the snapshot. This is markdown. const readmeHeaderFn = (name: string, snapshotRepo: string) => ` diff --git a/scripts/templates.mts b/scripts/templates.mts index 11ef2b385bdd..06623a193a4d 100644 --- a/scripts/templates.mts +++ b/scripts/templates.mts @@ -9,10 +9,9 @@ import lodash from 'lodash'; import * as fs from 'node:fs'; import * as path from 'node:path'; -import { fileURLToPath } from 'node:url'; import { releasePackages } from './packages.mjs'; -const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const __dirname = import.meta.dirname; async function _runTemplate(inputPath: string, outputPath: string) { inputPath = path.resolve(__dirname, inputPath); diff --git a/scripts/validate-user-analytics.mts b/scripts/validate-user-analytics.mts index b91556c752b0..521e17bbf924 100644 --- a/scripts/validate-user-analytics.mts +++ b/scripts/validate-user-analytics.mts @@ -11,14 +11,13 @@ import lodash from 'lodash'; import assert from 'node:assert'; import * as fs from 'node:fs'; import * as path from 'node:path'; -import { fileURLToPath } from 'node:url'; import { EventCustomDimension, EventCustomMetric, UserCustomDimension, } from '../packages/angular/cli/src/analytics/analytics-parameters.mjs'; -const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const __dirname = import.meta.dirname; const userAnalyticsTable = lodash.template( fs.readFileSync(path.join(__dirname, './templates/user-analytics-table.ejs'), 'utf-8'), ); diff --git a/tests/legacy-cli/e2e.bzl b/tests/legacy-cli/e2e.bzl index 1bed11a77596..2152f6dcd229 100644 --- a/tests/legacy-cli/e2e.bzl +++ b/tests/legacy-cli/e2e.bzl @@ -46,6 +46,7 @@ WEBPACK_IGNORE_TESTS = [ "tests/i18n/ivy-localize-app-shell.js", "tests/i18n/ivy-localize-app-shell-service-worker.js", "tests/commands/serve/ssr-http-requests-assets.js", + "tests/build/styles/sass-pkg-importer.js", "tests/build/prerender/http-requests-assets.js", "tests/build/prerender/error-with-sourcemaps.js", "tests/build/server-rendering/server-routes-*", diff --git a/tests/legacy-cli/e2e/assets/BUILD.bazel b/tests/legacy-cli/e2e/assets/BUILD.bazel index a3e838b59a7b..946db62d0d5a 100644 --- a/tests/legacy-cli/e2e/assets/BUILD.bazel +++ b/tests/legacy-cli/e2e/assets/BUILD.bazel @@ -1,4 +1,4 @@ -load("//tools:defaults2.bzl", "copy_to_bin") +load("//tools:defaults.bzl", "copy_to_bin") copy_to_bin( name = "assets", diff --git a/tests/legacy-cli/e2e/assets/ssr-project-webpack/package.json b/tests/legacy-cli/e2e/assets/ssr-project-webpack/package.json index c8588a03cc54..607ff8d87288 100644 --- a/tests/legacy-cli/e2e/assets/ssr-project-webpack/package.json +++ b/tests/legacy-cli/e2e/assets/ssr-project-webpack/package.json @@ -20,7 +20,6 @@ "@angular/core": "^20.0.0-next.0", "@angular/forms": "^20.0.0-next.0", "@angular/platform-browser": "^20.0.0-next.0", - "@angular/platform-browser-dynamic": "^20.0.0-next.0", "@angular/platform-server": "^20.0.0-next.0", "@angular/router": "^20.0.0-next.0", "@angular/ssr": "^20.0.0-next.0", @@ -36,7 +35,7 @@ "@types/express": "^4.17.17", "@types/jasmine": "~4.3.0", "@types/mime": "^3.0.0", - "@types/node": "^18.18.0", + "@types/node": "^20.17.19", "jasmine-core": "~4.6.0", "karma": "~6.4.0", "karma-chrome-launcher": "~3.2.0", diff --git a/tests/legacy-cli/e2e/assets/ssr-project-webpack/src/main.ts b/tests/legacy-cli/e2e/assets/ssr-project-webpack/src/main.ts index c58dc05cbc6d..f3a8a045a0a7 100644 --- a/tests/legacy-cli/e2e/assets/ssr-project-webpack/src/main.ts +++ b/tests/legacy-cli/e2e/assets/ssr-project-webpack/src/main.ts @@ -1,7 +1,5 @@ -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; - +import { platformBrowser } from '@angular/platform-browser'; import { AppModule } from './app/app.module'; - -platformBrowserDynamic().bootstrapModule(AppModule) +platformBrowser().bootstrapModule(AppModule) .catch(err => console.error(err)); diff --git a/tests/legacy-cli/e2e/ng-snapshot/BUILD.bazel b/tests/legacy-cli/e2e/ng-snapshot/BUILD.bazel index a6196b576d38..63d76e1a07da 100644 --- a/tests/legacy-cli/e2e/ng-snapshot/BUILD.bazel +++ b/tests/legacy-cli/e2e/ng-snapshot/BUILD.bazel @@ -1,4 +1,4 @@ -load("//tools:defaults2.bzl", "copy_to_bin") +load("//tools:defaults.bzl", "copy_to_bin") copy_to_bin( name = "ng-snapshot", diff --git a/tests/legacy-cli/e2e/ng-snapshot/package.json b/tests/legacy-cli/e2e/ng-snapshot/package.json index 68b49cc7f14b..b0ecbb5aef14 100644 --- a/tests/legacy-cli/e2e/ng-snapshot/package.json +++ b/tests/legacy-cli/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#e584028b42528409c7b03bc106ff0b464ab15bd1", - "@angular/cdk": "github:angular/cdk-builds#f2ce6604298eead771fdacc88ac9cb68c0df809d", - "@angular/common": "github:angular/common-builds#01d50485fe83c22951bae8cc1a4671c348126422", - "@angular/compiler": "github:angular/compiler-builds#523dac1689489b3d7343550b4db895d0985a22b5", - "@angular/compiler-cli": "github:angular/compiler-cli-builds#ff3ed451766275c62cd8318f0dc670b69bc2de2b", - "@angular/core": "github:angular/core-builds#10fc1e4ed3f0d68d3e5a88548b4c41161f8f163a", - "@angular/forms": "github:angular/forms-builds#25932d9c18080a8dd5abb247e699a41a3d8a3095", - "@angular/language-service": "github:angular/language-service-builds#7f8ee163b14ae930ee0eb048a814a3acd3892de6", - "@angular/localize": "github:angular/localize-builds#fcce120e4fecd67191852617c0943da9ecb634fa", - "@angular/material": "github:angular/material-builds#8acdf1d04acfdf819722953611164ae0766a597b", - "@angular/material-moment-adapter": "github:angular/material-moment-adapter-builds#8b9f4812852729a6ba9e33125d51ad6e008aa491", - "@angular/platform-browser": "github:angular/platform-browser-builds#95eaabd4669a61c7969f0b38ec4324441cd84818", - "@angular/platform-browser-dynamic": "github:angular/platform-browser-dynamic-builds#d0e03e61ff2a26d47ee227581f47b6f6902e5799", - "@angular/platform-server": "github:angular/platform-server-builds#c3f2e2235192a984e338a1a911bd1819d24b8916", - "@angular/router": "github:angular/router-builds#6b4daa7fcedc7455785d8c9eda943d91eb601031", - "@angular/service-worker": "github:angular/service-worker-builds#7479509d39a9e67d546524c00054151b6051f2cf" + "@angular/animations": "github:angular/animations-builds#936eb84ef4638b0e6113f1b880049869dbc9423e", + "@angular/cdk": "github:angular/cdk-builds#8fbf8be26679ad50fc72378ea87170dd582dc70b", + "@angular/common": "github:angular/common-builds#60a3713b22ebc0ecbef7adb24019c39d3598ad0b", + "@angular/compiler": "github:angular/compiler-builds#7b58b2a81f005d8b81f4235c3a62561bc6cbb993", + "@angular/compiler-cli": "github:angular/compiler-cli-builds#560a074fdae3819c8fd1d7a28c1fd3bb2ce9d11f", + "@angular/core": "github:angular/core-builds#e4403819ca11b065c4849f0cde627691822d5307", + "@angular/forms": "github:angular/forms-builds#abecbfe1ee3c96392c9557b257e67b2aa33dd9e0", + "@angular/language-service": "github:angular/language-service-builds#aad925773a49798db1a65882fbb9a4a20fa7de85", + "@angular/localize": "github:angular/localize-builds#f425d1f058145d6d1c6c45624f7924415bc5de3e", + "@angular/material": "github:angular/material-builds#7ed103efaf3599ddceb98768512650bb7f399f1f", + "@angular/material-moment-adapter": "github:angular/material-moment-adapter-builds#4a5c01a507b4a145ce1d3f92f056075ef776e1e6", + "@angular/platform-browser": "github:angular/platform-browser-builds#c04316b7244712afa9f71d4ed6666e23aa401b44", + "@angular/platform-browser-dynamic": "github:angular/platform-browser-dynamic-builds#4085458a50ddd4a2b0a27f20b8ec3590e2d3936b", + "@angular/platform-server": "github:angular/platform-server-builds#f6bc5fb6aa8addd996437e77f9463c12b195af8c", + "@angular/router": "github:angular/router-builds#913ecbd023eeade1c3271c71b729073d89ff8971", + "@angular/service-worker": "github:angular/service-worker-builds#9eecdde40236508b0b17a6a6e8af8807021afcb1" } } diff --git a/tests/legacy-cli/e2e/tests/basic/aot.ts b/tests/legacy-cli/e2e/tests/basic/aot.ts index becaecc9eae2..d462d817332a 100644 --- a/tests/legacy-cli/e2e/tests/basic/aot.ts +++ b/tests/legacy-cli/e2e/tests/basic/aot.ts @@ -8,5 +8,5 @@ import { ng } from '../../utils/process'; export default async function () { await ng('build', '--aot=true', '--configuration=development'); const content = await readFile('dist/test-project/browser/main.js', 'utf-8'); - assert.match(content, /AppComponent_Factory/); + assert.match(content, /App_Factory/); } diff --git a/tests/legacy-cli/e2e/tests/basic/rebuild.ts b/tests/legacy-cli/e2e/tests/basic/rebuild.ts index fd5d2b789500..d7c75cce9fc5 100644 --- a/tests/legacy-cli/e2e/tests/basic/rebuild.ts +++ b/tests/legacy-cli/e2e/tests/basic/rebuild.ts @@ -7,7 +7,7 @@ import { ngServe } from '../../utils/project'; export default async function () { const esbuild = getGlobalVariable('argv')['esbuild']; const validBundleRegEx = esbuild ? /sent to client/ : /Compiled successfully\./; - const lazyBundleRegEx = esbuild ? /chunk-/ : /src_app_lazy_lazy_component_ts\.js/; + const lazyBundleRegEx = esbuild ? /chunk-/ : /src_app_lazy_lazy_ts\.js/; // Disable HMR to support page reload based rebuild testing. const port = await ngServe('--no-hmr'); @@ -25,7 +25,7 @@ export default async function () { replaceInFile( 'src/app/app.routes.ts', 'routes: Routes = [];', - `routes: Routes = [{path: 'lazy', loadComponent: () => import('./lazy/lazy.component').then(c => c.LazyComponent)}];`, + `routes: Routes = [{path: 'lazy', loadComponent: () => import('./lazy/lazy').then(c => c.Lazy)}];`, ), ]); @@ -83,7 +83,7 @@ export default async function () { await Promise.all([ waitForAnyProcessOutputToMatch(validBundleRegEx), writeMultipleFiles({ - 'src/app/app.component.ng.html': '

testingTESTING123

', + 'src/app/app.html': '

testingTESTING123

', }), ]); @@ -99,7 +99,7 @@ export default async function () { await Promise.all([ waitForAnyProcessOutputToMatch(validBundleRegEx), writeMultipleFiles({ - 'src/app/app.component.css': ':host { color: blue; }', + 'src/app/app.css': ':host { color: blue; }', }), ]); diff --git a/tests/legacy-cli/e2e/tests/build/app-shell/app-shell-with-schematic.ts b/tests/legacy-cli/e2e/tests/build/app-shell/app-shell-with-schematic.ts index 08fd86aeb0e6..65f6fdb23c48 100644 --- a/tests/legacy-cli/e2e/tests/build/app-shell/app-shell-with-schematic.ts +++ b/tests/legacy-cli/e2e/tests/build/app-shell/app-shell-with-schematic.ts @@ -7,7 +7,7 @@ import { updateJsonFile } from '../../../utils/project'; const snapshots = require('../../../ng-snapshot/package.json'); export default async function () { - await appendToFile('src/app/app.component.ng.html', ''); + await appendToFile('src/app/app.html', ''); await ng('generate', 'app-shell', '--project', 'test-project'); const isSnapshotBuild = getGlobalVariable('argv')['ng-snapshots']; diff --git a/tests/legacy-cli/e2e/tests/build/app-shell/app-shell-with-service-worker.ts b/tests/legacy-cli/e2e/tests/build/app-shell/app-shell-with-service-worker.ts index d0649a7711ed..b69e28e9ea38 100644 --- a/tests/legacy-cli/e2e/tests/build/app-shell/app-shell-with-service-worker.ts +++ b/tests/legacy-cli/e2e/tests/build/app-shell/app-shell-with-service-worker.ts @@ -7,7 +7,7 @@ import { updateJsonFile } from '../../../utils/project'; const snapshots = require('../../../ng-snapshot/package.json'); export default async function () { - await appendToFile('src/app/app.component.ng.html', ''); + await appendToFile('src/app/app.html', ''); await ng('generate', 'service-worker', '--project', 'test-project'); await ng('generate', 'app-shell', '--project', 'test-project'); diff --git a/tests/legacy-cli/e2e/tests/build/assets.ts b/tests/legacy-cli/e2e/tests/build/assets.ts index 5c484f02d5cd..93c89b5cad86 100644 --- a/tests/legacy-cli/e2e/tests/build/assets.ts +++ b/tests/legacy-cli/e2e/tests/build/assets.ts @@ -1,20 +1,46 @@ -import * as fs from 'node:fs'; -import { expectFileToExist, expectFileToMatch, writeFile } from '../../utils/fs'; +import assert from 'node:assert/strict'; +import { writeFile, stat, mkdir, symlink, utimes } from 'node:fs/promises'; +import { expectFileToExist, expectFileToMatch } from '../../utils/fs'; import { ng } from '../../utils/process'; import { updateJsonFile } from '../../utils/project'; import { expectToFail } from '../../utils/utils'; +import { getGlobalVariable } from '../../utils/env'; + +const isNodeV22orHigher = Number(process.versions.node.split('.', 1)[0]) >= 22; export default async function () { + // Update the atime and mtime of the original file. + // Note: Node.js has different time precision, which may cause mtime-based tests to fail. + // Ensure both values are rounded to the same precision for consistency. + // Example: + // Original: '1742973507738.0234' + // Node.js CP: '1742973507737.999' + const { atime, mtime } = await stat('public/favicon.ico'); + await utimes('public/favicon.ico', atime, mtime); + await writeFile('public/.file', ''); await writeFile('public/test.abc', 'hello world'); await ng('build', '--configuration=development'); - await expectFileToExist('dist/test-project/browser/favicon.ico'); await expectFileToExist('dist/test-project/browser/.file'); await expectFileToMatch('dist/test-project/browser/test.abc', 'hello world'); await expectToFail(() => expectFileToExist('dist/test-project/browser/.gitkeep')); + // Timestamp preservation only supported with application build system on Node.js v22+ + if (isNodeV22orHigher && getGlobalVariable('argv')['esbuild']) { + const [originalStats, outputStats] = await Promise.all([ + stat('public/favicon.ico'), + stat('dist/test-project/browser/favicon.ico'), + ]); + + assert.equal( + originalStats.mtimeMs, + outputStats.mtimeMs, + 'Asset file modified timestamp should be preserved.', + ); + } + // Ensure `followSymlinks` option follows symlinks await updateJsonFile('angular.json', (workspaceJson) => { const appArchitect = workspaceJson.projects['test-project'].architect; @@ -22,13 +48,17 @@ export default async function () { { glob: '**/*', input: 'public', followSymlinks: true }, ]; }); - fs.mkdirSync('dirToSymlink/subdir1', { recursive: true }); - fs.mkdirSync('dirToSymlink/subdir2/subsubdir1', { recursive: true }); - fs.writeFileSync('dirToSymlink/a.txt', ''); - fs.writeFileSync('dirToSymlink/subdir1/b.txt', ''); - fs.writeFileSync('dirToSymlink/subdir2/c.txt', ''); - fs.writeFileSync('dirToSymlink/subdir2/subsubdir1/d.txt', ''); - fs.symlinkSync(process.cwd() + '/dirToSymlink', 'public/symlinkDir'); + + await mkdir('dirToSymlink/subdir1', { recursive: true }); + await mkdir('dirToSymlink/subdir2/subsubdir1', { recursive: true }); + await symlink(process.cwd() + '/dirToSymlink', 'public/symlinkDir'); + + await Promise.all([ + writeFile('dirToSymlink/a.txt', ''), + writeFile('dirToSymlink/subdir1/b.txt', ''), + writeFile('dirToSymlink/subdir2/c.txt', ''), + writeFile('dirToSymlink/subdir2/subsubdir1/d.txt', ''), + ]); await ng('build', '--configuration=development'); diff --git a/tests/legacy-cli/e2e/tests/build/css-urls.ts b/tests/legacy-cli/e2e/tests/build/css-urls.ts index 6ce16d5ada48..839ecf58f567 100644 --- a/tests/legacy-cli/e2e/tests/build/css-urls.ts +++ b/tests/legacy-cli/e2e/tests/build/css-urls.ts @@ -33,7 +33,7 @@ export default async function () { h1 { background: url('/assets/global-img-absolute.svg'); } h2 { background: url('./assets/global-img-relative.png'); } `, - 'src/app/app.component.css': ` + 'src/app/app.css': ` h3 { background: url('/assets/component-img-absolute.svg'); } h4 { background: url('../assets/component-img-relative.png'); } `, diff --git a/tests/legacy-cli/e2e/tests/build/jit-ngmodule.ts b/tests/legacy-cli/e2e/tests/build/jit-ngmodule.ts index f307f8de9c0d..8ce44ea32386 100644 --- a/tests/legacy-cli/e2e/tests/build/jit-ngmodule.ts +++ b/tests/legacy-cli/e2e/tests/build/jit-ngmodule.ts @@ -23,6 +23,7 @@ export default async function () { main: build.options.browser, browser: undefined, buildOptimizer: false, + outputPath: 'dist/test-project-two', }; build.configurations.development = { diff --git a/tests/legacy-cli/e2e/tests/build/jit-prod.ts b/tests/legacy-cli/e2e/tests/build/jit-prod.ts index 7d6e6e767736..2042b0a8c93d 100644 --- a/tests/legacy-cli/e2e/tests/build/jit-prod.ts +++ b/tests/legacy-cli/e2e/tests/build/jit-prod.ts @@ -7,7 +7,12 @@ export default async function () { await updateJsonFile('angular.json', (configJson) => { const appArchitect = configJson.projects['test-project'].architect; appArchitect.build.configurations['production'].aot = false; + + // JIT applications have significantly larger sizes + appArchitect.build.configurations['production'].budgets = []; + if (!getGlobalVariable('argv')['esbuild']) { + // The build optimizer option does not exist with the application build system appArchitect.build.configurations['production'].buildOptimizer = false; } }); diff --git a/tests/legacy-cli/e2e/tests/build/lazy-load-syntax.ts b/tests/legacy-cli/e2e/tests/build/lazy-load-syntax.ts index bdb7b53f61b1..2b91b3f63b45 100644 --- a/tests/legacy-cli/e2e/tests/build/lazy-load-syntax.ts +++ b/tests/legacy-cli/e2e/tests/build/lazy-load-syntax.ts @@ -18,7 +18,7 @@ export default async function () { 'routes: Routes = [];', `routes: Routes = [{ path: 'lazy', - loadComponent: () => import('./lazy-comp/lazy-comp.component').then(c => c.LazyCompComponent), + loadComponent: () => import('./lazy-comp/lazy-comp').then(c => c.LazyComp), }];`, ); diff --git a/tests/legacy-cli/e2e/tests/build/library/lib-consumption-full-jit.ts b/tests/legacy-cli/e2e/tests/build/library/lib-consumption-full-jit.ts index eaba4a907e4f..edded2bebc88 100644 --- a/tests/legacy-cli/e2e/tests/build/library/lib-consumption-full-jit.ts +++ b/tests/legacy-cli/e2e/tests/build/library/lib-consumption-full-jit.ts @@ -29,6 +29,6 @@ export default async function () { await ng('build', '--configuration=development'); await expectFileToMatch( 'dist/test-project/browser/main.js.map', - 'projects/my-lib/src/lib/my-lib.component.ts', + 'projects/my-lib/src/lib/my-lib.ts', ); } diff --git a/tests/legacy-cli/e2e/tests/build/library/lib-consumption-sourcemaps.ts b/tests/legacy-cli/e2e/tests/build/library/lib-consumption-sourcemaps.ts index 7578700bb0df..c0b7a5e78a73 100644 --- a/tests/legacy-cli/e2e/tests/build/library/lib-consumption-sourcemaps.ts +++ b/tests/legacy-cli/e2e/tests/build/library/lib-consumption-sourcemaps.ts @@ -12,6 +12,6 @@ export default async function () { await ng('build', '--configuration=development'); await expectFileToMatch( 'dist/test-project/browser/main.js.map', - 'projects/my-lib/src/lib/my-lib.component.ts', + 'projects/my-lib/src/lib/my-lib.ts', ); } diff --git a/tests/legacy-cli/e2e/tests/build/library/lib-unused-decorated-class-treeshake.ts b/tests/legacy-cli/e2e/tests/build/library/lib-unused-decorated-class-treeshake.ts index c3816870b334..33b221a32efe 100644 --- a/tests/legacy-cli/e2e/tests/build/library/lib-unused-decorated-class-treeshake.ts +++ b/tests/legacy-cli/e2e/tests/build/library/lib-unused-decorated-class-treeshake.ts @@ -11,7 +11,7 @@ export default async function () { // Add an unused class as part of the public api. await appendToFile( - 'projects/my-lib/src/lib/my-lib.component.ts', + 'projects/my-lib/src/lib/my-lib.ts', ` function something() { return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { diff --git a/tests/legacy-cli/e2e/tests/build/library/setup.ts b/tests/legacy-cli/e2e/tests/build/library/setup.ts index 42b7b3360ac3..bc67a5b1c6aa 100644 --- a/tests/legacy-cli/e2e/tests/build/library/setup.ts +++ b/tests/legacy-cli/e2e/tests/build/library/setup.ts @@ -6,18 +6,18 @@ export async function libraryConsumptionSetup(): Promise { // Force an external template await writeMultipleFiles({ - 'projects/my-lib/src/lib/my-lib.component.ng.html': `

my-lib works!

`, - 'projects/my-lib/src/lib/my-lib.component.ts': `import { Component } from '@angular/core'; + 'projects/my-lib/src/lib/my-lib.html': `

my-lib works!

`, + 'projects/my-lib/src/lib/my-lib.ts': `import { Component } from '@angular/core'; @Component({ standalone: true, selector: 'lib-my-lib', - templateUrl: './my-lib.component.ng.html', + templateUrl: './my-lib.html', }) export class MyLibComponent {}`, - './src/app/app.component.ts': ` + './src/app/app.ts': ` import { Component } from '@angular/core'; - import { MyLibService, MyLibComponent } from 'my-lib'; + import { MyLibComponent } from 'my-lib'; @Component({ standalone: true, @@ -25,11 +25,10 @@ export async function libraryConsumptionSetup(): Promise { template: '', imports: [MyLibComponent], }) - export class AppComponent { + export class App { title = 'test-project'; - constructor(myLibService: MyLibService) { - console.log(myLibService); + constructor() { } } `, diff --git a/tests/legacy-cli/e2e/tests/build/prerender/discover-routes-ngmodule.ts b/tests/legacy-cli/e2e/tests/build/prerender/discover-routes-ngmodule.ts index 8a4e074f6045..cc79e32f9185 100644 --- a/tests/legacy-cli/e2e/tests/build/prerender/discover-routes-ngmodule.ts +++ b/tests/legacy-cli/e2e/tests/build/prerender/discover-routes-ngmodule.ts @@ -1,7 +1,7 @@ import { join } from 'node:path'; import { getGlobalVariable } from '../../../utils/env'; -import { expectFileToMatch, rimraf, writeFile } from '../../../utils/fs'; -import { installWorkspacePackages } from '../../../utils/packages'; +import { expectFileToMatch, writeFile } from '../../../utils/fs'; +import { installWorkspacePackages, uninstallPackage } from '../../../utils/packages'; import { ng } from '../../../utils/process'; import { updateJsonFile, useSha } from '../../../utils/project'; @@ -31,58 +31,44 @@ export default async function () { } // Forcibly remove in case another test doesn't clean itself up. - await rimraf('node_modules/@angular/ssr'); - if (useWebpackBuilder) { - await ng( - 'add', - '@angular/ssr', - '--project', - projectName, - '--skip-confirmation', - '--skip-install', - // Server routing is not supported on `browser` builder. - // '--server-routing', - ); - } else { - await ng( - 'add', - '@angular/ssr', - '--project', - projectName, - '--skip-confirmation', - '--skip-install', - '--server-routing', - ); - } + await uninstallPackage('@angular/ssr'); + await ng( + 'add', + '@angular/ssr', + '--project', + projectName, + '--skip-confirmation', + '--skip-install', + ); await useSha(); await installWorkspacePackages(); // Add routes await writeFile( - `projects/${projectName}/src/app/app-routing.module.ts`, + `projects/${projectName}/src/app/app-routing-module.ts`, ` import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; - import { OneComponent } from './one/one.component'; - import { TwoChildOneComponent } from './two-child-one/two-child-one.component'; - import { TwoChildTwoComponent } from './two-child-two/two-child-two.component'; + import { One} from './one/one'; + import { TwoChildOne } from './two-child-one/two-child-one'; + import { TwoChildTwo } from './two-child-two/two-child-two'; const routes: Routes = [ { path: '', - component: OneComponent, + component: One, }, { path: 'two', children: [ { path: 'two-child-one', - component: TwoChildOneComponent, + component: TwoChildOne, }, { path: 'two-child-two', - component: TwoChildTwoComponent, + component: TwoChildTwo, }, ], }, @@ -105,9 +91,9 @@ export default async function () { // Generate lazy routes const lazyModules: [route: string, moduleName: string][] = [ - ['lazy-one', 'app.module'], - ['lazy-one-child', 'lazy-one/lazy-one.module'], - ['lazy-two', 'app.module'], + ['lazy-one', 'app-module'], + ['lazy-one-child', 'lazy-one/lazy-one-module'], + ['lazy-two', 'app-module'], ]; for (const [route, moduleName] of lazyModules) { diff --git a/tests/legacy-cli/e2e/tests/build/prerender/discover-routes-standalone.ts b/tests/legacy-cli/e2e/tests/build/prerender/discover-routes-standalone.ts index 25c63781de11..71a3ba2fb15d 100644 --- a/tests/legacy-cli/e2e/tests/build/prerender/discover-routes-standalone.ts +++ b/tests/legacy-cli/e2e/tests/build/prerender/discover-routes-standalone.ts @@ -1,7 +1,7 @@ import { join } from 'node:path'; import { getGlobalVariable } from '../../../utils/env'; -import { expectFileToMatch, readFile, rimraf, writeFile } from '../../../utils/fs'; -import { installWorkspacePackages } from '../../../utils/packages'; +import { expectFileToMatch, readFile, writeFile } from '../../../utils/fs'; +import { installWorkspacePackages, uninstallPackage } from '../../../utils/packages'; import { ng } from '../../../utils/process'; import { useSha } from '../../../utils/project'; import { deepStrictEqual } from 'node:assert'; @@ -9,7 +9,7 @@ import { deepStrictEqual } from 'node:assert'; export default async function () { const useWebpackBuilder = !getGlobalVariable('argv')['esbuild']; // Forcibly remove in case another test doesn't clean itself up. - await rimraf('node_modules/@angular/ssr'); + await uninstallPackage('@angular/ssr'); await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); await useSha(); @@ -20,25 +20,25 @@ export default async function () { 'src/app/app.routes.ts', ` import { Routes } from '@angular/router'; - import { OneComponent } from './one/one.component'; - import { TwoChildOneComponent } from './two-child-one/two-child-one.component'; - import { TwoChildTwoComponent } from './two-child-two/two-child-two.component'; + import { One } from './one/one'; + import { TwoChildOne } from './two-child-one/two-child-one'; + import { TwoChildTwo } from './two-child-two/two-child-two'; export const routes: Routes = [ { path: '', - component: OneComponent, + component: One, }, { path: 'two', children: [ { path: 'two-child-one', - component: TwoChildOneComponent, + component: TwoChildOne, }, { path: 'two-child-two', - component: TwoChildTwoComponent, + component: TwoChildTwo, }, ], }, @@ -47,21 +47,17 @@ export default async function () { children: [ { path: '', - loadComponent: () => import('./lazy-one/lazy-one.component').then(c => c.LazyOneComponent), + loadComponent: () => import('./lazy-one/lazy-one').then(c => c.LazyOne), }, { path: 'lazy-one-child', - loadComponent: () => import('./lazy-one-child/lazy-one-child.component').then(c => c.LazyOneChildComponent), + loadComponent: () => import('./lazy-one-child/lazy-one-child').then(c => c.LazyOneChild), }, ], }, { path: 'lazy-two', - loadComponent: () => import('./lazy-two/lazy-two.component').then(c => c.LazyTwoComponent), - }, - { - path: ':param', - component: OneComponent, + loadComponent: () => import('./lazy-two/lazy-two').then(c => c.LazyTwo), }, ]; `, diff --git a/tests/legacy-cli/e2e/tests/build/prerender/error-with-sourcemaps.ts b/tests/legacy-cli/e2e/tests/build/prerender/error-with-sourcemaps.ts index f872e25c77a2..b7970cec4000 100644 --- a/tests/legacy-cli/e2e/tests/build/prerender/error-with-sourcemaps.ts +++ b/tests/legacy-cli/e2e/tests/build/prerender/error-with-sourcemaps.ts @@ -19,7 +19,7 @@ export default async function () { await installWorkspacePackages(); await writeMultipleFiles({ - 'src/app/app.component.ts': ` + 'src/app/app.ts': ` import { Component } from '@angular/core'; import { CommonModule } from '@angular/common'; import { RouterOutlet } from '@angular/router'; @@ -28,10 +28,10 @@ export default async function () { selector: 'app-root', standalone: true, imports: [CommonModule, RouterOutlet], - templateUrl: './app.component.ng.html', - styleUrls: ['./app.component.css'] + templateUrl: './app.html', + styleUrls: ['./app.css'] }) - export class AppComponent { + export class App { title = 'test-ssr'; constructor() { @@ -48,6 +48,6 @@ export default async function () { message, // When babel is used it will add names to the sourcemap and `constructor` will be used in the stack trace. // This will currently only happen if AOT and script optimizations are set which enables advanced optimizations. - /window is not defined[.\s\S]*(?:constructor|_AppComponent) \(.*app\.component\.ts\:\d+:\d+\)/, + /window is not defined[.\s\S]*(?:constructor|_App) \(.*app\.ts\:\d+:\d+\)/, ); } diff --git a/tests/legacy-cli/e2e/tests/build/prerender/http-requests-assets.ts b/tests/legacy-cli/e2e/tests/build/prerender/http-requests-assets.ts index 81abed0008ba..b68e0a72b92a 100644 --- a/tests/legacy-cli/e2e/tests/build/prerender/http-requests-assets.ts +++ b/tests/legacy-cli/e2e/tests/build/prerender/http-requests-assets.ts @@ -13,7 +13,7 @@ export default async function () { // Forcibly remove in case another test doesn't clean itself up. await rimraf('node_modules/@angular/ssr'); - await ng('add', '@angular/ssr', '--server-routing', '--skip-confirmation'); + await ng('add', '@angular/ssr', '--skip-confirmation'); await useSha(); await installWorkspacePackages(); @@ -23,7 +23,7 @@ export default async function () { import { ApplicationConfig } from '@angular/core'; import { provideRouter } from '@angular/router'; - import {HomeComponent} from './home/home.component'; + import {Home} from './home/home'; import { provideClientHydration } from '@angular/platform-browser'; import { provideHttpClient, withFetch } from '@angular/common/http'; @@ -31,7 +31,7 @@ export default async function () { providers: [ provideRouter([{ path: '', - component: HomeComponent, + component: Home, }]), provideClientHydration(), provideHttpClient(withFetch()), @@ -44,7 +44,7 @@ export default async function () { 'public/media with-space.json': JSON.stringify({ dataFromAssetsWithSpace: true }), // Update component to do an HTTP call to asset. - 'src/app/app.component.ts': ` + 'src/app/app.ts': ` import { Component, inject } from '@angular/core'; import { CommonModule } from '@angular/common'; import { RouterOutlet } from '@angular/router'; @@ -60,7 +60,7 @@ export default async function () { \`, }) - export class AppComponent { + export class App { data: any; dataWithSpace: any; diff --git a/tests/legacy-cli/e2e/tests/build/rebuild-dot-dirname.ts b/tests/legacy-cli/e2e/tests/build/rebuild-dot-dirname.ts index 8eaba61f5fdc..ca6ab8ad2886 100644 --- a/tests/legacy-cli/e2e/tests/build/rebuild-dot-dirname.ts +++ b/tests/legacy-cli/e2e/tests/build/rebuild-dot-dirname.ts @@ -33,6 +33,7 @@ export default async function () { ...build.options, main: build.options.browser, browser: undefined, + outputPath: 'dist/subdirectory-test-project', }; build.configurations.development = { diff --git a/tests/legacy-cli/e2e/tests/build/relative-sourcemap.ts b/tests/legacy-cli/e2e/tests/build/relative-sourcemap.ts index 598661d873e1..789b52748796 100644 --- a/tests/legacy-cli/e2e/tests/build/relative-sourcemap.ts +++ b/tests/legacy-cli/e2e/tests/build/relative-sourcemap.ts @@ -18,6 +18,7 @@ export default async function () { ...build.options, main: build.options.browser, browser: undefined, + outputPath: 'dist/secondary-project', }; build.configurations.development = { diff --git a/tests/legacy-cli/e2e/tests/build/server-rendering/express-engine-csp-nonce.ts b/tests/legacy-cli/e2e/tests/build/server-rendering/express-engine-csp-nonce.ts index 96be34e524da..19e7dcd28b60 100644 --- a/tests/legacy-cli/e2e/tests/build/server-rendering/express-engine-csp-nonce.ts +++ b/tests/legacy-cli/e2e/tests/build/server-rendering/express-engine-csp-nonce.ts @@ -3,20 +3,13 @@ import { rimraf, writeMultipleFiles } from '../../../utils/fs'; import { findFreePort } from '../../../utils/network'; import { installWorkspacePackages } from '../../../utils/packages'; import { execAndWaitForOutputToMatch, ng } from '../../../utils/process'; -import { updateJsonFile, updateServerFileForWebpack, useSha } from '../../../utils/project'; +import { updateJsonFile, updateServerFileForEsbuild, useSha } from '../../../utils/project'; export default async function () { const useWebpackBuilder = !getGlobalVariable('argv')['esbuild']; // forcibly remove in case another test doesn't clean itself up await rimraf('node_modules/@angular/ssr'); - - if (useWebpackBuilder) { - // `--server-routing` not supported in `browser` builder. - await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); - } else { - await ng('add', '@angular/ssr', '--server-routing', '--skip-confirmation', '--skip-install'); - } - + await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); await useSha(); await installWorkspacePackages(); @@ -27,18 +20,18 @@ export default async function () { build.configurations.production.prerender = false; }); - await updateServerFileForWebpack('src/server.ts'); + await updateServerFileForEsbuild('src/server.ts'); } await writeMultipleFiles({ - 'src/app/app.component.css': `div { color: #000 }`, + 'src/app/app.css': `div { color: #000 }`, 'src/styles.css': `* { color: #000 }`, 'src/main.ts': `import { bootstrapApplication } from '@angular/platform-browser'; - import { AppComponent } from './app/app.component'; + import { App } from './app/app'; import { appConfig } from './app/app.config'; (window as any)['doBootstrap'] = () => { - bootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err)); + bootstrapApplication(App, appConfig).catch((err) => console.error(err)); }; `, 'src/index.html': ` diff --git a/tests/legacy-cli/e2e/tests/build/server-rendering/express-engine-ngmodule.ts b/tests/legacy-cli/e2e/tests/build/server-rendering/express-engine-ngmodule.ts index dda29bdced62..2fa393de929f 100644 --- a/tests/legacy-cli/e2e/tests/build/server-rendering/express-engine-ngmodule.ts +++ b/tests/legacy-cli/e2e/tests/build/server-rendering/express-engine-ngmodule.ts @@ -5,7 +5,7 @@ import { installWorkspacePackages } from '../../../utils/packages'; import { execAndWaitForOutputToMatch, ng } from '../../../utils/process'; import { updateJsonFile, - updateServerFileForWebpack, + updateServerFileForEsbuild, useCIChrome, useCIDefaults, useSha, @@ -62,18 +62,18 @@ export default async function () { build.options.outputMode = undefined; }); - await updateServerFileForWebpack('projects/test-project-two/src/server.ts'); + await updateServerFileForEsbuild('projects/test-project-two/src/server.ts'); } await writeMultipleFiles({ - 'projects/test-project-two/src/app/app.component.css': `div { color: #000 }`, + 'projects/test-project-two/src/app/app.css': `div { color: #000 }`, 'projects/test-project-two/src/styles.css': `* { color: #000 }`, 'projects/test-project-two/src/main.ts': ` - import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; - import { AppModule } from './app/app.module'; + import { platformBrowser } from '@angular/platform-browser'; + import { AppModule } from './app/app-module'; (window as any)['doBootstrap'] = () => { - platformBrowserDynamic() + platformBrowser() .bootstrapModule(AppModule) .catch((err) => console.error(err)); }; diff --git a/tests/legacy-cli/e2e/tests/build/server-rendering/express-engine-standalone.ts b/tests/legacy-cli/e2e/tests/build/server-rendering/express-engine-standalone.ts index b697ac513ab4..7c819e67693a 100644 --- a/tests/legacy-cli/e2e/tests/build/server-rendering/express-engine-standalone.ts +++ b/tests/legacy-cli/e2e/tests/build/server-rendering/express-engine-standalone.ts @@ -3,20 +3,14 @@ import { rimraf, writeMultipleFiles } from '../../../utils/fs'; import { findFreePort } from '../../../utils/network'; import { installWorkspacePackages } from '../../../utils/packages'; import { execAndWaitForOutputToMatch, ng } from '../../../utils/process'; -import { updateJsonFile, updateServerFileForWebpack, useSha } from '../../../utils/project'; +import { updateJsonFile, updateServerFileForEsbuild, useSha } from '../../../utils/project'; export default async function () { // forcibly remove in case another test doesn't clean itself up await rimraf('node_modules/@angular/ssr'); const useWebpackBuilder = !getGlobalVariable('argv')['esbuild']; - - if (useWebpackBuilder) { - // `--server-routing` not supported in `browser` builder. - await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); - } else { - await ng('add', '@angular/ssr', '--server-routing', '--skip-confirmation', '--skip-install'); - } + await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); if (!useWebpackBuilder) { // Disable prerendering @@ -25,21 +19,21 @@ export default async function () { build.options.outputMode = undefined; }); - await updateServerFileForWebpack('src/server.ts'); + await updateServerFileForEsbuild('src/server.ts'); } await useSha(); await installWorkspacePackages(); await writeMultipleFiles({ - 'src/app/app.component.css': `div { color: #000 }`, + 'src/app/app.css': `div { color: #000 }`, 'src/styles.css': `* { color: #000 }`, 'src/main.ts': `import { bootstrapApplication } from '@angular/platform-browser'; - import { AppComponent } from './app/app.component'; + import { App } from './app/app'; import { appConfig } from './app/app.config'; (window as any)['doBootstrap'] = () => { - bootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err)); + bootstrapApplication(App, appConfig).catch((err) => console.error(err)); }; `, 'e2e/src/app.e2e-spec.ts': ` diff --git a/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-external-dependencies.ts b/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-external-dependencies.ts index 9d01f375a211..52ceafa7b05f 100644 --- a/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-external-dependencies.ts +++ b/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-external-dependencies.ts @@ -12,7 +12,7 @@ export default async function () { // Forcibly remove in case another test doesn't clean itself up. await uninstallPackage('@angular/ssr'); - await ng('add', '@angular/ssr', '--server-routing', '--skip-confirmation', '--skip-install'); + await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); await useSha(); await installWorkspacePackages(); diff --git a/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-i18n-base-href.ts b/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-i18n-base-href.ts index c4c2065f8b64..6d0a45459a16 100644 --- a/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-i18n-base-href.ts +++ b/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-i18n-base-href.ts @@ -19,7 +19,7 @@ export default async function () { // Forcibly remove in case another test doesn't clean itself up. await uninstallPackage('@angular/ssr'); - await ng('add', '@angular/ssr', '--server-routing', '--skip-confirmation', '--skip-install'); + await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); await useSha(); await installWorkspacePackages(); @@ -28,22 +28,22 @@ export default async function () { 'src/app/app.routes.ts', ` import { Routes } from '@angular/router'; - import { HomeComponent } from './home/home.component'; - import { SsrComponent } from './ssr/ssr.component'; - import { SsgComponent } from './ssg/ssg.component'; + import { Home } from './home/home'; + import { Ssr } from './ssr/ssr'; + import { Ssg } from './ssg/ssg'; export const routes: Routes = [ { path: '', - component: HomeComponent, + component: Home, }, { path: 'ssg', - component: SsgComponent, + component: Ssg, }, { path: 'ssr', - component: SsrComponent, + component: Ssr, }, ]; `, diff --git a/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-i18n-sub-path.ts b/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-i18n-sub-path.ts index 9b7f75f04a87..79fc755c4477 100644 --- a/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-i18n-sub-path.ts +++ b/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-i18n-sub-path.ts @@ -44,7 +44,7 @@ export default async function () { // Forcibly remove in case another test doesn't clean itself up. await uninstallPackage('@angular/ssr'); - await ng('add', '@angular/ssr', '--server-routing', '--skip-confirmation', '--skip-install'); + await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); await useSha(); await installWorkspacePackages(); @@ -53,22 +53,22 @@ export default async function () { 'src/app/app.routes.ts', ` import { Routes } from '@angular/router'; - import { HomeComponent } from './home/home.component'; - import { SsrComponent } from './ssr/ssr.component'; - import { SsgComponent } from './ssg/ssg.component'; + import { Home } from './home/home'; + import { Ssr } from './ssr/ssr'; + import { Ssg } from './ssg/ssg'; export const routes: Routes = [ { path: '', - component: HomeComponent, + component: Home, }, { path: 'ssg', - component: SsgComponent, + component: Ssg, }, { path: 'ssr', - component: SsrComponent, + component: Ssr, }, ]; `, diff --git a/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-i18n.ts b/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-i18n.ts index 0f10a959a9de..994d77343d1e 100644 --- a/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-i18n.ts +++ b/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-i18n.ts @@ -19,7 +19,7 @@ export default async function () { // Forcibly remove in case another test doesn't clean itself up. await uninstallPackage('@angular/ssr'); - await ng('add', '@angular/ssr', '--server-routing', '--skip-confirmation', '--skip-install'); + await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); await useSha(); await installWorkspacePackages(); @@ -28,22 +28,22 @@ export default async function () { 'src/app/app.routes.ts', ` import { Routes } from '@angular/router'; - import { HomeComponent } from './home/home.component'; - import { SsrComponent } from './ssr/ssr.component'; - import { SsgComponent } from './ssg/ssg.component'; + import { Home } from './home/home'; + import { Ssr } from './ssr/ssr'; + import { Ssg } from './ssg/ssg'; export const routes: Routes = [ { path: '', - component: HomeComponent, + component: Home, }, { path: 'ssg', - component: SsgComponent, + component: Ssg, }, { path: 'ssr', - component: SsrComponent, + component: Ssr, }, ]; `, diff --git a/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-platform-neutral.ts b/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-platform-neutral.ts index 85b6891fa28c..130ade10ba9f 100644 --- a/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-platform-neutral.ts +++ b/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-platform-neutral.ts @@ -21,32 +21,32 @@ export default async function () { // Forcibly remove in case another test doesn't clean itself up. await uninstallPackage('@angular/ssr'); - await ng('add', '@angular/ssr', '--server-routing', '--skip-confirmation', '--skip-install'); + await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); await useSha(); await installWorkspacePackages(); await installPackage('h3@1'); await writeMultipleFiles({ - // Replace the template of app.component.ng.html as it makes it harder to debug - 'src/app/app.component.ng.html': '', + // Replace the template of app.ng.html as it makes it harder to debug + 'src/app/app.html': '', 'src/app/app.routes.ts': ` import { Routes } from '@angular/router'; - import { HomeComponent } from './home/home.component'; - import { SsrComponent } from './ssr/ssr.component'; - import { SsgWithParamsComponent } from './ssg-with-params/ssg-with-params.component'; + import { Home } from './home/home'; + import { Ssr } from './ssr/ssr'; + import { SsgWithParams } from './ssg-with-params/ssg-with-params'; export const routes: Routes = [ { path: '', - component: HomeComponent, + component: Home, }, { path: 'ssr', - component: SsrComponent, + component: Ssr, }, { path: 'ssg/:id', - component: SsgWithParamsComponent, + component: SsgWithParams, }, ]; `, diff --git a/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server.ts b/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server.ts index 891b646bfc38..77b9f9adab61 100644 --- a/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server.ts +++ b/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server.ts @@ -16,43 +16,43 @@ export default async function () { // Forcibly remove in case another test doesn't clean itself up. await uninstallPackage('@angular/ssr'); - await ng('add', '@angular/ssr', '--server-routing', '--skip-confirmation', '--skip-install'); + await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); await useSha(); await installWorkspacePackages(); // Test scenario to verify that the content length, including \r\n, is accurate - await replaceInFile('src/app/app.component.ts', "title = '", "title = 'Title\\r\\n"); + await replaceInFile('src/app/app.ts', "title = '", "title = 'Title\\r\\n"); // Ensure text has been updated. - assert.match(await readFile('src/app/app.component.ts'), /title = 'Title/); + assert.match(await readFile('src/app/app.ts'), /title = 'Title/); // Add routes await writeFile( 'src/app/app.routes.ts', ` import { Routes } from '@angular/router'; - import { HomeComponent } from './home/home.component'; - import { CsrComponent } from './csr/csr.component'; - import { SsrComponent } from './ssr/ssr.component'; - import { SsgComponent } from './ssg/ssg.component'; - import { SsgWithParamsComponent } from './ssg-with-params/ssg-with-params.component'; + import { Home } from './home/home'; + import { Csr } from './csr/csr'; + import { Ssr } from './ssr/ssr'; + import { Ssg } from './ssg/ssg'; + import { SsgWithParams } from './ssg-with-params/ssg-with-params'; export const routes: Routes = [ { path: '', - component: HomeComponent, + component: Home, }, { path: 'ssg', - component: SsgComponent, + component: Ssg, }, { path: 'ssr', - component: SsrComponent, + component: Ssr, }, { path: 'csr', - component: CsrComponent, + component: Csr, }, { path: 'redirect', @@ -60,7 +60,7 @@ export default async function () { }, { path: 'ssg/:id', - component: SsgWithParamsComponent, + component: SsgWithParams, }, ]; `, diff --git a/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-static-http-calls.ts b/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-static-http-calls.ts index 734f15e666e3..8e7483f77ee4 100644 --- a/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-static-http-calls.ts +++ b/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-static-http-calls.ts @@ -13,7 +13,7 @@ export default async function () { // Forcibly remove in case another test doesn't clean itself up. await uninstallPackage('@angular/ssr'); - await ng('add', '@angular/ssr', '--server-routing', '--skip-confirmation', '--skip-install'); + await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); await useSha(); await installWorkspacePackages(); @@ -21,7 +21,7 @@ export default async function () { // Add asset 'public/media.json': JSON.stringify({ dataFromAssets: true }), // Update component to do an HTTP call to asset and API. - 'src/app/app.component.ts': ` + 'src/app/app.ts': ` import { Component, inject } from '@angular/core'; import { JsonPipe } from '@angular/common'; import { RouterOutlet } from '@angular/router'; @@ -37,7 +37,7 @@ export default async function () { \`, }) - export class AppComponent { + export class App { assetsData: any; apiData: any; @@ -59,7 +59,7 @@ export default async function () { import { ApplicationConfig } from '@angular/core'; import { provideRouter } from '@angular/router'; - import { HomeComponent } from './home/home.component'; + import { Home } from './home/home'; import { provideClientHydration } from '@angular/platform-browser'; import { provideHttpClient, withFetch } from '@angular/common/http'; @@ -67,7 +67,7 @@ export default async function () { providers: [ provideRouter([{ path: 'home', - component: HomeComponent, + component: Home, }]), provideClientHydration(), provideHttpClient(withFetch()), @@ -77,23 +77,23 @@ export default async function () { 'src/server.ts': ` import { AngularNodeAppEngine, writeResponseToNodeResponse, isMainModule, createNodeRequestHandler } from '@angular/ssr/node'; import express from 'express'; - import { fileURLToPath } from 'node:url'; - import { dirname, resolve } from 'node:path'; + import { join } from 'node:path'; export function app(): express.Express { const server = express(); - const serverDistFolder = dirname(fileURLToPath(import.meta.url)); - const browserDistFolder = resolve(serverDistFolder, '../browser'); + const browserDistFolder = join(import.meta.dirname, '../browser'); const angularNodeAppEngine = new AngularNodeAppEngine(); - server.get('/api', (req, res) => res.json({ dataFromAPI: true })); + server.get('/api', (req, res) => { + res.json({ dataFromAPI: true }) + }); - server.get('**', express.static(browserDistFolder, { + server.use(express.static(browserDistFolder, { maxAge: '1y', index: 'index.html' })); - server.get('**', (req, res, next) => { + server.use((req, res, next) => { angularNodeAppEngine.handle(req) .then((response) => response ? writeResponseToNodeResponse(response, res) : next()) .catch(next); @@ -105,7 +105,10 @@ export default async function () { if (isMainModule(import.meta.url)) { const port = process.env['PORT'] || 4000; - server.listen(port, () => { + server.listen(port, (error) => { + if (error) { + throw error; + } console.log(\`Node Express server listening on http://localhost:\${port}\`); }); } diff --git a/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-static-i18n_APP_BASE_HREF.ts b/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-static-i18n_APP_BASE_HREF.ts index 1d5d7847fca6..51f5e3990bae 100644 --- a/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-static-i18n_APP_BASE_HREF.ts +++ b/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-static-i18n_APP_BASE_HREF.ts @@ -19,7 +19,7 @@ export default async function () { // Forcibly remove in case another test doesn't clean itself up. await uninstallPackage('@angular/ssr'); - await ng('add', '@angular/ssr', '--server-routing', '--skip-confirmation', '--skip-install'); + await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); await useSha(); await installWorkspacePackages(); @@ -28,21 +28,21 @@ export default async function () { 'src/app/app.routes.ts', ` import { Routes } from '@angular/router'; - import { HomeComponent } from './home/home.component'; - import { SsgComponent } from './ssg/ssg.component'; + import { Home } from './home/home'; + import { Ssg } from './ssg/ssg'; export const routes: Routes = [ { path: '', - component: HomeComponent, + component: Home, }, { path: 'ssg', - component: SsgComponent, + component: Ssg, }, { path: '**', - component: HomeComponent, + component: Home, }, ]; `, diff --git a/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-static.ts b/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-static.ts index 4fe4c249803d..617776a94dc7 100644 --- a/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-static.ts +++ b/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-static.ts @@ -21,7 +21,7 @@ export default async function () { // Forcibly remove in case another test doesn't clean itself up. await uninstallPackage('@angular/ssr'); - await ng('add', '@angular/ssr', '--server-routing', '--skip-confirmation', '--skip-install'); + await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); await useSha(); await installWorkspacePackages(); @@ -30,18 +30,18 @@ export default async function () { 'src/app/app.routes.ts', ` import { Routes } from '@angular/router'; - import { HomeComponent } from './home/home.component'; - import { SsgComponent } from './ssg/ssg.component'; - import { SsgWithParamsComponent } from './ssg-with-params/ssg-with-params.component'; + import { Home } from './home/home'; + import { Ssg } from './ssg/ssg'; + import { SsgWithParams } from './ssg-with-params/ssg-with-params'; export const routes: Routes = [ { path: '', - component: HomeComponent, + component: Home, }, { path: 'ssg', - component: SsgComponent, + component: Ssg, }, { path: 'ssg-redirect', @@ -49,11 +49,11 @@ export default async function () { }, { path: 'ssg/:id', - component: SsgWithParamsComponent, + component: SsgWithParams, }, { path: '**', - component: HomeComponent, + component: Home, }, ]; `, diff --git a/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-preload-links.ts b/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-preload-links.ts index 92c154db3891..19697ace5657 100644 --- a/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-preload-links.ts +++ b/tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-preload-links.ts @@ -14,7 +14,7 @@ export default async function () { // Forcibly remove in case another test doesn't clean itself up. await uninstallPackage('@angular/ssr'); - await ng('add', '@angular/ssr', '--server-routing', '--skip-confirmation', '--skip-install'); + await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); await useSha(); await installWorkspacePackages(); @@ -31,7 +31,7 @@ export default async function () { export const routes: Routes = [ { path: '', - loadComponent: () => import('./home/home.component').then(c => c.HomeComponent), + loadComponent: () => import('./home/home').then(c => c.Home), }, { path: 'ssg', @@ -39,11 +39,11 @@ export default async function () { }, { path: 'ssr', - loadComponent: () => import('./ssr/ssr.component').then(c => c.SsrComponent), + loadComponent: () => import('./ssr/ssr').then(c => c.Ssr), }, { path: 'csr', - loadComponent: () => import('./csr/csr.component').then(c => c.CsrComponent), + loadComponent: () => import('./csr/csr').then(c => c.Csr), }, ]; `, @@ -72,21 +72,21 @@ export default async function () { export const routes: Routes = [ { path: '', - loadComponent: () => import('./ssg/ssg.component').then(c => c.SsgComponent), + loadComponent: () => import('./ssg-component/ssg-component').then(c => c.SsgComponent), }, { path: 'one', - loadComponent: () => import('./ssg-one/ssg-one.component').then(c => c.SsgOneComponent), + loadComponent: () => import('./ssg-one/ssg-one').then(c => c.SsgOne), }, { path: 'two', - loadComponent: () => import('./ssg-two/ssg-two.component').then(c => c.SsgTwoComponent), + loadComponent: () => import('./ssg-two/ssg-two').then(c => c.SsgTwo), }, ];`, }); // Generate components for the above routes - const componentNames: string[] = ['home', 'ssg', 'csr', 'ssr', 'ssg-one', 'ssg-two']; + const componentNames: string[] = ['home', 'ssg-component', 'csr', 'ssr', 'ssg-one', 'ssg-two']; for (const componentName of componentNames) { await silentNg('generate', 'component', componentName); @@ -95,18 +95,18 @@ export default async function () { // Add a cross-dependency await Promise.all([ replaceInFile( - 'src/app/ssg-one/ssg-one.component.ts', - `OneComponent {`, - `OneComponent { + 'src/app/ssg-one/ssg-one.ts', + `One {`, + `One { async ngOnInit() { await import('../cross-dep'); } `, ), replaceInFile( - 'src/app/ssg-two/ssg-two.component.ts', - `TwoComponent {`, - `TwoComponent { + 'src/app/ssg-two/ssg-two.ts', + `Two {`, + `Two { async ngOnInit() { await import('../cross-dep'); } @@ -129,58 +129,39 @@ const RESPONSE_EXPECTS: Record< } > = { '/': { - matches: [//], - notMatches: [/ssg\.component/, /ssr\.component/, /csr\.component/, /cross-dep-/], + matches: [//], + notMatches: [/ssg\-component/, /ssr/, /csr/, /cross-dep-/], }, '/ssg': { matches: [ //, - //, - ], - notMatches: [ - /home\.component/, - /ssr\.component/, - /csr\.component/, - /ssg-one\.component/, - /ssg-two\.component/, - /cross-dep-/, + //, ], + notMatches: [/home/, /ssr/, /csr/, /ssg-one/, /ssg-two/, /cross-dep-/], }, '/ssg/one': { matches: [ //, - //, + //, //, ], - notMatches: [ - /home\.component/, - /ssr\.component/, - /csr\.component/, - /ssg-two\.component/, - /ssg\.component/, - ], + notMatches: [/home/, /ssr/, /csr/, /ssg-two/, /ssg\-component/], }, '/ssg/two': { matches: [ //, - //, + //, //, ], - notMatches: [ - /home\.component/, - /ssr\.component/, - /csr\.component/, - /ssg-one\.component/, - /ssg\.component/, - ], + notMatches: [/home/, /ssr/, /csr/, /ssg-one/, /ssg\-component/], }, '/ssr': { - matches: [//], - notMatches: [/home\.component/, /ssg\.component/, /csr\.component/], + matches: [//], + notMatches: [/home/, /ssg\-component/, /csr/], }, '/csr': { - matches: [//], - notMatches: [/home\.component/, /ssg\.component/, /ssr\.component/, /cross-dep-/], + matches: [//], + notMatches: [/home/, /ssg\-component/, /ssr/, /cross-dep-/], }, }; diff --git a/tests/legacy-cli/e2e/tests/build/styles/include-paths.ts b/tests/legacy-cli/e2e/tests/build/styles/include-paths.ts index b1149f79c6eb..fb1a0326ed9f 100644 --- a/tests/legacy-cli/e2e/tests/build/styles/include-paths.ts +++ b/tests/legacy-cli/e2e/tests/build/styles/include-paths.ts @@ -10,7 +10,7 @@ export default async function () { @import 'variables'; h1 { color: $primary-color; } `, - 'src/app/app.component.scss': ` + 'src/app/app.scss': ` @import 'variables'; h2 { color: $primary-color; } `, @@ -19,16 +19,16 @@ export default async function () { @import 'variables'; h5 { color: @primary-color; } `, - 'src/app/app.component.less': ` + 'src/app/app.less': ` @import 'variables'; h6 { color: @primary-color; } `, }); await replaceInFile( - 'src/app/app.component.ts', - `styleUrl: './app.component.css\'`, - `styleUrls: ['./app.component.scss', './app.component.less']`, + 'src/app/app.ts', + `styleUrl: './app.css\'`, + `styleUrls: ['./app.scss', './app.less']`, ); await updateJsonFile('angular.json', (workspaceJson) => { diff --git a/tests/legacy-cli/e2e/tests/build/styles/less.ts b/tests/legacy-cli/e2e/tests/build/styles/less.ts index 15376e17febc..c5d58d2d3b08 100644 --- a/tests/legacy-cli/e2e/tests/build/styles/less.ts +++ b/tests/legacy-cli/e2e/tests/build/styles/less.ts @@ -17,7 +17,7 @@ export default function () { body { background-color: blue; } `, 'src/imported-styles.less': 'p { background-color: red; }', - 'src/app/app.component.less': ` + 'src/app/app.less': ` .outer { .inner { background: #fff; @@ -25,16 +25,14 @@ export default function () { } `, }) - .then(() => deleteFile('src/app/app.component.css')) + .then(() => deleteFile('src/app/app.css')) .then(() => updateJsonFile('angular.json', (workspaceJson) => { const appArchitect = workspaceJson.projects['test-project'].architect; appArchitect.build.options.styles = [{ input: 'src/styles.less' }]; }), ) - .then(() => - replaceInFile('src/app/app.component.ts', './app.component.css', './app.component.less'), - ) + .then(() => replaceInFile('src/app/app.ts', './app.css', './app.less')) .then(() => ng('build', '--source-map', '--configuration=development')) .then(() => expectFileToMatch( diff --git a/tests/legacy-cli/e2e/tests/build/styles/loaders.ts b/tests/legacy-cli/e2e/tests/build/styles/loaders.ts index 81e5c87913cd..cbb602ece07b 100644 --- a/tests/legacy-cli/e2e/tests/build/styles/loaders.ts +++ b/tests/legacy-cli/e2e/tests/build/styles/loaders.ts @@ -15,7 +15,7 @@ export default async function () { body { background-color: blue; } `, 'src/imported-styles.scss': 'p { background-color: red; }', - 'src/app/app.component.scss': ` + 'src/app/app.scss': ` .outer { .inner { background: #fff; @@ -24,12 +24,12 @@ export default async function () { `, }); - await deleteFile('src/app/app.component.css'); + await deleteFile('src/app/app.css'); await updateJsonFile('angular.json', (workspaceJson) => { const appArchitect = workspaceJson.projects['test-project'].architect; appArchitect.build.options.styles = [{ input: 'src/styles.scss' }]; }); - await replaceInFile('src/app/app.component.ts', './app.component.css', './app.component.scss'); + await replaceInFile('src/app/app.ts', './app.css', './app.scss'); await ng('build', '--configuration=development'); diff --git a/tests/legacy-cli/e2e/tests/build/styles/sass-pkg-importer.ts b/tests/legacy-cli/e2e/tests/build/styles/sass-pkg-importer.ts new file mode 100644 index 000000000000..8fbb6e74310f --- /dev/null +++ b/tests/legacy-cli/e2e/tests/build/styles/sass-pkg-importer.ts @@ -0,0 +1,34 @@ +import assert from 'node:assert'; +import { writeFile } from '../../../utils/fs'; +import { getActivePackageManager, uninstallPackage } from '../../../utils/packages'; +import { ng } from '../../../utils/process'; +import { isPrereleaseCli, updateJsonFile } from '../../../utils/project'; +import { appendFile } from 'node:fs/promises'; +import { getGlobalVariable } from '../../../utils/env'; + +export default async function () { + assert( + getGlobalVariable('argv')['esbuild'], + 'This test should not be called in the Webpack suite.', + ); + + // forcibly remove in case another test doesn't clean itself up + await uninstallPackage('@angular/material'); + + const isPrerelease = await isPrereleaseCli(); + const tag = isPrerelease ? '@next' : ''; + if (getActivePackageManager() === 'npm') { + await appendFile('.npmrc', '\nlegacy-peer-deps=true'); + } + + await ng('add', `@angular/material${tag}`, '--skip-confirmation'); + await Promise.all([ + updateJsonFile('angular.json', (workspaceJson) => { + const appArchitect = workspaceJson.projects['test-project'].architect; + appArchitect.build.options.styles = ['src/styles.scss']; + }), + writeFile('src/styles.scss', `@use 'pkg:@angular/material' as mat;`), + ]); + + await ng('build'); +} diff --git a/tests/legacy-cli/e2e/tests/build/styles/sass.ts b/tests/legacy-cli/e2e/tests/build/styles/sass.ts index f4da7dce9474..f4259118317d 100644 --- a/tests/legacy-cli/e2e/tests/build/styles/sass.ts +++ b/tests/legacy-cli/e2e/tests/build/styles/sass.ts @@ -19,7 +19,7 @@ export default async function () { p background-color: red `, - 'src/app/app.component.sass': ` + 'src/app/app.sass': ` .outer .inner background: #fff @@ -31,8 +31,8 @@ export default async function () { appArchitect.build.options.styles = [{ input: 'src/styles.sass' }]; }); - await deleteFile('src/app/app.component.css'); - await replaceInFile('src/app/app.component.ts', './app.component.css', './app.component.sass'); + await deleteFile('src/app/app.css'); + await replaceInFile('src/app/app.ts', './app.css', './app.sass'); await ng('build', '--source-map', '--configuration=development'); diff --git a/tests/legacy-cli/e2e/tests/build/styles/scss-partial-resolution.ts b/tests/legacy-cli/e2e/tests/build/styles/scss-partial-resolution.ts index 313ec5e03e58..1a555b26e23b 100644 --- a/tests/legacy-cli/e2e/tests/build/styles/scss-partial-resolution.ts +++ b/tests/legacy-cli/e2e/tests/build/styles/scss-partial-resolution.ts @@ -16,7 +16,7 @@ export default async function () { @include button.core-styles; `, - 'src/app/app.component.scss': ` + 'src/app/app.scss': ` @use '@material/button/button'; @include button.core-styles; @@ -28,8 +28,8 @@ export default async function () { appArchitect.build.options.styles = ['src/styles.scss']; }); - await deleteFile('src/app/app.component.css'); - await replaceInFile('src/app/app.component.ts', './app.component.css', './app.component.scss'); + await deleteFile('src/app/app.css'); + await replaceInFile('src/app/app.ts', './app.css', './app.scss'); await ng('build', '--configuration=development'); } diff --git a/tests/legacy-cli/e2e/tests/build/styles/scss.ts b/tests/legacy-cli/e2e/tests/build/styles/scss.ts index 667eee47c068..69fcc1c0f060 100644 --- a/tests/legacy-cli/e2e/tests/build/styles/scss.ts +++ b/tests/legacy-cli/e2e/tests/build/styles/scss.ts @@ -15,7 +15,7 @@ export default async function () { body { background-color: blue; } `, 'src/imported-styles.scss': 'p { background-color: red; }', - 'src/app/app.component.scss': ` + 'src/app/app.scss': ` .outer { .inner { background: #fff; @@ -29,8 +29,8 @@ export default async function () { appArchitect.build.options.styles = [{ input: 'src/styles.scss' }]; }); - await deleteFile('src/app/app.component.css'); - await replaceInFile('src/app/app.component.ts', './app.component.css', './app.component.scss'); + await deleteFile('src/app/app.css'); + await replaceInFile('src/app/app.ts', './app.css', './app.scss'); await ng('build', '--source-map', '--configuration=development'); diff --git a/tests/legacy-cli/e2e/tests/build/styles/tailwind-v2.ts b/tests/legacy-cli/e2e/tests/build/styles/tailwind-v2.ts index fbb1222b2a95..f081e040dcb5 100644 --- a/tests/legacy-cli/e2e/tests/build/styles/tailwind-v2.ts +++ b/tests/legacy-cli/e2e/tests/build/styles/tailwind-v2.ts @@ -12,7 +12,7 @@ export default async function () { await silentExec('npx', 'tailwindcss@2', 'init'); // Add Tailwind directives to a component style - await writeFile('src/app/app.component.css', '@tailwind base; @tailwind components;'); + await writeFile('src/app/app.css', '@tailwind base; @tailwind components;'); // Add Tailwind directives to a global style await writeFile('src/styles.css', '@tailwind base; @tailwind components;'); diff --git a/tests/legacy-cli/e2e/tests/build/styles/tailwind-v3.ts b/tests/legacy-cli/e2e/tests/build/styles/tailwind-v3.ts index efda7dbcef66..97700a4c4b3e 100644 --- a/tests/legacy-cli/e2e/tests/build/styles/tailwind-v3.ts +++ b/tests/legacy-cli/e2e/tests/build/styles/tailwind-v3.ts @@ -16,7 +16,7 @@ export default async function () { await silentExec('npx', 'tailwindcss@3', 'init'); // Add Tailwind directives to a component style - await writeFile('src/app/app.component.css', '@tailwind base; @tailwind components;'); + await writeFile('src/app/app.css', '@tailwind base; @tailwind components;'); // Add Tailwind directives to a global style await writeFile( diff --git a/tests/legacy-cli/e2e/tests/build/ts-paths.ts b/tests/legacy-cli/e2e/tests/build/ts-paths.ts index 61aa8324ce4b..76ee53e5d2b2 100644 --- a/tests/legacy-cli/e2e/tests/build/ts-paths.ts +++ b/tests/legacy-cli/e2e/tests/build/ts-paths.ts @@ -19,7 +19,7 @@ export default async function () { 'src/app/shared/index.ts': `export * from './meaning'`, }); - await replaceInFile('src/main.ts', './app/app.component', '@root/app/app.component'); + await replaceInFile('src/main.ts', './app/app', '@root/app/app'); await ng('build', '--configuration=development'); await updateTsConfig((json) => { @@ -27,7 +27,7 @@ export default async function () { }); await appendToFile( - 'src/app/app.component.ts', + 'src/app/app.ts', ` import { meaning } from 'app/shared/meaning'; import { meaning as meaning2 } from '@shared'; diff --git a/tests/legacy-cli/e2e/tests/build/wasm-esm.ts b/tests/legacy-cli/e2e/tests/build/wasm-esm.ts index 8ed5accd131d..134584d40716 100644 --- a/tests/legacy-cli/e2e/tests/build/wasm-esm.ts +++ b/tests/legacy-cli/e2e/tests/build/wasm-esm.ts @@ -49,16 +49,12 @@ export default async function () { // Use WASM file in project await prependToFile( - 'src/app/app.component.ts', + 'src/app/app.ts', ` import { multiply, subtract1 } from './multiply.wasm'; `, ); - await replaceInFile( - 'src/app/app.component.ts', - "'test-project'", - 'multiply(4, 5) + subtract1(88)', - ); + await replaceInFile('src/app/app.ts', "'test-project'", 'multiply(4, 5) + subtract1(88)'); // Remove Zone.js from polyfills and make zoneless await updateJsonFile('angular.json', (json) => { diff --git a/tests/legacy-cli/e2e/tests/build/worker.ts b/tests/legacy-cli/e2e/tests/build/worker.ts index 31a997b02441..7b6cdb390cb7 100644 --- a/tests/legacy-cli/e2e/tests/build/worker.ts +++ b/tests/legacy-cli/e2e/tests/build/worker.ts @@ -16,7 +16,7 @@ export default async function () { const useWebpackBuilder = !getGlobalVariable('argv')['esbuild']; const workerPath = 'src/app/app.worker.ts'; - const snippetPath = 'src/app/app.component.ts'; + const snippetPath = 'src/app/app.ts'; const projectTsConfig = 'tsconfig.json'; const workerTsConfig = 'tsconfig.worker.json'; @@ -52,7 +52,7 @@ export default async function () { // console.warn has to be used because chrome only captures warnings and errors by default // https://github.com/angular/protractor/issues/2207 - await replaceInFile('src/app/app.component.ts', 'console.log', 'console.warn'); + await replaceInFile('src/app/app.ts', 'console.log', 'console.warn'); await writeFile( 'e2e/app.e2e-spec.ts', diff --git a/tests/legacy-cli/e2e/tests/commands/serve/ssr-http-requests-assets.ts b/tests/legacy-cli/e2e/tests/commands/serve/ssr-http-requests-assets.ts index 972c35be4452..78c5b4b94995 100644 --- a/tests/legacy-cli/e2e/tests/commands/serve/ssr-http-requests-assets.ts +++ b/tests/legacy-cli/e2e/tests/commands/serve/ssr-http-requests-assets.ts @@ -15,7 +15,7 @@ export default async function () { // `--server-routing` not supported in `browser` builder. await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); } else { - await ng('add', '@angular/ssr', '--server-routing', '--skip-confirmation', '--skip-install'); + await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); } await useSha(); @@ -27,7 +27,7 @@ export default async function () { import { ApplicationConfig } from '@angular/core'; import { provideRouter } from '@angular/router'; - import { HomeComponent } from './home/home.component'; + import { Home } from './home/home'; import { provideClientHydration } from '@angular/platform-browser'; import { provideHttpClient, withFetch } from '@angular/common/http'; @@ -35,7 +35,7 @@ export default async function () { providers: [ provideRouter([{ path: '', - component: HomeComponent, + component: Home, }]), provideClientHydration(), provideHttpClient(withFetch()), @@ -45,7 +45,7 @@ export default async function () { // Add asset 'public/media.json': JSON.stringify({ dataFromAssets: true }), // Update component to do an HTTP call to asset. - 'src/app/app.component.ts': ` + 'src/app/app.ts': ` import { Component, inject } from '@angular/core'; import { CommonModule } from '@angular/common'; import { RouterOutlet } from '@angular/router'; @@ -60,7 +60,7 @@ export default async function () { \`, }) - export class AppComponent { + export class App { data: any; constructor() { const http = inject(HttpClient); diff --git a/tests/legacy-cli/e2e/tests/generate/component/component-basic.ts b/tests/legacy-cli/e2e/tests/generate/component/component-basic.ts index 57b63edbed29..b87e6acad2bf 100644 --- a/tests/legacy-cli/e2e/tests/generate/component/component-basic.ts +++ b/tests/legacy-cli/e2e/tests/generate/component/component-basic.ts @@ -9,10 +9,10 @@ export default function () { return ( ng('generate', 'component', 'test-component') .then(() => expectFileToExist(componentDir)) - .then(() => expectFileToExist(join(componentDir, 'test-component.component.ts'))) - .then(() => expectFileToExist(join(componentDir, 'test-component.component.spec.ts'))) - .then(() => expectFileToExist(join(componentDir, 'test-component.component.ng.html'))) - .then(() => expectFileToExist(join(componentDir, 'test-component.component.css'))) + .then(() => expectFileToExist(join(componentDir, 'test-component.ts'))) + .then(() => expectFileToExist(join(componentDir, 'test-component.spec.ts'))) + .then(() => expectFileToExist(join(componentDir, 'test-component.html'))) + .then(() => expectFileToExist(join(componentDir, 'test-component.css'))) // Try to run the unit tests. .then(() => ng('test', '--watch=false')) diff --git a/tests/legacy-cli/e2e/tests/generate/component/component-child-dir.ts b/tests/legacy-cli/e2e/tests/generate/component/component-child-dir.ts index 844379aaddf3..6c7dc7506bab 100644 --- a/tests/legacy-cli/e2e/tests/generate/component/component-child-dir.ts +++ b/tests/legacy-cli/e2e/tests/generate/component/component-child-dir.ts @@ -19,10 +19,10 @@ export default async function () { // Ensure component is created in the correct location relative to the workspace root const componentDirectory = join(childDirectory, 'test-component'); - await expectFileToExist(join(componentDirectory, 'test-component.component.ts')); - await expectFileToExist(join(componentDirectory, 'test-component.component.spec.ts')); - await expectFileToExist(join(componentDirectory, 'test-component.component.ng.html')); - await expectFileToExist(join(componentDirectory, 'test-component.component.css')); + await expectFileToExist(join(componentDirectory, 'test-component.ts')); + await expectFileToExist(join(componentDirectory, 'test-component.spec.ts')); + await expectFileToExist(join(componentDirectory, 'test-component.html')); + await expectFileToExist(join(componentDirectory, 'test-component.css')); // Ensure unit test execute and pass await ng('test', '--watch=false'); diff --git a/tests/legacy-cli/e2e/tests/generate/component/component-flat.ts b/tests/legacy-cli/e2e/tests/generate/component/component-flat.ts index 7f1dff027d3e..4bdb101391fa 100644 --- a/tests/legacy-cli/e2e/tests/generate/component/component-flat.ts +++ b/tests/legacy-cli/e2e/tests/generate/component/component-flat.ts @@ -16,10 +16,10 @@ export default function () { ) .then(() => ng('generate', 'component', 'test-component')) .then(() => expectFileToExist(appDir)) - .then(() => expectFileToExist(join(appDir, 'test-component.component.ts'))) - .then(() => expectFileToExist(join(appDir, 'test-component.component.spec.ts'))) - .then(() => expectFileToExist(join(appDir, 'test-component.component.ng.html'))) - .then(() => expectFileToExist(join(appDir, 'test-component.component.css'))) + .then(() => expectFileToExist(join(appDir, 'test-component.ts'))) + .then(() => expectFileToExist(join(appDir, 'test-component.spec.ts'))) + .then(() => expectFileToExist(join(appDir, 'test-component.html'))) + .then(() => expectFileToExist(join(appDir, 'test-component.css'))) // Try to run the unit tests. .then(() => ng('test', '--watch=false')) diff --git a/tests/legacy-cli/e2e/tests/generate/component/component-inline-template.ts b/tests/legacy-cli/e2e/tests/generate/component/component-inline-template.ts index 88e610ed27a4..135b97c43fcb 100644 --- a/tests/legacy-cli/e2e/tests/generate/component/component-inline-template.ts +++ b/tests/legacy-cli/e2e/tests/generate/component/component-inline-template.ts @@ -18,14 +18,10 @@ export default function () { ) .then(() => ng('generate', 'component', 'test-component')) .then(() => expectFileToExist(componentDir)) - .then(() => expectFileToExist(join(componentDir, 'test-component.component.ts'))) - .then(() => expectFileToExist(join(componentDir, 'test-component.component.spec.ts'))) - .then(() => - expectToFail(() => - expectFileToExist(join(componentDir, 'test-component.component.ng.html')), - ), - ) - .then(() => expectFileToExist(join(componentDir, 'test-component.component.css'))) + .then(() => expectFileToExist(join(componentDir, 'test-component.ts'))) + .then(() => expectFileToExist(join(componentDir, 'test-component.spec.ts'))) + .then(() => expectToFail(() => expectFileToExist(join(componentDir, 'test-component.html')))) + .then(() => expectFileToExist(join(componentDir, 'test-component.css'))) // Try to run the unit tests. .then(() => ng('test', '--watch=false')) diff --git a/tests/legacy-cli/e2e/tests/generate/component/component-not-flat.ts b/tests/legacy-cli/e2e/tests/generate/component/component-not-flat.ts index 44dcc11b7542..eedc3926da89 100644 --- a/tests/legacy-cli/e2e/tests/generate/component/component-not-flat.ts +++ b/tests/legacy-cli/e2e/tests/generate/component/component-not-flat.ts @@ -17,10 +17,10 @@ export default function () { ) .then(() => ng('generate', 'component', 'test-component')) .then(() => expectFileToExist(componentDir)) - .then(() => expectFileToExist(join(componentDir, 'test-component.component.ts'))) - .then(() => expectFileToExist(join(componentDir, 'test-component.component.spec.ts'))) - .then(() => expectFileToExist(join(componentDir, 'test-component.component.ng.html'))) - .then(() => expectFileToExist(join(componentDir, 'test-component.component.css'))) + .then(() => expectFileToExist(join(componentDir, 'test-component.ts'))) + .then(() => expectFileToExist(join(componentDir, 'test-component.spec.ts'))) + .then(() => expectFileToExist(join(componentDir, 'test-component.html'))) + .then(() => expectFileToExist(join(componentDir, 'test-component.css'))) // Try to run the unit tests. .then(() => ng('test', '--watch=false')) diff --git a/tests/legacy-cli/e2e/tests/generate/component/component-path-case.ts b/tests/legacy-cli/e2e/tests/generate/component/component-path-case.ts index 371455156246..63d08af7099d 100644 --- a/tests/legacy-cli/e2e/tests/generate/component/component-path-case.ts +++ b/tests/legacy-cli/e2e/tests/generate/component/component-path-case.ts @@ -14,19 +14,19 @@ export default async function () { await ng('generate', 'component', `${upperDirs}/test-component`); // Ensure component is created in the correct location relative to the workspace root - await expectFileToExist(join(componentDirectory, 'test-component.component.ts')); - await expectFileToExist(join(componentDirectory, 'test-component.component.spec.ts')); - await expectFileToExist(join(componentDirectory, 'test-component.component.ng.html')); - await expectFileToExist(join(componentDirectory, 'test-component.component.css')); + await expectFileToExist(join(componentDirectory, 'test-component.ts')); + await expectFileToExist(join(componentDirectory, 'test-component.spec.ts')); + await expectFileToExist(join(componentDirectory, 'test-component.html')); + await expectFileToExist(join(componentDirectory, 'test-component.css')); // Generate another component await ng('generate', 'component', `${upperDirs}/Test-Component-Two`); // Ensure component is created in the correct location relative to the workspace root - await expectFileToExist(join(componentTwoDirectory, 'test-component-two.component.ts')); - await expectFileToExist(join(componentTwoDirectory, 'test-component-two.component.spec.ts')); - await expectFileToExist(join(componentTwoDirectory, 'test-component-two.component.ng.html')); - await expectFileToExist(join(componentTwoDirectory, 'test-component-two.component.css')); + await expectFileToExist(join(componentTwoDirectory, 'test-component-two.ts')); + await expectFileToExist(join(componentTwoDirectory, 'test-component-two.spec.ts')); + await expectFileToExist(join(componentTwoDirectory, 'test-component-two.html')); + await expectFileToExist(join(componentTwoDirectory, 'test-component-two.css')); // Ensure unit test execute and pass await ng('test', '--watch=false'); diff --git a/tests/legacy-cli/e2e/tests/generate/component/component-prefix.ts b/tests/legacy-cli/e2e/tests/generate/component/component-prefix.ts index e433dcc973b2..befa96939b00 100644 --- a/tests/legacy-cli/e2e/tests/generate/component/component-prefix.ts +++ b/tests/legacy-cli/e2e/tests/generate/component/component-prefix.ts @@ -17,11 +17,9 @@ export default function () { }), ) .then(() => ng('generate', 'component', 'test-component')) - .then(() => - expectFileToMatch(join(testCompDir, 'test-component.component.ts'), /selector: 'pre-/), - ) + .then(() => expectFileToMatch(join(testCompDir, 'test-component.ts'), /selector: 'pre-/)) .then(() => ng('g', 'c', 'alias')) - .then(() => expectFileToMatch(join(aliasCompDir, 'alias.component.ts'), /selector: 'pre-/)) + .then(() => expectFileToMatch(join(aliasCompDir, 'alias.ts'), /selector: 'pre-/)) // Try to run the unit tests. .then(() => ng('test', '--watch=false')) diff --git a/tests/legacy-cli/e2e/tests/generate/directive/directive-basic.ts b/tests/legacy-cli/e2e/tests/generate/directive/directive-basic.ts index 3706743c392b..9ad00dfa22a3 100644 --- a/tests/legacy-cli/e2e/tests/generate/directive/directive-basic.ts +++ b/tests/legacy-cli/e2e/tests/generate/directive/directive-basic.ts @@ -6,8 +6,8 @@ export default function () { const directiveDir = join('src', 'app'); return ( ng('generate', 'directive', 'test-directive') - .then(() => expectFileToExist(join(directiveDir, 'test-directive.directive.ts'))) - .then(() => expectFileToExist(join(directiveDir, 'test-directive.directive.spec.ts'))) + .then(() => expectFileToExist(join(directiveDir, 'test-directive.ts'))) + .then(() => expectFileToExist(join(directiveDir, 'test-directive.spec.ts'))) // Try to run the unit tests. .then(() => ng('test', '--watch=false')) diff --git a/tests/legacy-cli/e2e/tests/generate/directive/directive-prefix.ts b/tests/legacy-cli/e2e/tests/generate/directive/directive-prefix.ts index ce2d6da3e4f6..b0a95ce399cb 100644 --- a/tests/legacy-cli/e2e/tests/generate/directive/directive-prefix.ts +++ b/tests/legacy-cli/e2e/tests/generate/directive/directive-prefix.ts @@ -16,9 +16,7 @@ export default function () { }), ) .then(() => ng('generate', 'directive', 'test2-directive')) - .then(() => - expectFileToMatch(join(directiveDir, 'test2-directive.directive.ts'), /selector: '\[preW/), - ) + .then(() => expectFileToMatch(join(directiveDir, 'test2-directive.ts'), /selector: '\[preW/)) .then(() => ng('generate', 'application', 'app-two', '--skip-install')) .then(() => useCIDefaults('app-two')) .then(() => useCIChrome('app-two', './projects/app-two')) @@ -33,17 +31,12 @@ export default function () { .then(() => ng('generate', 'directive', '--skip-import', 'test3-directive')) .then(() => process.chdir('../..')) .then(() => - expectFileToMatch( - join('projects', 'app-two', 'test3-directive.directive.ts'), - /selector: '\[preW/, - ), + expectFileToMatch(join('projects', 'app-two', 'test3-directive.ts'), /selector: '\[preW/), ) .then(() => process.chdir('src/app')) .then(() => ng('generate', 'directive', 'test-directive')) .then(() => process.chdir('../..')) - .then(() => - expectFileToMatch(join(directiveDir, 'test-directive.directive.ts'), /selector: '\[preP/), - ) + .then(() => expectFileToMatch(join(directiveDir, 'test-directive.ts'), /selector: '\[preP/)) // Try to run the unit tests. .then(() => ng('test', '--watch=false')) diff --git a/tests/legacy-cli/e2e/tests/generate/generate-name-check.ts b/tests/legacy-cli/e2e/tests/generate/generate-name-check.ts index f849929e0085..6fe89a58face 100644 --- a/tests/legacy-cli/e2e/tests/generate/generate-name-check.ts +++ b/tests/legacy-cli/e2e/tests/generate/generate-name-check.ts @@ -16,10 +16,10 @@ export default function () { ) .then(() => ng('generate', 'component', 'test-component')) .then(() => expectFileToExist(compDir)) - .then(() => expectFileToExist(join(compDir, 'test-component.component.ts'))) - .then(() => expectFileToExist(join(compDir, 'test-component.component.spec.ts'))) - .then(() => expectFileToExist(join(compDir, 'test-component.component.ng.html'))) - .then(() => expectFileToExist(join(compDir, 'test-component.component.css'))) + .then(() => expectFileToExist(join(compDir, 'test-component.ts'))) + .then(() => expectFileToExist(join(compDir, 'test-component.spec.ts'))) + .then(() => expectFileToExist(join(compDir, 'test-component.html'))) + .then(() => expectFileToExist(join(compDir, 'test-component.css'))) // Try to run the unit tests. .then(() => ng('test', '--watch=false')) diff --git a/tests/legacy-cli/e2e/tests/generate/guard/guard-basic.ts b/tests/legacy-cli/e2e/tests/generate/guard/guard-basic.ts index 6b2a9717f328..ca4e9a547ff6 100644 --- a/tests/legacy-cli/e2e/tests/generate/guard/guard-basic.ts +++ b/tests/legacy-cli/e2e/tests/generate/guard/guard-basic.ts @@ -6,13 +6,10 @@ export default async function () { // Does not create a sub directory. const guardDir = join('src', 'app'); - await ng('generate', 'guard', 'test-guard'); + await ng('generate', 'guard', 'test'); await expectFileToExist(guardDir); - await expectFileToExist(join(guardDir, 'test-guard.guard.ts')); - await expectFileToMatch( - join(guardDir, 'test-guard.guard.ts'), - /export const testGuardGuard: CanActivateFn/, - ); - await expectFileToExist(join(guardDir, 'test-guard.guard.spec.ts')); + await expectFileToExist(join(guardDir, 'test-guard.ts')); + await expectFileToMatch(join(guardDir, 'test-guard.ts'), /export const testGuard: CanActivateFn/); + await expectFileToExist(join(guardDir, 'test-guard.spec.ts')); await ng('test', '--watch=false'); } diff --git a/tests/legacy-cli/e2e/tests/generate/guard/guard-implements.ts b/tests/legacy-cli/e2e/tests/generate/guard/guard-implements.ts index 70291fefecf5..ca7c35f754a4 100644 --- a/tests/legacy-cli/e2e/tests/generate/guard/guard-implements.ts +++ b/tests/legacy-cli/e2e/tests/generate/guard/guard-implements.ts @@ -8,8 +8,8 @@ export default async function () { await ng('generate', 'guard', 'match', '--implements=CanMatch'); await expectFileToExist(guardDir); - await expectFileToExist(join(guardDir, 'match.guard.ts')); - await expectFileToMatch(join(guardDir, 'match.guard.ts'), /export const matchGuard: CanMatch/); - await expectFileToExist(join(guardDir, 'match.guard.spec.ts')); + await expectFileToExist(join(guardDir, 'match-guard.ts')); + await expectFileToMatch(join(guardDir, 'match-guard.ts'), /export const matchGuard: CanMatch/); + await expectFileToExist(join(guardDir, 'match-guard.spec.ts')); await ng('test', '--watch=false'); } diff --git a/tests/legacy-cli/e2e/tests/generate/guard/guard-multiple-implements.ts b/tests/legacy-cli/e2e/tests/generate/guard/guard-multiple-implements.ts index 4dd66fc268a7..4359eaaf9f59 100644 --- a/tests/legacy-cli/e2e/tests/generate/guard/guard-multiple-implements.ts +++ b/tests/legacy-cli/e2e/tests/generate/guard/guard-multiple-implements.ts @@ -16,11 +16,11 @@ export default async function () { '--no-functional', ); await expectFileToExist(guardDir); - await expectFileToExist(join(guardDir, 'multiple.guard.ts')); + await expectFileToExist(join(guardDir, 'multiple-guard.ts')); await expectFileToMatch( - join(guardDir, 'multiple.guard.ts'), + join(guardDir, 'multiple-guard.ts'), /implements CanActivate, CanDeactivate/, ); - await expectFileToExist(join(guardDir, 'multiple.guard.spec.ts')); + await expectFileToExist(join(guardDir, 'multiple-guard.spec.ts')); await ng('test', '--watch=false'); } diff --git a/tests/legacy-cli/e2e/tests/generate/interceptor/interceptor-basic.ts b/tests/legacy-cli/e2e/tests/generate/interceptor/interceptor-basic.ts index 5046f2603da6..7dd0b48c439b 100755 --- a/tests/legacy-cli/e2e/tests/generate/interceptor/interceptor-basic.ts +++ b/tests/legacy-cli/e2e/tests/generate/interceptor/interceptor-basic.ts @@ -7,10 +7,10 @@ export default function () { const interceptorDir = join('src', 'app'); return ( - ng('generate', 'interceptor', 'test-interceptor') + ng('generate', 'interceptor', 'test') .then(() => expectFileToExist(interceptorDir)) - .then(() => expectFileToExist(join(interceptorDir, 'test-interceptor.interceptor.ts'))) - .then(() => expectFileToExist(join(interceptorDir, 'test-interceptor.interceptor.spec.ts'))) + .then(() => expectFileToExist(join(interceptorDir, 'test-interceptor.ts'))) + .then(() => expectFileToExist(join(interceptorDir, 'test-interceptor.spec.ts'))) // Try to run the unit tests. .then(() => ng('test', '--watch=false')) diff --git a/tests/legacy-cli/e2e/tests/generate/module/module-basic.ts b/tests/legacy-cli/e2e/tests/generate/module/module-basic.ts index 8b59c3147532..18e1a05fedde 100644 --- a/tests/legacy-cli/e2e/tests/generate/module/module-basic.ts +++ b/tests/legacy-cli/e2e/tests/generate/module/module-basic.ts @@ -13,10 +13,10 @@ export default async function () { await ng('generate', 'module', 'test', '--project', projectName); await expectFileToExist(moduleDir); - await expectFileToExist(join(moduleDir, 'test.module.ts')); - await expectToFail(() => expectFileToExist(join(moduleDir, 'test-routing.module.ts'))); + await expectFileToExist(join(moduleDir, 'test-module.ts')); + await expectToFail(() => expectFileToExist(join(moduleDir, 'test-routing-module.ts'))); await expectToFail(() => expectFileToExist(join(moduleDir, 'test.spec.ts'))); - await expectFileToMatch(join(moduleDir, 'test.module.ts'), 'TestModule'); + await expectFileToMatch(join(moduleDir, 'test-module.ts'), 'TestModule'); // Try to run the unit tests. await ng('test', projectName, '--watch=false'); diff --git a/tests/legacy-cli/e2e/tests/generate/module/module-import.ts b/tests/legacy-cli/e2e/tests/generate/module/module-import.ts index 07f280b918f5..533b3d19efe7 100644 --- a/tests/legacy-cli/e2e/tests/generate/module/module-import.ts +++ b/tests/legacy-cli/e2e/tests/generate/module/module-import.ts @@ -9,35 +9,35 @@ export default async function () { await ng('generate', 'module', 'sub/deep', '--project', projectName); const projectAppDir = `projects/${projectName}/src/app`; - const modulePath = join(projectAppDir, 'app.module.ts'); - const subModulePath = join(projectAppDir, 'sub/sub.module.ts'); - const deepSubModulePath = join(projectAppDir, 'sub/deep/deep.module.ts'); + const modulePath = join(projectAppDir, 'app-module.ts'); + const subModulePath = join(projectAppDir, 'sub/sub-module.ts'); + const deepSubModulePath = join(projectAppDir, 'sub/deep/deep-module.ts'); - await ng('generate', 'module', 'test1', '--module', 'app.module.ts', '--project', projectName); - await expectFileToMatch(modulePath, `import { Test1Module } from './test1/test1.module'`); + await ng('generate', 'module', 'test1', '--module', 'app-module.ts', '--project', projectName); + await expectFileToMatch(modulePath, `import { Test1Module } from './test1/test1-module'`); await expectFileToMatch(modulePath, /imports: \[.*?Test1Module.*?\]/s); - await ng('generate', 'module', 'test2', '--module', 'app.module', '--project', projectName); - await expectFileToMatch(modulePath, `import { Test2Module } from './test2/test2.module'`); + await ng('generate', 'module', 'test2', '--module', 'app-module', '--project', projectName); + await expectFileToMatch(modulePath, `import { Test2Module } from './test2/test2-module'`); await expectFileToMatch(modulePath, /imports: \[.*?Test2Module.*?\]/s); await ng('generate', 'module', 'test3', '--module', 'app', '--project', projectName); - await expectFileToMatch(modulePath, `import { Test3Module } from './test3/test3.module'`); + await expectFileToMatch(modulePath, `import { Test3Module } from './test3/test3-module'`); await expectFileToMatch(modulePath, /imports: \[.*?Test3Module.*?\]/s); await ng('generate', 'module', 'test4', '--routing', '--module', 'app', '--project', projectName); await expectFileToMatch(modulePath, /imports: \[.*?Test4Module.*?\]/s); await expectFileToMatch( - join(projectAppDir, 'test4/test4.module.ts'), - `import { Test4RoutingModule } from './test4-routing.module'`, + join(projectAppDir, 'test4/test4-module.ts'), + `import { Test4RoutingModule } from './test4-routing-module'`, ); await expectFileToMatch( - join(projectAppDir, 'test4/test4.module.ts'), + join(projectAppDir, 'test4/test4-module.ts'), /imports: \[.*?Test4RoutingModule.*?\]/s, ); await ng('generate', 'module', 'test5', '--module', 'sub', '--project', projectName); - await expectFileToMatch(subModulePath, `import { Test5Module } from '../test5/test5.module'`); + await expectFileToMatch(subModulePath, `import { Test5Module } from '../test5/test5-module'`); await expectFileToMatch(subModulePath, /imports: \[.*?Test5Module.*?\]/s); @@ -45,15 +45,15 @@ export default async function () { await expectFileToMatch( deepSubModulePath, - `import { Test6Module } from '../../test6/test6.module'`, + `import { Test6Module } from '../../test6/test6-module'`, ); await expectFileToMatch(deepSubModulePath, /imports: \[.*?Test6Module.*?\]/s); // E2E_DISABLE: temporarily disable pending investigation // await process.chdir(join(root, 'src', 'app'))) - // await ng('generate', 'module', 'test7', '--module', 'app.module.ts')) + // await ng('generate', 'module', 'test7', '--module', 'app-module.ts')) // await process.chdir('..')) // await expectFileToMatch(modulePath, - // /import { Test7Module } from '.\/test7\/test7.module'/)) + // /import { Test7Module } from '.\/test7\/test7-module'/)) // await expectFileToMatch(modulePath, /imports: \[(.|\s)*Test7Module(.|\s)*\]/m)); } diff --git a/tests/legacy-cli/e2e/tests/generate/module/module-routing-child-folder.ts b/tests/legacy-cli/e2e/tests/generate/module/module-routing-child-folder.ts index 2c1d56c6d251..f2ba0e3396f7 100644 --- a/tests/legacy-cli/e2e/tests/generate/module/module-routing-child-folder.ts +++ b/tests/legacy-cli/e2e/tests/generate/module/module-routing-child-folder.ts @@ -15,8 +15,8 @@ export default async function () { await ng('generate', 'module', 'sub-dir/child', '--routing'); await expectFileToExist(join(testPath, 'sub-dir/child')); - await expectFileToExist(join(testPath, 'sub-dir/child', 'child.module.ts')); - await expectFileToExist(join(testPath, 'sub-dir/child', 'child-routing.module.ts')); + await expectFileToExist(join(testPath, 'sub-dir/child', 'child-module.ts')); + await expectFileToExist(join(testPath, 'sub-dir/child', 'child-routing-module.ts')); await expectToFail(() => expectFileToExist(join(testPath, 'sub-dir/child', 'child.spec.ts'))); // Try to run the unit tests. diff --git a/tests/legacy-cli/e2e/tests/generate/pipe/pipe-basic.ts b/tests/legacy-cli/e2e/tests/generate/pipe/pipe-basic.ts index 500a45eeed9e..2ddb3ff4225f 100644 --- a/tests/legacy-cli/e2e/tests/generate/pipe/pipe-basic.ts +++ b/tests/legacy-cli/e2e/tests/generate/pipe/pipe-basic.ts @@ -8,10 +8,10 @@ export default function () { const pipeDir = join('src', 'app'); return ( - ng('generate', 'pipe', 'test-pipe') + ng('generate', 'pipe', 'test') .then(() => expectFileToExist(pipeDir)) - .then(() => expectFileToExist(join(pipeDir, 'test-pipe.pipe.ts'))) - .then(() => expectFileToExist(join(pipeDir, 'test-pipe.pipe.spec.ts'))) + .then(() => expectFileToExist(join(pipeDir, 'test-pipe.ts'))) + .then(() => expectFileToExist(join(pipeDir, 'test-pipe.spec.ts'))) // Try to run the unit tests. .then(() => ng('test', '--watch=false')) diff --git a/tests/legacy-cli/e2e/tests/generate/schematic-defaults.ts b/tests/legacy-cli/e2e/tests/generate/schematic-defaults.ts index 7e015a0d6638..7c9987d92321 100644 --- a/tests/legacy-cli/e2e/tests/generate/schematic-defaults.ts +++ b/tests/legacy-cli/e2e/tests/generate/schematic-defaults.ts @@ -12,8 +12,8 @@ export default async function () { // Generate component in application to verify that it's minimal const { stdout } = await ng('generate', 'component', 'foo'); - if (!stdout.includes('foo.component.scss')) { - throw new Error('Expected "foo.component.scss" to exist.'); + if (!stdout.includes('foo.scss')) { + throw new Error('Expected "foo.scss" to exist.'); } // Generate another project with different settings @@ -23,6 +23,7 @@ export default async function () { config.projects['test-project-two'].schematics = { '@schematics/angular:component': { style: 'less', + type: 'Component', }, }; }); diff --git a/tests/legacy-cli/e2e/tests/generate/schematics-collections-relative.ts b/tests/legacy-cli/e2e/tests/generate/schematics-collections-relative.ts new file mode 100644 index 000000000000..f6f583bf0e72 --- /dev/null +++ b/tests/legacy-cli/e2e/tests/generate/schematics-collections-relative.ts @@ -0,0 +1,53 @@ +import assert from 'node:assert'; +import { join } from 'node:path'; +import { ng } from '../../utils/process'; +import { writeMultipleFiles, createDir } from '../../utils/fs'; +import { updateJsonFile } from '../../utils/project'; + +export default async function () { + // setup temp collection + await createDir('./fake-schematics'); + await writeMultipleFiles({ + './fake-schematics/package.json': JSON.stringify({ + 'schematics': './collection.json', + }), + './fake-schematics/collection.json': JSON.stringify({ + 'schematics': { + 'fake': { + 'description': 'Fake schematic', + 'schema': './fake-schema.json', + 'factory': './fake', + }, + }, + }), + './fake-schematics/fake-schema.json': JSON.stringify({ + '$id': 'FakeSchema', + 'title': 'Fake Schema', + 'type': 'object', + }), + './fake-schematics/fake.js': ` + exports.default = () => (host, context) => context.logger.info('fake schematic run.'); + `, + }); + + await updateJsonFile('angular.json', (json) => { + json.cli ??= {}; + json.cli.schematicCollections = ['./fake-schematics']; + }); + + const { stdout: stdout1 } = await ng('generate', '--help'); + assert.match(stdout1, /Fake schematic/); + + const { stdout: stdout2 } = await ng('generate', 'fake'); + assert.match(stdout2, /fake schematic run/); + + // change cwd to a nested directory to validate the relative schematic is resolved correctly + const originalCwd = process.cwd(); + try { + process.chdir(join(originalCwd, 'src/app')); + const { stdout: stdout3 } = await ng('generate', 'fake'); + assert.match(stdout3, /fake schematic run/); + } finally { + process.chdir(originalCwd); + } +} diff --git a/tests/legacy-cli/e2e/tests/generate/service/service-basic.ts b/tests/legacy-cli/e2e/tests/generate/service/service-basic.ts index 26a18fc8a9d2..a7ddb3cb8310 100644 --- a/tests/legacy-cli/e2e/tests/generate/service/service-basic.ts +++ b/tests/legacy-cli/e2e/tests/generate/service/service-basic.ts @@ -9,8 +9,8 @@ export default function () { return ( ng('generate', 'service', 'test-service') .then(() => expectFileToExist(serviceDir)) - .then(() => expectFileToExist(join(serviceDir, 'test-service.service.ts'))) - .then(() => expectFileToExist(join(serviceDir, 'test-service.service.spec.ts'))) + .then(() => expectFileToExist(join(serviceDir, 'test-service.ts'))) + .then(() => expectFileToExist(join(serviceDir, 'test-service.spec.ts'))) // Try to run the unit tests. .then(() => ng('test', '--watch=false')) diff --git a/tests/legacy-cli/e2e/tests/i18n/extract-ivy-disk-cache.ts b/tests/legacy-cli/e2e/tests/i18n/extract-ivy-disk-cache.ts index 0fd91f8b8dae..e5a13de3c439 100644 --- a/tests/legacy-cli/e2e/tests/i18n/extract-ivy-disk-cache.ts +++ b/tests/legacy-cli/e2e/tests/i18n/extract-ivy-disk-cache.ts @@ -15,24 +15,21 @@ export default async function () { // Setup an i18n enabled component await ng('generate', 'component', 'i18n-test'); - await writeFile( - join('src/app/i18n-test', 'i18n-test.component.ng.html'), - '

Hello world

', - ); + await writeFile(join('src/app/i18n-test', 'i18n-test.html'), '

Hello world

'); await writeFile( - 'src/app/app.component.ts', + 'src/app/app.ts', ` import { Component } from '@angular/core'; - import { I18nTestComponent } from './i18n-test/i18n-test.component'; + import { I18nTest } from './i18n-test/i18n-test'; @Component({ standalone: true, selector: 'app-root', - imports: [I18nTestComponent], + imports: [I18nTest], template: '' }) - export class AppComponent {} + export class App {} `, ); diff --git a/tests/legacy-cli/e2e/tests/i18n/extract-ivy-libraries.ts b/tests/legacy-cli/e2e/tests/i18n/extract-ivy-libraries.ts index 754f5d6ebc02..a577a8c5e6a6 100644 --- a/tests/legacy-cli/e2e/tests/i18n/extract-ivy-libraries.ts +++ b/tests/legacy-cli/e2e/tests/i18n/extract-ivy-libraries.ts @@ -7,24 +7,17 @@ import { readNgVersion } from '../../utils/version'; export default async function () { // Setup a library await ng('generate', 'library', 'i18n-lib-test'); - await replaceInFile( - 'projects/i18n-lib-test/src/lib/i18n-lib-test.component.ts', - '

', - '

', - ); + await replaceInFile('projects/i18n-lib-test/src/lib/i18n-lib-test.ts', '

', '

'); // Build library await ng('build', 'i18n-lib-test', '--configuration=development'); // Consume library in application - await replaceInFile('src/app/app.component.ts', 'imports: [', 'imports: [I18nLibTestComponent,'); - await prependToFile( - 'src/app/app.component.ts', - `import { I18nLibTestComponent } from 'i18n-lib-test';`, - ); + await replaceInFile('src/app/app.ts', 'imports: [', 'imports: [I18nLibTest,'); + await prependToFile('src/app/app.ts', `import { I18nLibTest } from 'i18n-lib-test';`); await writeFile( - 'src/app/app.component.ng.html', + 'src/app/app.html', `

Hello world

@@ -42,11 +35,8 @@ export default async function () { await ng('extract-i18n'); await expectFileToMatch('messages.xlf', 'Hello world'); await expectFileToMatch('messages.xlf', 'i18n-lib-test works!'); - await expectFileToMatch('messages.xlf', 'src/app/app.component.ng.html'); - await expectFileToMatch( - 'messages.xlf', - 'projects/i18n-lib-test/src/lib/i18n-lib-test.component.ts', - ); + await expectFileToMatch('messages.xlf', 'src/app/app.html'); + await expectFileToMatch('messages.xlf', 'projects/i18n-lib-test/src/lib/i18n-lib-test.ts'); await uninstallPackage('@angular/localize'); } diff --git a/tests/legacy-cli/e2e/tests/i18n/extract-ivy.ts b/tests/legacy-cli/e2e/tests/i18n/extract-ivy.ts index e4ea4c39358b..72af7f87e712 100644 --- a/tests/legacy-cli/e2e/tests/i18n/extract-ivy.ts +++ b/tests/legacy-cli/e2e/tests/i18n/extract-ivy.ts @@ -9,24 +9,21 @@ import { readNgVersion } from '../../utils/version'; export default async function () { // Setup an i18n enabled component await ng('generate', 'component', 'i18n-test'); - await writeFile( - join('src/app/i18n-test', 'i18n-test.component.ng.html'), - '

Hello world

', - ); + await writeFile(join('src/app/i18n-test', 'i18n-test.html'), '

Hello world

'); // Actually use the generated component to ensure it is present in the application output await writeFile( - 'src/app/app.component.ts', + 'src/app/app.ts', ` import { Component } from '@angular/core'; - import { I18nTestComponent } from './i18n-test/i18n-test.component'; + import { I18nTest } from './i18n-test/i18n-test'; @Component({ standalone: true, selector: 'app-root', - imports: [I18nTestComponent], + imports: [I18nTest], template: '' }) - export class AppComponent {} + export class App {} `, ); diff --git a/tests/legacy-cli/e2e/tests/i18n/ivy-localize-app-shell-service-worker.ts b/tests/legacy-cli/e2e/tests/i18n/ivy-localize-app-shell-service-worker.ts index 46379cbe9bb9..b1568be95939 100644 --- a/tests/legacy-cli/e2e/tests/i18n/ivy-localize-app-shell-service-worker.ts +++ b/tests/legacy-cli/e2e/tests/i18n/ivy-localize-app-shell-service-worker.ts @@ -17,7 +17,7 @@ export default async function () { : readNgVersion(); }); - await appendToFile('src/app/app.component.ng.html', ''); + await appendToFile('src/app/app.html', ''); // Add app-shell and service-worker await silentNg('generate', 'app-shell'); diff --git a/tests/legacy-cli/e2e/tests/i18n/ivy-localize-app-shell.ts b/tests/legacy-cli/e2e/tests/i18n/ivy-localize-app-shell.ts index e997286febcd..cbabbae17140 100644 --- a/tests/legacy-cli/e2e/tests/i18n/ivy-localize-app-shell.ts +++ b/tests/legacy-cli/e2e/tests/i18n/ivy-localize-app-shell.ts @@ -23,7 +23,7 @@ export default async function () { : readNgVersion(); }); - await appendToFile('src/app/app.component.ng.html', ''); + await appendToFile('src/app/app.html', ''); await ng('generate', 'app-shell', '--project', 'test-project'); if (isSnapshotBuild) { @@ -62,7 +62,7 @@ export default async function () { }); await writeFile( - 'src/app/app-shell/app-shell.component.ng.html', + 'src/app/app-shell/app-shell.html', '

Hello i18n!

', ); @@ -70,7 +70,7 @@ export default async function () { // Extraction of i18n only works on browser targets. // Let's add the same translation that there is in the app-shell await writeFile( - 'src/app/app.component.ng.html', + 'src/app/app.html', '

Hello i18n!

', ); @@ -79,9 +79,9 @@ export default async function () { await expectFileToMatch('src/locale/messages.xlf', `source-language="en-US"`); await expectFileToMatch('src/locale/messages.xlf', `An introduction header for this sample`); - // Clean up app.component.ng.html so that we can easily + // Clean up app.ng.html so that we can easily // find the translation text - await writeFile('src/app/app.component.ng.html', ''); + await writeFile('src/app/app.html', ''); for (const { lang, translation } of langTranslations) { if (lang != 'en-US') { diff --git a/tests/legacy-cli/e2e/tests/i18n/setup.ts b/tests/legacy-cli/e2e/tests/i18n/setup.ts index aa8cde291d7a..30fdcee1d757 100644 --- a/tests/legacy-cli/e2e/tests/i18n/setup.ts +++ b/tests/legacy-cli/e2e/tests/i18n/setup.ts @@ -98,7 +98,7 @@ export const baseHrefs: { [l: string]: string } = { export async function setupI18nConfig() { // Add component with i18n content, both translations and localeData (plural, dates). await writeFile( - 'src/app/app.component.ts', + 'src/app/app.ts', ` import { Component, Inject, LOCALE_ID } from '@angular/core'; import { DatePipe } from '@angular/common'; @@ -108,9 +108,9 @@ export async function setupI18nConfig() { selector: 'app-root', imports: [DatePipe, RouterOutlet], standalone: true, - templateUrl: './app.component.ng.html' + templateUrl: './app.html' }) - export class AppComponent { + export class App { constructor(@Inject(LOCALE_ID) public locale: string) { } title = 'i18n'; jan = new Date(2000, 0, 1); @@ -119,7 +119,7 @@ export async function setupI18nConfig() { `, ); await writeFile( - `src/app/app.component.ng.html`, + `src/app/app.html`, `

Hello {{ title }}!

{{ locale }}

@@ -140,7 +140,7 @@ export async function setupI18nConfig() { Hello ! - src/app/app.component.ng.html + src/app/app.html 2,3 An introduction header for this sample @@ -148,14 +148,14 @@ export async function setupI18nConfig() { Updated - src/app/app.component.ng.html + src/app/app.html 5,6 {VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other { minutes ago}} - src/app/app.component.ng.html + src/app/app.html 5,6 @@ -168,7 +168,7 @@ export async function setupI18nConfig() { // ng serve support: https://github.com/angular/angular-cli/issues/16248 await writeFile('src/app/dynamic.ts', `export const abc = 5;`); await appendToFile( - 'src/app/app.component.ts', + 'src/app/app.ts', ` (async () => { await import('./dynamic'); })(); `, diff --git a/tests/legacy-cli/e2e/tests/misc/browsers.ts b/tests/legacy-cli/e2e/tests/misc/browsers.ts index cb133dbef117..14c085abaac5 100644 --- a/tests/legacy-cli/e2e/tests/misc/browsers.ts +++ b/tests/legacy-cli/e2e/tests/misc/browsers.ts @@ -11,7 +11,7 @@ export default async function () { } // Workaround for https://github.com/angular/angular/issues/32192 - await replaceInFile('src/app/app.component.ng.html', /class="material-icons"/g, ''); + await replaceInFile('src/app/app.html', /class="material-icons"/g, ''); await ng('build'); diff --git a/tests/legacy-cli/e2e/tests/misc/dedupe-duplicate-modules.ts b/tests/legacy-cli/e2e/tests/misc/dedupe-duplicate-modules.ts index 8c5a094cf9aa..5047021566eb 100644 --- a/tests/legacy-cli/e2e/tests/misc/dedupe-duplicate-modules.ts +++ b/tests/legacy-cli/e2e/tests/misc/dedupe-duplicate-modules.ts @@ -11,7 +11,7 @@ export default async function () { await updateJsonFile('package.json', (json) => { json.dependencies = { ...json.dependencies, - 'tslib': '2.0.0', + 'tslib': '^2.0.0', 'tslib-1': 'npm:tslib@1.13.0', 'tslib-1-copy': 'npm:tslib@1.13.0', }; @@ -56,7 +56,7 @@ export default async function () { throw new Error('Expected stderr to contain [DedupeModuleResolvePlugin] log for tslib.'); } - await expectFileToMatch(outFile, './node_modules/tslib/tslib.es6.js'); + await expectFileToMatch(outFile, './node_modules/tslib/tslib.es6.mjs'); } finally { await rimraf('node_modules/tslib'); await gitClean(); diff --git a/tests/legacy-cli/e2e/tests/misc/duplicate-command-line-option.ts b/tests/legacy-cli/e2e/tests/misc/duplicate-command-line-option.ts index a445e9051ade..0042a363e156 100644 --- a/tests/legacy-cli/e2e/tests/misc/duplicate-command-line-option.ts +++ b/tests/legacy-cli/e2e/tests/misc/duplicate-command-line-option.ts @@ -15,5 +15,5 @@ export default async function () { throw new Error(`Expected stderr to contain: "${warningMatch}".`); } - await expectFileToExist('src/app/test-component/test-component.component.sass'); + await expectFileToExist('src/app/test-component/test-component.sass'); } diff --git a/tests/legacy-cli/e2e/tests/misc/es2015-nometa.ts b/tests/legacy-cli/e2e/tests/misc/es2015-nometa.ts index 3973636e07f5..c8fad0e07954 100644 --- a/tests/legacy-cli/e2e/tests/misc/es2015-nometa.ts +++ b/tests/legacy-cli/e2e/tests/misc/es2015-nometa.ts @@ -2,15 +2,15 @@ import { prependToFile, replaceInFile } from '../../utils/fs'; import { ng } from '../../utils/process'; export default async function () { - await ng('generate', 'service', 'user'); + await ng('generate', 'service', 'user-service'); // Update the application to use the new service - await prependToFile('src/app/app.component.ts', "import { UserService } from './user.service';"); + await prependToFile('src/app/app.ts', "import { UserService } from './user-service';"); await replaceInFile( - 'src/app/app.component.ts', - 'export class AppComponent {', - 'export class AppComponent {\n constructor(user: UserService) {}', + 'src/app/app.ts', + 'export class App {', + 'export class App {\n constructor(user: UserService) {}', ); // Execute the application's tests with emitDecoratorMetadata disabled (default) diff --git a/tests/legacy-cli/e2e/tests/misc/forwardref-es2015.ts b/tests/legacy-cli/e2e/tests/misc/forwardref-es2015.ts index cdf3eef6a313..32ca39e89713 100644 --- a/tests/legacy-cli/e2e/tests/misc/forwardref-es2015.ts +++ b/tests/legacy-cli/e2e/tests/misc/forwardref-es2015.ts @@ -5,25 +5,25 @@ import { expectToFail } from '../../utils/utils'; export default async function () { // Update the application to use a forward reference await replaceInFile( - 'src/app/app.component.ts', + 'src/app/app.ts', "import { Component } from '@angular/core';", "import { Component, Inject, Injectable, forwardRef } from '@angular/core';", ); - await appendToFile('src/app/app.component.ts', '\n@Injectable() export class Lock { }\n'); + await appendToFile('src/app/app.ts', '\n@Injectable() export class Lock { }\n'); await replaceInFile( - 'src/app/app.component.ts', - 'export class AppComponent {', - 'export class AppComponent {\n constructor(@Inject(forwardRef(() => Lock)) lock: Lock) {}', + 'src/app/app.ts', + 'export class App {', + 'export class App {\n constructor(@Inject(forwardRef(() => Lock)) lock: Lock) {}', ); // Update the application's unit tests to include the new injectable await replaceInFile( - 'src/app/app.component.spec.ts', - "import { AppComponent } from './app.component';", - "import { AppComponent, Lock } from './app.component';", + 'src/app/app.spec.ts', + "import { App } from './app';", + "import { App, Lock } from './app';", ); await replaceInFile( - 'src/app/app.component.spec.ts', + 'src/app/app.spec.ts', 'TestBed.configureTestingModule({', 'TestBed.configureTestingModule({ providers: [Lock],', ); diff --git a/tests/legacy-cli/e2e/tests/misc/trusted-types.ts b/tests/legacy-cli/e2e/tests/misc/trusted-types.ts index 3c927f15ad8d..325ee521fe6d 100644 --- a/tests/legacy-cli/e2e/tests/misc/trusted-types.ts +++ b/tests/legacy-cli/e2e/tests/misc/trusted-types.ts @@ -16,7 +16,7 @@ export default async function () { await replaceInFile( 'src/app/app.routes.ts', 'routes: Routes = [];', - `routes: Routes = [{path: 'lazy', loadComponent: () => import('./lazy/lazy.component').then(c => c.LazyComponent)}];`, + `routes: Routes = [{path: 'lazy', loadComponent: () => import('./lazy/lazy').then(c => c.Lazy)}];`, ); // Add lazy route e2e diff --git a/tests/legacy-cli/e2e/tests/test/test-code-coverage-exclude.ts b/tests/legacy-cli/e2e/tests/test/test-code-coverage-exclude.ts index 52b8989218b5..3533e6c8e9a9 100644 --- a/tests/legacy-cli/e2e/tests/test/test-code-coverage-exclude.ts +++ b/tests/legacy-cli/e2e/tests/test/test-code-coverage-exclude.ts @@ -5,7 +5,7 @@ import { expectToFail } from '../../utils/utils'; export default async function () { // This test is already in build-angular, but that doesn't run on Windows. await silentNg('test', '--no-watch', '--code-coverage'); - await expectFileToExist('coverage/test-project/app.component.ts.html'); + await expectFileToExist('coverage/test-project/app.ts.html'); // Delete coverage directory await rimraf('coverage'); @@ -13,10 +13,10 @@ export default async function () { 'test', '--no-watch', '--code-coverage', - `--code-coverage-exclude='src/**/app.component.ts'`, + `--code-coverage-exclude='src/**/app.ts'`, ); // Doesn't include excluded. await expectFileToExist('coverage/test-project/index.html'); - await expectToFail(() => expectFileToExist('coverage/test-project/app.component.ts.html')); + await expectToFail(() => expectFileToExist('coverage/test-project/app.ts.html')); } diff --git a/tests/legacy-cli/e2e/tests/test/test-fail-single-run.ts b/tests/legacy-cli/e2e/tests/test/test-fail-single-run.ts index 90f7d73736c1..d2054e7c37ee 100644 --- a/tests/legacy-cli/e2e/tests/test/test-fail-single-run.ts +++ b/tests/legacy-cli/e2e/tests/test/test-fail-single-run.ts @@ -6,7 +6,7 @@ export default function () { // TODO(architect): Delete this test. It is now in devkit/build-angular. // Fails on single run with broken compilation. - return writeFile('src/app.component.spec.ts', '

definitely not typescript

').then(() => + return writeFile('src/app.spec.ts', '

definitely not typescript

').then(() => expectToFail(() => ng('test', '--watch=false')), ); } diff --git a/tests/legacy-cli/e2e/tests/test/test-jasmine-clock.ts b/tests/legacy-cli/e2e/tests/test/test-jasmine-clock.ts index f676b324a2c6..37b164ff5914 100644 --- a/tests/legacy-cli/e2e/tests/test/test-jasmine-clock.ts +++ b/tests/legacy-cli/e2e/tests/test/test-jasmine-clock.ts @@ -3,12 +3,12 @@ import { writeFile } from '../../utils/fs'; export default async function () { await writeFile( - 'src/app/app.component.spec.ts', + 'src/app/app.spec.ts', ` import { TestBed } from '@angular/core/testing'; - import { AppComponent } from './app.component'; + import { App } from './app'; - describe('AppComponent', () => { + describe('App', () => { beforeAll(() => { jasmine.clock().install(); }); @@ -18,11 +18,11 @@ export default async function () { }); beforeEach(() => TestBed.configureTestingModule({ - imports: [AppComponent] + imports: [App] })); it('should create the app', () => { - const fixture = TestBed.createComponent(AppComponent); + const fixture = TestBed.createComponent(App); expect(fixture.componentInstance).toBeTruthy(); }); }); diff --git a/tests/legacy-cli/e2e/tests/test/test-scripts.ts b/tests/legacy-cli/e2e/tests/test/test-scripts.ts index 4e308a6922b9..acbcc66dc230 100644 --- a/tests/legacy-cli/e2e/tests/test/test-scripts.ts +++ b/tests/legacy-cli/e2e/tests/test/test-scripts.ts @@ -16,31 +16,31 @@ export default async function () { declare var stringScriptGlobal: any; declare var inputScriptGlobal: any; `, - 'src/app/app.component.ts': ` + 'src/app/app.ts': ` import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: '', standalone: false }) - export class AppComponent { + export class App { stringScriptGlobalProp = stringScriptGlobal; inputScriptGlobalProp = inputScriptGlobal; } `, - 'src/app/app.component.spec.ts': ` + 'src/app/app.spec.ts': ` import { TestBed } from '@angular/core/testing'; - import { AppComponent } from './app.component'; + import { App } from './app'; - describe('AppComponent', () => { + describe('App', () => { beforeEach(() => TestBed.configureTestingModule({ - declarations: [AppComponent] + declarations: [App] })); it('should have access to string-script.js', () => { - let app = TestBed.createComponent(AppComponent).debugElement.componentInstance; + let app = TestBed.createComponent(App).debugElement.componentInstance; expect(app.stringScriptGlobalProp).toEqual('string-scripts.js'); }); it('should have access to input-script.js', () => { - let app = TestBed.createComponent(AppComponent).debugElement.componentInstance; + let app = TestBed.createComponent(App).debugElement.componentInstance; expect(app.inputScriptGlobalProp).toEqual('input-scripts.js'); }); }); diff --git a/tests/legacy-cli/e2e/tests/test/test-sourcemap.ts b/tests/legacy-cli/e2e/tests/test/test-sourcemap.ts index 797aba88e17f..9e2a8e3f36fa 100644 --- a/tests/legacy-cli/e2e/tests/test/test-sourcemap.ts +++ b/tests/legacy-cli/e2e/tests/test/test-sourcemap.ts @@ -6,7 +6,7 @@ import { assertIsError } from '../../utils/utils'; export default async function () { await writeFile( - 'src/app/app.component.spec.ts', + 'src/app/app.spec.ts', ` it('should fail', () => { expect(undefined).toBeTruthy(); @@ -20,7 +20,7 @@ export default async function () { throw new Error('ng test should have failed.'); } catch (error) { assertIsError(error); - assert.match(error.message, /src\/app\/app\.component\.spec\.ts/); + assert.match(error.message, /\(src\/app\/app\.spec\.ts:3:27/); assert.doesNotMatch(error.message, /_karma_webpack_/); } diff --git a/tests/legacy-cli/e2e/tests/vite/ssr-default.ts b/tests/legacy-cli/e2e/tests/vite/ssr-default.ts index cfaece9551ef..8b64a4b30f67 100644 --- a/tests/legacy-cli/e2e/tests/vite/ssr-default.ts +++ b/tests/legacy-cli/e2e/tests/vite/ssr-default.ts @@ -16,7 +16,7 @@ export default async function () { // Forcibly remove in case another test doesn't clean itself up. await uninstallPackage('@angular/ssr'); - await ng('add', '@angular/ssr', '--server-routing', '--skip-confirmation', '--skip-install'); + await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); await useSha(); await installWorkspacePackages(); diff --git a/tests/legacy-cli/e2e/tests/vite/ssr-entry-express.ts b/tests/legacy-cli/e2e/tests/vite/ssr-entry-express.ts index d5e045abef03..11cf671becbf 100644 --- a/tests/legacy-cli/e2e/tests/vite/ssr-entry-express.ts +++ b/tests/legacy-cli/e2e/tests/vite/ssr-entry-express.ts @@ -14,19 +14,19 @@ export default async function () { // Forcibly remove in case another test doesn't clean itself up. await uninstallPackage('@angular/ssr'); - await ng('add', '@angular/ssr', '--server-routing', '--skip-confirmation', '--skip-install'); + await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); await useSha(); await installWorkspacePackages(); await writeMultipleFiles({ - // Replace the template of app.component.ng.html as it makes it harder to debug - 'src/app/app.component.ng.html': '', + // Replace the template of app.ng.html as it makes it harder to debug + 'src/app/app.html': '', 'src/app/app.routes.ts': ` import { Routes } from '@angular/router'; - import { HomeComponent } from './home/home.component'; + import { Home } from './home/home'; export const routes: Routes = [ - { path: 'home', component: HomeComponent } + { path: 'home', component: Home } ]; `, 'src/app/app.routes.server.ts': ` @@ -39,26 +39,29 @@ export default async function () { 'src/server.ts': ` import { AngularNodeAppEngine, writeResponseToNodeResponse, isMainModule, createNodeRequestHandler } from '@angular/ssr/node'; import express from 'express'; - import { fileURLToPath } from 'node:url'; - import { dirname, resolve } from 'node:path'; + import { join } from 'node:path'; export function app(): express.Express { const server = express(); - const serverDistFolder = dirname(fileURLToPath(import.meta.url)); - const browserDistFolder = resolve(serverDistFolder, '../browser'); + const browserDistFolder = join(import.meta.dirname, '../browser'); const angularNodeAppEngine = new AngularNodeAppEngine(); - server.use('/api/**', (req, res) => res.json({ hello: 'foo' })); + server.use('/api/{*splat}', (req, res) => { + res.json({ hello: 'foo' }) + }); - server.get('**', express.static(browserDistFolder, { + server.use(express.static(browserDistFolder, { maxAge: '1y', index: 'index.html' })); - server.get('**', (req, res, next) => { - angularNodeAppEngine.handle(req) - .then((response) => response ? writeResponseToNodeResponse(response, res) : next()) - .catch(next); + server.use(async(req, res, next) => { + const response = await angularNodeAppEngine.handle(req); + if (response) { + writeResponseToNodeResponse(response, res); + } else { + next(); + } }); return server; @@ -67,7 +70,11 @@ export default async function () { const server = app(); if (isMainModule(import.meta.url)) { const port = process.env['PORT'] || 4000; - server.listen(port, () => { + server.listen(port, (error) => { + if (error) { + throw error; + } + console.log(\`Node Express server listening on http://localhost:\${port}\`); }); } @@ -87,7 +94,7 @@ export default async function () { // Modify the home component and validate the change. await modifyFileAndWaitUntilUpdated( - 'src/app/home/home.component.ng.html', + 'src/app/home/home.html', 'home works', 'yay home works!!!', true, diff --git a/tests/legacy-cli/e2e/tests/vite/ssr-entry-fastify.ts b/tests/legacy-cli/e2e/tests/vite/ssr-entry-fastify.ts index 0dceea441dda..c50e8c2200f6 100644 --- a/tests/legacy-cli/e2e/tests/vite/ssr-entry-fastify.ts +++ b/tests/legacy-cli/e2e/tests/vite/ssr-entry-fastify.ts @@ -14,20 +14,20 @@ export default async function () { // Forcibly remove in case another test doesn't clean itself up. await uninstallPackage('@angular/ssr'); - await ng('add', '@angular/ssr', '--server-routing', '--skip-confirmation', '--skip-install'); + await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); await useSha(); await installWorkspacePackages(); await installPackage('fastify@5'); await writeMultipleFiles({ - // Replace the template of app.component.ng.html as it makes it harder to debug - 'src/app/app.component.ng.html': '', + // Replace the template of app.ng.html as it makes it harder to debug + 'src/app/app.html': '', 'src/app/app.routes.ts': ` import { Routes } from '@angular/router'; - import { HomeComponent } from './home/home.component'; + import { Home } from './home/home'; export const routes: Routes = [ - { path: 'home', component: HomeComponent } + { path: 'home', component: Home } ]; `, 'src/app/app.routes.server.ts': ` @@ -87,7 +87,7 @@ export default async function () { // Modify the home component and validate the change. await modifyFileAndWaitUntilUpdated( - 'src/app/home/home.component.ng.html', + 'src/app/home/home.html', 'home works', 'yay home works!!!', true, diff --git a/tests/legacy-cli/e2e/tests/vite/ssr-entry-h3.ts b/tests/legacy-cli/e2e/tests/vite/ssr-entry-h3.ts index 5d2898370405..4a4f91066000 100644 --- a/tests/legacy-cli/e2e/tests/vite/ssr-entry-h3.ts +++ b/tests/legacy-cli/e2e/tests/vite/ssr-entry-h3.ts @@ -14,20 +14,20 @@ export default async function () { // Forcibly remove in case another test doesn't clean itself up. await uninstallPackage('@angular/ssr'); - await ng('add', '@angular/ssr', '--server-routing', '--skip-confirmation', '--skip-install'); + await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); await useSha(); await installWorkspacePackages(); await installPackage('h3@1'); await writeMultipleFiles({ - // Replace the template of app.component.ng.html as it makes it harder to debug - 'src/app/app.component.ng.html': '', + // Replace the template of app.ng.html as it makes it harder to debug + 'src/app/app.html': '', 'src/app/app.routes.ts': ` import { Routes } from '@angular/router'; - import { HomeComponent } from './home/home.component'; + import { Home } from './home/home'; export const routes: Routes = [ - { path: 'home', component: HomeComponent } + { path: 'home', component: Home } ]; `, 'src/app/app.routes.server.ts': ` @@ -78,7 +78,7 @@ export default async function () { // Modify the home component and validate the change. await modifyFileAndWaitUntilUpdated( - 'src/app/home/home.component.ng.html', + 'src/app/home/home.html', 'home works', 'yay home works!!!', true, diff --git a/tests/legacy-cli/e2e/tests/vite/ssr-entry-hono.ts b/tests/legacy-cli/e2e/tests/vite/ssr-entry-hono.ts index a71557a43948..0b0b8220fe6b 100644 --- a/tests/legacy-cli/e2e/tests/vite/ssr-entry-hono.ts +++ b/tests/legacy-cli/e2e/tests/vite/ssr-entry-hono.ts @@ -14,20 +14,20 @@ export default async function () { // Forcibly remove in case another test doesn't clean itself up. await uninstallPackage('@angular/ssr'); - await ng('add', '@angular/ssr', '--server-routing', '--skip-confirmation', '--skip-install'); + await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); await useSha(); await installWorkspacePackages(); await installPackage('hono@4'); await writeMultipleFiles({ - // Replace the template of app.component.ng.html as it makes it harder to debug - 'src/app/app.component.ng.html': '', + // Replace the template of app.ng.html as it makes it harder to debug + 'src/app/app.html': '', 'src/app/app.routes.ts': ` import { Routes } from '@angular/router'; - import { HomeComponent } from './home/home.component'; + import { Home } from './home/home'; export const routes: Routes = [ - { path: 'home', component: HomeComponent } + { path: 'home', component: Home } ]; `, 'src/app/app.routes.server.ts': ` @@ -70,7 +70,7 @@ export default async function () { // Modify the home component and validate the change. await modifyFileAndWaitUntilUpdated( - 'src/app/home/home.component.ng.html', + 'src/app/home/home.html', 'home works', 'yay home works!!!', true, diff --git a/tests/legacy-cli/e2e/tests/vite/ssr-error-stack.ts b/tests/legacy-cli/e2e/tests/vite/ssr-error-stack.ts index 7061e881fdff..a0d7c87bed13 100644 --- a/tests/legacy-cli/e2e/tests/vite/ssr-error-stack.ts +++ b/tests/legacy-cli/e2e/tests/vite/ssr-error-stack.ts @@ -14,7 +14,7 @@ export default async function () { // `--server-routing` not supported in `browser` builder. await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); } else { - await ng('add', '@angular/ssr', '--server-routing', '--skip-confirmation', '--skip-install'); + await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); } await useSha(); @@ -22,7 +22,7 @@ export default async function () { // Create Error. await appendToFile( - 'src/app/app.component.ts', + 'src/app/app.ts', ` (() => { throw new Error('something happened!'); @@ -37,7 +37,7 @@ export default async function () { // The error is also sent in the browser, so we don't need to scrap the stderr. match( text, - /something happened.+at eval \(.+[\\/]+e2e-test[\\/]+test-project[\\/]+src[\\/]+app[\\/]+app\.component\.ts:\d+:\d+\)/, + /something happened.+at eval \(.+[\\/]+e2e-test[\\/]+test-project[\\/]+src[\\/]+app[\\/]+app\.ts:\d+:\d+\)/, ); doesNotMatch(text, /vite-root/); } diff --git a/tests/legacy-cli/e2e/tests/vite/ssr-new-dep-optimization.ts b/tests/legacy-cli/e2e/tests/vite/ssr-new-dep-optimization.ts index be814b01bf89..d7b8a63813eb 100644 --- a/tests/legacy-cli/e2e/tests/vite/ssr-new-dep-optimization.ts +++ b/tests/legacy-cli/e2e/tests/vite/ssr-new-dep-optimization.ts @@ -22,7 +22,7 @@ export default async function () { // Forcibly remove in case another test doesn't clean itself up. await uninstallPackage('@angular/ssr'); - await ng('add', '@angular/ssr', '--server-routing', '--skip-confirmation', '--skip-install'); + await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); await useSha(); await installWorkspacePackages(); diff --git a/tests/legacy-cli/e2e/tests/vite/ssr-no-server-entry-sub-path.ts b/tests/legacy-cli/e2e/tests/vite/ssr-no-server-entry-sub-path.ts deleted file mode 100644 index a4d4ac2cfc61..000000000000 --- a/tests/legacy-cli/e2e/tests/vite/ssr-no-server-entry-sub-path.ts +++ /dev/null @@ -1,54 +0,0 @@ -import assert from 'node:assert'; -import { - execAndWaitForOutputToMatch, - ng, - silentNg, - waitForAnyProcessOutputToMatch, -} from '../../utils/process'; -import { installWorkspacePackages, uninstallPackage } from '../../utils/packages'; -import { useSha } from '../../utils/project'; -import { getGlobalVariable } from '../../utils/env'; -import { findFreePort } from '../../utils/network'; -import { writeFile } from '../../utils/fs'; - -export default async function () { - assert( - getGlobalVariable('argv')['esbuild'], - 'This test should not be called in the Webpack suite.', - ); - - // Forcibly remove in case another test doesn't clean itself up. - await uninstallPackage('@angular/ssr'); - await ng('add', '@angular/ssr', '--no-server-routing', '--skip-confirmation', '--skip-install'); - await useSha(); - await installWorkspacePackages(); - - await silentNg('generate', 'component', 'home'); - await writeFile( - 'src/app/app.routes.ts', - ` - import { Routes } from '@angular/router'; - import {HomeComponent} from './home/home.component'; - - export const routes: Routes = [{ - path: 'sub/home', - component: HomeComponent - }]; - `, - ); - - const port = await findFreePort(); - await execAndWaitForOutputToMatch('ng', ['serve', '--port', `${port}`], /complete/, { - ...process.env, - NO_COLOR: 'true', - }); - - const [, response] = await Promise.all([ - assert.rejects( - waitForAnyProcessOutputToMatch(/Pre-transform error: Failed to load url/, 8_000), - ), - fetch(`http://localhost:${port}/sub/home`), - ]); - - assert(response.ok, `Expected 'response.ok' to be 'true'.`); -} diff --git a/tests/legacy-cli/e2e/tests/vite/ssr-with-ssl.ts b/tests/legacy-cli/e2e/tests/vite/ssr-with-ssl.ts index 5e0a74638527..c4c0fd34ec75 100644 --- a/tests/legacy-cli/e2e/tests/vite/ssr-with-ssl.ts +++ b/tests/legacy-cli/e2e/tests/vite/ssr-with-ssl.ts @@ -13,19 +13,19 @@ export default async function () { // Forcibly remove in case another test doesn't clean itself up. await uninstallPackage('@angular/ssr'); - await ng('add', '@angular/ssr', '--server-routing', '--skip-confirmation', '--skip-install'); + await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install'); await useSha(); await installWorkspacePackages(); await writeMultipleFiles({ - // Replace the template of app.component.ng.html as it makes it harder to debug - 'src/app/app.component.ng.html': '', + // Replace the template of app.ng.html as it makes it harder to debug + 'src/app/app.html': '', 'src/app/app.routes.ts': ` import { Routes } from '@angular/router'; - import { HomeComponent } from './home/home.component'; + import { Home } from './home/home'; export const routes: Routes = [ - { path: 'home', component: HomeComponent } + { path: 'home', component: Home } ]; `, 'src/app/app.routes.server.ts': ` diff --git a/tests/legacy-cli/e2e/utils/BUILD.bazel b/tests/legacy-cli/e2e/utils/BUILD.bazel index 4d690d4bace2..044c1ba409bd 100644 --- a/tests/legacy-cli/e2e/utils/BUILD.bazel +++ b/tests/legacy-cli/e2e/utils/BUILD.bazel @@ -17,11 +17,11 @@ ts_project( "//:node_modules/fast-glob", "//:node_modules/npm", "//:node_modules/protractor", - "//:node_modules/rxjs", "//:node_modules/semver", "//:node_modules/tar", - "//:node_modules/tree-kill", "//:node_modules/verdaccio", "//:node_modules/verdaccio-auth-memory", + "//tests:node_modules/rxjs", + "//tests:node_modules/tree-kill", ], ) diff --git a/tests/legacy-cli/e2e/utils/project.ts b/tests/legacy-cli/e2e/utils/project.ts index 64419ccc1873..ea764bb20314 100644 --- a/tests/legacy-cli/e2e/utils/project.ts +++ b/tests/legacy-cli/e2e/utils/project.ts @@ -205,21 +205,20 @@ export function isPrereleaseCli(): boolean { return (prerelease(getNgCLIVersion())?.length ?? 0) > 0; } -export function updateServerFileForWebpack(filepath: string): Promise { +export function updateServerFileForEsbuild(filepath: string): Promise { return writeFile( filepath, ` import { APP_BASE_HREF } from '@angular/common'; import { CommonEngine } from '@angular/ssr/node'; import express from 'express'; - import { fileURLToPath } from 'node:url'; - import { dirname, join, resolve } from 'node:path'; + import { join, resolve } from 'node:path'; import bootstrap from './main.server'; // The Express app is exported so that it can be used by serverless Functions. export function app(): express.Express { const server = express(); - const serverDistFolder = dirname(fileURLToPath(import.meta.url)); + const serverDistFolder = import.meta.dirname; const browserDistFolder = resolve(serverDistFolder, '../browser'); const indexHtml = join(serverDistFolder, 'index.server.html'); @@ -228,13 +227,13 @@ export function updateServerFileForWebpack(filepath: string): Promise { server.set('view engine', 'html'); server.set('views', browserDistFolder); - server.get('**', express.static(browserDistFolder, { + server.use(express.static(browserDistFolder, { maxAge: '1y', - index: 'index.html', + index: false, })); // All regular routes use the Angular engine - server.get('**', (req, res, next) => { + server.use((req, res, next) => { const { protocol, originalUrl, baseUrl, headers } = req; commonEngine @@ -255,7 +254,10 @@ export function updateServerFileForWebpack(filepath: string): Promise { function run(): void { const port = process.env['PORT'] || 4000; const server = app(); - server.listen(port, () => { + server.listen(port, (error) => { + if (error) { + throw error; + } console.log(\`Node Express server listening on http://localhost:\${port}\`); }); } diff --git a/tests/legacy-cli/e2e_runner.ts b/tests/legacy-cli/e2e_runner.ts index 01f5a6683c27..21377c015845 100644 --- a/tests/legacy-cli/e2e_runner.ts +++ b/tests/legacy-cli/e2e_runner.ts @@ -257,10 +257,8 @@ Promise.all([findFreePort(), findFreePort(), findPackageTars()]) console.log(`Current Directory: ${process.cwd()}`); console.log('Will loop forever while you debug... CTRL-C to quit.'); - /* eslint-disable no-constant-condition */ - while (1) { - // That's right! - } + // Wait forever until user explicitly cancels. + await new Promise(() => {}); } process.exitCode = 1; diff --git a/tests/package.json b/tests/package.json index b185a3ce0da7..4aec9553824b 100644 --- a/tests/package.json +++ b/tests/package.json @@ -1,5 +1,7 @@ { "devDependencies": { - "@angular-devkit/schematics": "workspace:*" + "@angular-devkit/schematics": "workspace:*", + "rxjs": "7.8.2", + "tree-kill": "1.2.2" } } diff --git a/tools/BUILD.bazel b/tools/BUILD.bazel index ab42b524c5d5..3cb815f2db9c 100644 --- a/tools/BUILD.bazel +++ b/tools/BUILD.bazel @@ -1,5 +1,5 @@ load("@bazel_skylib//rules:copy_file.bzl", "copy_file") -load("//tools:defaults2.bzl", "js_binary") +load("//tools:defaults.bzl", "js_binary") package(default_visibility = ["//visibility:public"]) diff --git a/tools/bazel/npm_package.bzl b/tools/bazel/npm_package.bzl index fc912f3d125d..0a76bfe1bb73 100644 --- a/tools/bazel/npm_package.bzl +++ b/tools/bazel/npm_package.bzl @@ -63,8 +63,8 @@ def npm_package( out = "substituted_with_snapshot_repos/package.json", ) - nostamp_subs = dict(substitutions["rjs"]["nostamp"], **extra_substitutions) - stamp_subs = dict(substitutions["rjs"]["stamp"], **extra_substitutions) + nostamp_subs = dict(substitutions["nostamp"], **extra_substitutions) + stamp_subs = dict(substitutions["stamp"], **extra_substitutions) expand_template( name = "final_package_json", diff --git a/tools/defaults2.bzl b/tools/defaults.bzl similarity index 88% rename from tools/defaults2.bzl rename to tools/defaults.bzl index 31af54a7644a..ecd71071d42b 100644 --- a/tools/defaults2.bzl +++ b/tools/defaults.bzl @@ -1,7 +1,7 @@ load("@aspect_bazel_lib//lib:copy_to_bin.bzl", _copy_to_bin = "copy_to_bin") load("@aspect_rules_jasmine//jasmine:defs.bzl", _jasmine_test = "jasmine_test") load("@aspect_rules_js//js:defs.bzl", _js_binary = "js_binary") -load("@npm//@angular/bazel:index.bzl", _ng_package = "ng_package") +load("@rules_angular//src/ng_package:index.bzl", _ng_package = "ng_package") load("//tools:interop.bzl", _ts_project = "ts_project") load("//tools:substitutions.bzl", "substitutions") load("//tools/bazel:npm_package.bzl", _npm_package = "npm_package") @@ -23,8 +23,8 @@ def ng_package(deps = [], **kwargs): deps = deps, license = "//:LICENSE", substitutions = select({ - "//:stamp": substitutions["legacy"]["stamp"], - "//conditions:default": substitutions["legacy"]["nostamp"], + "//:stamp": substitutions["stamp"], + "//conditions:default": substitutions["nostamp"], }), **kwargs ) diff --git a/tools/substitutions.bzl b/tools/substitutions.bzl index ab0dfb46e0a9..098b511b1d6e 100644 --- a/tools/substitutions.bzl +++ b/tools/substitutions.bzl @@ -2,8 +2,8 @@ load("//:constants.bzl", "ANGULAR_FW_PEER_DEP", "ANGULAR_FW_VERSION", "NG_PACKAG _stamp_substitutions = { # Version of the local package being built, generated via the `--workspace_status_command` flag. - "0.0.0-PLACEHOLDER": "{STABLE_PROJECT_VERSION}", - "0.0.0-EXPERIMENTAL-PLACEHOLDER": "{STABLE_PROJECT_EXPERIMENTAL_VERSION}", + "0.0.0-PLACEHOLDER": "{{STABLE_PROJECT_VERSION}}", + "0.0.0-EXPERIMENTAL-PLACEHOLDER": "{{STABLE_PROJECT_EXPERIMENTAL_VERSION}}", # --- "BUILD_SCM_HASH-PLACEHOLDER": "{BUILD_SCM_ABBREV_HASH}", "0.0.0-ENGINES-NODE": RELEASE_ENGINES_NODE, @@ -22,21 +22,7 @@ _no_stamp_substitutions = dict(_stamp_substitutions, **{ "0.0.0-EXPERIMENTAL-PLACEHOLDER": "0.0.0", }) -def _adjust_substitutions_for_rules_js(subs): - result = {} - for key, value in subs.items(): - # in `rules_js`, or `expand_template` from `bazel-lib`, stamp variables - # can only be retrieved via `{{X}}` syntax. - result[key] = value.replace("{", "{{").replace("}", "}}") - return result - substitutions = { - "legacy": { - "stamp": _stamp_substitutions, - "nostamp": _no_stamp_substitutions, - }, - "rjs": { - "stamp": _adjust_substitutions_for_rules_js(_stamp_substitutions), - "nostamp": _adjust_substitutions_for_rules_js(_no_stamp_substitutions), - }, + "stamp": _stamp_substitutions, + "nostamp": _no_stamp_substitutions, } diff --git a/tsconfig.json b/tsconfig.json index 4df52a94fea7..f00528f2698f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,8 +11,8 @@ "isolatedModules": true, "skipLibCheck": true, "strict": true, - "target": "es2022", - "lib": ["es2022"], + "target": "es2023", + "lib": ["es2023"], "rootDir": ".", "rootDirs": [".", "./dist-schema/bin/"], "paths": {