diff --git a/.github/workflows/assistant-to-the-branch-manager.yml b/.github/workflows/assistant-to-the-branch-manager.yml index 87519e50b728..eb299f1e8855 100644 --- a/.github/workflows/assistant-to-the-branch-manager.yml +++ b/.github/workflows/assistant-to-the-branch-manager.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest if: github.event.repository.fork == false steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - uses: angular/dev-infra/github-actions/branch-manager@ba726e7bca0b08b125ccc6f93c233749e1213c17 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 6595df14c26d..dd199499e759 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -19,16 +19,16 @@ jobs: fail-fast: false steps: - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 + uses: github/codeql-action/init@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4.36.1 with: languages: javascript-typescript build-mode: none config-file: .github/codeql/config.yml - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 + uses: github/codeql-action/analyze@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4.36.1 with: category: '/language:javascript-typescript' diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index ae107e5c34d6..dd68d34f72e7 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -20,7 +20,7 @@ jobs: outputs: snapshots: ${{ steps.filter.outputs.snapshots }} steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index fb88be1f8b98..3cf9ef0b1a8d 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -25,7 +25,7 @@ jobs: steps: - name: 'Checkout code' - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false @@ -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@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 + uses: github/codeql-action/upload-sarif@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4.36.1 with: sarif_file: results.sarif diff --git a/CHANGELOG.md b/CHANGELOG.md index 6682a19d581f..83b5ee0ff761 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,37 @@ + + +# 22.0.1 (2026-06-10) + +### @angular/cli + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ----------------------------------------------------------------------------------- | +| [b54e9a549](https://github.com/angular/angular-cli/commit/b54e9a549d30871f6017b1db4cf7a4ab5f3e02db) | fix | do not sort migrations of the same version alphabetically | +| [d33311612](https://github.com/angular/angular-cli/commit/d333116123c7d3d5e87713b7baac048b78f28517) | fix | fallback to local package.json for schematic detection on first run | +| [918102a93](https://github.com/angular/angular-cli/commit/918102a9373085394c41f10d9f5df3e3c17b263f) | fix | isolate temporary package installation from parent pnpm workspace | +| [b048b5f4a](https://github.com/angular/angular-cli/commit/b048b5f4a83d7b20095d79654b849808e7d58fdb) | fix | remove forceAuth and unscoped credential parsing | +| [277934035](https://github.com/angular/angular-cli/commit/277934035138c5af803e8daeebc2313f0a4cb5b3) | fix | validate registry option is a valid URL in ng add | +| [4510dae02](https://github.com/angular/angular-cli/commit/4510dae021ab25bb852eeed6415dbd52cfabfce5) | perf | optimize update schematic registry query counts by fetching package metadata lazily | + +### @schematics/angular + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------------ | +| [c80012294](https://github.com/angular/angular-cli/commit/c8001229453211b37cd7bb12ed26a2deb9257fd5) | fix | fix browserMode option mapping in refactor-jasmine-vitest | +| [a9b6bd904](https://github.com/angular/angular-cli/commit/a9b6bd9042d6b859c384a6fc782541fca30dfb68) | fix | safely comment out multiline statements in refactor-jasmine-vitest | +| [12199df00](https://github.com/angular/angular-cli/commit/12199df00f2e3e8436ada13e04799e5825eb3f7b) | fix | use null objects and callbacks in karma-to-vitest migration | + +### @angular/build + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------- | +| [89d1be979](https://github.com/angular/angular-cli/commit/89d1be979f388d85e9c428bbf1df4e7fb4036dce) | fix | allow disabling Vitest isolation from builder | +| [d45b84be9](https://github.com/angular/angular-cli/commit/d45b84be9a607e49b391cb216cb6de7eca274931) | fix | exclude JSON imports from Vite dependency optimization | +| [e3cab4ddd](https://github.com/angular/angular-cli/commit/e3cab4dddade2538125e8a2f345f42c95e26aeae) | fix | prevent concurrent stylesheet bundling esbuild context leaks | +| [bd413b0eb](https://github.com/angular/angular-cli/commit/bd413b0eb156184ea432cbb7d4e6d7f6f70813ab) | fix | restrict application builder output paths to output directory | + + + # 22.0.0 (2026-06-03) diff --git a/MODULE.bazel b/MODULE.bazel index 90003774ce3b..8b1f6eb797d6 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -7,10 +7,10 @@ module( bazel_dep(name = "platforms", version = "1.1.0") bazel_dep(name = "yq.bzl", version = "0.3.6") bazel_dep(name = "rules_nodejs", version = "6.7.4") -bazel_dep(name = "aspect_rules_js", version = "3.1.2") +bazel_dep(name = "aspect_rules_js", version = "3.2.0") bazel_dep(name = "aspect_rules_ts", version = "3.8.10") bazel_dep(name = "rules_pkg", version = "1.2.0") -bazel_dep(name = "rules_cc", version = "0.2.18") +bazel_dep(name = "rules_cc", version = "0.2.19") bazel_dep(name = "jq.bzl", version = "0.6.1") bazel_dep(name = "bazel_lib", version = "3.3.1") bazel_dep(name = "bazel_skylib", version = "1.9.0") @@ -19,21 +19,21 @@ bazel_dep(name = "aspect_rules_jasmine", version = "2.0.4") bazel_dep(name = "rules_angular") git_override( module_name = "rules_angular", - commit = "c898ddb32c0428e7d97efc713393db84ffa6a38e", + commit = "02e0d38eb29b2721128ca7e93ee694e68d4f06f6", remote = "https://github.com/angular/rules_angular.git", ) bazel_dep(name = "devinfra") git_override( module_name = "devinfra", - commit = "9ee8a680dd018d61d21588bb04cf40d49a9f5deb", + commit = "cef5e36af124e7442d7e2868be3f8c0bba496952", remote = "https://github.com/angular/dev-infra.git", ) bazel_dep(name = "rules_browsers") git_override( module_name = "rules_browsers", - commit = "45441c79322943fc1638b3a40741e925d6089e7b", + commit = "c7e596a4a34f651113c42a9da3f82acc0a01484e", remote = "https://github.com/angular/rules_browsers.git", ) diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index af29118bb1f4..dc32a6881872 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -24,11 +24,10 @@ "https://bcr.bazel.build/modules/aspect_rules_jasmine/2.0.4/source.json": "81ffb708333cd98ec3c0b4cc004f4d5cf92a16914b5196a2892c45141bba7cff", "https://bcr.bazel.build/modules/aspect_rules_js/2.0.0/MODULE.bazel": "b45b507574aa60a92796e3e13c195cd5744b3b8aff516a9c0cb5ae6a048161c5", "https://bcr.bazel.build/modules/aspect_rules_js/3.0.3/MODULE.bazel": "28a30e8fc33bf64a67835d64d124f6e05a7d59648dcb27b110fb3502f761e503", - "https://bcr.bazel.build/modules/aspect_rules_js/3.1.2/MODULE.bazel": "e3685502155d3cc65f3bf98e714f7435de67d7f8f355d63478a80197310311fc", - "https://bcr.bazel.build/modules/aspect_rules_js/3.1.2/source.json": "a32ab71831452b945f3f83a1b1feb9402007e600bce55ac76e15ef0c1e08b520", + "https://bcr.bazel.build/modules/aspect_rules_js/3.2.0/MODULE.bazel": "c3d34345c51a4d90cf678d3b251c6f345b63d5e2e6b0253dbdda467a01efc31f", + "https://bcr.bazel.build/modules/aspect_rules_js/3.2.0/source.json": "3538ab18ac72ba3eaa3db0e4ec5171e04322768723afaa1149c0d822fe5411e2", "https://bcr.bazel.build/modules/aspect_rules_ts/3.8.10/MODULE.bazel": "a17a49a21226fc90163a29b3d6eac56703697205530b8d5cc38b3c074dbac039", "https://bcr.bazel.build/modules/aspect_rules_ts/3.8.10/source.json": "745c8dba237b4088409800143241bbb138e7ef37a359bd81a250c2c423f380ce", - "https://bcr.bazel.build/modules/aspect_rules_ts/3.8.9/MODULE.bazel": "bd5f9ebf517cfcd377eaa7ce1cb16035d167f00774b77789909590c53bc6f20c", "https://bcr.bazel.build/modules/aspect_tools_telemetry/0.2.8/MODULE.bazel": "aa975a83e72bcaac62ee61ab12b788ea324a1d05c4aab28aadb202f647881679", "https://bcr.bazel.build/modules/aspect_tools_telemetry/0.3.3/MODULE.bazel": "37c764292861c2f70314efa9846bb6dbb44fc0308903b3285da6528305450183", "https://bcr.bazel.build/modules/aspect_tools_telemetry/0.3.3/source.json": "605086bbc197743a0d360f7ddc550a1d4dfa0441bc807236e17170f636153348", @@ -45,8 +44,8 @@ "https://bcr.bazel.build/modules/bazel_features/1.39.0/MODULE.bazel": "28739425c1fc283c91931619749c832b555e60bcd1010b40d8441ce0a5cf726d", "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7", "https://bcr.bazel.build/modules/bazel_features/1.41.0/MODULE.bazel": "6e0f87fafed801273c371d41e22a15a6f8abf83fdd7f87d5e44ad317b94433d0", - "https://bcr.bazel.build/modules/bazel_features/1.43.0/MODULE.bazel": "defa2226f06ba20550d6548c3a2ea2a7929634437a52973869c20c225450eb91", - "https://bcr.bazel.build/modules/bazel_features/1.43.0/source.json": "1c4207dc858d6de0eecef30026793616bbf420c74aac27b6bad212534a730437", + "https://bcr.bazel.build/modules/bazel_features/1.47.0/MODULE.bazel": "e34df3cb35b1684cfa69923a61ae3803595babd3942cd306a488d51400886b30", + "https://bcr.bazel.build/modules/bazel_features/1.47.0/source.json": "4ba0b5138327f2d73352a51547a4e49a0a828ef400e046b15334d8905bf6b7ff", "https://bcr.bazel.build/modules/bazel_features/1.9.0/MODULE.bazel": "885151d58d90d8d9c811eb75e3288c11f850e1d6b481a8c9f766adee4712358b", "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", "https://bcr.bazel.build/modules/bazel_lib/3.0.0-rc.0/MODULE.bazel": "d6e00979a98ac14ada5e31c8794708b41434d461e7e7ca39b59b765e6d233b18", @@ -127,8 +126,8 @@ "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513", "https://bcr.bazel.build/modules/rules_cc/0.2.16/MODULE.bazel": "9242fa89f950c6ef7702801ab53922e99c69b02310c39fb6e62b2bd30df2a1d4", - "https://bcr.bazel.build/modules/rules_cc/0.2.18/MODULE.bazel": "4460ec36adc8f722a6a2a4ac9374cb91f2acebadaa93fc37966129afb3dece87", - "https://bcr.bazel.build/modules/rules_cc/0.2.18/source.json": "abad668ff2fd63ada1ac49bf386d37e27048b89a3465a6fd968bb832b00a09d3", + "https://bcr.bazel.build/modules/rules_cc/0.2.19/MODULE.bazel": "d5e0f05b63273281a16654eb6b1a8742a75ec153ac8b4f0419949d6e401e46f0", + "https://bcr.bazel.build/modules/rules_cc/0.2.19/source.json": "1ef48cdbd7aa6238015189b582d3d74ef0cbea3cb3e2cb259d782463f570c14a", "https://bcr.bazel.build/modules/rules_cc/0.2.4/MODULE.bazel": "1ff1223dfd24f3ecf8f028446d4a27608aa43c3f41e346d22838a4223980b8cc", "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8", @@ -199,7 +198,8 @@ "https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5", "https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216", "https://bcr.bazel.build/modules/tar.bzl/0.10.4/MODULE.bazel": "e8f9ff79199e8d9eaad7f1b0a77ad74b30bb82d794b87d8ca942bead5de83ae9", - "https://bcr.bazel.build/modules/tar.bzl/0.10.4/source.json": "20143442376c03426f6135292ba02d825cb75308aa47e6bf42dd4cc5a435c2ff", + "https://bcr.bazel.build/modules/tar.bzl/0.10.5/MODULE.bazel": "e964c1f07f7174478d43be7177f364640e24956d5994bd39d48548cc6a436e2c", + "https://bcr.bazel.build/modules/tar.bzl/0.10.5/source.json": "6703dc57a6c7118722ac452ffb0a05f6e205408b810c6aaf25741a635d5f4b89", "https://bcr.bazel.build/modules/tar.bzl/0.2.1/MODULE.bazel": "52d1c00a80a8cc67acbd01649e83d8dd6a9dc426a6c0b754a04fe8c219c76468", "https://bcr.bazel.build/modules/tar.bzl/0.5.1/MODULE.bazel": "7c2eb3dcfc53b0f3d6f9acdfd911ca803eaf92aadf54f8ca6e4c1f3aee288351", "https://bcr.bazel.build/modules/tar.bzl/0.6.0/MODULE.bazel": "a3584b4edcfafcabd9b0ef9819808f05b372957bbdff41601429d5fd0aac2e7c", @@ -219,7 +219,7 @@ "moduleExtensions": { "@@aspect_rules_esbuild+//esbuild:extensions.bzl%esbuild": { "general": { - "bzlTransitiveDigest": "eWM29sOFdgwS2/XR2bEHk1NS/hPrYIX7ly4yh7MH5As=", + "bzlTransitiveDigest": "8bNoUkbLk1vCab3fXdV3RN1UoOjEcHlo/bk9XxZ7e3A=", "usagesDigest": "LSQ+zZp7JNgnBONTxxXnwGr4NTh2qtQYk7qwXXz5qWo=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, @@ -498,7 +498,7 @@ "@@aspect_tools_telemetry+//:extension.bzl%telemetry": { "general": { "bzlTransitiveDigest": "cl5A2O84vDL6Tt+Qga8FCj1DUDGqn+e7ly5rZ+4xvcc=", - "usagesDigest": "SOv3fnWScyh5pAbfi8TO0WqlioqyUWt3t29KT0VkqLE=", + "usagesDigest": "bsm1cFI7hhC0zj7wvllOScDJKporKySjStBNr8xm+dY=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, @@ -507,7 +507,7 @@ "repoRuleId": "@@aspect_tools_telemetry+//:extension.bzl%tel_repository", "attributes": { "deps": { - "aspect_rules_js": "3.1.2", + "aspect_rules_js": "3.2.0", "aspect_rules_ts": "3.8.10", "aspect_rules_esbuild": "0.26.0", "aspect_rules_jasmine": "2.0.4", @@ -592,7 +592,7 @@ }, "@@rules_browsers+//browsers:extensions.bzl%browsers": { "general": { - "bzlTransitiveDigest": "lFwT6yuDqc73sJB9lqKqoCIJq/vYSrS0UPimP2c0ZWA=", + "bzlTransitiveDigest": "lQlRwI+HZTXohoZ41oufeudyNMhYrxQizk07ADXimPI=", "usagesDigest": "FmXYJVoVJlnfUU8x8gObSvu4qWcco/9Faw61aC/wBF0=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, @@ -601,9 +601,9 @@ "rules_browsers_chrome_linux": { "repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo", "attributes": { - "sha256": "f8b9f220f5691f88e00a64dafa98570158b50e7051637644df1152e3c96f9738", + "sha256": "fd4df6dcadda8641af4f5d79137b23f1b1271a1cfcc0b96f52cb1b8bcd7c01d5", "urls": [ - "https://storage.googleapis.com/chrome-for-testing-public/150.0.7860.0/linux64/chrome-headless-shell-linux64.zip" + "https://storage.googleapis.com/chrome-for-testing-public/151.0.7881.0/linux64/chrome-headless-shell-linux64.zip" ], "named_files": { "CHROME-HEADLESS-SHELL": "chrome-headless-shell-linux64/chrome-headless-shell" @@ -619,9 +619,9 @@ "rules_browsers_chrome_mac": { "repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo", "attributes": { - "sha256": "e989d33e0c27d8884ff95d8c485993205b554499587f33ca390041d54dd57415", + "sha256": "4136f1a9524ac5130dd29fe9eef82094139f079520af0b28f0d360f4f3f550ed", "urls": [ - "https://storage.googleapis.com/chrome-for-testing-public/150.0.7860.0/mac-x64/chrome-headless-shell-mac-x64.zip" + "https://storage.googleapis.com/chrome-for-testing-public/151.0.7881.0/mac-x64/chrome-headless-shell-mac-x64.zip" ], "named_files": { "CHROME-HEADLESS-SHELL": "chrome-headless-shell-mac-x64/chrome-headless-shell" @@ -637,9 +637,9 @@ "rules_browsers_chrome_mac_arm": { "repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo", "attributes": { - "sha256": "e92afa41f45c8cd5241572e21ec3a17a68d12926f7fad7047e8d4bbef0397f4e", + "sha256": "f2cb9d22ad425a23e1d58dab7ac91e546386099a5acb811ca5749d40bf2d9886", "urls": [ - "https://storage.googleapis.com/chrome-for-testing-public/150.0.7860.0/mac-arm64/chrome-headless-shell-mac-arm64.zip" + "https://storage.googleapis.com/chrome-for-testing-public/151.0.7881.0/mac-arm64/chrome-headless-shell-mac-arm64.zip" ], "named_files": { "CHROME-HEADLESS-SHELL": "chrome-headless-shell-mac-arm64/chrome-headless-shell" @@ -655,9 +655,9 @@ "rules_browsers_chrome_win64": { "repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo", "attributes": { - "sha256": "374efaa85908a078e41a0a75bded482eeb1d652aea6c5bb0c14cd854736943c8", + "sha256": "684055979848753211b24215d25993c453ee26cdb2d84d7bfb24f84118e02198", "urls": [ - "https://storage.googleapis.com/chrome-for-testing-public/150.0.7860.0/win64/chrome-headless-shell-win64.zip" + "https://storage.googleapis.com/chrome-for-testing-public/151.0.7881.0/win64/chrome-headless-shell-win64.zip" ], "named_files": { "CHROME-HEADLESS-SHELL": "chrome-headless-shell-win64/chrome-headless-shell.exe" @@ -673,9 +673,9 @@ "rules_browsers_chromedriver_linux": { "repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo", "attributes": { - "sha256": "69e0625253c89cc7f8d265016fa46bf63401f9f7ca0454d0dade828c58bd9a08", + "sha256": "d9e12133a8af192f8a28f2ef0d86ac54f7458c71e28bddf95947d5636472d508", "urls": [ - "https://storage.googleapis.com/chrome-for-testing-public/150.0.7860.0/linux64/chromedriver-linux64.zip" + "https://storage.googleapis.com/chrome-for-testing-public/151.0.7881.0/linux64/chromedriver-linux64.zip" ], "named_files": { "CHROMEDRIVER": "chromedriver-linux64/chromedriver" @@ -689,9 +689,9 @@ "rules_browsers_chromedriver_mac": { "repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo", "attributes": { - "sha256": "95e64bff15615dede9e6a690cf91fc76603354daa05d80437be39e15dfc94611", + "sha256": "7432080f1c3fc8131d58870e93ca9a96c807fedc04deaaf5c1a60942f3c1d321", "urls": [ - "https://storage.googleapis.com/chrome-for-testing-public/150.0.7860.0/mac-x64/chromedriver-mac-x64.zip" + "https://storage.googleapis.com/chrome-for-testing-public/151.0.7881.0/mac-x64/chromedriver-mac-x64.zip" ], "named_files": { "CHROMEDRIVER": "chromedriver-mac-x64/chromedriver" @@ -705,9 +705,9 @@ "rules_browsers_chromedriver_mac_arm": { "repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo", "attributes": { - "sha256": "63d0da6ef29c4ad9f6b5ddbe68466e3c301c9e04daed509ac31f339a5948fe8e", + "sha256": "0bfbda9352bbae72755b463f656a6f335481bc02be1ba8edfe1fb74a08ce0d7b", "urls": [ - "https://storage.googleapis.com/chrome-for-testing-public/150.0.7860.0/mac-arm64/chromedriver-mac-arm64.zip" + "https://storage.googleapis.com/chrome-for-testing-public/151.0.7881.0/mac-arm64/chromedriver-mac-arm64.zip" ], "named_files": { "CHROMEDRIVER": "chromedriver-mac-arm64/chromedriver" @@ -721,9 +721,9 @@ "rules_browsers_chromedriver_win64": { "repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo", "attributes": { - "sha256": "93b27d5b09340d650923cfd9d8e306c2e6430dcf0b826f34e79080b43dff7064", + "sha256": "766efed7d9c6a3aa89733d59b64316849775002bdde7e247318c8129bbd6d747", "urls": [ - "https://storage.googleapis.com/chrome-for-testing-public/150.0.7860.0/win64/chromedriver-win64.zip" + "https://storage.googleapis.com/chrome-for-testing-public/151.0.7881.0/win64/chromedriver-win64.zip" ], "named_files": { "CHROMEDRIVER": "chromedriver-win64/chromedriver.exe" @@ -952,7 +952,7 @@ "@@rules_nodejs+//nodejs:extensions.bzl%node": { "general": { "bzlTransitiveDigest": "oZFClfRhTTwsYzpxVPkOpOt/r0+OzEfEV37au0jFZ0s=", - "usagesDigest": "28HwARS2PIkmyhXuiSyS1jAaG14m/bsZo/Sm+OPn2M8=", + "usagesDigest": "00+3uj4j6s/drSt+SUad8w/R4Rp2/GHGBsCgrKvF7mE=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, @@ -2603,7 +2603,7 @@ }, "@@rules_python+//python/extensions:pip.bzl%pip": { "general": { - "bzlTransitiveDigest": "1CieYf7PBGYmx4QxddIeJFyAiJ2OB1ah39h4F4rtjxo=", + "bzlTransitiveDigest": "JOGVSMFw3XSY/6/iPEgXTZqFR5YFbDaa20WiXWZ8m4U=", "usagesDigest": "AK1R124YPWwAs8z1CQYyjYuci8RO5Ofot+EP5ZCNQDc=", "recordedFileInputs": { "@@protobuf+//python/requirements.txt": "983be60d3cec4b319dcab6d48aeb3f5b2f7c3350f26b3a9e97486c37967c73c5", @@ -5342,7 +5342,7 @@ "@@yq.bzl+//yq:extensions.bzl%yq": { "general": { "bzlTransitiveDigest": "UfFMy8CWK4/dVo/tfaSAIYUiDGNAPes5eRllx9O9Q9Q=", - "usagesDigest": "8e3rbqq064p0a9Kvcmva2jmDBY/XStrYwTWmi2gmqTY=", + "usagesDigest": "6JGNN6+d6JD7F98c3T4zg7eUxkfsfsMEDemA2CIoNQQ=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, diff --git a/package.json b/package.json index 1a9c92f1d769..f58f3a9452e9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@angular/devkit-repo", - "version": "22.0.0", + "version": "22.0.1", "private": true, "description": "Software Development Kit for Angular", "keywords": [ @@ -47,14 +47,14 @@ }, "devDependencies": { "@angular/animations": "22.0.0", - "@angular/cdk": "22.0.0-rc.2", + "@angular/cdk": "22.0.0", "@angular/common": "22.0.0", "@angular/compiler": "22.0.0", "@angular/core": "22.0.0", "@angular/forms": "22.0.0", "@angular/localize": "22.0.0", - "@angular/material": "22.0.0-rc.2", - "@angular/ng-dev": "https://github.com/angular/dev-infra-private-ng-dev-builds.git#a450a2420ca888116e6d4207b38819cd27b06179", + "@angular/material": "22.0.0", + "@angular/ng-dev": "https://github.com/angular/dev-infra-private-ng-dev-builds.git#68eef04ac1e37b69e3e61d3e32802e0a6046d54c", "@angular/platform-browser": "22.0.0", "@angular/platform-server": "22.0.0", "@angular/router": "22.0.0", diff --git a/packages/angular/build/src/builders/application/index.ts b/packages/angular/build/src/builders/application/index.ts index f127ef4bdc7f..b31fc0a8f81b 100644 --- a/packages/angular/build/src/builders/application/index.ts +++ b/packages/angular/build/src/builders/application/index.ts @@ -15,6 +15,7 @@ import { createJsonBuildManifest, emitFilesToDisk } from '../../tools/esbuild/ut import { colors as ansiColors } from '../../utils/color'; import { deleteOutputDir } from '../../utils/delete-output-dir'; import { bazelEsbuildPluginPath, useJSONBuildLogs } from '../../utils/environment-options'; +import { isSubDirectory } from '../../utils/path'; import { purgeStaleBuildCache } from '../../utils/purge-cache'; import { assertCompatibleAngularVersion } from '../../utils/version'; import { runEsBuildBuildAction } from './build-action'; @@ -197,45 +198,57 @@ export async function* buildApplication( // Writes the output files to disk and ensures the containing directories are present const directoryExists = new Set(); - await emitFilesToDisk(Object.entries(result.files), async ([filePath, file]) => { - if ( - outputOptions.ignoreServer && - (file.type === BuildOutputFileType.ServerApplication || - file.type === BuildOutputFileType.ServerRoot) - ) { - return; - } + try { + await emitFilesToDisk(Object.entries(result.files), async ([filePath, file]) => { + if ( + outputOptions.ignoreServer && + (file.type === BuildOutputFileType.ServerApplication || + file.type === BuildOutputFileType.ServerRoot) + ) { + return; + } - const fullFilePath = generateFullPath(filePath, file.type, outputOptions); + const fullFilePath = generateFullPath(filePath, file.type, outputOptions); - // Ensure output subdirectories exist - const fileBasePath = path.dirname(fullFilePath); - if (fileBasePath && !directoryExists.has(fileBasePath)) { - await fs.mkdir(fileBasePath, { recursive: true }); - directoryExists.add(fileBasePath); - } + // Ensure output subdirectories exist + const fileBasePath = path.dirname(fullFilePath); + if (fileBasePath && !directoryExists.has(fileBasePath)) { + await fs.mkdir(fileBasePath, { recursive: true }); + directoryExists.add(fileBasePath); + } - if (file.origin === 'memory') { - // Write file contents - await fs.writeFile(fullFilePath, file.contents); - } else { - // Copy file contents - await fs.cp(file.inputPath, fullFilePath, { - mode: fs.constants.COPYFILE_FICLONE, - preserveTimestamps: true, - }); - } - }); + if (file.origin === 'memory') { + // Write file contents + await fs.writeFile(fullFilePath, file.contents); + } else { + // Copy file contents + await fs.cp(file.inputPath, fullFilePath, { + mode: fs.constants.COPYFILE_FICLONE, + preserveTimestamps: true, + }); + } + }); + } catch (error) { + context.logger.error(error instanceof Error ? error.message : String(error)); + yield { success: false }; + continue; + } // Delete any removed files if incremental if (result.kind === ResultKind.Incremental && result.removed?.length) { - await Promise.all( - result.removed.map((file) => { - const fullFilePath = generateFullPath(file.path, file.type, outputOptions); + try { + await Promise.all( + result.removed.map((file) => { + const fullFilePath = generateFullPath(file.path, file.type, outputOptions); - return fs.rm(fullFilePath, { force: true, maxRetries: 3 }); - }), - ); + return fs.rm(fullFilePath, { force: true, maxRetries: 3 }); + }), + ); + } catch (error) { + context.logger.error(error instanceof Error ? error.message : String(error)); + yield { success: false }; + continue; + } } yield { success: true }; @@ -268,6 +281,12 @@ function generateFullPath( // NOTE: 'base' is a fully resolved path at this point const fullFilePath = path.join(outputOptions.base, typeDirectory, filePath); + if (!isSubDirectory(outputOptions.base, fullFilePath)) { + throw new Error( + `The output file path "${fullFilePath}" is outside of the configured output path "${outputOptions.base}".`, + ); + } + return fullFilePath; } diff --git a/packages/angular/build/src/builders/application/tests/options/output-path_spec.ts b/packages/angular/build/src/builders/application/tests/options/output-path_spec.ts index b6c72b9bee58..3fc98c83ed36 100644 --- a/packages/angular/build/src/builders/application/tests/options/output-path_spec.ts +++ b/packages/angular/build/src/builders/application/tests/options/output-path_spec.ts @@ -260,6 +260,28 @@ describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => { }), ); }); + + it('should error when browser directory escapes the output path base', async () => { + harness.useTarget('build', { + ...BASE_OPTIONS, + polyfills: [], + outputPath: { + base: 'dist', + browser: '..', + }, + ssr: false, + }); + + const { result, logs } = await harness.executeOnce({ outputLogsOnFailure: false }); + expect(result?.success).toBeFalse(); + expect(logs).toContain( + jasmine.objectContaining({ + message: jasmine.stringMatching( + `The output file path .* is outside of the configured output path`, + ), + }), + ); + }); }); }); }); diff --git a/packages/angular/build/src/builders/unit-test/options.ts b/packages/angular/build/src/builders/unit-test/options.ts index 5cd04c4ca7bf..ef09958885a7 100644 --- a/packages/angular/build/src/builders/unit-test/options.ts +++ b/packages/angular/build/src/builders/unit-test/options.ts @@ -126,7 +126,7 @@ export async function normalizeOptions( watch, debug: options.debug ?? false, ui: process.env['CI'] ? false : ui, - isolate: isolate ?? false, + isolate, quiet: options.quiet ?? (process.env['CI'] ? false : true), providersFile: options.providersFile && path.join(workspaceRoot, options.providersFile), setupFiles: options.setupFiles diff --git a/packages/angular/build/src/builders/unit-test/runners/vitest/plugins.ts b/packages/angular/build/src/builders/unit-test/runners/vitest/plugins.ts index eb3d7d106ab4..c5e3764043bb 100644 --- a/packages/angular/build/src/builders/unit-test/runners/vitest/plugins.ts +++ b/packages/angular/build/src/builders/unit-test/runners/vitest/plugins.ts @@ -54,7 +54,7 @@ interface VitestConfigPluginOptions { include: string[]; optimizeDepsInclude: string[]; watch: boolean; - isolate: boolean; + isolate: boolean | undefined; } async function findTestEnvironment( @@ -268,8 +268,8 @@ export async function createVitestConfigPlugin( include, // CLI provider browser options override, if present ...(browser ? { browser } : {}), - // Only override if the user explicitly enabled it via CLI - ...(options.isolate ? { isolate: true } : {}), + // Only override if the user explicitly set it via CLI + ...(options.isolate !== undefined ? { isolate: options.isolate } : {}), // If the user has not specified an environment, use a smart default. ...(!testConfig?.environment ? { environment: await findTestEnvironment(projectResolver) } diff --git a/packages/angular/build/src/builders/unit-test/tests/options/isolate_spec.ts b/packages/angular/build/src/builders/unit-test/tests/options/isolate_spec.ts index 6ca00a02d94d..a37bf597e91a 100644 --- a/packages/angular/build/src/builders/unit-test/tests/options/isolate_spec.ts +++ b/packages/angular/build/src/builders/unit-test/tests/options/isolate_spec.ts @@ -54,5 +54,59 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { const { result } = await harness.executeOnce(); expect(result?.success).toBeTrue(); }); + + it('should override isolate from the Vitest config file when set to false', async () => { + harness.writeFile( + 'vitest-base.config.ts', + ` + import { defineConfig } from 'vitest/config'; + + export default defineConfig({ + test: { + fileParallelism: false, + isolate: true, + setupFiles: ['./src/setup.ts'], + }, + }); + `, + ); + + harness.writeFile( + 'src/setup.ts', + ` + const global = globalThis as typeof globalThis & { setupCount?: number }; + global.setupCount = (global.setupCount ?? 0) + 1; + `, + ); + + harness.writeFile( + 'src/app/first.spec.ts', + ` + it('runs first', () => { + expect(true).toBe(true); + }); + `, + ); + + harness.writeFile( + 'src/app/second.spec.ts', + ` + it('shares the test environment with the first spec file', () => { + const global = globalThis as typeof globalThis & { setupCount?: number }; + expect(global.setupCount).toBeGreaterThan(1); + }); + `, + ); + + harness.useTarget('test', { + ...BASE_OPTIONS, + runner: 'vitest' as any, + runnerConfig: true, + isolate: false, + }); + + const { result } = await harness.executeOnce(); + expect(result?.success).toBeTrue(); + }); }); }); diff --git a/packages/angular/build/src/tools/esbuild/bundler-context.ts b/packages/angular/build/src/tools/esbuild/bundler-context.ts index dd2764c8c608..7fe28e5a51d4 100644 --- a/packages/angular/build/src/tools/esbuild/bundler-context.ts +++ b/packages/angular/build/src/tools/esbuild/bundler-context.ts @@ -59,6 +59,8 @@ export class BundlerContext { #esbuildContext?: BuildContext<{ metafile: true; write: false }>; #esbuildOptions?: BuildOptions & { metafile: true; write: false }; #esbuildResult?: BundleContextResult; + #activeBundlePromise?: Promise; + #disposed = false; #optionsFactory: BundlerOptionsFactory; #shouldCacheResult: boolean; #loadCache?: MemoryLoadResultCache; @@ -177,7 +179,18 @@ export class BundlerContext { return this.#esbuildResult; } - const result = await this.#performBundle(); + if (!force && this.#activeBundlePromise) { + return this.#activeBundlePromise; + } + + const bundlePromise = this.#performBundle().finally(() => { + if (this.#activeBundlePromise === bundlePromise) { + this.#activeBundlePromise = undefined; + } + }); + this.#activeBundlePromise = bundlePromise; + + const result = await bundlePromise; if (this.#shouldCacheResult) { this.#esbuildResult = result; } @@ -207,7 +220,12 @@ export class BundlerContext { } else { // Create a build context and perform the build. // Context creation does not perform a build. - this.#esbuildContext = await context(this.#esbuildOptions); + const esbuildContext = await context(this.#esbuildOptions); + if (this.#disposed) { + await esbuildContext.dispose(); + throw new Error('BundlerContext was disposed during build.'); + } + this.#esbuildContext = esbuildContext; result = await this.#esbuildContext.rebuild(); } } catch (failure) { @@ -446,9 +464,11 @@ export class BundlerContext { * @returns A promise that resolves when disposal is complete. */ async dispose(): Promise { + this.#disposed = true; try { this.#esbuildOptions = undefined; this.#esbuildResult = undefined; + this.#activeBundlePromise = undefined; this.#loadCache = undefined; await this.#esbuildContext?.dispose(); } finally { diff --git a/packages/angular/build/src/tools/esbuild/cache.ts b/packages/angular/build/src/tools/esbuild/cache.ts index 5bd0dc84d73f..0634ec5268e8 100644 --- a/packages/angular/build/src/tools/esbuild/cache.ts +++ b/packages/angular/build/src/tools/esbuild/cache.ts @@ -44,11 +44,26 @@ export interface CacheStore { * to use a cache. */ export class Cache = CacheStore> { + // In-flight creator promises to deduplicate concurrent requests for the same key. + readonly #requests = new Map>(); + // Track how many writes occurred for a key to detect mutations during await gaps. + readonly #writeCounts = new Map(); + // Count the number of active, pending getOrCreate operations per key to avoid memory leaks. + readonly #pendingGets = new Map(); + constructor( protected readonly store: S, readonly namespace?: string, ) {} + #incrementWrite(key: string) { + // Only track write counts if there is a pending getOrCreate operation active for the key. + // This ensures that write counts are not leaked when no concurrent gets are running. + if (this.#pendingGets.has(key)) { + this.#writeCounts.set(key, (this.#writeCounts.get(key) || 0) + 1); + } + } + /** * Prefixes a key with the cache namespace if present. * @param key A key string to prefix. @@ -72,14 +87,75 @@ export class Cache = CacheStore> { */ async getOrCreate(key: string, creator: () => V | Promise): Promise { const namespacedKey = this.withNamespace(key); - let value = await this.store.get(namespacedKey); - if (value === undefined) { - value = await creator(); - await this.store.set(namespacedKey, value); + // 1. If another call is already running the creator for this key, share its promise. + let activeRequest = this.#requests.get(namespacedKey); + if (activeRequest !== undefined) { + return activeRequest; } - return value; + // Increment pending gets count to enable write-tracking for this key. + const currentPending = this.#pendingGets.get(namespacedKey) || 0; + this.#pendingGets.set(namespacedKey, currentPending + 1); + + try { + const startWriteCount = this.#writeCounts.get(namespacedKey) || 0; + + // 2. Query the backing store. Since store.get can be async, we yield to the event loop. + const value = await this.store.get(namespacedKey); + + // If a write (e.g. put) occurred during the store.get await gap, we must abort + // the current execution and restart to ensure we return the newly written value. + if ((this.#writeCounts.get(namespacedKey) || 0) !== startWriteCount) { + return this.getOrCreate(key, creator); + } + + if (value !== undefined) { + return value; + } + + // 3. Recheck active request after the await gap in case another concurrent call + // initiated a creator during the store.get wait. + activeRequest = this.#requests.get(namespacedKey); + if (activeRequest !== undefined) { + return activeRequest; + } + + // 4. Run the creator to produce the new value, and store its promise in #requests. + activeRequest = Promise.resolve(creator()).then( + async (newValue) => { + // Ensure this request is still the active one before writing back to the store + // (prevents overwriting newer data if put() was called before resolution). + if (this.#requests.get(namespacedKey) === activeRequest) { + this.#incrementWrite(namespacedKey); + await this.store.set(namespacedKey, newValue); + this.#requests.delete(namespacedKey); + } + + return newValue; + }, + (error) => { + // Clean up the active request if the creator fails. + if (this.#requests.get(namespacedKey) === activeRequest) { + this.#requests.delete(namespacedKey); + } + throw error; + }, + ); + + this.#requests.set(namespacedKey, activeRequest); + + return activeRequest; + } finally { + // Clean up write counts and pending gets once all concurrent gets for this key finish. + const current = this.#pendingGets.get(namespacedKey) || 0; + if (current <= 1) { + this.#pendingGets.delete(namespacedKey); + this.#writeCounts.delete(namespacedKey); + } else { + this.#pendingGets.set(namespacedKey, current - 1); + } + } } /** @@ -100,7 +176,19 @@ export class Cache = CacheStore> { * @param value A value to put in the cache. */ async put(key: string, value: V): Promise { - await this.store.set(this.withNamespace(key), value); + const namespacedKey = this.withNamespace(key); + this.#requests.delete(namespacedKey); + this.#incrementWrite(namespacedKey); + await this.store.set(namespacedKey, value); + } + + /** + * Clears the base class internal state (requests, write counts, and pending gets). + */ + protected clearInternal(): void { + this.#requests.clear(); + this.#writeCounts.clear(); + this.#pendingGets.clear(); } } @@ -116,6 +204,7 @@ export class MemoryCache extends Cache> { * Removes all entries from the cache instance. */ clear() { + this.clearInternal(); this.store.clear(); } diff --git a/packages/angular/build/src/tools/esbuild/cache_spec.ts b/packages/angular/build/src/tools/esbuild/cache_spec.ts new file mode 100644 index 000000000000..a30852836eff --- /dev/null +++ b/packages/angular/build/src/tools/esbuild/cache_spec.ts @@ -0,0 +1,144 @@ +/** + * @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 { MemoryCache } from './cache'; + +describe('MemoryCache', () => { + let cache: MemoryCache; + + beforeEach(() => { + cache = new MemoryCache(); + }); + + it('should return cached value on subsequent getOrCreate calls', async () => { + let callCount = 0; + const creator = () => { + callCount++; + + return 'value'; + }; + + const val1 = await cache.getOrCreate('key', creator); + const val2 = await cache.getOrCreate('key', creator); + + expect(val1).toBe('value'); + expect(val2).toBe('value'); + expect(callCount).toBe(1); + }); + + it('should call creator only once for concurrent getOrCreate calls with the same key', async () => { + let callCount = 0; + let resolveCreator!: (value: string) => void; + const promise = new Promise((resolve) => { + resolveCreator = resolve; + }); + + const creator = () => { + callCount++; + + return promise; + }; + + const p1 = cache.getOrCreate('key', creator); + const p2 = cache.getOrCreate('key', creator); + + resolveCreator('concurrent-value'); + + const [val1, val2] = await Promise.all([p1, p2]); + + expect(val1).toBe('concurrent-value'); + expect(val2).toBe('concurrent-value'); + expect(callCount).toBe(1); + }); + + it('should call creator multiple times for concurrent getOrCreate calls with different keys', async () => { + let callCount = 0; + const creator = (val: string) => { + callCount++; + + return Promise.resolve(val); + }; + + const p1 = cache.getOrCreate('key1', () => creator('value1')); + const p2 = cache.getOrCreate('key2', () => creator('value2')); + + const [val1, val2] = await Promise.all([p1, p2]); + + expect(val1).toBe('value1'); + expect(val2).toBe('value2'); + expect(callCount).toBe(2); + }); + + it('should clean up active request if creator throws/rejects', async () => { + let callCount = 0; + let rejectCreator!: (err: Error) => void; + const promise = new Promise((_, reject) => { + rejectCreator = reject; + }); + + const creator = () => { + callCount++; + + return promise; + }; + + const p1 = cache.getOrCreate('key', creator); + const p2 = cache.getOrCreate('key', creator); + + rejectCreator(new Error('creator error')); + + await expectAsync(p1).toBeRejectedWithError('creator error'); + await expectAsync(p2).toBeRejectedWithError('creator error'); + + // Subsequent call should trigger the creator again + const p3 = cache.getOrCreate('key', () => { + callCount++; + + return Promise.resolve('new-value'); + }); + const val3 = await p3; + expect(val3).toBe('new-value'); + expect(callCount).toBe(2); + }); + + it('should override/clear active requests when put is called', async () => { + let resolveCreator!: (value: string) => void; + const promise = new Promise((resolve) => { + resolveCreator = resolve; + }); + + let creatorStarted!: (value: void) => void; + const creatorStartedPromise = new Promise((resolve) => { + creatorStarted = resolve; + }); + + const creator = () => { + creatorStarted(); + + return promise; + }; + + const p1 = cache.getOrCreate('key', creator); + + // Wait for the creator to be called so that the active request is created + await creatorStartedPromise; + + // Call put before the creator promise resolves + await cache.put('key', 'override-value'); + + resolveCreator('original-value'); + + const val1 = await p1; + // p1 was already returned, so it resolves to original-value + expect(val1).toBe('original-value'); + + // Subsequent getOrCreate should return the put/overridden value, not the resolved original-value + const val2 = await cache.getOrCreate('key', () => 'should-not-run'); + expect(val2).toBe('override-value'); + }); +}); diff --git a/packages/angular/build/src/tools/vite/utils.ts b/packages/angular/build/src/tools/vite/utils.ts index 8f3ded5325f7..7250fd93ceb7 100644 --- a/packages/angular/build/src/tools/vite/utils.ts +++ b/packages/angular/build/src/tools/vite/utils.ts @@ -140,8 +140,12 @@ export function updateExternalMetadata( } const { implicitBrowser, implicitServer, explicit } = result.detail['externalMetadata']; - const implicitServerFiltered = implicitServer.filter((m) => !isBuiltin(m) && !isAbsoluteUrl(m)); - const implicitBrowserFiltered = implicitBrowser.filter((m) => !isAbsoluteUrl(m)); + const implicitServerFiltered = implicitServer.filter( + (m) => !isBuiltin(m) && !isAbsoluteUrl(m) && !m.endsWith('.json'), + ); + const implicitBrowserFiltered = implicitBrowser.filter( + (m) => !isAbsoluteUrl(m) && !m.endsWith('.json'), + ); const explicitBrowserFiltered = explicitPackagesOnly ? explicit.filter((m) => !isAbsoluteUrl(m)) : explicit; diff --git a/packages/angular/build/src/utils/path.ts b/packages/angular/build/src/utils/path.ts index eafef4ee9f2b..e969d420e429 100644 --- a/packages/angular/build/src/utils/path.ts +++ b/packages/angular/build/src/utils/path.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ -import { normalize, posix, resolve } from 'node:path'; +import { isAbsolute, posix, relative, resolve } from 'node:path'; import { platform } from 'node:process'; const WINDOWS_PATH_SEPERATOR_REGEXP = /\\/g; @@ -44,8 +44,9 @@ export function toPosixPath(path: string): string { * @returns `true` if the child path is within the parent directory, `false` otherwise. */ export function isSubDirectory(parent: string, child: string): boolean { - const normalizedParent = normalize(parent); + const resolvedParent = resolve(parent); const resolvedChild = resolve(parent, child); + const relativePath = toPosixPath(relative(resolvedParent, resolvedChild)); - return resolvedChild.startsWith(normalizedParent); + return relativePath !== '..' && !relativePath.startsWith('../') && !isAbsolute(relativePath); } diff --git a/packages/angular/build/src/utils/path_spec.ts b/packages/angular/build/src/utils/path_spec.ts new file mode 100644 index 000000000000..84c7d8ac31c4 --- /dev/null +++ b/packages/angular/build/src/utils/path_spec.ts @@ -0,0 +1,41 @@ +/** + * @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 { isSubDirectory } from './path'; + +describe('isSubDirectory', () => { + it('should return true for a direct child', () => { + expect(isSubDirectory('/foo/bar', '/foo/bar/baz')).toBeTrue(); + }); + + it('should return true for a nested child', () => { + expect(isSubDirectory('/foo/bar', '/foo/bar/baz/qux/file.txt')).toBeTrue(); + }); + + it('should return true if paths are identical', () => { + expect(isSubDirectory('/foo/bar', '/foo/bar')).toBeTrue(); + }); + + it('should return false for a sibling directory starting with same prefix', () => { + expect(isSubDirectory('/foo/bar', '/foo/bar-outside')).toBeFalse(); + expect(isSubDirectory('/foo/bar', '/foo/bar-outside/file.txt')).toBeFalse(); + }); + + it('should return false for directory outside parent via traversal', () => { + expect(isSubDirectory('/foo/bar', '/foo/bar/../outside')).toBeFalse(); + }); + + it('should return false for parent directory', () => { + expect(isSubDirectory('/foo/bar', '/foo')).toBeFalse(); + }); + + it('should return true for children containing directory names starting with double dots', () => { + expect(isSubDirectory('/foo/bar', '/foo/bar/..baz')).toBeTrue(); + expect(isSubDirectory('/foo/bar', '/foo/bar/..baz/qux')).toBeTrue(); + }); +}); diff --git a/packages/angular/cli/src/commands/add/cli.ts b/packages/angular/cli/src/commands/add/cli.ts index 136704947e69..dd78b7038120 100644 --- a/packages/angular/cli/src/commands/add/cli.ts +++ b/packages/angular/cli/src/commands/add/cli.ts @@ -16,6 +16,7 @@ import npa from 'npm-package-arg'; import semver, { Range, compare, intersects, prerelease, satisfies, valid } from 'semver'; import { Argv } from 'yargs'; import { + CommandModuleError, CommandModuleImplementation, Options, OtherOptions, @@ -131,6 +132,17 @@ export default class AddCommandModule type: 'boolean', default: false, }) + .check(({ registry }) => { + if (registry === undefined) { + return true; + } + + if (typeof registry === 'string' && URL.canParse(registry)) { + return true; + } + + throw new CommandModuleError('Option --registry must be a valid URL.'); + }) // Prior to downloading we don't know the full schema and therefore we cannot be strict on the options. // Possibly in the future update the logic to use the following syntax: // `ng add @angular/localize -- --package-options`. @@ -245,6 +257,22 @@ export default class AddCommandModule const result = await tasks.run(taskContext); assert(result.collectionName, 'Collection name should always be available'); + let shouldCleanUp = false; + if (!result.hasSchematics && !options.dryRun) { + const packageJsonPath = this.resolvePackageJson(result.collectionName); + if (packageJsonPath && existsSync(packageJsonPath)) { + try { + const localManifest = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8')); + if (localManifest.schematics) { + result.hasSchematics = true; + if (localManifest['ng-add']?.save === false) { + shouldCleanUp = true; + } + } + } catch {} + } + } + // Check if the installed package has actual add actions and not just schematic support if (result.hasSchematics && !options.dryRun) { const workflow = this.getOrCreateWorkflowForBuilder(result.collectionName); @@ -299,7 +327,16 @@ export default class AddCommandModule return; } - return this.executeSchematic({ ...options, collection: result.collectionName }); + const schematicExitCode = await this.executeSchematic({ + ...options, + collection: result.collectionName, + }); + + if (shouldCleanUp) { + await this.cleanUpTemporaryDependency(result.collectionName); + } + + return schematicExitCode; } catch (e) { if (e instanceof CommandError) { logger.error(e.message); @@ -560,6 +597,36 @@ export default class AddCommandModule } } + private async cleanUpTemporaryDependency(packageName: string): Promise { + try { + this.context.logger.info(`Cleaning up temporary dependency '${packageName}'...`); + + // 1. Remove from root package.json + const projectManifest = await this.getProjectManifest(); + if (projectManifest) { + if (projectManifest.dependencies) { + delete projectManifest.dependencies[packageName]; + } + if (projectManifest.devDependencies) { + delete projectManifest.devDependencies[packageName]; + } + + await fs.writeFile( + join(this.context.root, 'package.json'), + JSON.stringify(projectManifest, null, 2) + '\n', + ); + } + + // 2. Silent install pass to prune files from node_modules and update the lockfile + await this.context.packageManager.install({ ignoreScripts: true }); + } catch (error) { + this.context.logger.warn( + `Failed to clean up temporary dependency '${packageName}': ` + + `${error instanceof Error ? error.message : error}`, + ); + } + } + private async installPackageTask( context: AddCommandTaskContext, task: AddCommandTaskWrapper, diff --git a/packages/angular/cli/src/commands/update/cli.ts b/packages/angular/cli/src/commands/update/cli.ts index de6d7f53fea0..62416b1c1ee7 100644 --- a/packages/angular/cli/src/commands/update/cli.ts +++ b/packages/angular/cli/src/commands/update/cli.ts @@ -256,6 +256,7 @@ export default class UpdateCommandModule extends CommandModule(); const packagesToUpdate = [...infoMap.entries()] .map(([name, info]) => { - let tag = options.next - ? info.npmPackageJson['dist-tags']['next'] - ? 'next' - : 'latest' - : 'latest'; - let version = info.npmPackageJson['dist-tags'][tag]; - let target = info.npmPackageJson.versions[version]; + const distTags = info.npmPackageJson['dist-tags'] ?? {}; + let tag = options.next ? (distTags['next'] ? 'next' : 'latest') : 'latest'; + let version = distTags[tag] ?? info.installed.version; + const versions = info.npmPackageJson.versions ?? {}; + let target = versions[version]; const versionDiff = semver.diff(info.installed.version, version); if ( @@ -426,13 +427,13 @@ function _usageMessage( installedMajorVersion < toInstallMajorVersion - 1 ) { const nextMajorVersion = `${installedMajorVersion + 1}.`; - const nextMajorVersions = Object.keys(info.npmPackageJson.versions) + const nextMajorVersions = Object.keys(versions) .filter((v) => v.startsWith(nextMajorVersion)) .sort((a, b) => (a > b ? -1 : 1)); if (nextMajorVersions.length) { version = nextMajorVersions[0]; - target = info.npmPackageJson.versions[version]; + target = versions[version]; tag = ''; } } @@ -525,11 +526,147 @@ function _usageMessage( return; } +/** + * Resolves a semver range or npm dist-tag to a specific version based on the package's registry metadata. + * It prioritizes non-deprecated versions and handles fallback to deprecated versions if necessary. + * + * @private + */ +function resolvePackageVersion( + metadata: NpmRepositoryPackageJson, + range: string, + next = false, +): string | null { + // Check if range matches an npm dist-tag directly (e.g. "latest", "next") + const distTags = metadata['dist-tags'] ?? {}; + if (distTags[range]) { + return distTags[range]; + } + // If 'next' is requested (e.g. via the --next CLI flag) but the package doesn't publish + // a 'next' pre-release tag, fallback to 'latest'. + if (range === 'next') { + return distTags['latest'] ?? null; + } + + // Split deprecated and non-deprecated versions from registry metadata + const packageVersionsNonDeprecated: string[] = []; + const packageVersionsDeprecated: string[] = []; + for (const [v, { deprecated }] of Object.entries(metadata.versions ?? {})) { + if (deprecated) { + packageVersionsDeprecated.push(v); + } else { + packageVersionsNonDeprecated.push(v); + } + } + + // Find the highest satisfying version, prioritizing non-deprecated versions + return ( + semver.maxSatisfying(packageVersionsNonDeprecated, range, { + includePrerelease: next || undefined, + }) ?? + semver.maxSatisfying(packageVersionsDeprecated, range, { + includePrerelease: next || undefined, + }) + ); +} + +/** + * Checks if Yarn Plug'n'Play is active in the current workspace. + * + * @private + */ +function isPnpActive(workspaceRoot: string): boolean { + return ( + process.versions.pnp !== undefined || + existsSync(path.join(workspaceRoot, '.pnp.cjs')) || + existsSync(path.join(workspaceRoot, '.pnp.js')) + ); +} + +/** + * Resolves and reads the installed package.json manifest for a package. + * It checks the virtual schematic Tree first (vital for unit tests/mocks), + * and falls back to physical disk resolution using createRequire only if Yarn PnP is active. + * + * @private + */ +function getInstalledPackageJson( + tree: Tree, + packageName: string, + workspaceRoot: string, +): PackageManifest | null { + // First, check the virtual tree (critical for testing mocks) + const pkgJsonPath = `/node_modules/${packageName}/package.json`; + if (tree.exists(pkgJsonPath)) { + try { + return tree.readJson(pkgJsonPath) as PackageManifest; + } catch {} + } + + // In Yarn PnP, mock package trees are not written to node_modules in the virtual tree, + // so we resolve the manifest physically from Yarn's zip cache via createRequire. + // Note: This fallback resolution is strictly gated on Yarn PnP being active. Because schematics + // operate on a virtual file system (Tree), running disk lookups in non-PnP + // environments could cause tests to resolve dependencies from this monorepo's own node_modules + // instead of the simulated virtual file system. + if (isPnpActive(workspaceRoot)) { + try { + const workspaceRequire = createRequire(path.join(workspaceRoot, 'package.json')); + const manifestPath = workspaceRequire.resolve(`${packageName}/package.json`); + const content = readFileSync(manifestPath, 'utf8'); + + return JSON.parse(content) as PackageManifest; + } catch {} + } + + return null; +} + +function getInstalledVersion( + tree: Tree, + packageName: string, + workspaceRoot: string, +): string | null { + const pkgJson = getInstalledPackageJson(tree, packageName, workspaceRoot); + + return pkgJson?.version ?? null; +} + +function _buildLocalPackageInfo( + tree: Tree, + name: string, + allDependencies: ReadonlyMap, + workspaceRoot: string, + logger: logging.LoggerApi, +): PackageInfo { + const packageJsonRange = allDependencies.get(name); + if (!packageJsonRange) { + throw new SchematicsException(`Package ${JSON.stringify(name)} was not found in package.json.`); + } + + const localPkgJson = getInstalledPackageJson(tree, name, workspaceRoot); + if (!localPkgJson) { + throw new SchematicsException(`Package ${name} is not installed.`); + } + + return { + name, + npmPackageJson: {} as NpmRepositoryPackageJson, + installed: { + version: localPkgJson.version as VersionRange, + packageJson: localPkgJson, + updateMetadata: _getUpdateMetadata(localPkgJson, logger), + }, + packageJsonRange, + }; +} + function _buildPackageInfo( tree: Tree, packages: Map, allDependencies: ReadonlyMap, npmPackageJson: NpmRepositoryPackageJson, + workspaceRoot: string, logger: logging.LoggerApi, ): PackageInfo { const name = npmPackageJson.name; @@ -538,21 +675,13 @@ function _buildPackageInfo( throw new SchematicsException(`Package ${JSON.stringify(name)} was not found in package.json.`); } - // Find out the currently installed version. Either from the package.json or the node_modules/ - // TODO: figure out a way to read package-lock.json and/or yarn.lock. - const pkgJsonPath = `/node_modules/${name}/package.json`; - const pkgJsonExists = tree.exists(pkgJsonPath); - - let installedVersion: string | undefined | null; - if (pkgJsonExists) { - const { version } = tree.readJson(pkgJsonPath) as PackageManifest; - installedVersion = version; - } + const localPkgJson = getInstalledPackageJson(tree, name, workspaceRoot); + let installedVersion = localPkgJson?.version; const packageVersionsNonDeprecated: string[] = []; const packageVersionsDeprecated: string[] = []; - for (const [version, { deprecated }] of Object.entries(npmPackageJson.versions)) { + for (const [version, { deprecated }] of Object.entries(npmPackageJson.versions ?? {})) { if (deprecated) { packageVersionsDeprecated.push(version); } else { @@ -576,7 +705,8 @@ function _buildPackageInfo( ); } - const installedPackageJson = npmPackageJson.versions[installedVersion] || pkgJsonExists; + const versions = npmPackageJson.versions ?? {}; + const installedPackageJson = versions[installedVersion] || localPkgJson; if (!installedPackageJson) { throw new SchematicsException( `An unexpected error happened; package ${name} has no version ${installedVersion}.`, @@ -585,10 +715,11 @@ function _buildPackageInfo( let targetVersion: VersionRange | undefined = packages.get(name); if (targetVersion) { - if (npmPackageJson['dist-tags'][targetVersion]) { - targetVersion = npmPackageJson['dist-tags'][targetVersion] as VersionRange; + const distTags = npmPackageJson['dist-tags'] ?? {}; + if (distTags[targetVersion]) { + targetVersion = distTags[targetVersion] as VersionRange; } else if (targetVersion == 'next') { - targetVersion = npmPackageJson['dist-tags']['latest'] as VersionRange; + targetVersion = distTags['latest'] as VersionRange; } else { targetVersion = findSatisfyingVersion(targetVersion); } @@ -602,19 +733,18 @@ function _buildPackageInfo( const target: PackageVersionInfo | undefined = targetVersion ? { version: targetVersion, - packageJson: npmPackageJson.versions[targetVersion], - updateMetadata: _getUpdateMetadata(npmPackageJson.versions[targetVersion], logger), + packageJson: versions[targetVersion], + updateMetadata: _getUpdateMetadata(versions[targetVersion], logger), } : undefined; - // Check if there's an installed version. return { name, npmPackageJson, installed: { version: installedVersion as VersionRange, - packageJson: installedPackageJson, - updateMetadata: _getUpdateMetadata(installedPackageJson, logger), + packageJson: installedPackageJson as PackageManifest, + updateMetadata: _getUpdateMetadata(installedPackageJson as PackageManifest, logger), }, target, packageJsonRange, @@ -665,16 +795,34 @@ function _addPackageGroup( return; } - const info = _buildPackageInfo(tree, packages, allDependencies, npmPackageJson, logger); + const distTags = npmPackageJson['dist-tags'] ?? {}; + let version = maybePackage; + if (distTags[version]) { + version = distTags[version] as VersionRange; + } else if (version === 'next') { + version = distTags['latest'] as VersionRange; + } else { + const packageVersionsNonDeprecated: string[] = []; + const packageVersionsDeprecated: string[] = []; + const versions = npmPackageJson.versions ?? {}; + for (const [v, { deprecated }] of Object.entries(versions)) { + if (deprecated) { + packageVersionsDeprecated.push(v); + } else { + packageVersionsNonDeprecated.push(v); + } + } + version = + ((semver.maxSatisfying(packageVersionsNonDeprecated, version) ?? + semver.maxSatisfying(packageVersionsDeprecated, version)) as VersionRange | null) ?? + version; + } - const version = - (info.target && info.target.version) || - npmPackageJson['dist-tags'][maybePackage] || - maybePackage; - if (!npmPackageJson.versions[version]) { + const versions = npmPackageJson.versions ?? {}; + if (!versions[version]) { return; } - const ngUpdateMetadata = npmPackageJson.versions[version]['ng-update']; + const ngUpdateMetadata = versions[version]['ng-update']; if (!ngUpdateMetadata) { return; } @@ -721,51 +869,64 @@ function _addPackageGroup( * be ignored by the --force flag). * @private */ -function _addPeerDependencies( +async function _addPeerDependencies( tree: Tree, packages: Map, allDependencies: ReadonlyMap, npmPackageJson: NpmRepositoryPackageJson, - npmPackageJsonMap: Map, + workspaceRoot: string, + fetchMetadata: (name: string) => Promise, logger: logging.LoggerApi, -): void { +): Promise { const maybePackage = packages.get(npmPackageJson.name); if (!maybePackage) { return; } - - const info = _buildPackageInfo(tree, packages, allDependencies, npmPackageJson, logger); - - const version = - (info.target && info.target.version) || - npmPackageJson['dist-tags'][maybePackage] || - maybePackage; - if (!npmPackageJson.versions[version]) { + const distTags = npmPackageJson['dist-tags'] ?? {}; + const version = distTags[maybePackage] || maybePackage; + const versions = npmPackageJson.versions ?? {}; + const packageJson = versions[version]; + if (!packageJson) { return; } - const packageJson = npmPackageJson.versions[version]; - const error = false; - for (const [peer, range] of Object.entries(packageJson.peerDependencies || {})) { if (packages.has(peer)) { continue; } - const peerPackageJson = npmPackageJsonMap.get(peer); - if (peerPackageJson) { - const peerInfo = _buildPackageInfo(tree, packages, allDependencies, peerPackageJson, logger); - if (semver.satisfies(peerInfo.installed.version, range)) { + const installedVersion = getInstalledVersion(tree, peer, workspaceRoot); + if (installedVersion) { + if (semver.satisfies(installedVersion, range)) { continue; } + } else { + const packageJsonRange = allDependencies.get(peer); + if (packageJsonRange) { + const peerMetadata = await fetchMetadata(peer); + if (peerMetadata) { + const packageVersionsNonDeprecated: string[] = []; + const packageVersionsDeprecated: string[] = []; + for (const [v, { deprecated }] of Object.entries(peerMetadata.versions ?? {})) { + if (deprecated) { + packageVersionsDeprecated.push(v); + } else { + packageVersionsNonDeprecated.push(v); + } + } + const resolvedInstalledVersion = + semver.maxSatisfying(packageVersionsNonDeprecated, packageJsonRange) ?? + semver.maxSatisfying(packageVersionsDeprecated, packageJsonRange); + + if (resolvedInstalledVersion && semver.satisfies(resolvedInstalledVersion, range)) { + continue; + } + } + } } packages.set(peer, range as VersionRange); } - - if (error) { - throw new SchematicsException('An error occured, see above.'); - } } function _getAllDependencies(tree: Tree): Array { @@ -846,67 +1007,109 @@ export default function (options: UpdateSchema): Rule { ); const packages = _buildPackageList(options, npmDeps, logger); - // Grab all package.json from the npm repository. This requires a lot of HTTP calls so we - // try to parallelize as many as possible. - const allPackageMetadata = await Promise.all( - Array.from(npmDeps.keys()).map((depName) => - getNpmPackageJson(depName, logger, { + const workspaceRoot = options.workspaceRoot ?? process.cwd(); + const npmPackageJsonMap = new Map(); + + const getOrFetchPackageMetadata = async ( + packageName: string, + ): Promise => { + let metadata = npmPackageJsonMap.get(packageName); + if (!metadata) { + const raw = await getNpmPackageJson(packageName, logger, { registry: options.registry, usingYarn, verbose: options.verbose, - }), - ), - ); - - // Build a map of all dependencies and their packageJson. - const npmPackageJsonMap = allPackageMetadata.reduce((acc, npmPackageJson) => { - // If the package was not found on the registry. It could be private, so we will just - // ignore. If the package was part of the list, we will error out, but will simply ignore - // if it's either not requested (so just part of package.json. silently). - if (!npmPackageJson.name) { - if (npmPackageJson.requestedName && packages.has(npmPackageJson.requestedName)) { - throw new SchematicsException( - `Package ${JSON.stringify(npmPackageJson.requestedName)} was not found on the ` + - 'registry. Cannot continue as this may be an error.', - ); + }); + if (raw.name) { + metadata = raw as NpmRepositoryPackageJson; + npmPackageJsonMap.set(packageName, metadata); } - } else { - // If a name is present, it is assumed to be fully populated - acc.set(npmPackageJson.name, npmPackageJson as NpmRepositoryPackageJson); } - return acc; - }, new Map()); - - // Augment the command line package list with packageGroups and forward peer dependencies. - // Each added package may uncover new package groups and peer dependencies, so we must - // repeat this process until the package list stabilizes. - let lastPackagesSize; - do { - lastPackagesSize = packages.size; + return metadata ?? null; + }; - let lastGroupSize; + if (packages.size === 0) { + // User ran just `ng update` to see the outdated package list. + // We must fetch metadata for all npm dependencies to generate the usage message. + await Promise.all( + Array.from(npmDeps.keys()).map(async (depName) => { + await getOrFetchPackageMetadata(depName); + }), + ); + } else { + // User requested updates. We resolve dependencies lazily. + let lastPackagesSize; do { - lastGroupSize = packages.size; - npmPackageJsonMap.forEach((npmPackageJson) => { - _addPackageGroup(tree, packages, npmDeps, npmPackageJson, logger); - }); - } while (packages.size > lastGroupSize); - - // This is done in seperate loop to ensure that package groups are added before peer dependencies. - npmPackageJsonMap.forEach((npmPackageJson) => { - _addPeerDependencies(tree, packages, npmDeps, npmPackageJson, npmPackageJsonMap, logger); - }); - } while (packages.size > lastPackagesSize); + lastPackagesSize = packages.size; + + let lastGroupSize; + do { + lastGroupSize = packages.size; + for (const name of Array.from(packages.keys())) { + const metadata = await getOrFetchPackageMetadata(name); + const spec = packages.get(name); + if (metadata && spec) { + const resolvedVersion = resolvePackageVersion(metadata, spec, !!options.next); + if (resolvedVersion) { + packages.set(name, resolvedVersion as VersionRange); + } + _addPackageGroup(tree, packages, npmDeps, metadata, logger); + } + } + } while (packages.size > lastGroupSize); + + for (const name of Array.from(packages.keys())) { + const metadata = await getOrFetchPackageMetadata(name); + const spec = packages.get(name); + if (metadata && spec) { + const resolvedVersion = resolvePackageVersion(metadata, spec, !!options.next); + if (resolvedVersion) { + packages.set(name, resolvedVersion as VersionRange); + } + await _addPeerDependencies( + tree, + packages, + npmDeps, + metadata, + workspaceRoot, + getOrFetchPackageMetadata, + logger, + ); + } + } + } while (packages.size > lastPackagesSize); + } // Build the PackageInfo for each module. const packageInfoMap = new Map(); - npmPackageJsonMap.forEach((npmPackageJson) => { - packageInfoMap.set( - npmPackageJson.name, - _buildPackageInfo(tree, packages, npmDeps, npmPackageJson, logger), - ); - }); + for (const depName of npmDeps.keys()) { + const isUpdating = packages.has(depName); + const localPkgJson = getInstalledPackageJson(tree, depName, workspaceRoot); + + if (isUpdating || !localPkgJson) { + // If updating OR not installed locally, resolve via registry metadata + const metadata = await getOrFetchPackageMetadata(depName); + if (metadata) { + packageInfoMap.set( + depName, + _buildPackageInfo(tree, packages, npmDeps, metadata, workspaceRoot, logger), + ); + } else { + // Fallback if metadata could not be fetched + packageInfoMap.set( + depName, + _buildLocalPackageInfo(tree, depName, npmDeps, workspaceRoot, logger), + ); + } + } else { + // If not updating and installed locally, resolve purely locally + packageInfoMap.set( + depName, + _buildLocalPackageInfo(tree, depName, npmDeps, workspaceRoot, logger), + ); + } + } // Now that we have all the information, check the flags. if (packages.size > 0) { diff --git a/packages/angular/cli/src/commands/update/schematic/index_spec.ts b/packages/angular/cli/src/commands/update/schematic/index_spec.ts index 11b2a0b5855e..7e8ca436150d 100644 --- a/packages/angular/cli/src/commands/update/schematic/index_spec.ts +++ b/packages/angular/cli/src/commands/update/schematic/index_spec.ts @@ -387,5 +387,5 @@ describe('@schematics/update', () => { expect(dependencies['@angular/cdk']).toMatch(version20Regexp); expect(dependencies['@angular/common']).toMatch(version20Regexp); expect(dependencies['@angular/core']).toMatch(version20Regexp); - }); + }, 45000); }); diff --git a/packages/angular/cli/src/commands/update/schematic/schema.json b/packages/angular/cli/src/commands/update/schematic/schema.json index 4768df46f2d5..63bf2df87813 100644 --- a/packages/angular/cli/src/commands/update/schematic/schema.json +++ b/packages/angular/cli/src/commands/update/schematic/schema.json @@ -58,6 +58,10 @@ "type": "string", "default": "npm", "enum": ["npm", "yarn", "pnpm", "bun"] + }, + "workspaceRoot": { + "description": "The path to the workspace root directory.", + "type": "string" } }, "required": [] diff --git a/packages/angular/cli/src/commands/update/utilities/migration.ts b/packages/angular/cli/src/commands/update/utilities/migration.ts index f52726de5523..21331364bc2f 100644 --- a/packages/angular/cli/src/commands/update/utilities/migration.ts +++ b/packages/angular/cli/src/commands/update/utilities/migration.ts @@ -153,9 +153,7 @@ export async function executeMigrations( if (requiredMigrations.length) { logger.info(colors.cyan(`** Executing migrations of package '${packageName}' **\n`)); - requiredMigrations.sort( - (a, b) => semver.compare(a.version, b.version) || a.name.localeCompare(b.name), - ); + requiredMigrations.sort(compareMigrations); const result = await executePackageMigrations( workflow, @@ -174,9 +172,7 @@ export async function executeMigrations( if (optionalMigrations.length) { logger.info(colors.magenta(`** Optional migrations of package '${packageName}' **\n`)); - optionalMigrations.sort( - (a, b) => semver.compare(a.version, b.version) || a.name.localeCompare(b.name), - ); + optionalMigrations.sort(compareMigrations); const migrationsToRun = await getOptionalMigrationsToRun( logger, @@ -372,3 +368,10 @@ function getMigrationTitleAndDescription(migration: MigrationSchematicDescriptio : undefined, }; } + +function compareMigrations( + a: MigrationSchematicDescriptionWithVersion, + b: MigrationSchematicDescriptionWithVersion, +): number { + return semver.compare(a.version, b.version); +} diff --git a/packages/angular/cli/src/package-managers/package-manager.ts b/packages/angular/cli/src/package-managers/package-manager.ts index 33b8b07d48e3..46adbd118b9b 100644 --- a/packages/angular/cli/src/package-managers/package-manager.ts +++ b/packages/angular/cli/src/package-managers/package-manager.ts @@ -647,6 +647,25 @@ export class PackageManager { // Writing an empty package.json file beforehand prevents this. await this.host.writeFile(join(workingDirectory, 'package.json'), '{}'); + // To prevent pnpm from traversing up the directory tree and modifying the project's workspace lockfile, + // copy the project's `pnpm-workspace.yaml` (excluding monorepo local overrides/packages) + // to the temporary directory if it exists, or write an empty one to act as a workspace boundary. + if (this.name === 'pnpm') { + try { + const workspaceConfigPath = join(this.cwd, 'pnpm-workspace.yaml'); + const content = await this.host.readFile(workspaceConfigPath); + await this.host.writeFile( + join(workingDirectory, 'pnpm-workspace.yaml'), + sanitizePnpmWorkspace(content), + ); + } catch { + await this.host.writeFile( + join(workingDirectory, 'pnpm-workspace.yaml'), + "packages:\n - '.'\n", + ); + } + } + // Copy configuration files if the package manager requires it (e.g., bun). if (this.descriptor.copyConfigFromProject) { for (const configFile of this.descriptor.configFiles) { @@ -675,3 +694,61 @@ export class PackageManager { return { workingDirectory, cleanup }; } } + +/** + * Sanitizes a `pnpm-workspace.yaml` file content to be safely used inside + * a temporary installation directory. + * + * This function removes monorepo-specific settings that would fail or cause + * unintended behaviors in a standalone, temporary project environment: + * 1. Removes the `overrides:` block, as it may contain `workspace:` protocol + * resolutions which cannot be resolved in a standalone folder. + * 2. Rewrites the `packages:` block to include only the current directory (`'.'`), + * isolating the temporary installation from other projects in the monorepo. + * + * All other settings (such as `minimumReleaseAge`, package extensions, etc.) + * are preserved intact. + * + * @param content The original `pnpm-workspace.yaml` content. + * @returns The sanitized YAML content. + */ +function sanitizePnpmWorkspace(content: string): string { + const lines = content.split(/\r?\n/); + const result: string[] = []; + let inBlockToRemove = false; + let blockIndent = 0; + + for (const line of lines) { + const trimmed = line.trim(); + if (!trimmed) { + result.push(line); + continue; + } + + // Determine the current line's indentation level. + const indent = line.length - line.trimStart().length; + + // If we are currently parsing a block to remove, skip any lines with larger indentation. + if (inBlockToRemove) { + if (indent > blockIndent) { + continue; + } + inBlockToRemove = false; + } + + // Identify blocks we want to remove or customize (e.g. 'overrides' or 'packages'). + if (trimmed.startsWith('overrides:') || trimmed.startsWith('packages:')) { + inBlockToRemove = true; + blockIndent = indent; + if (trimmed.startsWith('packages:')) { + // Replace packages list to restrict it strictly to the current standalone folder. + result.push(line.replace(/packages:.*/, "packages:\n - '.'")); + } + continue; + } + + result.push(line); + } + + return result.join('\n'); +} diff --git a/packages/angular/cli/src/package-managers/package-manager_spec.ts b/packages/angular/cli/src/package-managers/package-manager_spec.ts index 8d439d9b3b75..176b604eeca6 100644 --- a/packages/angular/cli/src/package-managers/package-manager_spec.ts +++ b/packages/angular/cli/src/package-managers/package-manager_spec.ts @@ -86,6 +86,115 @@ describe('PackageManager', () => { }); }); + describe('acquireTempPackage', () => { + it('should copy and sanitize pnpm-workspace.yaml when package manager is pnpm and workspace file exists', async () => { + const pnpmDescriptor = SUPPORTED_PACKAGE_MANAGERS['pnpm']; + const testHost = new MockHost({ '/tmp/project/node_modules': true }); + const pm = new PackageManager(testHost, '/tmp/project', pnpmDescriptor); + + const createTempDirectorySpy = spyOn(testHost, 'createTempDirectory').and.resolveTo( + '/tmp/project/node_modules/angular-cli-tmp-packages-abc', + ); + const mockWorkspaceContent = [ + 'packages:', + ' - .', + ' - packages/*', + 'minimumReleaseAge: 1440', + 'minimumReleaseAgeExclude:', + " - '@angular/*'", + 'overrides:', + " '@angular/build': workspace:*", + 'packageExtensions:', + ' vitest:', + ' peerDependencies:', + " '@vitest/coverage-v8': '*'", + ].join('\n'); + const readFileSpy = spyOn(testHost, 'readFile').and.resolveTo(mockWorkspaceContent); + const writeFileSpy = spyOn(testHost, 'writeFile').and.resolveTo(); + spyOn(testHost, 'runCommand').and.resolveTo({ stdout: '', stderr: '' }); + + const { workingDirectory } = await pm.acquireTempPackage('foo@1.0.0'); + + expect(workingDirectory).toBe('/tmp/project/node_modules/angular-cli-tmp-packages-abc'); + expect(createTempDirectorySpy).toHaveBeenCalledWith('/tmp/project/node_modules'); + expect(readFileSpy).toHaveBeenCalledWith('/tmp/project/pnpm-workspace.yaml'); + + const expectedSanitizedContent = [ + 'packages:', + " - '.'", + 'minimumReleaseAge: 1440', + 'minimumReleaseAgeExclude:', + " - '@angular/*'", + 'packageExtensions:', + ' vitest:', + ' peerDependencies:', + " '@vitest/coverage-v8': '*'", + ].join('\n'); + expect(writeFileSpy).toHaveBeenCalledWith( + '/tmp/project/node_modules/angular-cli-tmp-packages-abc/pnpm-workspace.yaml', + expectedSanitizedContent, + ); + expect(writeFileSpy).toHaveBeenCalledWith( + '/tmp/project/node_modules/angular-cli-tmp-packages-abc/package.json', + '{}', + ); + }); + + it('should write empty pnpm-workspace.yaml as fallback when package manager is pnpm and workspace file does not exist', async () => { + const pnpmDescriptor = SUPPORTED_PACKAGE_MANAGERS['pnpm']; + const testHost = new MockHost({ '/tmp/project/node_modules': true }); + const pm = new PackageManager(testHost, '/tmp/project', pnpmDescriptor); + + const createTempDirectorySpy = spyOn(testHost, 'createTempDirectory').and.resolveTo( + '/tmp/project/node_modules/angular-cli-tmp-packages-abc', + ); + const readFileSpy = spyOn(testHost, 'readFile').and.throwError( + new Error('ENOENT: no such file or directory'), + ); + const writeFileSpy = spyOn(testHost, 'writeFile').and.resolveTo(); + spyOn(testHost, 'runCommand').and.resolveTo({ stdout: '', stderr: '' }); + + const { workingDirectory } = await pm.acquireTempPackage('foo@1.0.0'); + + expect(workingDirectory).toBe('/tmp/project/node_modules/angular-cli-tmp-packages-abc'); + expect(createTempDirectorySpy).toHaveBeenCalledWith('/tmp/project/node_modules'); + expect(readFileSpy).toHaveBeenCalledWith('/tmp/project/pnpm-workspace.yaml'); + expect(writeFileSpy).toHaveBeenCalledWith( + '/tmp/project/node_modules/angular-cli-tmp-packages-abc/package.json', + '{}', + ); + expect(writeFileSpy).toHaveBeenCalledWith( + '/tmp/project/node_modules/angular-cli-tmp-packages-abc/pnpm-workspace.yaml', + "packages:\n - '.'\n", + ); + }); + + it('should NOT write pnpm-workspace.yaml when package manager is npm', async () => { + const npmDescriptor = SUPPORTED_PACKAGE_MANAGERS['npm']; + const testHost = new MockHost({ '/tmp/project/node_modules': true }); + const pm = new PackageManager(testHost, '/tmp/project', npmDescriptor); + + const createTempDirectorySpy = spyOn(testHost, 'createTempDirectory').and.resolveTo( + '/tmp/project/node_modules/angular-cli-tmp-packages-abc', + ); + const writeFileSpy = spyOn(testHost, 'writeFile').and.resolveTo(); + spyOn(testHost, 'runCommand').and.resolveTo({ stdout: '', stderr: '' }); + + const { workingDirectory } = await pm.acquireTempPackage('foo@1.0.0'); + + expect(workingDirectory).toBe('/tmp/project/node_modules/angular-cli-tmp-packages-abc'); + expect(createTempDirectorySpy).toHaveBeenCalledWith('/tmp/project/node_modules'); + expect(writeFileSpy).toHaveBeenCalledWith( + '/tmp/project/node_modules/angular-cli-tmp-packages-abc/package.json', + '{}', + ); + expect(writeFileSpy).not.toHaveBeenCalledWith( + '/tmp/project/node_modules/angular-cli-tmp-packages-abc/pnpm-workspace.yaml', + '', + ); + }); + }); + describe('initializationError', () => { it('should throw initializationError when running commands', async () => { const error = new Error('Not installed'); diff --git a/packages/angular/cli/src/package-managers/testing/mock-host.ts b/packages/angular/cli/src/package-managers/testing/mock-host.ts index 46e71be3cf60..9051cfae3b04 100644 --- a/packages/angular/cli/src/package-managers/testing/mock-host.ts +++ b/packages/angular/cli/src/package-managers/testing/mock-host.ts @@ -51,27 +51,36 @@ export class MockHost implements Host { } as Stats); } - runCommand(): Promise<{ stdout: string; stderr: string }> { + runCommand( + command: string, + args: readonly string[], + options?: { + timeout?: number; + stdio?: 'pipe' | 'ignore'; + cwd?: string; + env?: Record; + }, + ): Promise<{ stdout: string; stderr: string }> { throw new Error('Method not implemented.'); } - createTempDirectory(): Promise { + createTempDirectory(baseDir?: string): Promise { throw new Error('Method not implemented.'); } - deleteDirectory(): Promise { + deleteDirectory(path: string): Promise { throw new Error('Method not implemented.'); } - writeFile(): Promise { + writeFile(path: string, content: string): Promise { throw new Error('Method not implemented.'); } - readFile(): Promise { + readFile(path: string): Promise { throw new Error('Method not implemented.'); } - copyFile(): Promise { + copyFile(src: string, dest: string): Promise { throw new Error('Method not implemented.'); } } diff --git a/packages/angular/cli/src/utilities/package-metadata.ts b/packages/angular/cli/src/utilities/package-metadata.ts index fd31000f989a..05a739e898ae 100644 --- a/packages/angular/cli/src/utilities/package-metadata.ts +++ b/packages/angular/cli/src/utilities/package-metadata.ts @@ -52,9 +52,7 @@ export interface PackageManifest extends Manifest, NgPackageManifestProperties { peerDependenciesMeta?: Record; } -interface PackageManagerOptions extends Record { - forceAuth?: Record; -} +type PackageManagerOptions = Record; let npmrc: PackageManagerOptions; const npmPackageJsonCache = new Map>>(); @@ -175,19 +173,6 @@ function normalizeOptions( } switch (key) { - // Unless auth options are scope with the registry url it appears that npm-registry-fetch ignores them, - // even though they are documented. - // https://github.com/npm/npm-registry-fetch/blob/8954f61d8d703e5eb7f3d93c9b40488f8b1b62ac/README.md - // https://github.com/npm/npm-registry-fetch/blob/8954f61d8d703e5eb7f3d93c9b40488f8b1b62ac/auth.js#L45-L91 - case '_authToken': - case 'token': - case 'username': - case 'password': - case '_auth': - case 'auth': - options['forceAuth'] ??= {}; - options['forceAuth'][key] = substitutedValue; - break; case 'noproxy': case 'no-proxy': options['noProxy'] = substitutedValue; diff --git a/packages/schematics/angular/migrations/migrate-karma-to-vitest/karma-config-analyzer.ts b/packages/schematics/angular/migrations/migrate-karma-to-vitest/karma-config-analyzer.ts index d39e1a16bab6..8a1c49c58f61 100644 --- a/packages/schematics/angular/migrations/migrate-karma-to-vitest/karma-config-analyzer.ts +++ b/packages/schematics/angular/migrations/migrate-karma-to-vitest/karma-config-analyzer.ts @@ -142,7 +142,7 @@ export function analyzeKarmaConfig(content: string): KarmaConfigAnalysis { case ts.SyntaxKind.ArrayLiteralExpression: return (node as ts.ArrayLiteralExpression).elements.map(extractValue); case ts.SyntaxKind.ObjectLiteralExpression: { - const obj: { [key: string]: KarmaConfigValue } = {}; + const obj: { [key: string]: KarmaConfigValue } = Object.create(null); for (const prop of (node as ts.ObjectLiteralExpression).properties) { if (isSupportedPropertyAssignment(prop)) { // Recursively extract values for nested objects. diff --git a/packages/schematics/angular/migrations/migrate-karma-to-vitest/karma-config-comparer.ts b/packages/schematics/angular/migrations/migrate-karma-to-vitest/karma-config-comparer.ts index 0c11a7196f1c..f7bef0213b1f 100644 --- a/packages/schematics/angular/migrations/migrate-karma-to-vitest/karma-config-comparer.ts +++ b/packages/schematics/angular/migrations/migrate-karma-to-vitest/karma-config-comparer.ts @@ -46,11 +46,10 @@ export async function generateDefaultKarmaConfig( // TODO: Replace this with the actual schematic templating logic. template = template - .replace( - /<%= relativePathToWorkspaceRoot %>/g, + .replace(/<%= relativePathToWorkspaceRoot %>/g, () => path.normalize(relativePathToWorkspaceRoot).replace(/\\/g, '/'), ) - .replace(/<%= folderName %>/g, projectName); + .replace(/<%= folderName %>/g, () => projectName); const devkitPluginRegex = /<% if \(needDevkitPlugin\) { %>(.*?)<% } %>/gs; const replacement = needDevkitPlugin ? '$1' : ''; diff --git a/packages/schematics/angular/migrations/migrate-karma-to-vitest/migration.ts b/packages/schematics/angular/migrations/migrate-karma-to-vitest/migration.ts index 7d2306428b32..fc5b11fb5eb0 100644 --- a/packages/schematics/angular/migrations/migrate-karma-to-vitest/migration.ts +++ b/packages/schematics/angular/migrations/migrate-karma-to-vitest/migration.ts @@ -32,6 +32,7 @@ async function processTestTargetOptions( let needsIstanbul = false; for (const [configName, options] of allTargetOptions(testTarget, false)) { const configKey = configName || ''; + if (!customBuildOptions[configKey]) { // Match Karma behavior where AOT was disabled by default customBuildOptions[configKey] = { @@ -276,7 +277,10 @@ function updateProjects(tree: Tree, context: SchematicContext): Rule { tsConfigsToUpdate.add(join(project.root, 'tsconfig.spec.json')); // Store custom build options to move to a new build configuration if needed - const customBuildOptions: Record> = {}; + const customBuildOptions: Record< + string, + Record + > = Object.create(null); const projectCoverageInfo = await processTestTargetOptions( testTarget, diff --git a/packages/schematics/angular/refactor/jasmine-vitest/index.ts b/packages/schematics/angular/refactor/jasmine-vitest/index.ts index 493bb0eb1800..e163a88c6207 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/index.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/index.ts @@ -121,7 +121,7 @@ export default function (options: Schema): Rule { const content = tree.readText(file); const newContent = transformJasmineToVitest(file, content, reporter, { addImports: !!options.addImports, - browserMode: !!options.browerMode, + browserMode: !!options.browserMode, fakeAsync: !!options.fakeAsync, }); diff --git a/packages/schematics/angular/refactor/jasmine-vitest/index_spec.ts b/packages/schematics/angular/refactor/jasmine-vitest/index_spec.ts index a1abb7562ee8..2581d8bbacc9 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/index_spec.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/index_spec.ts @@ -238,4 +238,46 @@ describe('Jasmine to Vitest Schematic', () => { expect(logs).toContain('- 1 TODO(s) added for manual review:'); expect(logs).toContain(' - 1x spyOnAllFunctions'); }); + + it('should not transform toHaveClass when browserMode is true', async () => { + const specFilePath = 'projects/bar/src/app/app.spec.ts'; + const content = ` + describe('AppComponent', () => { + it('should check class', () => { + expect(element).toHaveClass('active'); + }); + }); + `; + appTree.overwrite(specFilePath, content); + + const tree = await schematicRunner.runSchematic( + 'refactor-jasmine-vitest', + { project: 'bar', browserMode: true }, + appTree, + ); + + const result = tree.readContent(specFilePath); + expect(result).toContain("expect(element).toHaveClass('active');"); + }); + + it('should transform toHaveClass when browserMode is false', async () => { + const specFilePath = 'projects/bar/src/app/app.spec.ts'; + const content = ` + describe('AppComponent', () => { + it('should check class', () => { + expect(element).toHaveClass('active'); + }); + }); + `; + appTree.overwrite(specFilePath, content); + + const tree = await schematicRunner.runSchematic( + 'refactor-jasmine-vitest', + { project: 'bar', browserMode: false }, + appTree, + ); + + const result = tree.readContent(specFilePath); + expect(result).toContain("expect(element.classList.contains('active')).toBe(true);"); + }); }); diff --git a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-lifecycle.ts b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-lifecycle.ts index 78ddd1e99316..eb58a7f9d5b9 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-lifecycle.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-lifecycle.ts @@ -15,7 +15,7 @@ import ts from 'typescript'; import { createPropertyAccess } from '../utils/ast-helpers'; -import { addTodoComment } from '../utils/comment-helpers'; +import { addCommentedNodeText, addTodoComment } from '../utils/comment-helpers'; import { RefactorContext } from '../utils/refactor-context'; const FOCUSED_SKIPPED_RENAMES = new Map([ @@ -77,7 +77,6 @@ export function transformPending( ) { hasPending = true; const replacement = ts.factory.createEmptyStatement(); - const originalText = bodyNode.getFullText().trim(); reporter.reportTransformation( sourceFile, @@ -87,12 +86,7 @@ export function transformPending( const category = 'pending'; reporter.recordTodo(category, sourceFile, bodyNode); addTodoComment(replacement, category); - ts.addSyntheticLeadingComment( - replacement, - ts.SyntaxKind.SingleLineCommentTrivia, - ` ${originalText}`, - true, - ); + addCommentedNodeText(replacement, bodyNode); return replacement; } diff --git a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-matcher.ts b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-matcher.ts index c1e669b144ef..1e0a87dc80f2 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-matcher.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-matcher.ts @@ -21,7 +21,7 @@ import { createPropertyAccess, } from '../utils/ast-helpers'; import { getJasmineMethodName, isJasmineCallExpression } from '../utils/ast-validation'; -import { addTodoComment } from '../utils/comment-helpers'; +import { addCommentedNodeText, addTodoComment } from '../utils/comment-helpers'; import { RefactorContext } from '../utils/refactor-context'; const SUGAR_MATCHER_CHANGES = new Map([ @@ -607,18 +607,12 @@ export function transformExpectNothing( // The statement is `expect().nothing()`, which can be removed. const replacement = ts.factory.createEmptyStatement(); - const originalText = node.getFullText().trim(); reporter.reportTransformation(sourceFile, node, 'Removed `expect().nothing()` statement.'); const category = 'expect-nothing'; reporter.recordTodo(category, sourceFile, node); addTodoComment(replacement, category); - ts.addSyntheticLeadingComment( - replacement, - ts.SyntaxKind.SingleLineCommentTrivia, - ` ${originalText}`, - true, - ); + addCommentedNodeText(replacement, node); return replacement; } diff --git a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-misc.ts b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-misc.ts index 6832e36b9273..f71353cc9783 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-misc.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-misc.ts @@ -16,7 +16,7 @@ import ts from 'typescript'; import { addVitestValueImport } from '../utils/ast-helpers'; import { getJasmineMethodName, isJasmineCallExpression } from '../utils/ast-validation'; -import { addTodoComment } from '../utils/comment-helpers'; +import { addCommentedNodeText, addTodoComment } from '../utils/comment-helpers'; import { RefactorContext } from '../utils/refactor-context'; import { createViCallExpression } from '../utils/refactor-helpers'; import { TodoCategory } from '../utils/todo-notes'; @@ -143,7 +143,6 @@ export function transformJasmineMembers(node: ts.Node, refactorCtx: RefactorCont case 'MAX_PRETTY_PRINT_DEPTH': case 'MAX_PRETTY_PRINT_CHARS': { const replacement = ts.factory.createEmptyStatement(); - const originalText = node.getFullText().trim(); reporter.reportTransformation( sourceFile, @@ -153,12 +152,7 @@ export function transformJasmineMembers(node: ts.Node, refactorCtx: RefactorCont const category = 'unsupported-jasmine-member'; reporter.recordTodo(category, sourceFile, node); addTodoComment(replacement, category, { name: memberName }); - ts.addSyntheticLeadingComment( - replacement, - ts.SyntaxKind.SingleLineCommentTrivia, - ` ${originalText}`, - true, - ); + addCommentedNodeText(replacement, node); return replacement; } diff --git a/packages/schematics/angular/refactor/jasmine-vitest/utils/comment-helpers.ts b/packages/schematics/angular/refactor/jasmine-vitest/utils/comment-helpers.ts index 2ece945e2951..02a9255deb3a 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/utils/comment-helpers.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/utils/comment-helpers.ts @@ -70,3 +70,23 @@ export function addTodoComment( true, ); } + +/** + * Safely comments out the full text of a node line-by-line and attaches + * it to a target node. This prevents multi-line statements from breaking + * syntax when converted to single-line comments. + * @param targetNode The node to which the comments will be added. + * @param nodeToComment The original node whose text will be commented out. + */ +export function addCommentedNodeText(targetNode: ts.Node, nodeToComment: ts.Node): void { + const originalText = nodeToComment.getFullText().trim(); + const lines = originalText.split('\n'); + for (const line of lines) { + ts.addSyntheticLeadingComment( + targetNode, + ts.SyntaxKind.SingleLineCommentTrivia, + ` ${line.trim()}`, + true, + ); + } +} diff --git a/packages/schematics/angular/refactor/jasmine-vitest/utils/comment-helpers_spec.ts b/packages/schematics/angular/refactor/jasmine-vitest/utils/comment-helpers_spec.ts index ddfb1b8b7ad1..4f44b2664368 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/utils/comment-helpers_spec.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/utils/comment-helpers_spec.ts @@ -7,7 +7,7 @@ */ import ts from 'typescript'; -import { addTodoComment } from './comment-helpers'; +import { addCommentedNodeText, addTodoComment } from './comment-helpers'; describe('addTodoComment', () => { function createTestHarness(sourceText: string) { @@ -65,4 +65,19 @@ describe('addTodoComment', () => { expect(result.trim().startsWith('// TODO')).toBe(true); expect(result).toContain('const mySpy = jasmine.createSpy()'); }); + + describe('addCommentedNodeText', () => { + it('should comment out a multiline node line-by-line', () => { + const sourceText = `expect()\n .nothing();`; + const sourceFile = ts.createSourceFile('test.ts', sourceText, ts.ScriptTarget.Latest, true); + const statement = sourceFile.statements[0]; + const replacement = ts.factory.createEmptyStatement(); + const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed }); + + addCommentedNodeText(replacement, statement); + + const result = printer.printNode(ts.EmitHint.Unspecified, replacement, sourceFile); + expect(result).toContain('// expect()\n// .nothing();'); + }); + }); }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6b66e16d5762..a16b16320684 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,8 +29,8 @@ importers: specifier: 22.0.0 version: 22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2)) '@angular/cdk': - specifier: 22.0.0-rc.2 - version: 22.0.0-rc.2(@angular/common@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.0.0(@angular/animations@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) + specifier: 22.0.0 + version: 22.0.0(@angular/common@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.0.0(@angular/animations@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) '@angular/common': specifier: 22.0.0 version: 22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) @@ -47,11 +47,11 @@ importers: specifier: 22.0.0 version: 22.0.0(@angular/compiler-cli@22.0.0(@angular/compiler@22.0.0)(typescript@6.0.3))(@angular/compiler@22.0.0) '@angular/material': - specifier: 22.0.0-rc.2 - version: 22.0.0-rc.2(626d92b70d6fd1515002dfba4bbacd97) + specifier: 22.0.0 + version: 22.0.0(6eb83275f51d1d41f72333b1955c7306) '@angular/ng-dev': - specifier: https://github.com/angular/dev-infra-private-ng-dev-builds.git#a450a2420ca888116e6d4207b38819cd27b06179 - version: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/a450a2420ca888116e6d4207b38819cd27b06179(@modelcontextprotocol/sdk@1.29.0(zod@4.4.2)) + specifier: https://github.com/angular/dev-infra-private-ng-dev-builds.git#68eef04ac1e37b69e3e61d3e32802e0a6046d54c + version: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/68eef04ac1e37b69e3e61d3e32802e0a6046d54c(@modelcontextprotocol/sdk@1.29.0(zod@4.4.2)) '@angular/platform-browser': specifier: 22.0.0 version: 22.0.0(@angular/animations@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2)) @@ -90,7 +90,7 @@ importers: version: 6.0.0(rollup@4.60.2) '@rollup/plugin-commonjs': specifier: ^29.0.0 - version: 29.0.2(rollup@4.60.2) + version: 29.0.3(rollup@4.60.2) '@rollup/plugin-json': specifier: ^6.1.0 version: 6.1.0(rollup@4.60.2) @@ -144,7 +144,7 @@ importers: version: 4.17.24 '@types/node': specifier: ^22.12.0 - version: 22.19.19 + version: 22.19.20 '@types/npm-package-arg': specifier: ^6.1.0 version: 6.1.4 @@ -273,7 +273,7 @@ importers: version: 6.4.1(rollup@4.60.2)(typescript@6.0.3) rollup-plugin-sourcemaps2: specifier: 0.5.6 - version: 0.5.6(@types/node@22.19.19)(rollup@4.60.2) + version: 0.5.6(@types/node@22.19.20)(rollup@4.60.2) semver: specifier: 7.7.4 version: 7.7.4 @@ -333,7 +333,7 @@ importers: version: 7.8.2 vitest: specifier: 4.1.5 - version: 4.1.5(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(@vitest/coverage-v8@4.1.5)(jiti@2.7.0)(jsdom@29.1.1)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.3)(yaml@2.9.0) + version: 4.1.5(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(@vitest/coverage-v8@4.1.5)(jiti@2.7.0)(jsdom@29.1.1)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.4)(yaml@2.9.0) packages/angular/build: dependencies: @@ -357,7 +357,7 @@ importers: version: 6.0.12(@types/node@24.12.4) '@vitejs/plugin-basic-ssl': specifier: 2.3.0 - version: 2.3.0(vite@7.3.2(@types/node@24.12.4)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.3)(yaml@2.9.0)) + version: 2.3.0(vite@7.3.2(@types/node@24.12.4)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.4)(yaml@2.9.0)) beasties: specifier: 0.4.2 version: 0.4.2 @@ -408,7 +408,7 @@ importers: version: 0.2.16 vite: specifier: 7.3.2 - version: 7.3.2(@types/node@24.12.4)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.3)(yaml@2.9.0) + version: 7.3.2(@types/node@24.12.4)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.4)(yaml@2.9.0) watchpack: specifier: 2.5.1 version: 2.5.1 @@ -442,7 +442,7 @@ importers: version: 7.8.2 vitest: specifier: 4.1.5 - version: 4.1.5(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(@vitest/coverage-v8@4.1.5)(jiti@2.7.0)(jsdom@29.1.1)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.3)(yaml@2.9.0) + version: 4.1.5(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(@vitest/coverage-v8@4.1.5)(jiti@2.7.0)(jsdom@29.1.1)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.4)(yaml@2.9.0) optionalDependencies: lmdb: specifier: 3.5.4 @@ -941,12 +941,12 @@ packages: peerDependencies: '@angular/core': 22.0.0 - '@angular/cdk@22.0.0-rc.2': - resolution: {integrity: sha512-KiQInxX5WrPgsNjqqaD3/voRXNNsp0cuvH8VZerIeRUrOxsuqsyU8bUk6q6GWobL4LDj7afiqjDTEdwnq9KVww==} + '@angular/cdk@22.0.0': + resolution: {integrity: sha512-mahXlRD4V8Tj2NtttRNFfuTru5HmMgJt8ny/SJ/Bx1NCOymxLEqxREACNpuwMf/3q1XUe33/oh++mvJQ2JYkgw==} peerDependencies: - '@angular/common': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 - '@angular/core': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 - '@angular/platform-browser': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 + '@angular/common': ^22.0.0 || ^23.0.0 + '@angular/core': ^22.0.0 || ^23.0.0 + '@angular/platform-browser': ^22.0.0 || ^23.0.0 rxjs: ^6.5.3 || ^7.4.0 '@angular/common@22.0.0': @@ -1001,19 +1001,19 @@ packages: '@angular/compiler': 22.0.0 '@angular/compiler-cli': 22.0.0 - '@angular/material@22.0.0-rc.2': - resolution: {integrity: sha512-pHs8iMDjyX9o07B2qQqsQ1/n7WgonV2RVVJjxp4c9cralKDufizCpQSCgrkq9fnGu4Ijv7f8ShqHVXLGITMAPg==} + '@angular/material@22.0.0': + resolution: {integrity: sha512-sRxbEEgmaVqbwcT65PWfZV/cIpLsZ8vD+yc6rH83L83jDJWVABpqDWFg8Hl88iFMOts8iffml6GddvXhsNHAEQ==} peerDependencies: - '@angular/cdk': 22.0.0-rc.2 - '@angular/common': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 - '@angular/core': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 - '@angular/forms': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 - '@angular/platform-browser': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 + '@angular/cdk': 22.0.0 + '@angular/common': ^22.0.0 || ^23.0.0 + '@angular/core': ^22.0.0 || ^23.0.0 + '@angular/forms': ^22.0.0 || ^23.0.0 + '@angular/platform-browser': ^22.0.0 || ^23.0.0 rxjs: ^6.5.3 || ^7.4.0 - '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/a450a2420ca888116e6d4207b38819cd27b06179': - resolution: {gitHosted: true, integrity: sha512-yKQqLu4g+2WiIoXV4M7F0x94929zZESjhTj0kTrincYgJ6GrAzfzdeayD5D2ZVg6xUg6ubPEMDDVUwEMeB93Mw==, tarball: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/a450a2420ca888116e6d4207b38819cd27b06179} - version: 0.0.0-9ee8a680dd018d61d21588bb04cf40d49a9f5deb + '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/68eef04ac1e37b69e3e61d3e32802e0a6046d54c': + resolution: {gitHosted: true, integrity: sha512-T6Drp02fXuaD+9yiRcv4bXTKsMROEIuCATiKQSgcILd02lT9FoyqBzNHdNHzHEYNtOZeLhMn+hkhooTTAlcpPw==, tarball: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/68eef04ac1e37b69e3e61d3e32802e0a6046d54c} + version: 0.0.0-cef5e36af124e7442d7e2868be3f8c0bba496952 hasBin: true '@angular/platform-browser@22.0.0': @@ -1648,8 +1648,8 @@ packages: peerDependencies: '@csstools/css-tokenizer': ^4.0.0 - '@csstools/css-syntax-patches-for-csstree@1.1.4': - resolution: {integrity: sha512-wgsqt92b7C7tQhIdPNxj0n9zuUbQlvAuI1exyzeNrOKOi62SD7ren8zqszmpVREjAOqg8cD2FqYhQfAuKjk4sw==} + '@csstools/css-syntax-patches-for-csstree@1.1.5': + resolution: {integrity: sha512-oNjBvzLq2GPZtJphCjLqXow/cHySHSgtxvKZb7OqSZ/xHgw6NWNhfad+6AB9cLeVm6eA9d/qMll3JdEHjy6M+A==} peerDependencies: css-tree: ^3.2.1 peerDependenciesMeta: @@ -2037,8 +2037,8 @@ packages: resolution: {integrity: sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/plugin-kit@0.7.1': - resolution: {integrity: sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==} + '@eslint/plugin-kit@0.7.2': + resolution: {integrity: sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} '@exodus/bytes@1.15.1': @@ -2050,8 +2050,8 @@ packages: '@noble/hashes': optional: true - '@firebase/ai@2.12.0': - resolution: {integrity: sha512-b+OL4vdyiSLZL/7dLd67V55CjKJvU9MpNmwnday7eA6GG2+J4iwUEsEHgw0/jKY3A41FfkF0SrnYFvtKbQZ65A==} + '@firebase/ai@2.13.0': + resolution: {integrity: sha512-nJJDQKqjAcbkZdZGT/5WTVLrGZ+pYhWbwKC90nNzmvtoRTtnOJaNS34fhKSHQeB9SALgD2kxuWT5I4AkytdZ/Q==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app': 0.x @@ -2070,8 +2070,8 @@ packages: peerDependencies: '@firebase/app': 0.x - '@firebase/app-check-compat@0.4.3': - resolution: {integrity: sha512-L3AKIRTJxT9b7cDUH3OyV8gWTnmW3vYkwdzRsukWt4kbPBTct12xalnyvHDkm1lKkr+cQq/4uzBx1bOWsQ2ciw==} + '@firebase/app-check-compat@0.4.4': + resolution: {integrity: sha512-9iP0MvmaVagulNXmrca96U3tqNAI3j98wsC1z7rj62nnOTajlrHM//jjB9VoHqRw6/islMskp6RsKnM7vhLDqA==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app-compat': 0.x @@ -2082,25 +2082,25 @@ packages: '@firebase/app-check-types@0.5.4': resolution: {integrity: sha512-xV7JsIyzVr15aA7f3Pi0rB9gdBuVubs89FGA8VkRYA4g0l78poADgdfrScgf7NndSg9mm7cR7PJyY0+t22KaGw==} - '@firebase/app-check@0.11.3': - resolution: {integrity: sha512-aJ4DfubWfTO8/2vhEhIAizOoOmiycESTU32e+OUgbWcS/G3PA4Vxlr/9zaiN2wfUG2AptQ7DTvj00tyuFZP5Bg==} + '@firebase/app-check@0.11.4': + resolution: {integrity: sha512-G8EsbVJV9gSfoibx0dNoNOUrvr+PkL7J//+W/BST/oUassimkZeq9bjj3bKkB0pn4og5GMQ9qs7FefwP00kkgg==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app': 0.x - '@firebase/app-compat@0.5.12': - resolution: {integrity: sha512-Pe513OBerK/CIBxz4/za9atd5MsZtd6DzHz4cmqkvkrcDWhQChAoHBpZ3McuZNuSP8YZiKwfX/J1frR07l15/w==} + '@firebase/app-compat@0.5.13': + resolution: {integrity: sha512-pn3FvXwUR34kWPccDQfCKsNZcM2wD1OS+J1jeEgzM1ZNXoxR2NaF6e5DjDuRrnTwR6LN2XQQt0IqE6yKmgpCQg==} engines: {node: '>=20.0.0'} '@firebase/app-types@0.9.5': resolution: {integrity: sha512-YevqTjvo7Iujsa9Dwowmd6dSoElhzmD63ZSrq6bzjvQ6POjYgNjOFHLmNIgJs48eNO093NCERibuFnxbfOvU7A==} - '@firebase/app@0.14.12': - resolution: {integrity: sha512-FT+HoNp1NdaZ/N26hCwV3WbxS1m6gTn3p2QRBQ3KH7YqyCQqJx0iT7126RgVk68/Rq+9DeL/zCFnHZ0C4u1nLQ==} + '@firebase/app@0.14.13': + resolution: {integrity: sha512-H89Jeyp31+EZk9GPu6vaeL9mEmoXgM3nASB7UPBYYS/lqAks21mO1BU1dF8NbsVTL6tgGZkGUtiGJgxtDiwHkw==} engines: {node: '>=20.0.0'} - '@firebase/auth-compat@0.6.6': - resolution: {integrity: sha512-KDJ/GAf/rt7galOpn3DRb2buFfGkZCsHTryKjXDG0eeRnok4+2B4nnkMOMdjRnPkElmcJv2Ao0vEA6kp5m98PQ==} + '@firebase/auth-compat@0.6.7': + resolution: {integrity: sha512-XgKnOgY1Siq7gylAmLkYtHAlRxNeWEAspH+nO3gJZJnfHqoTHbr9UjJ3nHNFALYXV5CfpQlyPROyB2ztySBHBQ==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app-compat': 0.x @@ -2114,8 +2114,8 @@ packages: '@firebase/app-types': 0.x '@firebase/util': 1.x - '@firebase/auth@1.13.1': - resolution: {integrity: sha512-/1nkKY/MicI+I9WWcx6R4NKs77AaW9NQ0IwsFdUBomWrW0/cXEmopfM2dtLm2oI1qG6z6vom3CXZDHJIJXoMuw==} + '@firebase/auth@1.13.2': + resolution: {integrity: sha512-B4w0iS7MxRg28oIh2fJFTE6cM0lYdBrW19eHpc42jqEcloUjlYyVrpPqZvqA4+v9KFEVSKEs2SfWyta7hbzkJQ==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app': 0.x @@ -2128,8 +2128,8 @@ packages: resolution: {integrity: sha512-wFofIaa2879ogD/WvkjYXJxRmfnL0scen6ORgaC3na1FNOR9ASIUANQdhqQcmWu/h77/pVHY7ch5flewa5Bcew==} engines: {node: '>=20.0.0'} - '@firebase/data-connect@0.7.0': - resolution: {integrity: sha512-ar9sNOJh5poQCSMSVlnVE8eo8+usTD1POWDCv65omkKUvnFMcdXaQ7J/e7WGKqJzcEMgiezSX/TZiKHZkItMbQ==} + '@firebase/data-connect@0.7.1': + resolution: {integrity: sha512-2LbUU8mmSA63HknxQMmWHjpzuNLBKflvVwQc2tpoVKg0biWleNEJX031ELks0vzFs+dDjOUkCJR72RP6mQHFOg==} peerDependencies: '@firebase/app': 0.x @@ -2144,8 +2144,8 @@ packages: resolution: {integrity: sha512-XwWCa+E4TvNGpGwXrycLRNfdogADwFcvuhyow6wDWma9W54roaQIhe+4PM0KiLsIftBdSCGI7OKCXrdSRHbIhw==} engines: {node: '>=20.0.0'} - '@firebase/firestore-compat@0.4.9': - resolution: {integrity: sha512-NPtBuFr79BbIQJXFWhW4xFC6rBksK8/ewqCTYbbAYfZBDDx0/iHTUj4WpKi5D4d0Pn2Md/3T/e5V9379G5N/Zg==} + '@firebase/firestore-compat@0.4.10': + resolution: {integrity: sha512-yMP3FADDjikdrQv4YmvL4EkIny6Hw+N+a2O5T40rlHiniyMpRPxgYkKiFOvMZnsqKLqBVnKqCAElC0pa/IZtdw==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app-compat': 0.x @@ -2156,14 +2156,14 @@ packages: '@firebase/app-types': 0.x '@firebase/util': 1.x - '@firebase/firestore@4.14.1': - resolution: {integrity: sha512-PouS0NJZ3NYOZE/tPDvXa8VUeJ10Ll//7jIdFvMYdhQkd/P3O7nlqhyoTmY0h8Xa9hxg+H0j6gxUytJcoZ9YOg==} + '@firebase/firestore@4.15.0': + resolution: {integrity: sha512-Fj9osqYkz2Rqr7kW3/A8BRd8CyJ7yA5K8YjhihRdyJWbL+FsELVcR6DpoCplrp1IyU+xeGgTubo1UOySXpY+EA==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app': 0.x - '@firebase/functions-compat@0.4.4': - resolution: {integrity: sha512-Be+MwhseVf/eFAZwGrFJGok6S7cmsLrAPK8MgyM8LjM0MewTsx2n01WOOca9jio1UsCZOJ0aVyQobnINcdNuIQ==} + '@firebase/functions-compat@0.4.5': + resolution: {integrity: sha512-10qlUXGY25G5/1g9UihqksPp2po+ZqSE7LEizsrdUP7vrTmkysXxGSZCDyojSEp6mQe/ecRDdDDI+z4XRdb4wQ==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app-compat': 0.x @@ -2171,8 +2171,8 @@ packages: '@firebase/functions-types@0.6.4': resolution: {integrity: sha512-zV6kgqtduR4rUAdC/ilS7kmb93XD7bEZoJDlVBZqlOw2uGGGCNBQBuleww2rr0Ulr3L9o2TDjumEt68/l1f9DQ==} - '@firebase/functions@0.13.4': - resolution: {integrity: sha512-oB5rpm2Emxn2+IS1gRelAeT/5tSZMwM/KhqC5LnJsmTNnS1ZDhD7ZMZNgCI8vchTW6PbaXIwEnpUryGuIQsNbg==} + '@firebase/functions@0.13.5': + resolution: {integrity: sha512-bWCx713f4kE/uFV7gdFOLBS7lDoiZj48MRkbAqe35gkXcCeWF4QjRNO07Jhmve7EJIoQOBczL29y2r8VRuN1kw==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app': 0.x @@ -2196,16 +2196,16 @@ packages: resolution: {integrity: sha512-vZKLsqE1ABOy8OjQiE7cUTFn4gvaqlk88yp8N94Pk/sDpq61YqZGqmVFZTvOyflTwuYFcWirBdYGoJgbDaXKYQ==} engines: {node: '>=20.0.0'} - '@firebase/messaging-compat@0.2.26': - resolution: {integrity: sha512-fn0XvWOfK4tsDLSipwJUW9Cp6ahWA6z+iJHxZ0pHp9MzMSUNQx85yuxZAuI7gkGXfqs7+DqEDHyyS7jDGswrmQ==} + '@firebase/messaging-compat@0.2.27': + resolution: {integrity: sha512-JNOiu1PPgdHzEPEtoFiNxQuu0x9bm4bfETSQCpGfcTlgWkhlSK7uh7nlsjC10TQLUNgYetLmuutaYTh8aeYLVA==} peerDependencies: '@firebase/app-compat': 0.x - '@firebase/messaging-interop-types@0.2.4': - resolution: {integrity: sha512-wrzITQq+xw5LtygX7O0fu43/k9ABQ4x5H9/sR5m1SbNnhIRI5xd3+raSNJaJkYC4BUhM9A4ZNSnyR2sjhxnb2Q==} + '@firebase/messaging-interop-types@0.2.5': + resolution: {integrity: sha512-tUEKnaAP2Y/MNIqgnriPpV6e5l13Vs/+p2yrd6NGlncPJT9O3a8muYZtdnWe+IJ4fgKLHJVC79n/asxk/N5Msw==} - '@firebase/messaging@0.12.26': - resolution: {integrity: sha512-lHVTO9uLofymHVWkYeUtMddIPcmJvSzVbHRB88W6XKfxbcKF+p3QrfqKhDxremSB4NQjUla1Gwn7d9umSMmt/w==} + '@firebase/messaging@0.13.0': + resolution: {integrity: sha512-GZoo0uGRvEbszo83xcgbjJp4FpkmBEr4l8Z4hi8gl+P1Spn/MTK3HapanMzSX4yUHuTEiF5hasWRxOaz+o5sxQ==} peerDependencies: '@firebase/app': 0.x @@ -2222,16 +2222,16 @@ packages: peerDependencies: '@firebase/app': 0.x - '@firebase/remote-config-compat@0.2.24': - resolution: {integrity: sha512-EWZTt6fJ7YmPHodQNsSxAIDZY2x8P5kRPvXAc5CmzzBm+NyPFhODbfDsNllDXDL8jlzp50bVWjDY+BXepZS9Mg==} + '@firebase/remote-config-compat@0.2.25': + resolution: {integrity: sha512-FnA5S4IxFJAAFrCnYzWlO0FCaizlYdqhe42ygFMA+wE/mUP+w36iXzHyKj1OO1A+2gyMFjeRHyg8HhkJ6c5vRA==} peerDependencies: '@firebase/app-compat': 0.x '@firebase/remote-config-types@0.5.1': resolution: {integrity: sha512-cX/1LT6KQwkXzck2eSzeKnuvXZCyr8qaPpDcikoJs7jmI+oBOXixpDLeDtWj1U6GNMkIoXrEDNoyT2Ypcyp5/A==} - '@firebase/remote-config@0.8.3': - resolution: {integrity: sha512-ggGKAaLy9YNOvpFoQZgm5p5SiFw3ZFtwti08dojnBQmQicpThTxvG5xZMSpCTYMj2o3gM/yK9CVd2w+kZub8YA==} + '@firebase/remote-config@0.8.4': + resolution: {integrity: sha512-lslywR5lGvHWTu4z/MPoYs3UwS3CKdeY+ELXY87087VsOpBpkD+9Orra23tA9GW683arPTDOM3CM6eKmtiOO3g==} peerDependencies: '@firebase/app': 0.x @@ -2267,36 +2267,36 @@ packages: '@glideapps/ts-necessities@2.2.3': resolution: {integrity: sha512-gXi0awOZLHk3TbW55GZLCPP6O+y/b5X1pBXKBVckFONSwF1z1E5ND2BGJsghQFah+pW7pkkyFb2VhUQI2qhL5w==} - '@google-cloud/common@6.0.0': - resolution: {integrity: sha512-IXh04DlkLMxWgYLIUYuHHKXKOUwPDzDgke1ykkkJPe48cGIS9kkL2U/o0pm4ankHLlvzLF/ma1eO86n/bkumIA==} + '@google-cloud/common@6.0.1': + resolution: {integrity: sha512-1uvKzbmAWUdchIYRsg0f4rUmezOamWuVBSWAPAhnYoUE5OiPEx6v6JOxFIdr3MsrqV+6fyLV3EI1vMPlHoeRvw==} engines: {node: '>=18'} - '@google-cloud/precise-date@5.0.0': - resolution: {integrity: sha512-9h0Gvw92EvPdE8AK8AgZPbMnH5ftDyPtKm7/KUfcJVaPEPjwGDsJd1QV0H8esBDV4II41R/2lDWH1epBqIoKUw==} + '@google-cloud/precise-date@5.0.1': + resolution: {integrity: sha512-9HlRbOcDb8b2tSsOvljPD/Rm+Jn9KxMVB6sLf85CBnoIYdCFTNO1FIizQ13P75itXpSXsLuMlg1XK5opHKVzjg==} engines: {node: '>=18'} '@google-cloud/projectify@4.0.0': resolution: {integrity: sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==} engines: {node: '>=14.0.0'} - '@google-cloud/projectify@5.0.0': - resolution: {integrity: sha512-XXQLaIcLrOAMWvRrzz+mlUGtN6vlVNja3XQbMqRi/V7XJTAVwib3VcKd7oRwyZPkp7rBVlHGcaqdyGRrcnkhlA==} + '@google-cloud/projectify@5.0.1': + resolution: {integrity: sha512-yAIqOAlDwx1nPmmA0WICFMSGttVuWX97HpphN71JQ7G+tD/Q6lHbiCTcMJ9r2+PwX6sIwK3ahO4FdSNt5pwhFg==} engines: {node: '>=18'} '@google-cloud/promisify@4.1.0': resolution: {integrity: sha512-G/FQx5cE/+DqBbOpA5jKsegGwdPniU6PuIEMt+qxWgFxvxuFOzVmp6zYchtYuwAWV5/8Dgs0yAmjvNZv3uXLQg==} engines: {node: '>=18'} - '@google-cloud/promisify@5.0.0': - resolution: {integrity: sha512-N8qS6dlORGHwk7WjGXKOSsLjIjNINCPicsOX6gyyLiYk7mq3MtII96NZ9N2ahwA2vnkLmZODOIH9rlNniYWvCQ==} + '@google-cloud/promisify@5.0.1': + resolution: {integrity: sha512-Ste6NGraHq30ge3Sdq7m+pZE6lRUlkt2YgsEdq/vcoEgdbdZ/7h37Z1dMvivjhlbgrcmYRvlLF9FgI7tXm5wjg==} engines: {node: '>=18'} '@google-cloud/spanner@8.0.0': resolution: {integrity: sha512-IJn+8A3QZJfe7FUtWqHVNo3xJs7KFpurCWGWCiCz3oEh+BkRymKZ1QxfAbU2yGMDzTytLGQ2IV6T2r3cuo75/w==} engines: {node: '>=18'} - '@google/genai@2.6.0': - resolution: {integrity: sha512-HjoW3mPuEn7pnuKABJl9VbDoWDSF4nbwYKYvYYor7YjPeDxrrBxHzu2d1Prcd+BAuC4w+85UP6y7ZdcrQAoO7g==} + '@google/genai@2.7.0': + resolution: {integrity: sha512-tv0DRtcndt2oEhBYy+5mA0TaXH98+L1Gt0AP9unBfH7DP20KhB7+O3QqAN1Lz+laMARGTHS7BFQSNpLbl4gm1g==} engines: {node: '>=20.0.0'} peerDependencies: '@modelcontextprotocol/sdk': ^1.25.2 @@ -2351,13 +2351,13 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} - '@inquirer/ansi@2.0.5': - resolution: {integrity: sha512-doc2sWgJpbFQ64UflSVd17ibMGDuxO1yKgOgLMwavzESnXjFWJqUeG8saYosqKpHp4kWiM5x1nXvEjbpx90gzw==} - engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + '@inquirer/ansi@2.0.7': + resolution: {integrity: sha512-3eTuUO1vH2cZm2ZKHeQxnOqlTi9EfZDGgIe3BL3I4u+rJHocr9Fz86M4fjYABPvFnQG/gGK551HqDiIcETwU6Q==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} - '@inquirer/checkbox@5.1.5': - resolution: {integrity: sha512-Jmf9tgBHIEK5SAOB7swYfStqmtkZb00xOTpSQmkoGEpdxOTpJi9RS0A8bkfDPHTTItZRJrRdZrEMu25wyj0VfQ==} - engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + '@inquirer/checkbox@5.2.1': + resolution: {integrity: sha512-b6xmA/VlTe0ZgDQHDui+Nav470u7u49nRd8/iuhOcQPO9Ch7lGuogydhi2VOmNlZ+zXcM8IcPuNSwQcdJaF/kw==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' peerDependenciesMeta: @@ -2373,76 +2373,76 @@ packages: '@types/node': optional: true - '@inquirer/confirm@6.0.13': - resolution: {integrity: sha512-wkGPC7yJ5WJk1DJ5SX7fzk+gfj4BM8cf5dDDi71B/551xHrdsZVRJOC0WyikXd0pEsb/9cLniuE4atbsMqmFkw==} - engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + '@inquirer/confirm@6.1.1': + resolution: {integrity: sha512-eb8DBZcz/2qHWQda4rk2JiQk5h9QV/cVHi1yjt0f69WFZMRFn0sJTye3EAP8icut8UDMjQPsaH5KbcOogefrFQ==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' peerDependenciesMeta: '@types/node': optional: true - '@inquirer/core@11.1.10': - resolution: {integrity: sha512-a4Q5BXHQAHa9eO202sTaFCHFYVB3x5fauDuThEAdZ9gfn76pSxiKU7wWcEH0N1O0XmQvNfQNU6QXpiRxmYQx+A==} - engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + '@inquirer/core@11.2.1': + resolution: {integrity: sha512-Qd6GJT1yVyrZZCfN8W2qKF5ApmqryXRhRKCuip8h01x2w/esJQ2XIYc6f9abMIHgKQdBfFTSOdbHRLAhuM09UA==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' peerDependenciesMeta: '@types/node': optional: true - '@inquirer/editor@5.1.2': - resolution: {integrity: sha512-Y3Nor7S/DhIPo+8Ym/dSY4efwKI4BsflKDwXh0jNeXJsSF3dteS/3Yf+z4wkibVZDvYMyCgknSTQlNahfunGHg==} - engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + '@inquirer/editor@5.2.2': + resolution: {integrity: sha512-ZRVd/oD+sYsUd5zVm0NflqEzlqfYCyHNsqkHl2oWXEUHs12tCbcSFi+wVFEvD8+LGRaMUsVrE7qeo6lSG/S1Vg==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' peerDependenciesMeta: '@types/node': optional: true - '@inquirer/expand@5.0.14': - resolution: {integrity: sha512-qyY9zcIX2eKYwaAUiQo9zORd61Lc3sXeM72fVbeHkYnDkqfr8/armcRbmVAIrExeJhI2puk+uomeKtWrpUVUmQ==} - engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + '@inquirer/expand@5.1.1': + resolution: {integrity: sha512-YmQpenjbFSHAK3sOd44puHh3V1KXXr+JiNpUztoSQ4drLh2rTVzTap/YtlAVu/5xavifIlBfNEzJ/neZJ1a/1g==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' peerDependenciesMeta: '@types/node': optional: true - '@inquirer/external-editor@3.0.0': - resolution: {integrity: sha512-lDSwMgg+M5rq6JKBYaJwSX6T9e/HK2qqZ1oxmOwn4AQoJE5D+7TumsxLGC02PWS//rkIVqbZv3XA3ejsc9FYvg==} - engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + '@inquirer/external-editor@3.0.3': + resolution: {integrity: sha512-6thf5I8q7lZwzGLAxPaaGEREEkZ3nyePPDQ1oyobblxmEE8mqTLguScP7pDjUTAibiyb4hfXl+qjUEJ+di/aNA==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' peerDependenciesMeta: '@types/node': optional: true - '@inquirer/figures@2.0.5': - resolution: {integrity: sha512-NsSs4kzfm12lNetHwAn3GEuH317IzpwrMCbOuMIVytpjnJ90YYHNwdRgYGuKmVxwuIqSgqk3M5qqQt1cDk0tGQ==} - engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + '@inquirer/figures@2.0.7': + resolution: {integrity: sha512-aJ8TBPOGB6f/2qziPfElISTCEd5XOYTFckA2SGjhNmiKzfK/u4ot3v0DUzGVdUnKjN10EqnnEPck36BkyfLnJw==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} - '@inquirer/input@5.0.13': - resolution: {integrity: sha512-0l0jCHlJnXIV8CTxwQC0C+5Ziq8WP22edWgmciW2xYvoeoSck4v5FvCS1ctKdqLLR0dUo93uAHgWHywgBSoRyw==} - engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + '@inquirer/input@5.1.2': + resolution: {integrity: sha512-9K/DDBSQpOyZSkt6sOVP9Vo0TR7atX2kuILsUu0x3wVcVbe97lJwIJKMLdMw25tDYuXl/qp6erT0Xs1rfmcfZg==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' peerDependenciesMeta: '@types/node': optional: true - '@inquirer/number@4.0.13': - resolution: {integrity: sha512-WHmkYnnJAou5gx7RgcvAfUggnHNM1zWfoh0dFPl3dxVssuqt+dK5rIbaOYQXNyOegvFnopbKupjnhw2O8gANNg==} - engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + '@inquirer/number@4.1.1': + resolution: {integrity: sha512-XF4IXAbPnGPgw0wsbC/i2tPcyfdZgDpUlhsqU0SfT4IRIGWha6Xm9VRgN5yYxJq+jnyXlfXI/nQ3ulfk0iEICA==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' peerDependenciesMeta: '@types/node': optional: true - '@inquirer/password@5.0.13': - resolution: {integrity: sha512-XDGu64ROHZjOOXLAANvJN7iIxWKhOSCG5VakrZ5kaScVR+snVJCFglD/hL3/677awtWcu4pXoWa280CDIYcBeg==} - engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + '@inquirer/password@5.1.1': + resolution: {integrity: sha512-3XBfF7DAsp5qeDsvN5Rd1HmbNokVvEQoUM0QLrRcybC9nX96w3Pbmu7qUsb3IT3J3jBvs2+mTXaKHOUsgHMLzg==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' peerDependenciesMeta: @@ -2458,45 +2458,45 @@ packages: '@types/node': optional: true - '@inquirer/prompts@8.4.3': - resolution: {integrity: sha512-ai5LseTw9HhegupIgmo4cn7RpnCGznjjXu4OI+7jMR8vu7T1ZCCNMzFFAovUCjL1fl0cceksIN1++yQE59SmZw==} - engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + '@inquirer/prompts@8.5.2': + resolution: {integrity: sha512-IYR/3C/paEVVQYQvdDlFZVjRCJVYHHON0XXMH91KO9GSxs0TdKYWlUdvfQl2EfAHDxUaN3IBffkE/BDTh5nJ6g==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' peerDependenciesMeta: '@types/node': optional: true - '@inquirer/rawlist@5.2.9': - resolution: {integrity: sha512-a1ErXEfgjfPYpyQ89dp+7n2IISjH9oQg3ygvF5adz8B7aHn4n2PjEgu1wpVTp69K3bj3lVLxP0qJ2b1clk1Whw==} - engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + '@inquirer/rawlist@5.3.1': + resolution: {integrity: sha512-QqdTqQddL3qPX/PPrjobpsO25NZ4dWXgTLenrR445L2ptLEYE6Z+PD5c5CNDJNx4ugRgELAIpSIJxZaO2jJ2Og==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' peerDependenciesMeta: '@types/node': optional: true - '@inquirer/search@4.1.9': - resolution: {integrity: sha512-ZlbM28Q9lmLkFPNAIv+ZuY530n5Km8U1WW48oYEvDhe9yc2uL3m3t+JSdRUkQlk5fuIuskgiIVjcb7czFzQpuA==} - engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + '@inquirer/search@4.2.1': + resolution: {integrity: sha512-xJj8QWKRSrfKoBIITLZK61dD3zwo0Rz11fgDImku30/Oe81zMdIdGgrLY2h6RkJ+KZ/GhNYIRMKnH/62qBTA5g==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' peerDependenciesMeta: '@types/node': optional: true - '@inquirer/select@5.1.5': - resolution: {integrity: sha512-6SRg6kHfK/sjLXOsuqNebuir+sjwrf/iWuRUnXgB2slzEewppI1WfzeS16XxDcOQmXBruMmmB9Cgrz7wsAxqMg==} - engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + '@inquirer/select@5.2.1': + resolution: {integrity: sha512-FlDndEUww8m7BfukO2nJa25vhD+H5jxxCv4oGioKqzyWz3nPHhhw4LKdYRSlXuAx7DsdWia7iyaBPKKS95Evfw==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' peerDependenciesMeta: '@types/node': optional: true - '@inquirer/type@4.0.5': - resolution: {integrity: sha512-aetVUNeKNc/VriqXlw1NRSW0zhMBB0W4bNbWRJgzRl/3d0QNDQFfk0GO5SDdtjMZVg6o8ZKEiadd7SCCzoOn5Q==} - engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + '@inquirer/type@4.0.7': + resolution: {integrity: sha512-t28inv14nMQ1PhKpsJPY+kEs/c00qzeCOS2gTNRyTjG5d6qsVA2fItxW4hkvGZ5lvanGLdtCzVIx5dwdRpN1+g==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' peerDependenciesMeta: @@ -2576,50 +2576,50 @@ packages: peerDependencies: tslib: '2' - '@jsonjoy.com/fs-core@4.57.2': - resolution: {integrity: sha512-SVjwklkpIV5wrynpYtuYnfYH1QF4/nDuLBX7VXdb+3miglcAgBVZb/5y0cOsehRV/9Vb+3UqhkMq3/NR3ztdkQ==} + '@jsonjoy.com/fs-core@4.57.6': + resolution: {integrity: sha512-uI++Wx6VkBJqVmkb4ZeExwAVpZiA2Do5NrEtXoDk0Pdvce3ytFXJoviT1sLOj16+qDIMnD5nWPfOhVpnDmRJKg==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/fs-fsa@4.57.2': - resolution: {integrity: sha512-fhO8+iR2I+OCw668ISDJdn1aArc9zx033sWejIyzQ8RBeXa9bDSaUeA3ix0poYOfrj1KdOzytmYNv2/uLDfV6g==} + '@jsonjoy.com/fs-fsa@4.57.6': + resolution: {integrity: sha512-pKkw/yC5CzSZKhIIUIsH1przOa+K5jGmZIg1sWaSF24JojyrUFbjcQv7QrcGAudriei6HQ6R0BFj+V8NbQinJw==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/fs-node-builtins@4.57.2': - resolution: {integrity: sha512-xhiegylRmhw43Ki2HO1ZBL7DQ5ja/qpRsL29VtQ2xuUHiuDGbgf2uD4p9Qd8hJI5P6RCtGYD50IXHXVq/Ocjcg==} + '@jsonjoy.com/fs-node-builtins@4.57.6': + resolution: {integrity: sha512-V4DgEFT3Cg5S9fCMOZSCVdTxdJWWLBO0WnAazV7hnCM96u5zXHyW/ubDAfcSVwqjkMJ50W1Y44IXtxRoIwaCVg==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/fs-node-to-fsa@4.57.2': - resolution: {integrity: sha512-18LmWTSONhoAPW+IWRuf8w/+zRolPFGPeGwMxlAhhfY11EKzX+5XHDBPAw67dBF5dxDErHJbl40U+3IXSDRXSQ==} + '@jsonjoy.com/fs-node-to-fsa@4.57.6': + resolution: {integrity: sha512-+JptNw3iifihxH2rEXrninDzX4FFVW8JD/wPR8GbJPAeL9CQUSblrlumOPB5gZuS7tYRX+PJPLtT7XzKoRhv/Q==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/fs-node-utils@4.57.2': - resolution: {integrity: sha512-rsPSJgekz43IlNbLyAM/Ab+ouYLWGp5DDBfYBNNEqDaSpsbXfthBn29Q4muFA9L0F+Z3mKo+CWlgSCXrf+mOyQ==} + '@jsonjoy.com/fs-node-utils@4.57.6': + resolution: {integrity: sha512-foyUrfS7WmYEUzqYXSNxmJBcSj04TABrkpFabwO9SCDCpVCfJ+qG+2sk5FjfiflG2n0SDFZDCJ6vYlJAEpxJFg==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/fs-node@4.57.2': - resolution: {integrity: sha512-nX2AdL6cOFwLdju9G4/nbRnYevmCJbh7N7hvR3gGm97Cs60uEjyd0rpR+YBS7cTg175zzl22pGKXR5USaQMvKg==} + '@jsonjoy.com/fs-node@4.57.6': + resolution: {integrity: sha512-Kbn1jdkvDN4F2+BhoB6mMu7NCbhP0bgA5NcI1aJj/Q5UcU+I1JLLW+dEQean33iV4tXv35AzBVKPICnDltBpxw==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/fs-print@4.57.2': - resolution: {integrity: sha512-wK9NSow48i4DbDl9F1CQE5TqnyZOJ04elU3WFG5aJ76p+YxO/ulyBBQvKsessPxdo381Bc2pcEoyPujMOhcRqQ==} + '@jsonjoy.com/fs-print@4.57.6': + resolution: {integrity: sha512-96eAn4Dudtt67LTeuU47yUD+pg9/G/oKpI10zei9ljk3X3WK4lYKc+n3cpaPCAbKPzoyfxl0mXm8f8Y7BOSFXw==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/fs-snapshot@4.57.2': - resolution: {integrity: sha512-GdduDZuoP5V/QCgJkx9+BZ6SC0EZ/smXAdTS7PfMqgMTGXLlt/bH/FqMYaqB9JmLf05sJPtO0XRbAwwkEEPbVw==} + '@jsonjoy.com/fs-snapshot@4.57.6': + resolution: {integrity: sha512-V57CMzbOgTzUWGOWQ8GzHQdpJP6JnrYVNCtTBNxVYEnlVRvo4uEJqHhtAT8vhDFrIuJOXLrTL1Fki4h5oI7xxg==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' @@ -2715,33 +2715,33 @@ packages: '@cfworker/json-schema': optional: true - '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': - resolution: {integrity: sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==} + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4': + resolution: {integrity: sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ==} cpu: [arm64] os: [darwin] - '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3': - resolution: {integrity: sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==} + '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.4': + resolution: {integrity: sha512-zExlW9zUJKZH/tOtVMttwjKa4Xm/3KcNjnE3dPN92uCktwavMxpgCA3MoJK/DOnTWsQgo224OaST27/mPNAf+w==} cpu: [x64] os: [darwin] - '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3': - resolution: {integrity: sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==} + '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.4': + resolution: {integrity: sha512-dgX0P/9wGPJeHFBG+ZmhgE6bmtMt7NP5CRBGyyktpopdk/mW4POnrpQsSLtKI1dwpc+pPLuXHDh6vvskyQE/sw==} cpu: [arm64] os: [linux] - '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3': - resolution: {integrity: sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==} + '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.4': + resolution: {integrity: sha512-Tg3yX65f5GbtXLkrYEHE5oibZG9epyYWas7FogTTEJeDEF9JlXJzKgXaNhT3UXlTOeA+AfZpYZYZ0uPj7Cfquw==} cpu: [arm] os: [linux] - '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3': - resolution: {integrity: sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==} + '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.4': + resolution: {integrity: sha512-8TNXMEjJc3QEy7R/x1INhgiU+XakDAFUzBhaz7+Rbrs8NH5UQeHQxxmzsSBJGyV6I1jW79undiQm8tOI+D+8FQ==} cpu: [x64] os: [linux] - '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': - resolution: {integrity: sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==} + '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4': + resolution: {integrity: sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ==} cpu: [x64] os: [win32] @@ -2884,8 +2884,8 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@npmcli/agent@4.0.0': - resolution: {integrity: sha512-kAQTcEN9E8ERLVg5AsGwLNoFb+oEG6engbqAU2P43gD4JEIkNGMHdVQ096FsOAAYpZPB0RSt0zgInKIAS1l5QA==} + '@npmcli/agent@4.0.2': + resolution: {integrity: sha512-EUEuWAxnL07Sp5/iC/1X6Xj+XThUvnbei9zfRWZdEXa7lss9RTHMhAHBeg+MZ5To9s/gGaSI+UwZTPdYMvKSeg==} engines: {node: ^20.17.0 || >=22.9.0} '@npmcli/fs@5.0.0': @@ -2989,8 +2989,8 @@ packages: resolution: {integrity: sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==} engines: {node: '>= 20'} - '@octokit/request@10.0.9': - resolution: {integrity: sha512-o8Bi3f608eyM+7BmBiUWxFsdjLb3/ym1cQek5LZOv9KkZcxRrHCPhhRzm6xjO6HVZ85ItD6+sTsjxo821SVa/A==} + '@octokit/request@10.0.10': + resolution: {integrity: sha512-KxNC2pTqqhszMNrf12ZRd4PonRgyJdsM4F/jySiddQK+DsRcfBtUvqn8t7UsyZhnRJHvX46OohDt5N3VqIWC2w==} engines: {node: '>= 20'} '@octokit/rest@22.0.1': @@ -3326,8 +3326,8 @@ packages: rollup: optional: true - '@rollup/plugin-commonjs@29.0.2': - resolution: {integrity: sha512-S/ggWH1LU7jTyi9DxZOKyxpVd4hF/OZ0JrEbeLjXk/DFXwRny0tjD2c992zOUYQobLrVkRVMDdmHP16HKP7GRg==} + '@rollup/plugin-commonjs@29.0.3': + resolution: {integrity: sha512-ZaOxZceP7SOUW7Lqw5IRVweSQYWaeIPnXIGLiB690EBA3FGJTO40EEr2L5yZplJWsgTCogILRSpcAe7+U0Otdg==} engines: {node: '>=16.0.0 || 14 >= 14.17'} peerDependencies: rollup: ^2.68.0||^3.0.0||^4.0.0 @@ -3362,6 +3362,15 @@ packages: rollup: optional: true + '@rollup/pluginutils@5.4.0': + resolution: {integrity: sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + '@rollup/rollup-android-arm-eabi@4.60.2': resolution: {integrity: sha512-dnlp69efPPg6Uaw2dVqzWRfAWRnYVb1XJ8CyyhIbZeaq4CA5/mLeZ1IEt9QqQxmbdvagjLIm2ZL8BxXv5lH4Yw==} cpu: [arm] @@ -3705,8 +3714,8 @@ packages: '@types/node-fetch@2.6.13': resolution: {integrity: sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==} - '@types/node@22.19.19': - resolution: {integrity: sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==} + '@types/node@22.19.20': + resolution: {integrity: sha512-6tELRwSDYWW9EdZhbeZmYGZ1/7Djkt+Ah3/ScEYT9cDord7UJzasR/4D3VONg9tQI5CDp+/CZC1AXj2pCFOvpw==} '@types/node@24.12.4': resolution: {integrity: sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA==} @@ -3846,8 +3855,8 @@ packages: resolution: {integrity: sha512-ZDCjgccSdYPw5Bxh+my4Z0lJU96ZDN7jbBzvmEn0FZx3RtU1C7VWl6NbDx94bwY3V5YsgwRzJPOgeY2Q/nLG8A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/types@8.59.4': - resolution: {integrity: sha512-F1o7WJcCq+bc8dwcO/YsSEOudAH8RDtaOhM6wcAQhcUsFhnWQl81JKy48q1hoxAU0qrzM89+31GYh1515Zde3Q==} + '@typescript-eslint/types@8.60.1': + resolution: {integrity: sha512-4h0tY8ppCkdCzcrl2YM5M3my0xsE1Tf8om3owEu5oPWmXwkKRmk0j0LGDzYBGUcAlesEbxBhazqu/K4cu3Ug7w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@typescript-eslint/typescript-estree@8.59.1': @@ -4238,8 +4247,8 @@ packages: resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} engines: {node: '>=4'} - ast-v8-to-istanbul@1.0.2: - resolution: {integrity: sha512-dKmJxJsGItLmc5CYZKuEjuG6GnBs6PG4gohMhyFOWKaNQoYCuRZJDECaBlHmcG0lv2wc2E0uU8lESmBEumC3DQ==} + ast-v8-to-istanbul@1.0.3: + resolution: {integrity: sha512-jCMQ6ZylLPudp0CDfBmQBZUsrh1/8psbmu9ibeVWKuHWD0YrH9YABwlKu5kVEFoT0GCQQW9Z/SxfuEbbkGQCRg==} async-each-series@0.1.1: resolution: {integrity: sha512-p4jj6Fws4Iy2m0iCmI2am2ZNZCgbdgE+P8F/8csmn2vx7ixXrO2zGcuNsD46X5uZSVecmkEy/M06X2vG8KD6dQ==} @@ -4327,16 +4336,16 @@ packages: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} - bare-events@2.8.3: - resolution: {integrity: sha512-HdUm8EMQBLaJvGUdidNNbqpA1kYkwNcb+MYxkxCLAPJGQzlv9J0C24h8V65Z4c5GLd/JEALDvpFCQgpLJqc0zw==} + bare-events@2.9.1: + resolution: {integrity: sha512-Z0oHEHAFDZkffN8Qc39zNZjQlMDkPJRyyyZieU1VH7u8c5S+qHZ2S8ixdKIAxEjfHO7FJxXmJWgteOghVanIsg==} peerDependencies: bare-abort-controller: '*' peerDependenciesMeta: bare-abort-controller: optional: true - bare-fs@4.7.1: - resolution: {integrity: sha512-WDRsyVN52eAx/lBamKD6uyw8H4228h/x0sGGGegOamM2cd7Pag88GfMQalobXI+HaEUxpCkbKQUDOQqt9wawRw==} + bare-fs@4.7.2: + resolution: {integrity: sha512-aTvMFUWkBmjzKtEQMDGGDNF8bkfpD5N1b/FCwt7A3wrU4t1o/e/85Wzkluh6JlODCjqVESYCkQCdTXqZ9G7VFg==} engines: {bare: '>=1.16.0'} peerDependencies: bare-buffer: '*' @@ -4348,8 +4357,8 @@ packages: resolution: {integrity: sha512-6M5XjcnsygQNPMCMPXSK379xrJFiZ/AEMNBmFEmQW8d/789VQATvriyi5r0HYTL9TkQ26rn3kgdTG3aisbrXkQ==} engines: {bare: '>=1.14.0'} - bare-path@3.0.0: - resolution: {integrity: sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==} + bare-path@3.0.1: + resolution: {integrity: sha512-ghj2DSK/2e99a1anTVPCV4m4YIYtrbXhfM7V3D7XZLOTsybnYyaJloymGqssQc8l/or0UoDyRtNQkmkEF/ysgQ==} bare-stream@2.13.1: resolution: {integrity: sha512-Vp0cnjYyrEC4whYTymQ+YZi6pBpfiICZO3cfRG8sy67ZNWe951urv1x4eW1BKNngw3U+3fPYb5JQvHbCtxH7Ow==} @@ -4365,8 +4374,8 @@ packages: bare-events: optional: true - bare-url@2.4.3: - resolution: {integrity: sha512-Kccpc7ACfXaxfeInfqKcZtW4pT5YBn1mesc4sCsun6sRwtbJ4h+sNOaksUpYEJUKfN65YWC6Bw2OJEFiKxq8nQ==} + bare-url@2.4.5: + resolution: {integrity: sha512-K+y9xF1tN+CdPu4qWwr0QiK1Al07eFPGYK5M2pDXcmHdMdgC/tT/bpmMe1hrmRHaidKLkXrC+cRNYf3XVDUhSQ==} base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -4375,8 +4384,8 @@ packages: resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} engines: {node: ^4.5.0 || >= 5.9} - baseline-browser-mapping@2.10.32: - resolution: {integrity: sha512-wbPvpyjJPC0zdfdKXxqEL3Ea+bOMD/87X4lftiJkkaBiuG6ALQy1SLmEd7BSmVCuwCQsBrCamgBoLyfFDD1EPg==} + baseline-browser-mapping@2.10.34: + resolution: {integrity: sha512-IMDedajPifLnHNY0X9n8hKxRTQ6/eTHwr5bDo04WnuqxyKw6LYtQywCuuqPZwhl3aBXMvQpJov42GLCwRRdQzw==} engines: {node: '>=6.0.0'} hasBin: true @@ -4430,8 +4439,8 @@ packages: boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - brace-expansion@1.1.14: - resolution: {integrity: sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==} + brace-expansion@1.1.15: + resolution: {integrity: sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==} brace-expansion@2.1.1: resolution: {integrity: sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==} @@ -4526,8 +4535,8 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - caniuse-lite@1.0.30001793: - resolution: {integrity: sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==} + caniuse-lite@1.0.30001797: + resolution: {integrity: sha512-l8xKG+gwAIExZGl9FrF7KUwuOmk6wbEPC9Xoy/RtnWv1XG0Q4LFlagaLpUv3Kiza3W/wm27zy0yWJEieYKAP6w==} caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} @@ -4746,8 +4755,8 @@ packages: resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} engines: {node: '>= 0.10'} - cosmiconfig@9.0.1: - resolution: {integrity: sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==} + cosmiconfig@9.0.2: + resolution: {integrity: sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg==} engines: {node: '>=14'} peerDependencies: typescript: '>=4.9.5' @@ -5013,8 +5022,8 @@ packages: engines: {node: '>=0.12.18'} hasBin: true - electron-to-chromium@1.5.361: - resolution: {integrity: sha512-Q6Hts7N9FnJc5LeGRINFvLhCI9xZmNtTDe5ZbcVezQz7cU4a8Aua3GH1b8J2XY8Al9PF+OCwYqhgsOOheMdvkA==} + electron-to-chromium@1.5.368: + resolution: {integrity: sha512-7RckJJK4uESJF9PxvfMWd3TGqIiieUTG4HxnKaKuIpGbcr+r2ZEB3g2gAhCP3Fqm42vJSzLfgab9eva/C4/XVw==} emoji-regex@10.6.0: resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} @@ -5054,8 +5063,8 @@ packages: resolution: {integrity: sha512-2agL3ueZhqxoVrfmntO8yuVj+uNSlIOnhykYHk3Cq0ShYPdUjjUiSJrQvXjq01I9jAuI0Zl2YO8Evv5Mqytm5g==} engines: {node: '>=10.2.0'} - enhanced-resolve@5.22.0: - resolution: {integrity: sha512-xYcDWrpELkFzz9SpZ3PlI6Eu6eD93Yf0WLDRxikGhWJ3MAir2SNZTIVCVZqZ/NUyx8AdMc2gT9C0gPiw18kG+A==} + enhanced-resolve@5.23.0: + resolution: {integrity: sha512-yJN/BOOLxcOW2aQgeif9mSnaUB8KtvmMMp56oA1kx1CRfBKbhZm2pJ+NBY+3eOboHxix8lfjWpHE0Ei5U8RbSA==} engines: {node: '>=10.13.0'} ent@2.2.2: @@ -5165,8 +5174,8 @@ packages: eslint-import-resolver-node@0.3.10: resolution: {integrity: sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==} - eslint-module-utils@2.12.1: - resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==} + eslint-module-utils@2.13.0: + resolution: {integrity: sha512-bLohSkT6469rRs8czj0tLTD8vaeIS/whvPRJVjDr7IuoTT1k5DYDERlNycjDj/HkOlvQdYurmfZ/g3fG5bgeLQ==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' @@ -5289,8 +5298,8 @@ packages: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} - eventsource-parser@3.0.8: - resolution: {integrity: sha512-70QWGkr4snxr0OXLRWsFLeRBIRPuQOvt4s8QYjmUlmlkyTZkRqS7EDVRZtzU3TiyDbXSzaOeF0XUKy8PchzukQ==} + eventsource-parser@3.1.0: + resolution: {integrity: sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==} engines: {node: '>=18.0.0'} eventsource@3.0.7: @@ -5337,9 +5346,6 @@ packages: resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} engines: {'0': node >=0.6.0} - fast-content-type-parse@3.0.0: - resolution: {integrity: sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==} - fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -5427,8 +5433,8 @@ packages: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} - firebase@12.13.0: - resolution: {integrity: sha512-iutR8ejvAqk6qUClnsPz3U3VIjTWp243AX4cD3iifak5t56to1J29xUIQgSDDzaAqKvhshZerzSahwMQj2TlvA==} + firebase@12.14.0: + resolution: {integrity: sha512-aEZ/lniDR1hOCYpx/x/V8Nrrqq9pepKDNkqP/4WGZFC69gTv6F59Z4/54W/SUP4L/hFlrRNmWj35aweQq+IHow==} flat-cache@4.0.1: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} @@ -5521,14 +5527,22 @@ packages: functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - gaxios@7.1.4: - resolution: {integrity: sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA==} + gaxios@7.1.3: + resolution: {integrity: sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==} + engines: {node: '>=18'} + + gaxios@7.1.5: + resolution: {integrity: sha512-5FZy72Rh8LhtjmvDrKkI+lVhrsQrVKVsItxMoDm5mNQE+xR0WVIIs+jzPSJgBvKVsLi24fZhXJIsNI0bihDzFg==} engines: {node: '>=18'} gcp-metadata@8.1.2: resolution: {integrity: sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==} engines: {node: '>=18'} + gcp-metadata@8.1.3: + resolution: {integrity: sha512-ziTrzUhhpL9Zk5k0HHzgP/KIpWDJT0VMBC/ynt/QIBvTW+UUcSivQRl6VlwTf/EilDxtSWklHoRsKy1c4k+59w==} + engines: {node: '>=18'} + generator-function@2.0.1: resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} engines: {node: '>= 0.4'} @@ -5618,12 +5632,16 @@ packages: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} - google-auth-library@10.6.2: - resolution: {integrity: sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw==} + google-auth-library@10.5.0: + resolution: {integrity: sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w==} engines: {node: '>=18'} - google-gax@5.0.6: - resolution: {integrity: sha512-1kGbqVQBZPAAu4+/R1XxPQKP0ydbNYoLAr4l0ZO2bMV0kLyLW4I1gAk++qBLWt7DPORTzmWRMsCZe86gDjShJA==} + google-auth-library@10.7.0: + resolution: {integrity: sha512-QpTAbNJ36TliZLx3TTtahR8HG0hN9RllL1e3FymOvQSIKK8JmgV58H924ub2wa2DsS3ANjjP1Aw1N+Ramc8hqQ==} + engines: {node: '>=18'} + + google-gax@5.0.7: + resolution: {integrity: sha512-EhiqaWWJ+9h7sCcKJTsoo6tMcjokVHhWsbSuWCnZJT4vIBP3y4mAoFLnt9SzgkVZeq24ZsFaArr06nnYYku2yA==} engines: {node: '>=18'} google-logging-utils@1.1.3: @@ -5647,8 +5665,8 @@ packages: peerDependencies: graphql: ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - graphql@16.14.0: - resolution: {integrity: sha512-BBvQ/406p+4CZbTpCbVPSxfzrZrbnuWSP1ELYgyS6B+hNeKzgrdB4JczCa5VZUBQrDa9hUngm0KnexY6pJRN5Q==} + graphql@16.14.1: + resolution: {integrity: sha512-cQOsSMS/IrDz82PVyRDvf/Q1F/bRbBVjJlh+xYOkI1qw2bWRvWGiWc+m2O0d6l4Bt1fyY+8kzJ8JFWGJqNeDBg==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} grpc-gcp@1.0.1: @@ -5657,6 +5675,10 @@ packages: peerDependencies: protobufjs: '*' + gtoken@8.0.0: + resolution: {integrity: sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==} + engines: {node: '>=18'} + gunzip-maybe@1.4.2: resolution: {integrity: sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==} hasBin: true @@ -5692,8 +5714,8 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} - hasown@2.0.3: - resolution: {integrity: sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==} + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} engines: {node: '>= 0.4'} hono@4.12.23: @@ -5839,8 +5861,8 @@ packages: resolution: {integrity: sha512-AUY/VyX0E5XlibOmWt10uabJzam1zlYjwiEgQSDc5+UIkFNaF9WM0JxXKaNMGf+F/ffUF+7kRKXM9A7C0xXqMg==} engines: {node: '>=0.10.0'} - immutable@5.1.5: - resolution: {integrity: sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==} + immutable@5.1.6: + resolution: {integrity: sha512-q1swsS8K7L8usSHuOqF2TAoCCkonYz0SG38wLAggaa4Wml70zixIvt2ql4coQ2C2B3hTjltJry4r6bULwgAXLQ==} import-fresh@3.3.1: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} @@ -6177,6 +6199,10 @@ packages: resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true + js-yaml@4.2.0: + resolution: {integrity: sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==} + hasBin: true + jsbn@0.1.1: resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} @@ -6299,8 +6325,8 @@ packages: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} - launch-editor@2.13.2: - resolution: {integrity: sha512-4VVDnbOpLXy/s8rdRCSXb+zfMeFR0WlJWpET1iA9CQdlZDfwyLjUuGQzXU4VeOoey6AicSAluWan7Etga6Kcmg==} + launch-editor@2.14.1: + resolution: {integrity: sha512-QWBrQsMpH7gPr965dsKD/3cKWiNoTjpATQf++Xq63N6sKRGMwlVXz41O1IZTMfZQgBctD/K5Zt06+/I6pP6+HA==} less-loader@12.3.2: resolution: {integrity: sha512-uLV5c702ff2jBvO7qewpkLRzkh/I9QW07ur2NKkv8TVTrtX2lrKjEbEU/LLXAn7cgpCIBbkfyUm4qYXCQs5/+w==} @@ -6430,8 +6456,8 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - lru-cache@11.5.0: - resolution: {integrity: sha512-5YgH9UJd7wVb9hIouI2adWpgqrrICkt070Dnj8EUY1+B4B2P9eRLPAkAAo6NICA7CEhOIeBHl46u9zSNpNu7zA==} + lru-cache@11.5.1: + resolution: {integrity: sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==} engines: {node: 20 || >=22} lru-cache@5.1.1: @@ -6455,8 +6481,8 @@ packages: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} - make-fetch-happen@15.0.5: - resolution: {integrity: sha512-uCbIa8jWWmQZt4dSnEStkVC6gdakiinAm4PiGsywIkguF0eWMdcjDz0ECYhUolFU3pFLOev9VNPCEygydXnddg==} + make-fetch-happen@15.0.6: + resolution: {integrity: sha512-Je0fLJ0F5atA7F+eIlLzk+Wkcl57JDf4kf+EW8xiP5E31xOQxkIxTbgf1Oi1Lw9tRI9UEMRdI5Vz2xTzoNU1Jw==} engines: {node: ^20.17.0 || >=22.9.0} math-intrinsics@1.1.0: @@ -6474,8 +6500,8 @@ packages: resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} engines: {node: '>= 0.8'} - memfs@4.57.2: - resolution: {integrity: sha512-2nWzSsJzrukurSDna4Z0WywuScK4Id3tSKejgu74u8KCdW4uNrseKRSIDg75C6Yw5ZRqBe0F0EtMNlTbUq8bAQ==} + memfs@4.57.6: + resolution: {integrity: sha512-WQK+DGjKCnPdpSyJUXphz+COF2uEhhsxQ3VIWBSbzpbbXuch3h4FePMqXrXGdLjsTgo4JFzBFsP6AWd9pVazGw==} peerDependencies: tslib: '2' @@ -6636,12 +6662,12 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - msgpackr-extract@3.0.3: - resolution: {integrity: sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==} + msgpackr-extract@3.0.4: + resolution: {integrity: sha512-4kmO/MdyUIkLIvTPr8VHLil4AtoKIoniWPIEk5+CDy0xnWC84azhSFmuJ7PxZdsYtiP5kEeQsORAVIeMgxT+Hw==} hasBin: true - msgpackr@1.11.12: - resolution: {integrity: sha512-RBdJ1Un7yGlXWajrkxcSa93nvQ0w4zBf60c0yYv7YtBelP8H2FA7XsfBbMHtXKXUMUxH7zV3Zuozh+kUQWhHvg==} + msgpackr@1.11.13: + resolution: {integrity: sha512-pWaxg0k1iiNdkAayUQ7Zlz/vYNfVefUttmHxqFcQjjtyqFa3w4x5rginOEzy/GvbWhBDD9K65/ZXyq8qz8utaQ==} multicast-dns@7.2.5: resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==} @@ -6752,13 +6778,13 @@ packages: resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} hasBin: true - node-gyp@12.3.0: - resolution: {integrity: sha512-QNcUWM+HgJplcPzBvFBZ9VXacyGZ4+VTOb80PwWR+TlVzoHbRKULNEzpRsnaoxG3Wzr7Qh7BYxGDU3CbKib2Yg==} + node-gyp@12.4.0: + resolution: {integrity: sha512-OMcPNvqTCFUnNaBlmdgq+lfNqY7gTiSmNRDjY3uAXRyudeKZEZxu3CLtjMQrx4zZxCX2b/mpNqTtwuCJgXhHkw==} engines: {node: ^20.17.0 || >=22.9.0} hasBin: true - node-releases@2.0.46: - resolution: {integrity: sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ==} + node-releases@2.0.47: + resolution: {integrity: sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==} engines: {node: '>=18'} nopt@9.0.0: @@ -6844,8 +6870,9 @@ packages: obuf@1.1.2: resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} - obug@2.1.1: - resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + obug@2.1.2: + resolution: {integrity: sha512-AWGB9WFcRXOQs48Z/udjI5ZcZMHXwX8XPByNpOydgcGsDLIzjGizhoMWJyKAWze7AVW/2W1i+/gPX4YtKe5cyg==} + engines: {node: '>=12.20.0'} on-exit-leak-free@2.1.2: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} @@ -7190,8 +7217,8 @@ packages: resolution: {integrity: sha512-E1sbAYg3aEbXrq0n1ojJkRHQJGE1kaE/O6GLA94y8rnJBfgvOPTOd1b9hOceQK1FFZI9qMh1vBERCyO2ifubcw==} engines: {node: '>=18'} - protobufjs@7.6.1: - resolution: {integrity: sha512-4K0myLaWL5EteuSAro91EGFgcfVgxb64Jx+7oDAY6GOkXD4M69yuSEljNcInGVCA5sOPxmZ/EqDLj2x0Q0+Ygg==} + protobufjs@7.6.2: + resolution: {integrity: sha512-N9EiLovGEQOJSPF26Ij7qUGvahfEnq0eeYZ02aigIedkmz1qZSwjnP9SBITHJuF/6MYbIW4HDN8zdYjsjqJKXQ==} engines: {node: '>=12.0.0'} proxy-addr@2.0.7: @@ -7383,8 +7410,8 @@ packages: resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} engines: {node: '>=18'} - retry-request@8.0.2: - resolution: {integrity: sha512-JzFPAfklk1kjR1w76f0QOIhoDkNkSqW8wYKT08n9yysTmZfB+RQ2QoXoTAeOi1HD9ZipTyTAZg3c4pM/jeqgSw==} + retry-request@8.0.3: + resolution: {integrity: sha512-qqoc4kkGgP9cmQDWELlOpAmfgJOg0Yi7MT82ZjiPWu451ayju4itwomjM4/dBEliify8C1b3tSaeCOldugtwPQ==} engines: {node: '>=18'} retry@0.13.1: @@ -7543,8 +7570,8 @@ packages: engines: {node: '>=10'} hasBin: true - semver@7.8.0: - resolution: {integrity: sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==} + semver@7.8.1: + resolution: {integrity: sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==} engines: {node: '>=10'} hasBin: true @@ -7797,8 +7824,8 @@ packages: resolution: {integrity: sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==} engines: {node: '>=8.0'} - streamx@2.25.0: - resolution: {integrity: sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg==} + streamx@2.27.0: + resolution: {integrity: sha512-WZ189TKnHoAokYHvwzaAQMpd55cgUmFIcJFzBSgGcb886jau5DL+XdDhTWV4ps3FLvk+OORp0dLRTPsLZ21CSA==} strict-event-emitter@0.5.1: resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==} @@ -7819,12 +7846,12 @@ packages: resolution: {integrity: sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==} engines: {node: '>=20'} - string.prototype.trim@1.2.10: - resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} + string.prototype.trim@1.2.11: + resolution: {integrity: sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==} engines: {node: '>= 0.4'} - string.prototype.trimend@1.0.9: - resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} + string.prototype.trimend@1.0.10: + resolution: {integrity: sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==} engines: {node: '>= 0.4'} string.prototype.trimstart@1.0.8: @@ -7888,19 +7915,19 @@ packages: tar-stream@3.2.0: resolution: {integrity: sha512-ojzvCvVaNp6aOTFmG7jaRD0meowIAuPc3cMMhSgKiVWws1GyHbGd/xvnyuRKcKlMpt3qvxx6r0hreCNITP9hIg==} - tar@7.5.15: - resolution: {integrity: sha512-dzGK0boVlC4W5QFuQN1EFSl3bIDYsk7Tj40U6eIBnK2k/8ml7TZ5agbI5j5+qnoVcAA+rNtBml8SEiLxZpNqRQ==} + tar@7.5.16: + resolution: {integrity: sha512-56adEpPMouktRlBLXiaYFFzZ/3+JXa8P9n7WbR+ibIjtviN55mEaOkiysCnPnWm+7kkui1Dn8J9l+g6zV8731w==} engines: {node: '>=18'} - teeny-request@10.1.2: - resolution: {integrity: sha512-Xj0ZAQ0CeuQn6UxCDPLbFRlgcSTUEyO3+wiepr2grjIjyL/lMMs1Z4OwXn8kLvn/V1OuaEP0UY7Na6UDNNsYrQ==} + teeny-request@10.1.3: + resolution: {integrity: sha512-5yDliI1uWkYPo7W+Zvrxg6YmoWuj5iC5EydewqrRTvc68nyMTZhlPPlLg6cptUGfbQAb+N9XDPDPzF6N081lug==} engines: {node: '>=18'} teex@1.0.1: resolution: {integrity: sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==} - terser-webpack-plugin@5.6.0: - resolution: {integrity: sha512-Eum+5ajkaOhf5KbM26osvv21kLD7BaGqQ1UA4Ami4arYwylmGUQTgHFpHDdmJod1q4QXa66p0to/FBKID+J1vA==} + terser-webpack-plugin@5.6.1: + resolution: {integrity: sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==} engines: {node: '>= 10.13.0'} peerDependencies: '@minify-html/node': '*' @@ -7956,8 +7983,8 @@ packages: peerDependencies: tslib: ^2 - thread-stream@3.1.0: - resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} + thread-stream@3.2.0: + resolution: {integrity: sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==} through2@2.0.5: resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} @@ -7977,8 +8004,8 @@ packages: tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - tinyexec@1.2.2: - resolution: {integrity: sha512-M/Q0B2cp4K7kynaT/vnED1j8TlLY+Pp7C6Wl2bl/7u/F0mUVwdyOpwomQb8JpYLitHUssAJRmLZdMCGsrx7i+g==} + tinyexec@1.2.4: + resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} engines: {node: '>=18'} tinyglobby@0.2.16: @@ -7992,19 +8019,19 @@ packages: tldts-core@6.1.86: resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} - tldts-core@7.3.1: - resolution: {integrity: sha512-CSjiLuHll9lt9l+jf0poLVfgddqGAj4vUHoipeTPx3RvVjgCu/krg7t7lsW000y9vNBP34FbXH8S6BuciRtoIw==} + tldts-core@7.4.2: + resolution: {integrity: sha512-nwEyF4vl4RSJjwSjBUmOSxc3BFPoIFdlRthJ6e+5v9P3bHNsoD06UjuqMUspqp7vsEZ1beaHi1km+optiE17yA==} tldts@6.1.86: resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} hasBin: true - tldts@7.3.1: - resolution: {integrity: sha512-+tHFHaNlvYCC1g4cwAcPWy/0BXvWZCMVk6WwohwXUupkcFYKpX3EH1jD8gRMIbDBbVKGKzacFf9aSsdXISKz0g==} + tldts@7.4.2: + resolution: {integrity: sha512-kCwffuaH8ntKtygnWe1b4BJKWiCUH30n5KfoTr6IchcXOwR7chAOFJxFrH3vjANafUYrIA4a7SDL+nn7SiR4Sw==} hasBin: true - tmp@0.2.5: - resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} + tmp@0.2.7: + resolution: {integrity: sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==} engines: {node: '>=14.14'} to-regex-range@5.0.1: @@ -8055,8 +8082,8 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tsx@4.22.3: - resolution: {integrity: sha512-mdoNxBC/cSQObGGVQ5Bpn5i+yv7j68gk3Nfm3wFjcJg3Z0Mix9jzAFfP12prmm5eVGmDKtp0yyArrs0Q+8gZHg==} + tsx@4.22.4: + resolution: {integrity: sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==} engines: {node: '>=18.0.0'} hasBin: true @@ -8105,8 +8132,8 @@ packages: resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} engines: {node: '>= 0.4'} - typed-array-length@1.0.7: - resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} + typed-array-length@1.0.8: + resolution: {integrity: sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==} engines: {node: '>= 0.4'} typed-assert@1.0.9: @@ -8146,12 +8173,12 @@ packages: undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} - undici@6.25.0: - resolution: {integrity: sha512-ZgpWDC5gmNiuY9CnLVXEH8rl50xhRCuLNA97fAUnKi8RRuV4E6KG31pDTsLVUKnohJE0I3XDrTeEydAXRw47xg==} + undici@6.26.0: + resolution: {integrity: sha512-4yqz8a3n5HmGTlsbADNtr/dJlhkh/55Rq798G6ibiULcXbDtaLpTl1pvdqcbFfeoj3iSi52lePFM7h9H21cw/A==} engines: {node: '>=18.17'} - undici@7.25.0: - resolution: {integrity: sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==} + undici@7.27.2: + resolution: {integrity: sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==} engines: {node: '>=20.18.1'} undici@8.2.0: @@ -8435,8 +8462,8 @@ packages: webpack-cli: optional: true - websocket-driver@0.7.4: - resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} + websocket-driver@0.7.5: + resolution: {integrity: sha512-ZL2+3c7kMBdIRCMz6l8jQMHyGVxj+UL+xVk74Ombiciboca8rHa15L86B19E5oh1pL9Ii/uj54gtsIrZGMo6zA==} engines: {node: '>=0.8.0'} websocket-extensions@0.1.4: @@ -8466,8 +8493,8 @@ packages: resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} engines: {node: '>= 0.4'} - which-typed-array@1.1.20: - resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==} + which-typed-array@1.1.22: + resolution: {integrity: sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==} engines: {node: '>= 0.4'} which@1.3.1: @@ -8656,7 +8683,7 @@ snapshots: '@actions/http-client@4.0.1': dependencies: tunnel: 0.0.6 - undici: 6.25.0 + undici: 6.26.0 '@actions/io@3.0.2': {} @@ -8754,7 +8781,7 @@ snapshots: '@angular/core': 22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2) tslib: 2.8.1 - '@angular/cdk@22.0.0-rc.2(@angular/common@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.0.0(@angular/animations@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2)': + '@angular/cdk@22.0.0(@angular/common@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.0.0(@angular/animations@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2)': dependencies: '@angular/common': 22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) '@angular/core': 22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2) @@ -8818,9 +8845,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@angular/material@22.0.0-rc.2(626d92b70d6fd1515002dfba4bbacd97)': + '@angular/material@22.0.0(6eb83275f51d1d41f72333b1955c7306)': dependencies: - '@angular/cdk': 22.0.0-rc.2(@angular/common@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.0.0(@angular/animations@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) + '@angular/cdk': 22.0.0(@angular/common@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.0.0(@angular/animations@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) '@angular/common': 22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) '@angular/core': 22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2) '@angular/forms': 22.0.0(@angular/common@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@22.0.0(@angular/animations@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@22.0.0(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@22.0.0(@angular/compiler@22.0.0)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) @@ -8828,14 +8855,14 @@ snapshots: rxjs: 7.8.2 tslib: 2.8.1 - '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/a450a2420ca888116e6d4207b38819cd27b06179(@modelcontextprotocol/sdk@1.29.0(zod@4.4.2))': + '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/68eef04ac1e37b69e3e61d3e32802e0a6046d54c(@modelcontextprotocol/sdk@1.29.0(zod@4.4.2))': dependencies: '@actions/core': 3.0.1 '@conventional-changelog/git-client': 2.7.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0) '@google-cloud/spanner': 8.0.0(supports-color@10.2.2) - '@google/genai': 2.6.0(@modelcontextprotocol/sdk@1.29.0(zod@4.4.2))(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) - '@inquirer/prompts': 8.4.3(@types/node@24.12.4) - '@inquirer/type': 4.0.5(@types/node@24.12.4) + '@google/genai': 2.7.0(@modelcontextprotocol/sdk@1.29.0(zod@4.4.2))(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) + '@inquirer/prompts': 8.5.2(@types/node@24.12.4) + '@inquirer/type': 4.0.7(@types/node@24.12.4) '@octokit/auth-app': 8.2.0 '@octokit/core': 7.0.6 '@octokit/graphql': 9.0.3 @@ -8865,7 +8892,7 @@ snapshots: ejs: 5.0.2 encoding: 0.1.13 fast-glob: 3.3.3 - firebase: 12.13.0 + firebase: 12.14.0 folder-hash: 4.1.3(supports-color@10.2.2) jasmine: 6.2.0 jasmine-core: 6.2.0 @@ -8874,9 +8901,9 @@ snapshots: minimatch: 10.2.5 multimatch: 8.0.0 nock: 14.0.15 - semver: 7.8.0 + semver: 7.8.1 supports-color: 10.2.2 - tsx: 4.22.3 + tsx: 4.22.4 typed-graphqlify: 3.1.6 typescript: 6.0.3 utf-8-validate: 6.0.6 @@ -9672,7 +9699,7 @@ snapshots: dependencies: '@csstools/css-tokenizer': 4.0.0 - '@csstools/css-syntax-patches-for-csstree@1.1.4(css-tree@3.2.1)': + '@csstools/css-syntax-patches-for-csstree@1.1.5(css-tree@3.2.1)': optionalDependencies: css-tree: 3.2.1 @@ -9910,7 +9937,7 @@ snapshots: globals: 14.0.0 ignore: 5.3.2 import-fresh: 3.3.1 - js-yaml: 4.1.1 + js-yaml: 4.2.0 minimatch: 3.1.5 strip-json-comments: 3.1.1 transitivePeerDependencies: @@ -9922,16 +9949,16 @@ snapshots: '@eslint/object-schema@3.0.5': {} - '@eslint/plugin-kit@0.7.1': + '@eslint/plugin-kit@0.7.2': dependencies: '@eslint/core': 1.2.1 levn: 0.4.1 '@exodus/bytes@1.15.1': {} - '@firebase/ai@2.12.0(@firebase/app-types@0.9.5)(@firebase/app@0.14.12)': + '@firebase/ai@2.13.0(@firebase/app-types@0.9.5)(@firebase/app@0.14.13)': dependencies: - '@firebase/app': 0.14.12 + '@firebase/app': 0.14.13 '@firebase/app-check-interop-types': 0.3.4 '@firebase/app-types': 0.9.5 '@firebase/component': 0.7.3 @@ -9939,11 +9966,11 @@ snapshots: '@firebase/util': 1.15.1 tslib: 2.8.1 - '@firebase/analytics-compat@0.2.28(@firebase/app-compat@0.5.12)(@firebase/app@0.14.12)': + '@firebase/analytics-compat@0.2.28(@firebase/app-compat@0.5.13)(@firebase/app@0.14.13)': dependencies: - '@firebase/analytics': 0.10.22(@firebase/app@0.14.12) + '@firebase/analytics': 0.10.22(@firebase/app@0.14.13) '@firebase/analytics-types': 0.8.4 - '@firebase/app-compat': 0.5.12 + '@firebase/app-compat': 0.5.13 '@firebase/component': 0.7.3 '@firebase/util': 1.15.1 tslib: 2.8.1 @@ -9952,20 +9979,20 @@ snapshots: '@firebase/analytics-types@0.8.4': {} - '@firebase/analytics@0.10.22(@firebase/app@0.14.12)': + '@firebase/analytics@0.10.22(@firebase/app@0.14.13)': dependencies: - '@firebase/app': 0.14.12 + '@firebase/app': 0.14.13 '@firebase/component': 0.7.3 - '@firebase/installations': 0.6.22(@firebase/app@0.14.12) + '@firebase/installations': 0.6.22(@firebase/app@0.14.13) '@firebase/logger': 0.5.1 '@firebase/util': 1.15.1 tslib: 2.8.1 - '@firebase/app-check-compat@0.4.3(@firebase/app-compat@0.5.12)(@firebase/app@0.14.12)': + '@firebase/app-check-compat@0.4.4(@firebase/app-compat@0.5.13)(@firebase/app@0.14.13)': dependencies: - '@firebase/app-check': 0.11.3(@firebase/app@0.14.12) + '@firebase/app-check': 0.11.4(@firebase/app@0.14.13) '@firebase/app-check-types': 0.5.4 - '@firebase/app-compat': 0.5.12 + '@firebase/app-compat': 0.5.13 '@firebase/component': 0.7.3 '@firebase/logger': 0.5.1 '@firebase/util': 1.15.1 @@ -9977,17 +10004,17 @@ snapshots: '@firebase/app-check-types@0.5.4': {} - '@firebase/app-check@0.11.3(@firebase/app@0.14.12)': + '@firebase/app-check@0.11.4(@firebase/app@0.14.13)': dependencies: - '@firebase/app': 0.14.12 + '@firebase/app': 0.14.13 '@firebase/component': 0.7.3 '@firebase/logger': 0.5.1 '@firebase/util': 1.15.1 tslib: 2.8.1 - '@firebase/app-compat@0.5.12': + '@firebase/app-compat@0.5.13': dependencies: - '@firebase/app': 0.14.12 + '@firebase/app': 0.14.13 '@firebase/component': 0.7.3 '@firebase/logger': 0.5.1 '@firebase/util': 1.15.1 @@ -9997,7 +10024,7 @@ snapshots: dependencies: '@firebase/logger': 0.5.1 - '@firebase/app@0.14.12': + '@firebase/app@0.14.13': dependencies: '@firebase/component': 0.7.3 '@firebase/logger': 0.5.1 @@ -10005,10 +10032,10 @@ snapshots: idb: 7.1.1 tslib: 2.8.1 - '@firebase/auth-compat@0.6.6(@firebase/app-compat@0.5.12)(@firebase/app-types@0.9.5)(@firebase/app@0.14.12)': + '@firebase/auth-compat@0.6.7(@firebase/app-compat@0.5.13)(@firebase/app-types@0.9.5)(@firebase/app@0.14.13)': dependencies: - '@firebase/app-compat': 0.5.12 - '@firebase/auth': 1.13.1(@firebase/app@0.14.12) + '@firebase/app-compat': 0.5.13 + '@firebase/auth': 1.13.2(@firebase/app@0.14.13) '@firebase/auth-types': 0.13.1(@firebase/app-types@0.9.5)(@firebase/util@1.15.1) '@firebase/component': 0.7.3 '@firebase/util': 1.15.1 @@ -10025,9 +10052,9 @@ snapshots: '@firebase/app-types': 0.9.5 '@firebase/util': 1.15.1 - '@firebase/auth@1.13.1(@firebase/app@0.14.12)': + '@firebase/auth@1.13.2(@firebase/app@0.14.13)': dependencies: - '@firebase/app': 0.14.12 + '@firebase/app': 0.14.13 '@firebase/component': 0.7.3 '@firebase/logger': 0.5.1 '@firebase/util': 1.15.1 @@ -10038,9 +10065,9 @@ snapshots: '@firebase/util': 1.15.1 tslib: 2.8.1 - '@firebase/data-connect@0.7.0(@firebase/app@0.14.12)': + '@firebase/data-connect@0.7.1(@firebase/app@0.14.13)': dependencies: - '@firebase/app': 0.14.12 + '@firebase/app': 0.14.13 '@firebase/auth-interop-types': 0.2.5 '@firebase/component': 0.7.3 '@firebase/logger': 0.5.1 @@ -10071,11 +10098,11 @@ snapshots: faye-websocket: 0.11.4 tslib: 2.8.1 - '@firebase/firestore-compat@0.4.9(@firebase/app-compat@0.5.12)(@firebase/app-types@0.9.5)(@firebase/app@0.14.12)': + '@firebase/firestore-compat@0.4.10(@firebase/app-compat@0.5.13)(@firebase/app-types@0.9.5)(@firebase/app@0.14.13)': dependencies: - '@firebase/app-compat': 0.5.12 + '@firebase/app-compat': 0.5.13 '@firebase/component': 0.7.3 - '@firebase/firestore': 4.14.1(@firebase/app@0.14.12) + '@firebase/firestore': 4.15.0(@firebase/app@0.14.13) '@firebase/firestore-types': 3.0.4(@firebase/app-types@0.9.5)(@firebase/util@1.15.1) '@firebase/util': 1.15.1 tslib: 2.8.1 @@ -10088,9 +10115,9 @@ snapshots: '@firebase/app-types': 0.9.5 '@firebase/util': 1.15.1 - '@firebase/firestore@4.14.1(@firebase/app@0.14.12)': + '@firebase/firestore@4.15.0(@firebase/app@0.14.13)': dependencies: - '@firebase/app': 0.14.12 + '@firebase/app': 0.14.13 '@firebase/component': 0.7.3 '@firebase/logger': 0.5.1 '@firebase/util': 1.15.1 @@ -10099,11 +10126,11 @@ snapshots: '@grpc/proto-loader': 0.7.15 tslib: 2.8.1 - '@firebase/functions-compat@0.4.4(@firebase/app-compat@0.5.12)(@firebase/app@0.14.12)': + '@firebase/functions-compat@0.4.5(@firebase/app-compat@0.5.13)(@firebase/app@0.14.13)': dependencies: - '@firebase/app-compat': 0.5.12 + '@firebase/app-compat': 0.5.13 '@firebase/component': 0.7.3 - '@firebase/functions': 0.13.4(@firebase/app@0.14.12) + '@firebase/functions': 0.13.5(@firebase/app@0.14.13) '@firebase/functions-types': 0.6.4 '@firebase/util': 1.15.1 tslib: 2.8.1 @@ -10112,21 +10139,21 @@ snapshots: '@firebase/functions-types@0.6.4': {} - '@firebase/functions@0.13.4(@firebase/app@0.14.12)': + '@firebase/functions@0.13.5(@firebase/app@0.14.13)': dependencies: - '@firebase/app': 0.14.12 + '@firebase/app': 0.14.13 '@firebase/app-check-interop-types': 0.3.4 '@firebase/auth-interop-types': 0.2.5 '@firebase/component': 0.7.3 - '@firebase/messaging-interop-types': 0.2.4 + '@firebase/messaging-interop-types': 0.2.5 '@firebase/util': 1.15.1 tslib: 2.8.1 - '@firebase/installations-compat@0.2.22(@firebase/app-compat@0.5.12)(@firebase/app-types@0.9.5)(@firebase/app@0.14.12)': + '@firebase/installations-compat@0.2.22(@firebase/app-compat@0.5.13)(@firebase/app-types@0.9.5)(@firebase/app@0.14.13)': dependencies: - '@firebase/app-compat': 0.5.12 + '@firebase/app-compat': 0.5.13 '@firebase/component': 0.7.3 - '@firebase/installations': 0.6.22(@firebase/app@0.14.12) + '@firebase/installations': 0.6.22(@firebase/app@0.14.13) '@firebase/installations-types': 0.5.4(@firebase/app-types@0.9.5) '@firebase/util': 1.15.1 tslib: 2.8.1 @@ -10138,9 +10165,9 @@ snapshots: dependencies: '@firebase/app-types': 0.9.5 - '@firebase/installations@0.6.22(@firebase/app@0.14.12)': + '@firebase/installations@0.6.22(@firebase/app@0.14.13)': dependencies: - '@firebase/app': 0.14.12 + '@firebase/app': 0.14.13 '@firebase/component': 0.7.3 '@firebase/util': 1.15.1 idb: 7.1.1 @@ -10150,34 +10177,34 @@ snapshots: dependencies: tslib: 2.8.1 - '@firebase/messaging-compat@0.2.26(@firebase/app-compat@0.5.12)(@firebase/app@0.14.12)': + '@firebase/messaging-compat@0.2.27(@firebase/app-compat@0.5.13)(@firebase/app@0.14.13)': dependencies: - '@firebase/app-compat': 0.5.12 + '@firebase/app-compat': 0.5.13 '@firebase/component': 0.7.3 - '@firebase/messaging': 0.12.26(@firebase/app@0.14.12) + '@firebase/messaging': 0.13.0(@firebase/app@0.14.13) '@firebase/util': 1.15.1 tslib: 2.8.1 transitivePeerDependencies: - '@firebase/app' - '@firebase/messaging-interop-types@0.2.4': {} + '@firebase/messaging-interop-types@0.2.5': {} - '@firebase/messaging@0.12.26(@firebase/app@0.14.12)': + '@firebase/messaging@0.13.0(@firebase/app@0.14.13)': dependencies: - '@firebase/app': 0.14.12 + '@firebase/app': 0.14.13 '@firebase/component': 0.7.3 - '@firebase/installations': 0.6.22(@firebase/app@0.14.12) - '@firebase/messaging-interop-types': 0.2.4 + '@firebase/installations': 0.6.22(@firebase/app@0.14.13) + '@firebase/messaging-interop-types': 0.2.5 '@firebase/util': 1.15.1 idb: 7.1.1 tslib: 2.8.1 - '@firebase/performance-compat@0.2.25(@firebase/app-compat@0.5.12)(@firebase/app@0.14.12)': + '@firebase/performance-compat@0.2.25(@firebase/app-compat@0.5.13)(@firebase/app@0.14.13)': dependencies: - '@firebase/app-compat': 0.5.12 + '@firebase/app-compat': 0.5.13 '@firebase/component': 0.7.3 '@firebase/logger': 0.5.1 - '@firebase/performance': 0.7.12(@firebase/app@0.14.12) + '@firebase/performance': 0.7.12(@firebase/app@0.14.13) '@firebase/performance-types': 0.2.4 '@firebase/util': 1.15.1 tslib: 2.8.1 @@ -10186,22 +10213,22 @@ snapshots: '@firebase/performance-types@0.2.4': {} - '@firebase/performance@0.7.12(@firebase/app@0.14.12)': + '@firebase/performance@0.7.12(@firebase/app@0.14.13)': dependencies: - '@firebase/app': 0.14.12 + '@firebase/app': 0.14.13 '@firebase/component': 0.7.3 - '@firebase/installations': 0.6.22(@firebase/app@0.14.12) + '@firebase/installations': 0.6.22(@firebase/app@0.14.13) '@firebase/logger': 0.5.1 '@firebase/util': 1.15.1 tslib: 2.8.1 web-vitals: 4.2.4 - '@firebase/remote-config-compat@0.2.24(@firebase/app-compat@0.5.12)(@firebase/app@0.14.12)': + '@firebase/remote-config-compat@0.2.25(@firebase/app-compat@0.5.13)(@firebase/app@0.14.13)': dependencies: - '@firebase/app-compat': 0.5.12 + '@firebase/app-compat': 0.5.13 '@firebase/component': 0.7.3 '@firebase/logger': 0.5.1 - '@firebase/remote-config': 0.8.3(@firebase/app@0.14.12) + '@firebase/remote-config': 0.8.4(@firebase/app@0.14.13) '@firebase/remote-config-types': 0.5.1 '@firebase/util': 1.15.1 tslib: 2.8.1 @@ -10210,20 +10237,20 @@ snapshots: '@firebase/remote-config-types@0.5.1': {} - '@firebase/remote-config@0.8.3(@firebase/app@0.14.12)': + '@firebase/remote-config@0.8.4(@firebase/app@0.14.13)': dependencies: - '@firebase/app': 0.14.12 + '@firebase/app': 0.14.13 '@firebase/component': 0.7.3 - '@firebase/installations': 0.6.22(@firebase/app@0.14.12) + '@firebase/installations': 0.6.22(@firebase/app@0.14.13) '@firebase/logger': 0.5.1 '@firebase/util': 1.15.1 tslib: 2.8.1 - '@firebase/storage-compat@0.4.3(@firebase/app-compat@0.5.12)(@firebase/app-types@0.9.5)(@firebase/app@0.14.12)': + '@firebase/storage-compat@0.4.3(@firebase/app-compat@0.5.13)(@firebase/app-types@0.9.5)(@firebase/app@0.14.13)': dependencies: - '@firebase/app-compat': 0.5.12 + '@firebase/app-compat': 0.5.13 '@firebase/component': 0.7.3 - '@firebase/storage': 0.14.3(@firebase/app@0.14.12) + '@firebase/storage': 0.14.3(@firebase/app@0.14.13) '@firebase/storage-types': 0.8.4(@firebase/app-types@0.9.5)(@firebase/util@1.15.1) '@firebase/util': 1.15.1 tslib: 2.8.1 @@ -10236,9 +10263,9 @@ snapshots: '@firebase/app-types': 0.9.5 '@firebase/util': 1.15.1 - '@firebase/storage@0.14.3(@firebase/app@0.14.12)': + '@firebase/storage@0.14.3(@firebase/app@0.14.13)': dependencies: - '@firebase/app': 0.14.12 + '@firebase/app': 0.14.13 '@firebase/component': 0.7.3 '@firebase/util': 1.15.1 tslib: 2.8.1 @@ -10253,36 +10280,36 @@ snapshots: '@glideapps/ts-necessities@2.2.3': {} - '@google-cloud/common@6.0.0(supports-color@10.2.2)': + '@google-cloud/common@6.0.1(supports-color@10.2.2)': dependencies: '@google-cloud/projectify': 4.0.0 '@google-cloud/promisify': 4.1.0 arrify: 2.0.1 duplexify: 4.1.3 extend: 3.0.2 - google-auth-library: 10.6.2(supports-color@10.2.2) + google-auth-library: 10.7.0(supports-color@10.2.2) html-entities: 2.6.0 - retry-request: 8.0.2(supports-color@10.2.2) - teeny-request: 10.1.2(supports-color@10.2.2) + retry-request: 8.0.3(supports-color@10.2.2) + teeny-request: 10.1.3(supports-color@10.2.2) transitivePeerDependencies: - supports-color - '@google-cloud/precise-date@5.0.0': {} + '@google-cloud/precise-date@5.0.1': {} '@google-cloud/projectify@4.0.0': {} - '@google-cloud/projectify@5.0.0': {} + '@google-cloud/projectify@5.0.1': {} '@google-cloud/promisify@4.1.0': {} - '@google-cloud/promisify@5.0.0': {} + '@google-cloud/promisify@5.0.1': {} '@google-cloud/spanner@8.0.0(supports-color@10.2.2)': dependencies: - '@google-cloud/common': 6.0.0(supports-color@10.2.2) - '@google-cloud/precise-date': 5.0.0 - '@google-cloud/projectify': 5.0.0 - '@google-cloud/promisify': 5.0.0 + '@google-cloud/common': 6.0.1(supports-color@10.2.2) + '@google-cloud/precise-date': 5.0.1 + '@google-cloud/projectify': 5.0.1 + '@google-cloud/promisify': 5.0.1 '@grpc/proto-loader': 0.7.15 '@opentelemetry/api': 1.9.1 '@opentelemetry/context-async-hooks': 2.7.1(@opentelemetry/api@1.9.1) @@ -10295,28 +10322,28 @@ snapshots: duplexify: 4.1.3 events-intercept: 2.0.0 extend: 3.0.2 - google-auth-library: 10.6.2(supports-color@10.2.2) - google-gax: 5.0.6(supports-color@10.2.2) - grpc-gcp: 1.0.1(protobufjs@7.6.1) + google-auth-library: 10.7.0(supports-color@10.2.2) + google-gax: 5.0.7(supports-color@10.2.2) + grpc-gcp: 1.0.1(protobufjs@7.6.2) is: 3.3.2 lodash.snakecase: 4.1.1 merge-stream: 2.0.0 p-queue: 6.6.2 - protobufjs: 7.6.1 - retry-request: 8.0.2(supports-color@10.2.2) + protobufjs: 7.6.2 + retry-request: 8.0.3(supports-color@10.2.2) split-array-stream: 2.0.0 stack-trace: 0.0.10 stream-events: 1.0.5 - teeny-request: 10.1.2(supports-color@10.2.2) + teeny-request: 10.1.3(supports-color@10.2.2) through2: 4.0.2 transitivePeerDependencies: - supports-color - '@google/genai@2.6.0(@modelcontextprotocol/sdk@1.29.0(zod@4.4.2))(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6)': + '@google/genai@2.7.0(@modelcontextprotocol/sdk@1.29.0(zod@4.4.2))(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6)': dependencies: - google-auth-library: 10.6.2(supports-color@10.2.2) + google-auth-library: 10.7.0(supports-color@10.2.2) p-retry: 4.6.2 - protobufjs: 7.6.1 + protobufjs: 7.6.2 ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) optionalDependencies: '@modelcontextprotocol/sdk': 1.29.0(zod@4.4.2) @@ -10333,20 +10360,20 @@ snapshots: '@grpc/grpc-js@1.9.16': dependencies: '@grpc/proto-loader': 0.7.15 - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@grpc/proto-loader@0.7.15': dependencies: lodash.camelcase: 4.3.0 long: 5.3.2 - protobufjs: 7.6.1 + protobufjs: 7.6.2 yargs: 17.7.2 '@grpc/proto-loader@0.8.1': dependencies: lodash.camelcase: 4.3.0 long: 5.3.2 - protobufjs: 7.6.1 + protobufjs: 7.6.2 yargs: 17.7.2 '@harperfast/extended-iterable@1.0.3': @@ -10372,36 +10399,36 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} - '@inquirer/ansi@2.0.5': {} + '@inquirer/ansi@2.0.7': {} - '@inquirer/checkbox@5.1.5(@types/node@24.12.4)': + '@inquirer/checkbox@5.2.1(@types/node@24.12.4)': dependencies: - '@inquirer/ansi': 2.0.5 - '@inquirer/core': 11.1.10(@types/node@24.12.4) - '@inquirer/figures': 2.0.5 - '@inquirer/type': 4.0.5(@types/node@24.12.4) + '@inquirer/ansi': 2.0.7 + '@inquirer/core': 11.2.1(@types/node@24.12.4) + '@inquirer/figures': 2.0.7 + '@inquirer/type': 4.0.7(@types/node@24.12.4) optionalDependencies: '@types/node': 24.12.4 '@inquirer/confirm@6.0.12(@types/node@24.12.4)': dependencies: - '@inquirer/core': 11.1.10(@types/node@24.12.4) - '@inquirer/type': 4.0.5(@types/node@24.12.4) + '@inquirer/core': 11.2.1(@types/node@24.12.4) + '@inquirer/type': 4.0.7(@types/node@24.12.4) optionalDependencies: '@types/node': 24.12.4 - '@inquirer/confirm@6.0.13(@types/node@24.12.4)': + '@inquirer/confirm@6.1.1(@types/node@24.12.4)': dependencies: - '@inquirer/core': 11.1.10(@types/node@24.12.4) - '@inquirer/type': 4.0.5(@types/node@24.12.4) + '@inquirer/core': 11.2.1(@types/node@24.12.4) + '@inquirer/type': 4.0.7(@types/node@24.12.4) optionalDependencies: '@types/node': 24.12.4 - '@inquirer/core@11.1.10(@types/node@24.12.4)': + '@inquirer/core@11.2.1(@types/node@24.12.4)': dependencies: - '@inquirer/ansi': 2.0.5 - '@inquirer/figures': 2.0.5 - '@inquirer/type': 4.0.5(@types/node@24.12.4) + '@inquirer/ansi': 2.0.7 + '@inquirer/figures': 2.0.7 + '@inquirer/type': 4.0.7(@types/node@24.12.4) cli-width: 4.1.0 fast-wrap-ansi: 0.2.2 mute-stream: 3.0.0 @@ -10409,107 +10436,107 @@ snapshots: optionalDependencies: '@types/node': 24.12.4 - '@inquirer/editor@5.1.2(@types/node@24.12.4)': + '@inquirer/editor@5.2.2(@types/node@24.12.4)': dependencies: - '@inquirer/core': 11.1.10(@types/node@24.12.4) - '@inquirer/external-editor': 3.0.0(@types/node@24.12.4) - '@inquirer/type': 4.0.5(@types/node@24.12.4) + '@inquirer/core': 11.2.1(@types/node@24.12.4) + '@inquirer/external-editor': 3.0.3(@types/node@24.12.4) + '@inquirer/type': 4.0.7(@types/node@24.12.4) optionalDependencies: '@types/node': 24.12.4 - '@inquirer/expand@5.0.14(@types/node@24.12.4)': + '@inquirer/expand@5.1.1(@types/node@24.12.4)': dependencies: - '@inquirer/core': 11.1.10(@types/node@24.12.4) - '@inquirer/type': 4.0.5(@types/node@24.12.4) + '@inquirer/core': 11.2.1(@types/node@24.12.4) + '@inquirer/type': 4.0.7(@types/node@24.12.4) optionalDependencies: '@types/node': 24.12.4 - '@inquirer/external-editor@3.0.0(@types/node@24.12.4)': + '@inquirer/external-editor@3.0.3(@types/node@24.12.4)': dependencies: chardet: 2.1.1 iconv-lite: 0.7.2 optionalDependencies: '@types/node': 24.12.4 - '@inquirer/figures@2.0.5': {} + '@inquirer/figures@2.0.7': {} - '@inquirer/input@5.0.13(@types/node@24.12.4)': + '@inquirer/input@5.1.2(@types/node@24.12.4)': dependencies: - '@inquirer/core': 11.1.10(@types/node@24.12.4) - '@inquirer/type': 4.0.5(@types/node@24.12.4) + '@inquirer/core': 11.2.1(@types/node@24.12.4) + '@inquirer/type': 4.0.7(@types/node@24.12.4) optionalDependencies: '@types/node': 24.12.4 - '@inquirer/number@4.0.13(@types/node@24.12.4)': + '@inquirer/number@4.1.1(@types/node@24.12.4)': dependencies: - '@inquirer/core': 11.1.10(@types/node@24.12.4) - '@inquirer/type': 4.0.5(@types/node@24.12.4) + '@inquirer/core': 11.2.1(@types/node@24.12.4) + '@inquirer/type': 4.0.7(@types/node@24.12.4) optionalDependencies: '@types/node': 24.12.4 - '@inquirer/password@5.0.13(@types/node@24.12.4)': + '@inquirer/password@5.1.1(@types/node@24.12.4)': dependencies: - '@inquirer/ansi': 2.0.5 - '@inquirer/core': 11.1.10(@types/node@24.12.4) - '@inquirer/type': 4.0.5(@types/node@24.12.4) + '@inquirer/ansi': 2.0.7 + '@inquirer/core': 11.2.1(@types/node@24.12.4) + '@inquirer/type': 4.0.7(@types/node@24.12.4) optionalDependencies: '@types/node': 24.12.4 '@inquirer/prompts@8.4.2(@types/node@24.12.4)': dependencies: - '@inquirer/checkbox': 5.1.5(@types/node@24.12.4) + '@inquirer/checkbox': 5.2.1(@types/node@24.12.4) '@inquirer/confirm': 6.0.12(@types/node@24.12.4) - '@inquirer/editor': 5.1.2(@types/node@24.12.4) - '@inquirer/expand': 5.0.14(@types/node@24.12.4) - '@inquirer/input': 5.0.13(@types/node@24.12.4) - '@inquirer/number': 4.0.13(@types/node@24.12.4) - '@inquirer/password': 5.0.13(@types/node@24.12.4) - '@inquirer/rawlist': 5.2.9(@types/node@24.12.4) - '@inquirer/search': 4.1.9(@types/node@24.12.4) - '@inquirer/select': 5.1.5(@types/node@24.12.4) + '@inquirer/editor': 5.2.2(@types/node@24.12.4) + '@inquirer/expand': 5.1.1(@types/node@24.12.4) + '@inquirer/input': 5.1.2(@types/node@24.12.4) + '@inquirer/number': 4.1.1(@types/node@24.12.4) + '@inquirer/password': 5.1.1(@types/node@24.12.4) + '@inquirer/rawlist': 5.3.1(@types/node@24.12.4) + '@inquirer/search': 4.2.1(@types/node@24.12.4) + '@inquirer/select': 5.2.1(@types/node@24.12.4) optionalDependencies: '@types/node': 24.12.4 - '@inquirer/prompts@8.4.3(@types/node@24.12.4)': - dependencies: - '@inquirer/checkbox': 5.1.5(@types/node@24.12.4) - '@inquirer/confirm': 6.0.13(@types/node@24.12.4) - '@inquirer/editor': 5.1.2(@types/node@24.12.4) - '@inquirer/expand': 5.0.14(@types/node@24.12.4) - '@inquirer/input': 5.0.13(@types/node@24.12.4) - '@inquirer/number': 4.0.13(@types/node@24.12.4) - '@inquirer/password': 5.0.13(@types/node@24.12.4) - '@inquirer/rawlist': 5.2.9(@types/node@24.12.4) - '@inquirer/search': 4.1.9(@types/node@24.12.4) - '@inquirer/select': 5.1.5(@types/node@24.12.4) + '@inquirer/prompts@8.5.2(@types/node@24.12.4)': + dependencies: + '@inquirer/checkbox': 5.2.1(@types/node@24.12.4) + '@inquirer/confirm': 6.1.1(@types/node@24.12.4) + '@inquirer/editor': 5.2.2(@types/node@24.12.4) + '@inquirer/expand': 5.1.1(@types/node@24.12.4) + '@inquirer/input': 5.1.2(@types/node@24.12.4) + '@inquirer/number': 4.1.1(@types/node@24.12.4) + '@inquirer/password': 5.1.1(@types/node@24.12.4) + '@inquirer/rawlist': 5.3.1(@types/node@24.12.4) + '@inquirer/search': 4.2.1(@types/node@24.12.4) + '@inquirer/select': 5.2.1(@types/node@24.12.4) optionalDependencies: '@types/node': 24.12.4 - '@inquirer/rawlist@5.2.9(@types/node@24.12.4)': + '@inquirer/rawlist@5.3.1(@types/node@24.12.4)': dependencies: - '@inquirer/core': 11.1.10(@types/node@24.12.4) - '@inquirer/type': 4.0.5(@types/node@24.12.4) + '@inquirer/core': 11.2.1(@types/node@24.12.4) + '@inquirer/type': 4.0.7(@types/node@24.12.4) optionalDependencies: '@types/node': 24.12.4 - '@inquirer/search@4.1.9(@types/node@24.12.4)': + '@inquirer/search@4.2.1(@types/node@24.12.4)': dependencies: - '@inquirer/core': 11.1.10(@types/node@24.12.4) - '@inquirer/figures': 2.0.5 - '@inquirer/type': 4.0.5(@types/node@24.12.4) + '@inquirer/core': 11.2.1(@types/node@24.12.4) + '@inquirer/figures': 2.0.7 + '@inquirer/type': 4.0.7(@types/node@24.12.4) optionalDependencies: '@types/node': 24.12.4 - '@inquirer/select@5.1.5(@types/node@24.12.4)': + '@inquirer/select@5.2.1(@types/node@24.12.4)': dependencies: - '@inquirer/ansi': 2.0.5 - '@inquirer/core': 11.1.10(@types/node@24.12.4) - '@inquirer/figures': 2.0.5 - '@inquirer/type': 4.0.5(@types/node@24.12.4) + '@inquirer/ansi': 2.0.7 + '@inquirer/core': 11.2.1(@types/node@24.12.4) + '@inquirer/figures': 2.0.7 + '@inquirer/type': 4.0.7(@types/node@24.12.4) optionalDependencies: '@types/node': 24.12.4 - '@inquirer/type@4.0.5(@types/node@24.12.4)': + '@inquirer/type@4.0.7(@types/node@24.12.4)': optionalDependencies: '@types/node': 24.12.4 @@ -10580,58 +10607,58 @@ snapshots: dependencies: tslib: 2.8.1 - '@jsonjoy.com/fs-core@4.57.2(tslib@2.8.1)': + '@jsonjoy.com/fs-core@4.57.6(tslib@2.8.1)': dependencies: - '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.6(tslib@2.8.1) thingies: 2.6.0(tslib@2.8.1) tslib: 2.8.1 - '@jsonjoy.com/fs-fsa@4.57.2(tslib@2.8.1)': + '@jsonjoy.com/fs-fsa@4.57.6(tslib@2.8.1)': dependencies: - '@jsonjoy.com/fs-core': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-core': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.6(tslib@2.8.1) thingies: 2.6.0(tslib@2.8.1) tslib: 2.8.1 - '@jsonjoy.com/fs-node-builtins@4.57.2(tslib@2.8.1)': + '@jsonjoy.com/fs-node-builtins@4.57.6(tslib@2.8.1)': dependencies: tslib: 2.8.1 - '@jsonjoy.com/fs-node-to-fsa@4.57.2(tslib@2.8.1)': + '@jsonjoy.com/fs-node-to-fsa@4.57.6(tslib@2.8.1)': dependencies: - '@jsonjoy.com/fs-fsa': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-fsa': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.6(tslib@2.8.1) tslib: 2.8.1 - '@jsonjoy.com/fs-node-utils@4.57.2(tslib@2.8.1)': + '@jsonjoy.com/fs-node-utils@4.57.6(tslib@2.8.1)': dependencies: - '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.6(tslib@2.8.1) tslib: 2.8.1 - '@jsonjoy.com/fs-node@4.57.2(tslib@2.8.1)': + '@jsonjoy.com/fs-node@4.57.6(tslib@2.8.1)': dependencies: - '@jsonjoy.com/fs-core': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-print': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-snapshot': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-core': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-print': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-snapshot': 4.57.6(tslib@2.8.1) glob-to-regex.js: 1.2.0(tslib@2.8.1) thingies: 2.6.0(tslib@2.8.1) tslib: 2.8.1 - '@jsonjoy.com/fs-print@4.57.2(tslib@2.8.1)': + '@jsonjoy.com/fs-print@4.57.6(tslib@2.8.1)': dependencies: - '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.6(tslib@2.8.1) tree-dump: 1.1.0(tslib@2.8.1) tslib: 2.8.1 - '@jsonjoy.com/fs-snapshot@4.57.2(tslib@2.8.1)': + '@jsonjoy.com/fs-snapshot@4.57.6(tslib@2.8.1)': dependencies: '@jsonjoy.com/buffers': 17.67.0(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.6(tslib@2.8.1) '@jsonjoy.com/json-pack': 17.67.0(tslib@2.8.1) '@jsonjoy.com/util': 17.67.0(tslib@2.8.1) tslib: 2.8.1 @@ -10688,7 +10715,7 @@ snapshots: '@listr2/prompt-adapter-inquirer@4.2.3(@inquirer/prompts@8.4.2(@types/node@24.12.4))(@types/node@24.12.4)(listr2@10.2.1)': dependencies: '@inquirer/prompts': 8.4.2(@types/node@24.12.4) - '@inquirer/type': 4.0.5(@types/node@24.12.4) + '@inquirer/type': 4.0.7(@types/node@24.12.4) listr2: 10.2.1 transitivePeerDependencies: - '@types/node' @@ -10723,7 +10750,7 @@ snapshots: cors: 2.8.6 cross-spawn: 7.0.6 eventsource: 3.0.7 - eventsource-parser: 3.0.8 + eventsource-parser: 3.1.0 express: 5.2.1 express-rate-limit: 8.5.2(express@5.2.1) hono: 4.12.23 @@ -10736,22 +10763,22 @@ snapshots: transitivePeerDependencies: - supports-color - '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4': optional: true - '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3': + '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.4': optional: true - '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3': + '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.4': optional: true - '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3': + '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.4': optional: true - '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3': + '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.4': optional: true - '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': + '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4': optional: true '@mswjs/interceptors@0.41.9': @@ -10856,12 +10883,12 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - '@npmcli/agent@4.0.0': + '@npmcli/agent@4.0.2': dependencies: agent-base: 7.1.4 http-proxy-agent: 7.0.2(supports-color@10.2.2) https-proxy-agent: 7.0.6(supports-color@10.2.2) - lru-cache: 11.5.0 + lru-cache: 11.5.1 socks-proxy-agent: 8.0.5 transitivePeerDependencies: - supports-color @@ -10875,7 +10902,7 @@ snapshots: '@gar/promise-retry': 1.0.3 '@npmcli/promise-spawn': 9.0.1 ini: 6.0.0 - lru-cache: 11.5.0 + lru-cache: 11.5.1 npm-pick-manifest: 11.0.3 proc-log: 6.1.0 semver: 7.7.4 @@ -10909,14 +10936,14 @@ snapshots: '@npmcli/node-gyp': 5.0.0 '@npmcli/package-json': 7.0.5 '@npmcli/promise-spawn': 9.0.1 - node-gyp: 12.3.0 + node-gyp: 12.4.0 proc-log: 6.1.0 '@octokit/auth-app@8.2.0': dependencies: '@octokit/auth-oauth-app': 9.0.3 '@octokit/auth-oauth-user': 6.0.2 - '@octokit/request': 10.0.9 + '@octokit/request': 10.0.10 '@octokit/request-error': 7.1.0 '@octokit/types': 16.0.0 toad-cache: 3.7.1 @@ -10927,14 +10954,14 @@ snapshots: dependencies: '@octokit/auth-oauth-device': 8.0.3 '@octokit/auth-oauth-user': 6.0.2 - '@octokit/request': 10.0.9 + '@octokit/request': 10.0.10 '@octokit/types': 16.0.0 universal-user-agent: 7.0.3 '@octokit/auth-oauth-device@8.0.3': dependencies: '@octokit/oauth-methods': 6.0.2 - '@octokit/request': 10.0.9 + '@octokit/request': 10.0.10 '@octokit/types': 16.0.0 universal-user-agent: 7.0.3 @@ -10942,7 +10969,7 @@ snapshots: dependencies: '@octokit/auth-oauth-device': 8.0.3 '@octokit/oauth-methods': 6.0.2 - '@octokit/request': 10.0.9 + '@octokit/request': 10.0.10 '@octokit/types': 16.0.0 universal-user-agent: 7.0.3 @@ -10952,7 +10979,7 @@ snapshots: dependencies: '@octokit/auth-token': 6.0.0 '@octokit/graphql': 9.0.3 - '@octokit/request': 10.0.9 + '@octokit/request': 10.0.10 '@octokit/request-error': 7.1.0 '@octokit/types': 16.0.0 before-after-hook: 4.0.0 @@ -10965,12 +10992,12 @@ snapshots: '@octokit/graphql-schema@15.26.1': dependencies: - graphql: 16.14.0 - graphql-tag: 2.12.6(graphql@16.14.0) + graphql: 16.14.1 + graphql-tag: 2.12.6(graphql@16.14.1) '@octokit/graphql@9.0.3': dependencies: - '@octokit/request': 10.0.9 + '@octokit/request': 10.0.10 '@octokit/types': 16.0.0 universal-user-agent: 7.0.3 @@ -10979,7 +11006,7 @@ snapshots: '@octokit/oauth-methods@6.0.2': dependencies: '@octokit/oauth-authorization-url': 8.0.0 - '@octokit/request': 10.0.9 + '@octokit/request': 10.0.10 '@octokit/request-error': 7.1.0 '@octokit/types': 16.0.0 @@ -11003,13 +11030,12 @@ snapshots: dependencies: '@octokit/types': 16.0.0 - '@octokit/request@10.0.9': + '@octokit/request@10.0.10': dependencies: '@octokit/endpoint': 11.0.3 '@octokit/request-error': 7.1.0 '@octokit/types': 16.0.0 content-type: 2.0.0 - fast-content-type-parse: 3.0.0 json-with-bigint: 3.5.8 universal-user-agent: 7.0.3 @@ -11320,9 +11346,9 @@ snapshots: optionalDependencies: rollup: 4.60.2 - '@rollup/plugin-commonjs@29.0.2(rollup@4.60.2)': + '@rollup/plugin-commonjs@29.0.3(rollup@4.60.2)': dependencies: - '@rollup/pluginutils': 5.3.0(rollup@4.60.2) + '@rollup/pluginutils': 5.4.0(rollup@4.60.2) commondir: 1.0.1 estree-walker: 2.0.2 fdir: 6.5.0(picomatch@4.0.4) @@ -11334,13 +11360,13 @@ snapshots: '@rollup/plugin-json@6.1.0(rollup@4.60.2)': dependencies: - '@rollup/pluginutils': 5.3.0(rollup@4.60.2) + '@rollup/pluginutils': 5.4.0(rollup@4.60.2) optionalDependencies: rollup: 4.60.2 '@rollup/plugin-node-resolve@16.0.3(rollup@4.60.2)': dependencies: - '@rollup/pluginutils': 5.3.0(rollup@4.60.2) + '@rollup/pluginutils': 5.4.0(rollup@4.60.2) '@types/resolve': 1.20.2 deepmerge: 4.3.1 is-module: 1.0.0 @@ -11356,6 +11382,14 @@ snapshots: optionalDependencies: rollup: 4.60.2 + '@rollup/pluginutils@5.4.0(rollup@4.60.2)': + dependencies: + '@types/estree': 1.0.9 + estree-walker: 2.0.2 + picomatch: 4.0.4 + optionalDependencies: + rollup: 4.60.2 + '@rollup/rollup-android-arm-eabi@4.60.2': optional: true @@ -11453,7 +11487,7 @@ snapshots: '@sigstore/bundle': 4.0.0 '@sigstore/core': 3.2.1 '@sigstore/protobuf-specs': 0.5.1 - make-fetch-happen: 15.0.5 + make-fetch-happen: 15.0.6 proc-log: 6.1.0 transitivePeerDependencies: - supports-color @@ -11486,7 +11520,7 @@ snapshots: '@stylistic/eslint-plugin@5.10.0(eslint@10.3.0(jiti@2.7.0))': dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@10.3.0(jiti@2.7.0)) - '@typescript-eslint/types': 8.59.4 + '@typescript-eslint/types': 8.60.1 eslint: 10.3.0(jiti@2.7.0) eslint-visitor-keys: 4.2.1 espree: 10.4.0 @@ -11541,16 +11575,16 @@ snapshots: '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/bonjour@3.5.13': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/browser-sync@2.29.1': dependencies: '@types/micromatch': 2.3.35 - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/serve-static': 2.2.0 chokidar: 3.6.0 @@ -11561,26 +11595,26 @@ snapshots: '@types/cli-progress@3.11.6': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/connect-history-api-fallback@1.5.4': dependencies: '@types/express-serve-static-core': 4.19.8 - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/connect@3.4.38': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/cors@2.8.19': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/deep-eql@4.0.2': {} '@types/duplexify@3.6.5': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/ejs@3.1.5': {} @@ -11604,14 +11638,14 @@ snapshots: '@types/express-serve-static-core@4.19.8': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/qs': 6.15.1 '@types/range-parser': 1.2.7 '@types/send': 1.2.1 '@types/express-serve-static-core@5.1.1': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/qs': 6.15.1 '@types/range-parser': 1.2.7 '@types/send': 1.2.1 @@ -11633,13 +11667,13 @@ snapshots: '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/http-errors@2.0.5': {} '@types/http-proxy@1.17.17': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/ini@4.1.1': {} @@ -11655,7 +11689,7 @@ snapshots: '@types/karma@6.3.9': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 log4js: 6.9.1 transitivePeerDependencies: - supports-color @@ -11664,7 +11698,7 @@ snapshots: '@types/loader-utils@3.0.0(esbuild@0.28.0)': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 webpack: 5.106.2(esbuild@0.28.0) transitivePeerDependencies: - '@minify-html/node' @@ -11691,10 +11725,10 @@ snapshots: '@types/node-fetch@2.6.13': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 form-data: 4.0.5 - '@types/node@22.19.19': + '@types/node@22.19.20': dependencies: undici-types: 6.21.0 @@ -11706,7 +11740,7 @@ snapshots: '@types/npm-registry-fetch@8.0.9': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/node-fetch': 2.6.13 '@types/npm-package-arg': 6.1.4 '@types/npmlog': 7.0.0 @@ -11714,11 +11748,11 @@ snapshots: '@types/npmlog@7.0.0': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/pacote@11.1.8': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/npm-registry-fetch': 8.0.9 '@types/npmlog': 7.0.0 '@types/ssri': 7.1.5 @@ -11729,12 +11763,12 @@ snapshots: '@types/progress@2.0.7': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/pumpify@1.4.5': dependencies: '@types/duplexify': 3.6.5 - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/qs@6.15.1': {} @@ -11744,7 +11778,7 @@ snapshots: '@types/responselike@1.0.0': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/retry@0.12.0': {} @@ -11755,11 +11789,11 @@ snapshots: '@types/send@0.17.6': dependencies: '@types/mime': 1.3.5 - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/send@1.2.1': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/serve-index@1.9.4': dependencies: @@ -11768,38 +11802,38 @@ snapshots: '@types/serve-static@1.15.10': dependencies: '@types/http-errors': 2.0.5 - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/send': 0.17.6 '@types/serve-static@2.2.0': dependencies: '@types/http-errors': 2.0.5 - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/sockjs@0.3.36': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/ssri@7.1.5': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/stack-trace@0.0.33': {} '@types/tar-stream@3.1.4': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/watchpack@2.4.5': dependencies: '@types/graceful-fs': 4.1.9 - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/which@3.0.4': {} '@types/ws@8.18.1': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/yargs-parser@21.0.3': {} @@ -11811,7 +11845,7 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 optional: true '@typescript-eslint/eslint-plugin@8.59.1(@typescript-eslint/parser@8.59.1(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3)': @@ -11874,7 +11908,7 @@ snapshots: '@typescript-eslint/types@8.59.1': {} - '@typescript-eslint/types@8.59.4': {} + '@typescript-eslint/types@8.60.1': {} '@typescript-eslint/typescript-estree@8.59.1(typescript@6.0.3)': dependencies: @@ -12085,23 +12119,23 @@ snapshots: lodash: 4.18.1 minimatch: 7.4.9 - '@vitejs/plugin-basic-ssl@2.3.0(vite@7.3.2(@types/node@24.12.4)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.3)(yaml@2.9.0))': + '@vitejs/plugin-basic-ssl@2.3.0(vite@7.3.2(@types/node@24.12.4)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.4)(yaml@2.9.0))': dependencies: - vite: 7.3.2(@types/node@24.12.4)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.3)(yaml@2.9.0) + vite: 7.3.2(@types/node@24.12.4)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.4)(yaml@2.9.0) '@vitest/coverage-v8@4.1.5(vitest@4.1.5)': dependencies: '@bcoe/v8-coverage': 1.0.2 '@vitest/utils': 4.1.5 - ast-v8-to-istanbul: 1.0.2 + ast-v8-to-istanbul: 1.0.3 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-reports: 3.2.0 magicast: 0.5.3 - obug: 2.1.1 + obug: 2.1.2 std-env: 4.1.0 tinyrainbow: 3.1.0 - vitest: 4.1.5(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(@vitest/coverage-v8@4.1.5)(jiti@2.7.0)(jsdom@29.1.1)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.3)(yaml@2.9.0) + vitest: 4.1.5(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(@vitest/coverage-v8@4.1.5)(jiti@2.7.0)(jsdom@29.1.1)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.4)(yaml@2.9.0) '@vitest/expect@4.1.5': dependencies: @@ -12112,13 +12146,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.5(vite@7.3.2(@types/node@24.12.4)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.3)(yaml@2.9.0))': + '@vitest/mocker@4.1.5(vite@7.3.2(@types/node@24.12.4)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.4)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.5 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.3.2(@types/node@24.12.4)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.3)(yaml@2.9.0) + vite: 7.3.2(@types/node@24.12.4)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.4)(yaml@2.9.0) '@vitest/pretty-format@4.1.5': dependencies: @@ -12435,7 +12469,7 @@ snapshots: dependencies: tslib: 2.8.1 - ast-v8-to-istanbul@1.0.2: + ast-v8-to-istanbul@1.0.3: dependencies: '@jridgewell/trace-mapping': 0.3.31 estree-walker: 3.0.3 @@ -12458,7 +12492,7 @@ snapshots: autoprefixer@10.5.0(postcss@8.5.13): dependencies: browserslist: 4.28.2 - caniuse-lite: 1.0.30001793 + caniuse-lite: 1.0.30001797 fraction.js: 5.3.4 picocolors: 1.1.1 postcss: 8.5.13 @@ -12517,14 +12551,14 @@ snapshots: balanced-match@4.0.4: {} - bare-events@2.8.3: {} + bare-events@2.9.1: {} - bare-fs@4.7.1: + bare-fs@4.7.2: dependencies: - bare-events: 2.8.3 - bare-path: 3.0.0 - bare-stream: 2.13.1(bare-events@2.8.3) - bare-url: 2.4.3 + bare-events: 2.9.1 + bare-path: 3.0.1 + bare-stream: 2.13.1(bare-events@2.9.1) + bare-url: 2.4.5 fast-fifo: 1.3.2 transitivePeerDependencies: - bare-abort-controller @@ -12532,28 +12566,28 @@ snapshots: bare-os@3.9.1: {} - bare-path@3.0.0: + bare-path@3.0.1: dependencies: bare-os: 3.9.1 - bare-stream@2.13.1(bare-events@2.8.3): + bare-stream@2.13.1(bare-events@2.9.1): dependencies: - streamx: 2.25.0 + streamx: 2.27.0 teex: 1.0.1 optionalDependencies: - bare-events: 2.8.3 + bare-events: 2.9.1 transitivePeerDependencies: - react-native-b4a - bare-url@2.4.3: + bare-url@2.4.5: dependencies: - bare-path: 3.0.0 + bare-path: 3.0.1 base64-js@1.5.1: {} base64id@2.0.0: {} - baseline-browser-mapping@2.10.32: {} + baseline-browser-mapping@2.10.34: {} basic-ftp@5.3.1: {} @@ -12629,7 +12663,7 @@ snapshots: boolbase@1.0.0: {} - brace-expansion@1.1.14: + brace-expansion@1.1.15: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 @@ -12710,10 +12744,10 @@ snapshots: browserslist@4.28.2: dependencies: - baseline-browser-mapping: 2.10.32 - caniuse-lite: 1.0.30001793 - electron-to-chromium: 1.5.361 - node-releases: 2.0.46 + baseline-browser-mapping: 2.10.34 + caniuse-lite: 1.0.30001797 + electron-to-chromium: 1.5.368 + node-releases: 2.0.47 update-browserslist-db: 1.2.3(browserslist@4.28.2) bs-recipes@1.3.4: {} @@ -12746,7 +12780,7 @@ snapshots: '@npmcli/fs': 5.0.0 fs-minipass: 3.0.3 glob: 13.0.6 - lru-cache: 11.5.0 + lru-cache: 11.5.1 minipass: 7.1.3 minipass-collect: 2.0.1 minipass-flush: 1.0.7 @@ -12785,7 +12819,7 @@ snapshots: callsites@3.1.0: {} - caniuse-lite@1.0.30001793: {} + caniuse-lite@1.0.30001797: {} caseless@0.12.0: {} @@ -13006,11 +13040,11 @@ snapshots: object-assign: 4.1.1 vary: 1.1.2 - cosmiconfig@9.0.1(typescript@6.0.3): + cosmiconfig@9.0.2(typescript@6.0.3): dependencies: env-paths: 2.2.1 import-fresh: 3.3.1 - js-yaml: 4.1.1 + js-yaml: 4.2.0 parse-json: 5.2.0 optionalDependencies: typescript: 6.0.3 @@ -13258,7 +13292,7 @@ snapshots: ejs@5.0.2: {} - electron-to-chromium@1.5.361: {} + electron-to-chromium@1.5.368: {} emoji-regex@10.6.0: {} @@ -13297,7 +13331,7 @@ snapshots: engine.io@6.6.8(bufferutil@4.1.0)(utf-8-validate@6.0.6): dependencies: '@types/cors': 2.8.19 - '@types/node': 22.19.19 + '@types/node': 22.19.20 '@types/ws': 8.18.1 accepts: 1.3.8 base64id: 2.0.0 @@ -13311,7 +13345,7 @@ snapshots: - supports-color - utf-8-validate - enhanced-resolve@5.22.0: + enhanced-resolve@5.23.0: dependencies: graceful-fs: 4.2.11 tapable: 2.3.3 @@ -13368,7 +13402,7 @@ snapshots: has-property-descriptors: 1.0.2 has-proto: 1.2.0 has-symbols: 1.1.0 - hasown: 2.0.3 + hasown: 2.0.4 internal-slot: 1.1.0 is-array-buffer: 3.0.5 is-callable: 1.2.7 @@ -13391,15 +13425,15 @@ snapshots: safe-regex-test: 1.1.0 set-proto: 1.0.0 stop-iteration-iterator: 1.1.0 - string.prototype.trim: 1.2.10 - string.prototype.trimend: 1.0.9 + string.prototype.trim: 1.2.11 + string.prototype.trimend: 1.0.10 string.prototype.trimstart: 1.0.8 typed-array-buffer: 1.0.3 typed-array-byte-length: 1.0.3 typed-array-byte-offset: 1.0.4 - typed-array-length: 1.0.7 + typed-array-length: 1.0.8 unbox-primitive: 1.1.0 - which-typed-array: 1.1.20 + which-typed-array: 1.1.22 es-define-property@1.0.1: {} @@ -13416,11 +13450,11 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.3.0 has-tostringtag: 1.0.2 - hasown: 2.0.3 + hasown: 2.0.4 es-shim-unscopables@1.1.0: dependencies: - hasown: 2.0.3 + hasown: 2.0.4 es-to-primitive@1.3.0: dependencies: @@ -13514,7 +13548,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.59.1(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3))(eslint-import-resolver-node@0.3.10)(eslint@10.3.0(jiti@2.7.0)): + eslint-module-utils@2.13.0(@typescript-eslint/parser@8.59.1(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3))(eslint-import-resolver-node@0.3.10)(eslint@10.3.0(jiti@2.7.0)): dependencies: debug: 3.2.7 optionalDependencies: @@ -13535,8 +13569,8 @@ snapshots: doctrine: 2.1.0 eslint: 10.3.0(jiti@2.7.0) eslint-import-resolver-node: 0.3.10 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.59.1(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3))(eslint-import-resolver-node@0.3.10)(eslint@10.3.0(jiti@2.7.0)) - hasown: 2.0.3 + eslint-module-utils: 2.13.0(@typescript-eslint/parser@8.59.1(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3))(eslint-import-resolver-node@0.3.10)(eslint@10.3.0(jiti@2.7.0)) + hasown: 2.0.4 is-core-module: 2.16.2 is-glob: 4.0.3 minimatch: 3.1.5 @@ -13544,7 +13578,7 @@ snapshots: object.groupby: 1.0.3 object.values: 1.2.1 semver: 6.3.1 - string.prototype.trimend: 1.0.9 + string.prototype.trimend: 1.0.10 tsconfig-paths: 3.15.0 optionalDependencies: '@typescript-eslint/parser': 8.59.1(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) @@ -13578,7 +13612,7 @@ snapshots: '@eslint/config-array': 0.23.5 '@eslint/config-helpers': 0.5.5 '@eslint/core': 1.2.1 - '@eslint/plugin-kit': 0.7.1 + '@eslint/plugin-kit': 0.7.2 '@humanfs/node': 0.16.8 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 @@ -13654,17 +13688,17 @@ snapshots: events-universal@1.0.1: dependencies: - bare-events: 2.8.3 + bare-events: 2.9.1 transitivePeerDependencies: - bare-abort-controller events@3.3.0: {} - eventsource-parser@3.0.8: {} + eventsource-parser@3.1.0: {} eventsource@3.0.7: dependencies: - eventsource-parser: 3.0.8 + eventsource-parser: 3.1.0 expect-type@1.3.0: {} @@ -13796,8 +13830,6 @@ snapshots: extsprintf@1.3.0: {} - fast-content-type-parse@3.0.0: {} - fast-deep-equal@3.1.3: {} fast-fifo@1.3.2: {} @@ -13832,7 +13864,7 @@ snapshots: faye-websocket@0.11.4: dependencies: - websocket-driver: 0.7.4 + websocket-driver: 0.7.5 fd-slicer@1.1.0: dependencies: @@ -13914,35 +13946,35 @@ snapshots: locate-path: 6.0.0 path-exists: 4.0.0 - firebase@12.13.0: + firebase@12.14.0: dependencies: - '@firebase/ai': 2.12.0(@firebase/app-types@0.9.5)(@firebase/app@0.14.12) - '@firebase/analytics': 0.10.22(@firebase/app@0.14.12) - '@firebase/analytics-compat': 0.2.28(@firebase/app-compat@0.5.12)(@firebase/app@0.14.12) - '@firebase/app': 0.14.12 - '@firebase/app-check': 0.11.3(@firebase/app@0.14.12) - '@firebase/app-check-compat': 0.4.3(@firebase/app-compat@0.5.12)(@firebase/app@0.14.12) - '@firebase/app-compat': 0.5.12 + '@firebase/ai': 2.13.0(@firebase/app-types@0.9.5)(@firebase/app@0.14.13) + '@firebase/analytics': 0.10.22(@firebase/app@0.14.13) + '@firebase/analytics-compat': 0.2.28(@firebase/app-compat@0.5.13)(@firebase/app@0.14.13) + '@firebase/app': 0.14.13 + '@firebase/app-check': 0.11.4(@firebase/app@0.14.13) + '@firebase/app-check-compat': 0.4.4(@firebase/app-compat@0.5.13)(@firebase/app@0.14.13) + '@firebase/app-compat': 0.5.13 '@firebase/app-types': 0.9.5 - '@firebase/auth': 1.13.1(@firebase/app@0.14.12) - '@firebase/auth-compat': 0.6.6(@firebase/app-compat@0.5.12)(@firebase/app-types@0.9.5)(@firebase/app@0.14.12) - '@firebase/data-connect': 0.7.0(@firebase/app@0.14.12) + '@firebase/auth': 1.13.2(@firebase/app@0.14.13) + '@firebase/auth-compat': 0.6.7(@firebase/app-compat@0.5.13)(@firebase/app-types@0.9.5)(@firebase/app@0.14.13) + '@firebase/data-connect': 0.7.1(@firebase/app@0.14.13) '@firebase/database': 1.1.3 '@firebase/database-compat': 2.1.4 - '@firebase/firestore': 4.14.1(@firebase/app@0.14.12) - '@firebase/firestore-compat': 0.4.9(@firebase/app-compat@0.5.12)(@firebase/app-types@0.9.5)(@firebase/app@0.14.12) - '@firebase/functions': 0.13.4(@firebase/app@0.14.12) - '@firebase/functions-compat': 0.4.4(@firebase/app-compat@0.5.12)(@firebase/app@0.14.12) - '@firebase/installations': 0.6.22(@firebase/app@0.14.12) - '@firebase/installations-compat': 0.2.22(@firebase/app-compat@0.5.12)(@firebase/app-types@0.9.5)(@firebase/app@0.14.12) - '@firebase/messaging': 0.12.26(@firebase/app@0.14.12) - '@firebase/messaging-compat': 0.2.26(@firebase/app-compat@0.5.12)(@firebase/app@0.14.12) - '@firebase/performance': 0.7.12(@firebase/app@0.14.12) - '@firebase/performance-compat': 0.2.25(@firebase/app-compat@0.5.12)(@firebase/app@0.14.12) - '@firebase/remote-config': 0.8.3(@firebase/app@0.14.12) - '@firebase/remote-config-compat': 0.2.24(@firebase/app-compat@0.5.12)(@firebase/app@0.14.12) - '@firebase/storage': 0.14.3(@firebase/app@0.14.12) - '@firebase/storage-compat': 0.4.3(@firebase/app-compat@0.5.12)(@firebase/app-types@0.9.5)(@firebase/app@0.14.12) + '@firebase/firestore': 4.15.0(@firebase/app@0.14.13) + '@firebase/firestore-compat': 0.4.10(@firebase/app-compat@0.5.13)(@firebase/app-types@0.9.5)(@firebase/app@0.14.13) + '@firebase/functions': 0.13.5(@firebase/app@0.14.13) + '@firebase/functions-compat': 0.4.5(@firebase/app-compat@0.5.13)(@firebase/app@0.14.13) + '@firebase/installations': 0.6.22(@firebase/app@0.14.13) + '@firebase/installations-compat': 0.2.22(@firebase/app-compat@0.5.13)(@firebase/app-types@0.9.5)(@firebase/app@0.14.13) + '@firebase/messaging': 0.13.0(@firebase/app@0.14.13) + '@firebase/messaging-compat': 0.2.27(@firebase/app-compat@0.5.13)(@firebase/app@0.14.13) + '@firebase/performance': 0.7.12(@firebase/app@0.14.13) + '@firebase/performance-compat': 0.2.25(@firebase/app-compat@0.5.13)(@firebase/app@0.14.13) + '@firebase/remote-config': 0.8.4(@firebase/app@0.14.13) + '@firebase/remote-config-compat': 0.2.25(@firebase/app-compat@0.5.13)(@firebase/app@0.14.13) + '@firebase/storage': 0.14.3(@firebase/app@0.14.13) + '@firebase/storage-compat': 0.4.3(@firebase/app-compat@0.5.13)(@firebase/app-types@0.9.5)(@firebase/app@0.14.13) '@firebase/util': 1.15.1 transitivePeerDependencies: - '@react-native-async-storage/async-storage' @@ -13985,7 +14017,7 @@ snapshots: asynckit: 0.4.0 combined-stream: 1.0.8 es-set-tostringtag: 2.1.0 - hasown: 2.0.3 + hasown: 2.0.4 mime-types: 2.1.35 formdata-polyfill@4.0.10: @@ -14029,12 +14061,21 @@ snapshots: call-bound: 1.0.4 define-properties: 1.2.1 functions-have-names: 1.2.3 - hasown: 2.0.3 + hasown: 2.0.4 is-callable: 1.2.7 functions-have-names@1.2.3: {} - gaxios@7.1.4(supports-color@10.2.2): + gaxios@7.1.3(supports-color@10.2.2): + dependencies: + extend: 3.0.2 + https-proxy-agent: 7.0.6(supports-color@10.2.2) + node-fetch: 3.3.2 + rimraf: 5.0.10 + transitivePeerDependencies: + - supports-color + + gaxios@7.1.5(supports-color@10.2.2): dependencies: extend: 3.0.2 https-proxy-agent: 7.0.6(supports-color@10.2.2) @@ -14044,7 +14085,15 @@ snapshots: gcp-metadata@8.1.2(supports-color@10.2.2): dependencies: - gaxios: 7.1.4(supports-color@10.2.2) + gaxios: 7.1.5(supports-color@10.2.2) + google-logging-utils: 1.1.3 + json-bigint: 1.0.0 + transitivePeerDependencies: + - supports-color + + gcp-metadata@8.1.3(supports-color@10.2.2): + dependencies: + gaxios: 7.1.3(supports-color@10.2.2) google-logging-utils: 1.1.3 json-bigint: 1.0.0 transitivePeerDependencies: @@ -14068,7 +14117,7 @@ snapshots: get-proto: 1.0.1 gopd: 1.2.0 has-symbols: 1.1.0 - hasown: 2.0.3 + hasown: 2.0.4 math-intrinsics: 1.1.0 get-npm-tarball-url@2.1.0: {} @@ -14149,29 +14198,41 @@ snapshots: define-properties: 1.2.1 gopd: 1.2.0 - google-auth-library@10.6.2(supports-color@10.2.2): + google-auth-library@10.5.0(supports-color@10.2.2): + dependencies: + base64-js: 1.5.1 + ecdsa-sig-formatter: 1.0.11 + gaxios: 7.1.5(supports-color@10.2.2) + gcp-metadata: 8.1.3(supports-color@10.2.2) + google-logging-utils: 1.1.3 + gtoken: 8.0.0(supports-color@10.2.2) + jws: 4.0.1 + transitivePeerDependencies: + - supports-color + + google-auth-library@10.7.0(supports-color@10.2.2): dependencies: base64-js: 1.5.1 ecdsa-sig-formatter: 1.0.11 - gaxios: 7.1.4(supports-color@10.2.2) + gaxios: 7.1.5(supports-color@10.2.2) gcp-metadata: 8.1.2(supports-color@10.2.2) google-logging-utils: 1.1.3 jws: 4.0.1 transitivePeerDependencies: - supports-color - google-gax@5.0.6(supports-color@10.2.2): + google-gax@5.0.7(supports-color@10.2.2): dependencies: '@grpc/grpc-js': 1.14.4 '@grpc/proto-loader': 0.8.1 duplexify: 4.1.3 - google-auth-library: 10.6.2(supports-color@10.2.2) + google-auth-library: 10.5.0(supports-color@10.2.2) google-logging-utils: 1.1.3 node-fetch: 3.3.2 object-hash: 3.0.0 proto3-json-serializer: 3.0.4 - protobufjs: 7.6.1 - retry-request: 8.0.2(supports-color@10.2.2) + protobufjs: 7.6.2 + retry-request: 8.0.3(supports-color@10.2.2) rimraf: 5.0.10 transitivePeerDependencies: - supports-color @@ -14197,17 +14258,24 @@ snapshots: graceful-fs@4.2.11: {} - graphql-tag@2.12.6(graphql@16.14.0): + graphql-tag@2.12.6(graphql@16.14.1): dependencies: - graphql: 16.14.0 + graphql: 16.14.1 tslib: 2.8.1 - graphql@16.14.0: {} + graphql@16.14.1: {} - grpc-gcp@1.0.1(protobufjs@7.6.1): + grpc-gcp@1.0.1(protobufjs@7.6.2): dependencies: '@grpc/grpc-js': 1.14.4 - protobufjs: 7.6.1 + protobufjs: 7.6.2 + + gtoken@8.0.0(supports-color@10.2.2): + dependencies: + gaxios: 7.1.5(supports-color@10.2.2) + jws: 4.0.1 + transitivePeerDependencies: + - supports-color gunzip-maybe@1.4.2: dependencies: @@ -14247,7 +14315,7 @@ snapshots: dependencies: has-symbols: 1.1.0 - hasown@2.0.3: + hasown@2.0.4: dependencies: function-bind: 1.1.2 @@ -14255,7 +14323,7 @@ snapshots: hosted-git-info@9.0.3: dependencies: - lru-cache: 11.5.0 + lru-cache: 11.5.1 hpack.js@2.1.6: dependencies: @@ -14420,7 +14488,7 @@ snapshots: immutable@3.8.3: {} - immutable@5.1.5: {} + immutable@5.1.6: {} import-fresh@3.3.1: dependencies: @@ -14445,7 +14513,7 @@ snapshots: internal-slot@1.1.0: dependencies: es-errors: 1.3.0 - hasown: 2.0.3 + hasown: 2.0.4 side-channel: 1.1.0 ip-address@10.2.0: {} @@ -14487,7 +14555,7 @@ snapshots: is-core-module@2.16.2: dependencies: - hasown: 2.0.3 + hasown: 2.0.4 is-data-view@1.0.2: dependencies: @@ -14582,7 +14650,7 @@ snapshots: call-bound: 1.0.4 gopd: 1.2.0 has-tostringtag: 1.0.2 - hasown: 2.0.3 + hasown: 2.0.4 is-set@2.0.3: {} @@ -14605,7 +14673,7 @@ snapshots: is-typed-array@1.1.15: dependencies: - which-typed-array: 1.1.20 + which-typed-array: 1.1.22 is-typedarray@1.0.0: {} @@ -14716,7 +14784,7 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -14734,6 +14802,10 @@ snapshots: dependencies: argparse: 2.0.1 + js-yaml@4.2.0: + dependencies: + argparse: 2.0.1 + jsbn@0.1.1: {} jsdom@29.1.1: @@ -14741,19 +14813,19 @@ snapshots: '@asamuzakjp/css-color': 5.1.11 '@asamuzakjp/dom-selector': 7.1.1 '@bramus/specificity': 2.4.2 - '@csstools/css-syntax-patches-for-csstree': 1.1.4(css-tree@3.2.1) + '@csstools/css-syntax-patches-for-csstree': 1.1.5(css-tree@3.2.1) '@exodus/bytes': 1.15.1 css-tree: 3.2.1 data-urls: 7.0.0 decimal.js: 10.6.0 html-encoding-sniffer: 6.0.0 is-potential-custom-element-name: 1.0.1 - lru-cache: 11.5.0 + lru-cache: 11.5.1 parse5: 8.0.1 saxes: 6.0.0 symbol-tree: 3.2.4 tough-cookie: 6.0.1 - undici: 7.25.0 + undici: 7.27.2 w3c-xmlserializer: 5.0.0 webidl-conversions: 8.0.1 whatwg-mimetype: 5.0.0 @@ -14890,7 +14962,7 @@ snapshots: rimraf: 3.0.2 socket.io: 4.8.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) source-map: 0.6.1 - tmp: 0.2.5 + tmp: 0.2.7 ua-parser-js: 0.7.41 yargs: 16.2.0 transitivePeerDependencies: @@ -14905,7 +14977,7 @@ snapshots: kind-of@6.0.3: {} - launch-editor@2.13.2: + launch-editor@2.14.1: dependencies: picocolors: 1.1.1 shell-quote: 1.8.4 @@ -14955,7 +15027,7 @@ snapshots: lmdb@3.5.4: dependencies: '@harperfast/extended-iterable': 1.0.3 - msgpackr: 1.11.12 + msgpackr: 1.11.13 node-addon-api: 6.1.0 node-gyp-build-optional-packages: 5.2.2 ordered-binary: 1.6.1 @@ -15051,7 +15123,7 @@ snapshots: lru-cache@10.4.3: {} - lru-cache@11.5.0: {} + lru-cache@11.5.1: {} lru-cache@5.1.1: dependencies: @@ -15079,10 +15151,10 @@ snapshots: dependencies: semver: 7.7.4 - make-fetch-happen@15.0.5: + make-fetch-happen@15.0.6: dependencies: '@gar/promise-retry': 1.0.3 - '@npmcli/agent': 4.0.0 + '@npmcli/agent': 4.0.2 '@npmcli/redact': 4.0.0 cacache: 20.0.4 http-cache-semantics: 4.2.0 @@ -15104,16 +15176,16 @@ snapshots: media-typer@1.1.0: {} - memfs@4.57.2(tslib@2.8.1): + memfs@4.57.6(tslib@2.8.1): dependencies: - '@jsonjoy.com/fs-core': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-fsa': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-node': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-node-to-fsa': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-print': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-snapshot': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-core': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-fsa': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-node': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-node-to-fsa': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-print': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-snapshot': 4.57.6(tslib@2.8.1) '@jsonjoy.com/json-pack': 1.21.0(tslib@2.8.1) '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) glob-to-regex.js: 1.2.0(tslib@2.8.1) @@ -15176,7 +15248,7 @@ snapshots: minimatch@3.1.5: dependencies: - brace-expansion: 1.1.14 + brace-expansion: 1.1.15 minimatch@7.4.6: dependencies: @@ -15242,21 +15314,21 @@ snapshots: ms@2.1.3: {} - msgpackr-extract@3.0.3: + msgpackr-extract@3.0.4: dependencies: node-gyp-build-optional-packages: 5.2.2 optionalDependencies: - '@msgpackr-extract/msgpackr-extract-darwin-arm64': 3.0.3 - '@msgpackr-extract/msgpackr-extract-darwin-x64': 3.0.3 - '@msgpackr-extract/msgpackr-extract-linux-arm': 3.0.3 - '@msgpackr-extract/msgpackr-extract-linux-arm64': 3.0.3 - '@msgpackr-extract/msgpackr-extract-linux-x64': 3.0.3 - '@msgpackr-extract/msgpackr-extract-win32-x64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-darwin-arm64': 3.0.4 + '@msgpackr-extract/msgpackr-extract-darwin-x64': 3.0.4 + '@msgpackr-extract/msgpackr-extract-linux-arm': 3.0.4 + '@msgpackr-extract/msgpackr-extract-linux-arm64': 3.0.4 + '@msgpackr-extract/msgpackr-extract-linux-x64': 3.0.4 + '@msgpackr-extract/msgpackr-extract-win32-x64': 3.0.4 optional: true - msgpackr@1.11.12: + msgpackr@1.11.13: optionalDependencies: - msgpackr-extract: 3.0.3 + msgpackr-extract: 3.0.4 optional: true multicast-dns@7.2.5: @@ -15368,7 +15440,7 @@ snapshots: node-gyp-build@4.8.4: {} - node-gyp@12.3.0: + node-gyp@12.4.0: dependencies: env-paths: 2.2.1 exponential-backoff: 3.1.3 @@ -15376,12 +15448,12 @@ snapshots: nopt: 9.0.0 proc-log: 6.1.0 semver: 7.7.4 - tar: 7.5.15 + tar: 7.5.16 tinyglobby: 0.2.16 - undici: 6.25.0 + undici: 6.26.0 which: 6.0.1 - node-releases@2.0.46: {} + node-releases@2.0.47: {} nopt@9.0.0: dependencies: @@ -15424,7 +15496,7 @@ snapshots: dependencies: '@npmcli/redact': 4.0.0 jsonparse: 1.3.1 - make-fetch-happen: 15.0.5 + make-fetch-happen: 15.0.6 minipass: 7.1.3 minipass-fetch: 5.0.2 minizlib: 3.1.0 @@ -15483,7 +15555,7 @@ snapshots: obuf@1.1.2: {} - obug@2.1.1: {} + obug@2.1.2: {} on-exit-leak-free@2.1.2: {} @@ -15628,7 +15700,7 @@ snapshots: proc-log: 6.1.0 sigstore: 4.1.1 ssri: 13.0.1 - tar: 7.5.15 + tar: 7.5.16 transitivePeerDependencies: - supports-color @@ -15680,7 +15752,7 @@ snapshots: path-scurry@2.0.2: dependencies: - lru-cache: 11.5.0 + lru-cache: 11.5.1 minipass: 7.1.3 path-to-regexp@0.1.13: {} @@ -15735,7 +15807,7 @@ snapshots: real-require: 0.2.0 safe-stable-stringify: 2.5.0 sonic-boom: 4.2.1 - thread-stream: 3.1.0 + thread-stream: 3.2.0 piscina@5.1.4: optionalDependencies: @@ -15767,7 +15839,7 @@ snapshots: postcss-loader@8.2.1(postcss@8.5.13)(typescript@6.0.3)(webpack@5.106.2(esbuild@0.28.0)(postcss@8.5.13)): dependencies: - cosmiconfig: 9.0.1(typescript@6.0.3) + cosmiconfig: 9.0.2(typescript@6.0.3) jiti: 2.7.0 postcss: 8.5.13 semver: 7.7.4 @@ -15844,9 +15916,9 @@ snapshots: proto3-json-serializer@3.0.4: dependencies: - protobufjs: 7.6.1 + protobufjs: 7.6.2 - protobufjs@7.6.1: + protobufjs@7.6.2: dependencies: '@protobufjs/aspromise': 1.1.2 '@protobufjs/base64': 1.1.2 @@ -15858,7 +15930,7 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.1 - '@types/node': 22.19.19 + '@types/node': 22.19.20 long: 5.3.2 proxy-addr@2.0.7: @@ -15925,7 +15997,7 @@ snapshots: dependencies: '@puppeteer/browsers': 2.13.0 chromium-bidi: 14.0.0(devtools-protocol@0.0.1595872) - cosmiconfig: 9.0.1(typescript@6.0.3) + cosmiconfig: 9.0.2(typescript@6.0.3) devtools-protocol: 0.0.1595872 puppeteer-core: 24.42.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) typed-query-selector: 2.12.2 @@ -16132,10 +16204,10 @@ snapshots: onetime: 7.0.0 signal-exit: 4.1.0 - retry-request@8.0.2(supports-color@10.2.2): + retry-request@8.0.3(supports-color@10.2.2): dependencies: extend: 3.0.2 - teeny-request: 10.1.2(supports-color@10.2.2) + teeny-request: 10.1.3(supports-color@10.2.2) transitivePeerDependencies: - supports-color @@ -16192,12 +16264,12 @@ snapshots: optionalDependencies: '@babel/code-frame': 7.29.7 - rollup-plugin-sourcemaps2@0.5.6(@types/node@22.19.19)(rollup@4.60.2): + rollup-plugin-sourcemaps2@0.5.6(@types/node@22.19.20)(rollup@4.60.2): dependencies: '@rollup/pluginutils': 5.3.0(rollup@4.60.2) rollup: 4.60.2 optionalDependencies: - '@types/node': 22.19.19 + '@types/node': 22.19.20 rollup@4.60.2: dependencies: @@ -16289,7 +16361,7 @@ snapshots: sass@1.99.0: dependencies: chokidar: 4.0.3 - immutable: 5.1.5 + immutable: 5.1.6 source-map-js: 1.2.1 optionalDependencies: '@parcel/watcher': 2.5.6 @@ -16324,7 +16396,7 @@ snapshots: semver@7.7.4: {} - semver@7.8.0: {} + semver@7.8.1: {} send@0.19.2: dependencies: @@ -16532,7 +16604,7 @@ snapshots: dependencies: faye-websocket: 0.11.4 uuid: 8.3.2 - websocket-driver: 0.7.4 + websocket-driver: 0.7.5 socks-proxy-agent@8.0.5: dependencies: @@ -16686,7 +16758,7 @@ snapshots: transitivePeerDependencies: - supports-color - streamx@2.25.0: + streamx@2.27.0: dependencies: events-universal: 1.0.1 fast-fifo: 1.3.2 @@ -16720,7 +16792,7 @@ snapshots: get-east-asian-width: 1.6.0 strip-ansi: 7.2.0 - string.prototype.trim@1.2.10: + string.prototype.trim@1.2.11: dependencies: call-bind: 1.0.9 call-bound: 1.0.4 @@ -16729,8 +16801,9 @@ snapshots: es-abstract: 1.24.2 es-object-atoms: 1.1.2 has-property-descriptors: 1.0.2 + safe-regex-test: 1.1.0 - string.prototype.trimend@1.0.9: + string.prototype.trimend@1.0.10: dependencies: call-bind: 1.0.9 call-bound: 1.0.4 @@ -16786,8 +16859,8 @@ snapshots: pump: 3.0.4 tar-stream: 3.2.0 optionalDependencies: - bare-fs: 4.7.1 - bare-path: 3.0.0 + bare-fs: 4.7.2 + bare-path: 3.0.1 transitivePeerDependencies: - bare-abort-controller - bare-buffer @@ -16797,7 +16870,7 @@ snapshots: dependencies: b4a: 1.8.1 fast-fifo: 1.3.2 - streamx: 2.25.0 + streamx: 2.27.0 transitivePeerDependencies: - bare-abort-controller - react-native-b4a @@ -16805,15 +16878,15 @@ snapshots: tar-stream@3.2.0: dependencies: b4a: 1.8.1 - bare-fs: 4.7.1 + bare-fs: 4.7.2 fast-fifo: 1.3.2 - streamx: 2.25.0 + streamx: 2.27.0 transitivePeerDependencies: - bare-abort-controller - bare-buffer - react-native-b4a - tar@7.5.15: + tar@7.5.16: dependencies: '@isaacs/fs-minipass': 4.0.1 chownr: 3.0.0 @@ -16821,7 +16894,7 @@ snapshots: minizlib: 3.1.0 yallist: 5.0.0 - teeny-request@10.1.2(supports-color@10.2.2): + teeny-request@10.1.3(supports-color@10.2.2): dependencies: http-proxy-agent: 7.0.2(supports-color@10.2.2) https-proxy-agent: 7.0.6(supports-color@10.2.2) @@ -16832,12 +16905,12 @@ snapshots: teex@1.0.1: dependencies: - streamx: 2.25.0 + streamx: 2.27.0 transitivePeerDependencies: - bare-abort-controller - react-native-b4a - terser-webpack-plugin@5.6.0(esbuild@0.28.0)(postcss@8.5.13)(webpack@5.106.2(esbuild@0.28.0)(postcss@8.5.13)): + terser-webpack-plugin@5.6.1(esbuild@0.28.0)(postcss@8.5.13)(webpack@5.106.2(esbuild@0.28.0)(postcss@8.5.13)): dependencies: '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 @@ -16848,7 +16921,7 @@ snapshots: esbuild: 0.28.0 postcss: 8.5.13 - terser-webpack-plugin@5.6.0(esbuild@0.28.0)(webpack@5.106.2(esbuild@0.28.0)): + terser-webpack-plugin@5.6.1(esbuild@0.28.0)(webpack@5.106.2(esbuild@0.28.0)): dependencies: '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 @@ -16875,7 +16948,7 @@ snapshots: dependencies: tslib: 2.8.1 - thread-stream@3.1.0: + thread-stream@3.2.0: dependencies: real-require: 0.2.0 @@ -16896,7 +16969,7 @@ snapshots: tinybench@2.9.0: {} - tinyexec@1.2.2: {} + tinyexec@1.2.4: {} tinyglobby@0.2.16: dependencies: @@ -16907,17 +16980,17 @@ snapshots: tldts-core@6.1.86: {} - tldts-core@7.3.1: {} + tldts-core@7.4.2: {} tldts@6.1.86: dependencies: tldts-core: 6.1.86 - tldts@7.3.1: + tldts@7.4.2: dependencies: - tldts-core: 7.3.1 + tldts-core: 7.4.2 - tmp@0.2.5: {} + tmp@0.2.7: {} to-regex-range@5.0.1: dependencies: @@ -16933,7 +17006,7 @@ snapshots: tough-cookie@6.0.1: dependencies: - tldts: 7.3.1 + tldts: 7.4.2 tr46@0.0.3: {} @@ -16960,7 +17033,7 @@ snapshots: tslib@2.8.1: {} - tsx@4.22.3: + tsx@4.22.4: dependencies: esbuild: 0.28.0 optionalDependencies: @@ -16974,7 +17047,7 @@ snapshots: dependencies: '@tufjs/models': 4.1.0 debug: 4.4.3(supports-color@10.2.2) - make-fetch-happen: 15.0.5 + make-fetch-happen: 15.0.6 transitivePeerDependencies: - supports-color @@ -17027,7 +17100,7 @@ snapshots: is-typed-array: 1.1.15 reflect.getprototypeof: 1.0.10 - typed-array-length@1.0.7: + typed-array-length@1.0.8: dependencies: call-bind: 1.0.9 for-each: 0.3.5 @@ -17062,9 +17135,9 @@ snapshots: undici-types@7.16.0: {} - undici@6.25.0: {} + undici@6.26.0: {} - undici@7.25.0: {} + undici@7.27.2: {} undici@8.2.0: {} @@ -17210,7 +17283,7 @@ snapshots: core-util-is: 1.0.2 extsprintf: 1.3.0 - vite@7.3.2(@types/node@24.12.4)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.3)(yaml@2.9.0): + vite@7.3.2(@types/node@24.12.4)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.4)(yaml@2.9.0): dependencies: esbuild: 0.27.7 fdir: 6.5.0(picomatch@4.0.4) @@ -17225,13 +17298,13 @@ snapshots: less: 4.6.4 sass: 1.99.0 terser: 5.46.2 - tsx: 4.22.3 + tsx: 4.22.4 yaml: 2.9.0 - vitest@4.1.5(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(@vitest/coverage-v8@4.1.5)(jiti@2.7.0)(jsdom@29.1.1)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.3)(yaml@2.9.0): + vitest@4.1.5(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(@vitest/coverage-v8@4.1.5)(jiti@2.7.0)(jsdom@29.1.1)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.4)(yaml@2.9.0): dependencies: '@vitest/expect': 4.1.5 - '@vitest/mocker': 4.1.5(vite@7.3.2(@types/node@24.12.4)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.3)(yaml@2.9.0)) + '@vitest/mocker': 4.1.5(vite@7.3.2(@types/node@24.12.4)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.4)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.5 '@vitest/runner': 4.1.5 '@vitest/snapshot': 4.1.5 @@ -17240,15 +17313,15 @@ snapshots: es-module-lexer: 2.1.0 expect-type: 1.3.0 magic-string: 0.30.21 - obug: 2.1.1 + obug: 2.1.2 pathe: 2.0.3 picomatch: 4.0.4 std-env: 4.1.0 tinybench: 2.9.0 - tinyexec: 1.2.2 + tinyexec: 1.2.4 tinyglobby: 0.2.16 tinyrainbow: 3.1.0 - vite: 7.3.2(@types/node@24.12.4)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.3)(yaml@2.9.0) + vite: 7.3.2(@types/node@24.12.4)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(terser@5.46.2)(tsx@4.22.4)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: '@opentelemetry/api': 1.9.1 @@ -17299,7 +17372,7 @@ snapshots: webpack-dev-middleware@7.4.5(tslib@2.8.1)(webpack@5.106.2(esbuild@0.28.0)(postcss@8.5.13)): dependencies: colorette: 2.0.20 - memfs: 4.57.2(tslib@2.8.1) + memfs: 4.57.6(tslib@2.8.1) mime-types: 3.0.2 on-finished: 2.4.1 range-parser: 1.2.1 @@ -17312,7 +17385,7 @@ snapshots: webpack-dev-middleware@7.4.5(tslib@2.8.1)(webpack@5.106.2(esbuild@0.28.0)): dependencies: colorette: 2.0.20 - memfs: 4.57.2(tslib@2.8.1) + memfs: 4.57.6(tslib@2.8.1) mime-types: 3.0.2 on-finished: 2.4.1 range-parser: 1.2.1 @@ -17324,7 +17397,7 @@ snapshots: webpack-dev-middleware@8.0.3(tslib@2.8.1)(webpack@5.106.2(esbuild@0.28.0)(postcss@8.5.13)): dependencies: - memfs: 4.57.2(tslib@2.8.1) + memfs: 4.57.6(tslib@2.8.1) mime-types: 3.0.2 on-finished: 2.4.1 range-parser: 1.2.1 @@ -17354,7 +17427,7 @@ snapshots: graceful-fs: 4.2.11 http-proxy-middleware: 2.0.9(@types/express@4.17.25) ipaddr.js: 2.4.0 - launch-editor: 2.13.2 + launch-editor: 2.14.1 open: 10.2.0 p-retry: 6.2.1 schema-utils: 4.3.3 @@ -17393,7 +17466,7 @@ snapshots: graceful-fs: 4.2.11 http-proxy-middleware: 2.0.9(@types/express@4.17.25) ipaddr.js: 2.4.0 - launch-editor: 2.13.2 + launch-editor: 2.14.1 open: 10.2.0 p-retry: 6.2.1 schema-utils: 4.3.3 @@ -17437,7 +17510,7 @@ snapshots: acorn-import-phases: 1.0.4(acorn@8.16.0) browserslist: 4.28.2 chrome-trace-event: 1.0.4 - enhanced-resolve: 5.22.0 + enhanced-resolve: 5.23.0 es-module-lexer: 2.1.0 eslint-scope: 5.1.1 events: 3.3.0 @@ -17448,7 +17521,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 4.3.3 tapable: 2.3.3 - terser-webpack-plugin: 5.6.0(esbuild@0.28.0)(webpack@5.106.2(esbuild@0.28.0)) + terser-webpack-plugin: 5.6.1(esbuild@0.28.0)(webpack@5.106.2(esbuild@0.28.0)) watchpack: 2.5.1 webpack-sources: 3.5.0 transitivePeerDependencies: @@ -17477,7 +17550,7 @@ snapshots: acorn-import-phases: 1.0.4(acorn@8.16.0) browserslist: 4.28.2 chrome-trace-event: 1.0.4 - enhanced-resolve: 5.22.0 + enhanced-resolve: 5.23.0 es-module-lexer: 2.1.0 eslint-scope: 5.1.1 events: 3.3.0 @@ -17488,7 +17561,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 4.3.3 tapable: 2.3.3 - terser-webpack-plugin: 5.6.0(esbuild@0.28.0)(postcss@8.5.13)(webpack@5.106.2(esbuild@0.28.0)(postcss@8.5.13)) + terser-webpack-plugin: 5.6.1(esbuild@0.28.0)(postcss@8.5.13)(webpack@5.106.2(esbuild@0.28.0)(postcss@8.5.13)) watchpack: 2.5.1 webpack-sources: 3.5.0 transitivePeerDependencies: @@ -17505,7 +17578,7 @@ snapshots: - postcss - uglify-js - websocket-driver@0.7.4: + websocket-driver@0.7.5: dependencies: http-parser-js: 0.5.10 safe-buffer: 5.2.1 @@ -17550,7 +17623,7 @@ snapshots: isarray: 2.0.5 which-boxed-primitive: 1.1.1 which-collection: 1.0.2 - which-typed-array: 1.1.20 + which-typed-array: 1.1.22 which-collection@1.0.2: dependencies: @@ -17559,7 +17632,7 @@ snapshots: is-weakmap: 2.0.2 is-weakset: 2.0.4 - which-typed-array@1.1.20: + which-typed-array@1.1.22: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.9 diff --git a/tests/e2e/assets/19.0-project/package.json b/tests/e2e/assets/19.0-project/package.json deleted file mode 100644 index 7b65d66807a2..000000000000 --- a/tests/e2e/assets/19.0-project/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "nineteen-project", - "version": "0.0.0", - "scripts": { - "ng": "ng", - "start": "ng serve", - "build": "ng build", - "watch": "ng build --watch --configuration development", - "test": "ng test" - }, - "private": true, - "dependencies": { - "@angular/common": "^19.2.0", - "@angular/compiler": "^19.2.0", - "@angular/core": "^19.2.0", - "@angular/forms": "^19.2.0", - "@angular/platform-browser": "^19.2.0", - "@angular/platform-browser-dynamic": "^19.2.0", - "@angular/router": "^19.2.0", - "rxjs": "~7.8.0", - "tslib": "^2.3.0", - "zone.js": "~0.15.0" - }, - "devDependencies": { - "@angular-devkit/build-angular": "^19.2.13", - "@angular/cli": "^19.2.13", - "@angular/compiler-cli": "^19.2.0", - "@types/jasmine": "~5.1.0", - "jasmine-core": "~5.6.0", - "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", - "typescript": "~5.7.2" - } -} diff --git a/tests/e2e/assets/19.0-project/src/app/app.component.spec.ts b/tests/e2e/assets/19.0-project/src/app/app.component.spec.ts deleted file mode 100644 index e390fd7bd137..000000000000 --- a/tests/e2e/assets/19.0-project/src/app/app.component.spec.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { TestBed } from '@angular/core/testing'; -import { AppComponent } from './app.component'; - -describe('AppComponent', () => { - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [AppComponent], - }).compileComponents(); - }); - - it('should create the app', () => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.componentInstance; - expect(app).toBeTruthy(); - }); - - it(`should have the 'nineteen-project' title`, () => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.componentInstance; - expect(app.title).toEqual('nineteen-project'); - }); - - it('should render title', () => { - const fixture = TestBed.createComponent(AppComponent); - fixture.detectChanges(); - const compiled = fixture.nativeElement as HTMLElement; - expect(compiled.querySelector('h1')?.textContent).toContain('Hello, nineteen-project'); - }); -}); diff --git a/tests/e2e/assets/19.0-project/src/app/app.component.ts b/tests/e2e/assets/19.0-project/src/app/app.component.ts deleted file mode 100644 index 620c8a058372..000000000000 --- a/tests/e2e/assets/19.0-project/src/app/app.component.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Component } from '@angular/core'; -import { RouterOutlet } from '@angular/router'; - -@Component({ - selector: 'app-root', - imports: [RouterOutlet], - templateUrl: './app.component.html', - styleUrl: './app.component.css', -}) -export class AppComponent { - title = 'nineteen-project'; -} diff --git a/tests/e2e/assets/19.0-project/src/app/app.config.ts b/tests/e2e/assets/19.0-project/src/app/app.config.ts deleted file mode 100644 index 7afc797fbab7..000000000000 --- a/tests/e2e/assets/19.0-project/src/app/app.config.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; -import { provideRouter } from '@angular/router'; - -import { routes } from './app.routes'; - -export const appConfig: ApplicationConfig = { - providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes)], -}; diff --git a/tests/e2e/assets/19.0-project/src/index.html b/tests/e2e/assets/19.0-project/src/index.html deleted file mode 100644 index f374b0fe3d5e..000000000000 --- a/tests/e2e/assets/19.0-project/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - NineteenProject - - - - - - - - diff --git a/tests/e2e/assets/19.0-project/src/main.ts b/tests/e2e/assets/19.0-project/src/main.ts deleted file mode 100644 index 17447a5dce2c..000000000000 --- a/tests/e2e/assets/19.0-project/src/main.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { bootstrapApplication } from '@angular/platform-browser'; -import { appConfig } from './app/app.config'; -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err)); diff --git a/tests/e2e/assets/19.0-project/.editorconfig b/tests/e2e/assets/20.0-project/.editorconfig similarity index 100% rename from tests/e2e/assets/19.0-project/.editorconfig rename to tests/e2e/assets/20.0-project/.editorconfig diff --git a/tests/e2e/assets/19.0-project/.gitignore b/tests/e2e/assets/20.0-project/.gitignore similarity index 97% rename from tests/e2e/assets/19.0-project/.gitignore rename to tests/e2e/assets/20.0-project/.gitignore index cc7b141350ff..b1d225e26e57 100644 --- a/tests/e2e/assets/19.0-project/.gitignore +++ b/tests/e2e/assets/20.0-project/.gitignore @@ -36,6 +36,7 @@ yarn-error.log /libpeerconnection.log testem.log /typings +__screenshots__/ # System files .DS_Store diff --git a/tests/e2e/assets/20.0-project/.vscode/extensions.json b/tests/e2e/assets/20.0-project/.vscode/extensions.json new file mode 100644 index 000000000000..77b374577de8 --- /dev/null +++ b/tests/e2e/assets/20.0-project/.vscode/extensions.json @@ -0,0 +1,4 @@ +{ + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 + "recommendations": ["angular.ng-template"] +} diff --git a/tests/e2e/assets/20.0-project/.vscode/launch.json b/tests/e2e/assets/20.0-project/.vscode/launch.json new file mode 100644 index 000000000000..925af837050a --- /dev/null +++ b/tests/e2e/assets/20.0-project/.vscode/launch.json @@ -0,0 +1,20 @@ +{ + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "ng serve", + "type": "chrome", + "request": "launch", + "preLaunchTask": "npm: start", + "url": "http://localhost:4200/" + }, + { + "name": "ng test", + "type": "chrome", + "request": "launch", + "preLaunchTask": "npm: test", + "url": "http://localhost:9876/debug.html" + } + ] +} diff --git a/tests/e2e/assets/20.0-project/.vscode/tasks.json b/tests/e2e/assets/20.0-project/.vscode/tasks.json new file mode 100644 index 000000000000..a298b5bd8796 --- /dev/null +++ b/tests/e2e/assets/20.0-project/.vscode/tasks.json @@ -0,0 +1,42 @@ +{ + // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558 + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "start", + "isBackground": true, + "problemMatcher": { + "owner": "typescript", + "pattern": "$tsc", + "background": { + "activeOnStart": true, + "beginsPattern": { + "regexp": "(.*?)" + }, + "endsPattern": { + "regexp": "bundle generation complete" + } + } + } + }, + { + "type": "npm", + "script": "test", + "isBackground": true, + "problemMatcher": { + "owner": "typescript", + "pattern": "$tsc", + "background": { + "activeOnStart": true, + "beginsPattern": { + "regexp": "(.*?)" + }, + "endsPattern": { + "regexp": "bundle generation complete" + } + } + } + } + ] +} diff --git a/tests/e2e/assets/19.0-project/README.md b/tests/e2e/assets/20.0-project/README.md similarity index 96% rename from tests/e2e/assets/19.0-project/README.md rename to tests/e2e/assets/20.0-project/README.md index 80d80f5a3f1f..1f4d992edb5b 100644 --- a/tests/e2e/assets/19.0-project/README.md +++ b/tests/e2e/assets/20.0-project/README.md @@ -1,6 +1,6 @@ -# NineteenProject +# TwentyProject -This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 19.2.13. +This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 20.3.27. ## Development server diff --git a/tests/e2e/assets/19.0-project/angular.json b/tests/e2e/assets/20.0-project/angular.json similarity index 70% rename from tests/e2e/assets/19.0-project/angular.json rename to tests/e2e/assets/20.0-project/angular.json index b435223e9930..6c24b184adf2 100644 --- a/tests/e2e/assets/19.0-project/angular.json +++ b/tests/e2e/assets/20.0-project/angular.json @@ -3,7 +3,7 @@ "version": 1, "newProjectRoot": "projects", "projects": { - "nineteen-project": { + "twenty-project": { "projectType": "application", "schematics": {}, "root": "", @@ -11,12 +11,13 @@ "prefix": "app", "architect": { "build": { - "builder": "@angular-devkit/build-angular:application", + "builder": "@angular/build:application", "options": { - "outputPath": "dist/nineteen-project", - "index": "src/index.html", + "outputPath": "dist/twenty-project", "browser": "src/main.ts", - "polyfills": ["zone.js"], + "polyfills": [ + "zone.js" + ], "tsConfig": "tsconfig.app.json", "assets": [ { @@ -24,8 +25,9 @@ "input": "public" } ], - "styles": ["src/styles.css"], - "scripts": [] + "styles": [ + "src/styles.css" + ] }, "configurations": { "production": { @@ -52,24 +54,27 @@ "defaultConfiguration": "production" }, "serve": { - "builder": "@angular-devkit/build-angular:dev-server", + "builder": "@angular/build:dev-server", "configurations": { "production": { - "buildTarget": "nineteen-project:build:production" + "buildTarget": "twenty-project:build:production" }, "development": { - "buildTarget": "nineteen-project:build:development" + "buildTarget": "twenty-project:build:development" } }, "defaultConfiguration": "development" }, "extract-i18n": { - "builder": "@angular-devkit/build-angular:extract-i18n" + "builder": "@angular/build:extract-i18n" }, "test": { - "builder": "@angular-devkit/build-angular:karma", + "builder": "@angular/build:karma", "options": { - "polyfills": ["zone.js", "zone.js/testing"], + "polyfills": [ + "zone.js", + "zone.js/testing" + ], "tsConfig": "tsconfig.spec.json", "assets": [ { @@ -77,8 +82,9 @@ "input": "public" } ], - "styles": ["src/styles.css"], - "scripts": [] + "styles": [ + "src/styles.css" + ] } } } diff --git a/tests/e2e/assets/20.0-project/package.json b/tests/e2e/assets/20.0-project/package.json new file mode 100644 index 000000000000..dbbe2cd1478a --- /dev/null +++ b/tests/e2e/assets/20.0-project/package.json @@ -0,0 +1,48 @@ +{ + "name": "twenty-project", + "version": "0.0.0", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build", + "watch": "ng build --watch --configuration development", + "test": "ng test" + }, + "prettier": { + "printWidth": 100, + "singleQuote": true, + "overrides": [ + { + "files": "*.html", + "options": { + "parser": "angular" + } + } + ] + }, + "private": true, + "dependencies": { + "@angular/common": "^20.3.0", + "@angular/compiler": "^20.3.0", + "@angular/core": "^20.3.0", + "@angular/forms": "^20.3.0", + "@angular/platform-browser": "^20.3.0", + "@angular/router": "^20.3.0", + "rxjs": "~7.8.0", + "tslib": "^2.3.0", + "zone.js": "~0.15.0" + }, + "devDependencies": { + "@angular/build": "^20.3.27", + "@angular/cli": "^20.3.27", + "@angular/compiler-cli": "^20.3.0", + "@types/jasmine": "~5.1.0", + "jasmine-core": "~5.9.0", + "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", + "typescript": "~5.9.2" + } +} \ No newline at end of file diff --git a/tests/e2e/assets/19.0-project/public/favicon.ico b/tests/e2e/assets/20.0-project/public/favicon.ico similarity index 100% rename from tests/e2e/assets/19.0-project/public/favicon.ico rename to tests/e2e/assets/20.0-project/public/favicon.ico diff --git a/tests/e2e/assets/20.0-project/src/app/app.config.ts b/tests/e2e/assets/20.0-project/src/app/app.config.ts new file mode 100644 index 000000000000..d953f4c41b31 --- /dev/null +++ b/tests/e2e/assets/20.0-project/src/app/app.config.ts @@ -0,0 +1,12 @@ +import { ApplicationConfig, provideBrowserGlobalErrorListeners, provideZoneChangeDetection } from '@angular/core'; +import { provideRouter } from '@angular/router'; + +import { routes } from './app.routes'; + +export const appConfig: ApplicationConfig = { + providers: [ + provideBrowserGlobalErrorListeners(), + provideZoneChangeDetection({ eventCoalescing: true }), + provideRouter(routes) + ] +}; diff --git a/tests/e2e/assets/19.0-project/src/app/app.component.css b/tests/e2e/assets/20.0-project/src/app/app.css similarity index 100% rename from tests/e2e/assets/19.0-project/src/app/app.component.css rename to tests/e2e/assets/20.0-project/src/app/app.css diff --git a/tests/e2e/assets/19.0-project/src/app/app.component.html b/tests/e2e/assets/20.0-project/src/app/app.html similarity index 91% rename from tests/e2e/assets/19.0-project/src/app/app.component.html rename to tests/e2e/assets/20.0-project/src/app/app.html index f8135391366c..752837241913 100644 --- a/tests/e2e/assets/19.0-project/src/app/app.component.html +++ b/tests/e2e/assets/20.0-project/src/app/app.html @@ -36,18 +36,9 @@ --pill-accent: var(--bright-blue); - font-family: - 'Inter', - -apple-system, - BlinkMacSystemFont, - 'Segoe UI', - Roboto, - Helvetica, - Arial, - sans-serif, - 'Apple Color Emoji', - 'Segoe UI Emoji', - 'Segoe UI Symbol'; + font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, + Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", + "Segoe UI Symbol"; box-sizing: border-box; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; @@ -60,18 +51,9 @@ line-height: 100%; letter-spacing: -0.125rem; margin: 0; - font-family: - 'Inter Tight', - -apple-system, - BlinkMacSystemFont, - 'Segoe UI', - Roboto, - Helvetica, - Arial, - sans-serif, - 'Apple Color Emoji', - 'Segoe UI Emoji', - 'Segoe UI Symbol'; + font-family: "Inter Tight", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, + Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", + "Segoe UI Symbol"; } p { @@ -142,6 +124,7 @@ line-height: 1.4rem; letter-spacing: -0.00875rem; text-decoration: none; + white-space: nowrap; } .pill:hover { @@ -152,11 +135,15 @@ --pill-accent: var(--bright-blue); } .pill-group .pill:nth-child(6n + 2) { + --pill-accent: var(--electric-violet); + } + .pill-group .pill:nth-child(6n + 3) { --pill-accent: var(--french-violet); } - .pill-group .pill:nth-child(6n + 3), + .pill-group .pill:nth-child(6n + 4), - .pill-group .pill:nth-child(6n + 5) { + .pill-group .pill:nth-child(6n + 5), + .pill-group .pill:nth-child(6n + 6) { --pill-accent: var(--hot-red); } @@ -227,7 +214,14 @@ - + @@ -236,26 +230,26 @@ -

Hello, {{ title }}

+

Hello, {{ title() }}

Congratulations! Your app is running. 🎉

- @for ( - item of [ - { title: 'Explore the Docs', link: 'https://angular.dev' }, - { title: 'Learn with Tutorials', link: 'https://angular.dev/tutorials' }, - { title: 'CLI Docs', link: 'https://angular.dev/tools/cli' }, - { - title: 'Angular Language Service', - link: 'https://angular.dev/tools/language-service', - }, - { title: 'Angular DevTools', link: 'https://angular.dev/tools/devtools' }, - ]; - track item.title - ) { - + @for (item of [ + { title: 'Explore the Docs', link: 'https://angular.dev' }, + { title: 'Learn with Tutorials', link: 'https://angular.dev/tutorials' }, + { title: 'Prompt and best practices for AI', link: 'https://angular.dev/ai/develop-with-ai'}, + { title: 'CLI Docs', link: 'https://angular.dev/tools/cli' }, + { title: 'Angular Language Service', link: 'https://angular.dev/tools/language-service' }, + { title: 'Angular DevTools', link: 'https://angular.dev/tools/devtools' }, + ]; track item.title) { + {{ item.title }} Hello, {{ title }} /> - + Hello, {{ title }} + diff --git a/tests/e2e/assets/19.0-project/src/app/app.routes.ts b/tests/e2e/assets/20.0-project/src/app/app.routes.ts similarity index 100% rename from tests/e2e/assets/19.0-project/src/app/app.routes.ts rename to tests/e2e/assets/20.0-project/src/app/app.routes.ts diff --git a/tests/e2e/assets/20.0-project/src/app/app.spec.ts b/tests/e2e/assets/20.0-project/src/app/app.spec.ts new file mode 100644 index 000000000000..e2efaa52a155 --- /dev/null +++ b/tests/e2e/assets/20.0-project/src/app/app.spec.ts @@ -0,0 +1,23 @@ +import { TestBed } from '@angular/core/testing'; +import { App } from './app'; + +describe('App', () => { + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [App], + }).compileComponents(); + }); + + it('should create the app', () => { + const fixture = TestBed.createComponent(App); + const app = fixture.componentInstance; + expect(app).toBeTruthy(); + }); + + it('should render title', () => { + const fixture = TestBed.createComponent(App); + fixture.detectChanges(); + const compiled = fixture.nativeElement as HTMLElement; + expect(compiled.querySelector('h1')?.textContent).toContain('Hello, twenty-project'); + }); +}); diff --git a/tests/e2e/assets/20.0-project/src/app/app.ts b/tests/e2e/assets/20.0-project/src/app/app.ts new file mode 100644 index 000000000000..41950ee52c8b --- /dev/null +++ b/tests/e2e/assets/20.0-project/src/app/app.ts @@ -0,0 +1,12 @@ +import { Component, signal } from '@angular/core'; +import { RouterOutlet } from '@angular/router'; + +@Component({ + selector: 'app-root', + imports: [RouterOutlet], + templateUrl: './app.html', + styleUrl: './app.css' +}) +export class App { + protected readonly title = signal('twenty-project'); +} diff --git a/tests/e2e/assets/20.0-project/src/index.html b/tests/e2e/assets/20.0-project/src/index.html new file mode 100644 index 000000000000..72285bc13676 --- /dev/null +++ b/tests/e2e/assets/20.0-project/src/index.html @@ -0,0 +1,13 @@ + + + + + TwentyProject + + + + + + + + diff --git a/tests/e2e/assets/20.0-project/src/main.ts b/tests/e2e/assets/20.0-project/src/main.ts new file mode 100644 index 000000000000..5df75f9c838e --- /dev/null +++ b/tests/e2e/assets/20.0-project/src/main.ts @@ -0,0 +1,6 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { appConfig } from './app/app.config'; +import { App } from './app/app'; + +bootstrapApplication(App, appConfig) + .catch((err) => console.error(err)); diff --git a/tests/e2e/assets/19.0-project/src/styles.css b/tests/e2e/assets/20.0-project/src/styles.css similarity index 100% rename from tests/e2e/assets/19.0-project/src/styles.css rename to tests/e2e/assets/20.0-project/src/styles.css diff --git a/tests/e2e/assets/19.0-project/tsconfig.app.json b/tests/e2e/assets/20.0-project/tsconfig.app.json similarity index 81% rename from tests/e2e/assets/19.0-project/tsconfig.app.json rename to tests/e2e/assets/20.0-project/tsconfig.app.json index 8886e903f8d0..264f459bf876 100644 --- a/tests/e2e/assets/19.0-project/tsconfig.app.json +++ b/tests/e2e/assets/20.0-project/tsconfig.app.json @@ -6,6 +6,10 @@ "outDir": "./out-tsc/app", "types": [] }, - "files": ["src/main.ts"], - "include": ["src/**/*.d.ts"] + "include": [ + "src/**/*.ts" + ], + "exclude": [ + "src/**/*.spec.ts" + ] } diff --git a/tests/e2e/assets/19.0-project/tsconfig.json b/tests/e2e/assets/20.0-project/tsconfig.json similarity index 79% rename from tests/e2e/assets/19.0-project/tsconfig.json rename to tests/e2e/assets/20.0-project/tsconfig.json index 5525117c6744..e4955f26b14b 100644 --- a/tests/e2e/assets/19.0-project/tsconfig.json +++ b/tests/e2e/assets/20.0-project/tsconfig.json @@ -3,7 +3,6 @@ { "compileOnSave": false, "compilerOptions": { - "outDir": "./dist/out-tsc", "strict": true, "noImplicitOverride": true, "noPropertyAccessFromIndexSignature": true, @@ -11,17 +10,25 @@ "noFallthroughCasesInSwitch": true, "skipLibCheck": true, "isolatedModules": true, - "esModuleInterop": true, "experimentalDecorators": true, - "moduleResolution": "bundler", "importHelpers": true, "target": "ES2022", - "module": "ES2022" + "module": "preserve" }, "angularCompilerOptions": { "enableI18nLegacyMessageIdFormat": false, "strictInjectionParameters": true, "strictInputAccessModifiers": true, + "typeCheckHostBindings": true, "strictTemplates": true - } + }, + "files": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] } diff --git a/tests/e2e/assets/19.0-project/tsconfig.spec.json b/tests/e2e/assets/20.0-project/tsconfig.spec.json similarity index 76% rename from tests/e2e/assets/19.0-project/tsconfig.spec.json rename to tests/e2e/assets/20.0-project/tsconfig.spec.json index e00e30e6d4fb..940b30a5fcc8 100644 --- a/tests/e2e/assets/19.0-project/tsconfig.spec.json +++ b/tests/e2e/assets/20.0-project/tsconfig.spec.json @@ -4,7 +4,12 @@ "extends": "./tsconfig.json", "compilerOptions": { "outDir": "./out-tsc/spec", - "types": ["jasmine"] + "types": [ + "jasmine" + ] }, - "include": ["src/**/*.spec.ts", "src/**/*.d.ts"] + "include": [ + "src/**/*.d.ts", + "src/**/*.spec.ts" + ] } diff --git a/tests/e2e/tests/commands/add/add-registry-stripped-schematics.ts b/tests/e2e/tests/commands/add/add-registry-stripped-schematics.ts new file mode 100644 index 000000000000..c6356dc8d92c --- /dev/null +++ b/tests/e2e/tests/commands/add/add-registry-stripped-schematics.ts @@ -0,0 +1,121 @@ +import { join } from 'node:path'; +import { promises as fs } from 'node:fs'; +import { getGlobalVariable } from '../../../utils/env'; +import { expectFileToExist, expectFileNotToExist, rimraf } from '../../../utils/fs'; +import { getActivePackageManager } from '../../../utils/packages'; +import { ng, silentNpm } from '../../../utils/process'; +import { mktempd } from '../../../utils/utils'; + +export default async function () { + const testRegistry = getGlobalVariable('package-registry'); + const tmpRoot = getGlobalVariable('tmp-root'); + + // 1. Create a temp directory for the custom package + const pkgDir = await mktempd('registry-stripped-pkg-', tmpRoot); + + try { + // 2. Write the package files + const packageJson = { + name: '@angular-devkit/ng-add-registry-stripped', + version: '1.0.0', + schematics: './collection.json', + 'ng-add': { + save: false, + }, + }; + + const collectionJson = { + schematics: { + 'ng-add': { + factory: './index.js', + description: 'Add test empty file to your application.', + }, + }, + }; + + const indexJs = ` + exports.default = function() { + return function(tree) { + tree.create('schematic-executed-successfully.txt', 'Registry Stripped schematic works!'); + return tree; + }; + }; + `; + + await fs.writeFile(join(pkgDir, 'package.json'), JSON.stringify(packageJson, null, 2)); + await fs.writeFile(join(pkgDir, 'collection.json'), JSON.stringify(collectionJson, null, 2)); + await fs.writeFile(join(pkgDir, 'index.js'), indexJs); + + // Write a temporary .npmrc with a fake authentication token so that npm publish succeeds + // without needing real credentials or throwing ENEEDAUTH. + const npmrcContent = ` +${testRegistry.replace(/^https?:/, '')}/:_authToken=fake-secret +registry=${testRegistry} +`; + await fs.writeFile(join(pkgDir, '.npmrc'), npmrcContent); + + // 3. Pack the package + const packResult = await silentNpm(['pack'], { cwd: pkgDir }); + const tarballName = packResult.stdout.trim().split('\n').pop() || ''; + + // 4. Publish the package to the local verdaccio registry + // Verdaccio has publish: $all for @angular-devkit/* so this will succeed + await silentNpm(['publish'], { cwd: pkgDir }); + + // 5. Strip "schematics" and "ng-add" from Verdaccio's metadata on disk + const verdaccioDbPath = join( + tmpRoot, + 'registry', + 'storage', + '@angular-devkit', + 'ng-add-registry-stripped', + 'package.json', + ); + + const verdaccioDb = JSON.parse(await fs.readFile(verdaccioDbPath, 'utf-8')); + + // Strip from the top-level versions list + if (verdaccioDb.versions) { + for (const versionKey of Object.keys(verdaccioDb.versions)) { + delete verdaccioDb.versions[versionKey].schematics; + delete verdaccioDb.versions[versionKey]['ng-add']; + } + } + + // Write back the modified metadata + await fs.writeFile(verdaccioDbPath, JSON.stringify(verdaccioDb, null, 2), 'utf-8'); + + // 6. Execute `ng add` on the registry-stripped package + // Ensure file doesn't already exist + await expectFileNotToExist('schematic-executed-successfully.txt'); + + await ng('add', '@angular-devkit/ng-add-registry-stripped', '--skip-confirmation'); + + // 7. Assertions + // A. The schematic executed successfully + await expectFileToExist('schematic-executed-successfully.txt'); + + // B. The dependency was pruned from package.json since save: false + const rootPackageJson = JSON.parse(await fs.readFile('package.json', 'utf-8')); + const hasDep = + (rootPackageJson.dependencies && + rootPackageJson.dependencies['@angular-devkit/ng-add-registry-stripped']) || + (rootPackageJson.devDependencies && + rootPackageJson.devDependencies['@angular-devkit/ng-add-registry-stripped']); + + if (hasDep) { + throw new Error( + 'Package @angular-devkit/ng-add-registry-stripped was not cleaned up from package.json dependencies!', + ); + } + + // C. The dependency was pruned from node_modules physical folder + // Bun intentionally does not prune unreferenced packages from node_modules automatically. + if (getActivePackageManager() !== 'bun') { + await expectFileNotToExist('node_modules/@angular-devkit/ng-add-registry-stripped'); + } + } finally { + // Cleanup temp package source folder + await rimraf(pkgDir); + } +} diff --git a/tests/e2e/tests/commands/add/registry-option.ts b/tests/e2e/tests/commands/add/registry-option.ts index dc336cdd5b30..1343cebf4dd1 100644 --- a/tests/e2e/tests/commands/add/registry-option.ts +++ b/tests/e2e/tests/commands/add/registry-option.ts @@ -1,11 +1,37 @@ import { getGlobalVariable } from '../../../utils/env'; import { expectFileToExist } from '../../../utils/fs'; -import { ng } from '../../../utils/process'; +import { execAndCaptureError, ng } from '../../../utils/process'; import { expectToFail } from '../../../utils/utils'; export default async function () { const testRegistry = getGlobalVariable('package-registry'); + // Validate that a non-URL registry string fails with a validation error + const error = await execAndCaptureError('ng', [ + 'add', + '--registry=not-a-valid-url', + '@angular/pwa', + '--skip-confirmation', + ]); + if (!error.message.includes('Option --registry must be a valid URL.')) { + throw new Error( + `Expected registry validation error, but got different error: ${error.message}`, + ); + } + + // Validate that an empty registry string fails with a validation error + const errorEmpty = await execAndCaptureError('ng', [ + 'add', + '--registry=', + '@angular/pwa', + '--skip-confirmation', + ]); + if (!errorEmpty.message.includes('Option --registry must be a valid URL.')) { + throw new Error( + `Expected registry validation error for empty string, but got: ${errorEmpty.message}`, + ); + } + // Set an invalid registry process.env['NPM_CONFIG_REGISTRY'] = 'http://127.0.0.1:9999'; diff --git a/tests/e2e/tests/commands/add/secure-registry.ts b/tests/e2e/tests/commands/add/secure-registry.ts index 4a640607f8be..e585444b02e4 100644 --- a/tests/e2e/tests/commands/add/secure-registry.ts +++ b/tests/e2e/tests/commands/add/secure-registry.ts @@ -1,5 +1,5 @@ -import { expectFileNotToExist, expectFileToExist, rimraf } from '../../../utils/fs'; -import { getActivePackageManager, installWorkspacePackages } from '../../../utils/packages'; +import { expectFileNotToExist, expectFileToExist } from '../../../utils/fs'; +import { installWorkspacePackages } from '../../../utils/packages'; import { git, ng } from '../../../utils/process'; import { createNpmConfigForAuthentication } from '../../../utils/registry'; import { expectToFail } from '../../../utils/utils'; @@ -9,37 +9,17 @@ export default async function () { try { // The environment variable has priority over the .npmrc delete process.env['NPM_CONFIG_REGISTRY']; - const packageManager = getActivePackageManager(); - const supportsUnscopedAuth = packageManager === 'yarn'; const command = ['add', '@angular/pwa', '--skip-confirmation']; - // Works with unscoped registry authentication details - if (supportsUnscopedAuth) { - // Some package managers such as Bun and NPM do not support unscoped auth. - await createNpmConfigForAuthentication(false); - - await expectFileNotToExist('public/manifest.webmanifest'); - - await ng(...command); - await expectFileToExist('public/manifest.webmanifest'); - await git('clean', '-dxf'); - } - // Works with scoped registry authentication details await expectFileNotToExist('public/manifest.webmanifest'); - await createNpmConfigForAuthentication(true); + await createNpmConfigForAuthentication(); await ng(...command); await expectFileToExist('public/manifest.webmanifest'); await git('clean', '-dxf'); // Invalid authentication token - if (supportsUnscopedAuth) { - // Some package managers such as Bun and NPM do not support unscoped auth. - await createNpmConfigForAuthentication(false, true); - await expectToFail(() => ng(...command)); - } - await createNpmConfigForAuthentication(true, true); await expectToFail(() => ng(...command)); } finally { diff --git a/tests/e2e/tests/update/update-multiple-versions.ts b/tests/e2e/tests/update/update-multiple-versions.ts index 6fecb7b15b58..c9070b1a090b 100644 --- a/tests/e2e/tests/update/update-multiple-versions.ts +++ b/tests/e2e/tests/update/update-multiple-versions.ts @@ -7,7 +7,7 @@ import { expectToFail } from '../../utils/utils'; export default async function () { let restoreRegistry: (() => Promise) | undefined; try { - restoreRegistry = await createProjectFromAsset('19.0-project', true); + restoreRegistry = await createProjectFromAsset('20.0-project', true); await setRegistry(true); const extraArgs = ['--force']; diff --git a/tests/e2e/tests/update/update-pnpm-workspace.ts b/tests/e2e/tests/update/update-pnpm-workspace.ts new file mode 100644 index 000000000000..29aff7bff42a --- /dev/null +++ b/tests/e2e/tests/update/update-pnpm-workspace.ts @@ -0,0 +1,33 @@ +import { createProjectFromAsset } from '../../utils/assets'; +import { readFile, writeFile } from '../../utils/fs'; +import { getActivePackageManager } from '../../utils/packages'; +import { ng } from '../../utils/process'; + +export default async function () { + if (getActivePackageManager() !== 'pnpm') { + return; + } + + let restoreRegistry: (() => Promise) | undefined; + + try { + // Setup project from older asset using the public registry + restoreRegistry = await createProjectFromAsset('20.0-project', true); + + // Create pnpm-workspace.yaml inside the project directory + await writeFile('pnpm-workspace.yaml', "packages:\n - '.'\n"); + + // Run ng update on @angular/cli to trigger the update from version 20 to the next major version + await ng('update', '@angular/cli@21', '@angular/core@21'); + + // Verify that the pnpm lockfile does not contain references to the temporary package directory + const lockfileContent = await readFile('pnpm-lock.yaml'); + if (lockfileContent.includes('angular-cli-tmp-packages-')) { + throw new Error( + 'pnpm-lock.yaml contains reference to temporary package directory, isolation failed!', + ); + } + } finally { + await restoreRegistry?.(); + } +} diff --git a/tests/e2e/tests/update/update-secure-registry.ts b/tests/e2e/tests/update/update-secure-registry.ts index b52d311a622f..3c0a9d468e44 100644 --- a/tests/e2e/tests/update/update-secure-registry.ts +++ b/tests/e2e/tests/update/update-secure-registry.ts @@ -6,9 +6,6 @@ import { getActivePackageManager } from '../../utils/packages'; import assert from 'node:assert'; export default async function () { - const packageManager = getActivePackageManager(); - const supportsUnscopedAuth = packageManager === 'yarn'; - // The environment variable has priority over the .npmrc delete process.env['NPM_CONFIG_REGISTRY']; const worksMessage = 'We analyzed your package.json'; @@ -20,15 +17,7 @@ export default async function () { // Valid authentication token - if (supportsUnscopedAuth) { - await createNpmConfigForAuthentication(false); - const { stdout: stdout1 } = await ng('update', ...extraArgs); - if (!stdout1.includes(worksMessage)) { - throw new Error(`Expected stdout to contain "${worksMessage}"`); - } - } - - await createNpmConfigForAuthentication(true); + await createNpmConfigForAuthentication(); const { stdout: stdout2 } = await ng('update', ...extraArgs); if (!stdout2.includes(worksMessage)) { throw new Error(`Expected stdout to contain "${worksMessage}"`); @@ -36,11 +25,6 @@ export default async function () { // Invalid authentication token - if (supportsUnscopedAuth) { - await createNpmConfigForAuthentication(false, true); - await expectToFail(() => ng('update', ...extraArgs)); - } - await createNpmConfigForAuthentication(true, true); await expectToFail(() => ng('update', ...extraArgs)); diff --git a/tests/e2e/tests/update/update.ts b/tests/e2e/tests/update/update.ts index ae941762d6ca..fd8663503ecc 100644 --- a/tests/e2e/tests/update/update.ts +++ b/tests/e2e/tests/update/update.ts @@ -12,10 +12,10 @@ export default async function () { try { // We need to use the public registry because in the local NPM server we don't have // older versions @angular/cli packages which would cause `npm install` during `ng update` to fail. - restoreRegistry = await createProjectFromAsset('19.0-project', true); + restoreRegistry = await createProjectFromAsset('20.0-project', true); // CLI project version - const cliMajorProjectVersion = 19; + const cliMajorProjectVersion = 20; // If using npm, enable legacy peer deps mode to avoid defects in npm 7+'s peer dependency resolution // Example error where 11.2.14 satisfies the SemVer range ^11.0.0 but still fails: @@ -72,8 +72,8 @@ export default async function () { await ng('update', '@angular/cli', ...extraUpdateArgs); // Setup testing to use CI Chrome. - await useCIChrome('nineteen-project', './'); - await useCIDefaults('nineteen-project'); + await useCIChrome('twenty-project', './'); + await useCIDefaults('twenty-project'); // Run CLI commands. await ng('generate', 'component', 'my-comp'); @@ -81,14 +81,14 @@ export default async function () { await executeBrowserTest({ configuration: 'production', - expectedTitleText: 'Hello, nineteen-project', + expectedTitleText: 'Hello, twenty-project', }); await executeBrowserTest({ configuration: 'development', - expectedTitleText: 'Hello, nineteen-project', + expectedTitleText: 'Hello, twenty-project', }); // Verify project now creates bundles await noSilentNg('build', '--configuration=production'); - await expectFileMatchToExist('dist/nineteen-project/browser', /main-[a-zA-Z0-9]{8}\.js/); + await expectFileMatchToExist('dist/twenty-project/browser', /main-[a-zA-Z0-9]{8}\.js/); } diff --git a/tests/e2e/utils/registry.ts b/tests/e2e/utils/registry.ts index fd557c116120..d8d75b566fb9 100644 --- a/tests/e2e/utils/registry.ts +++ b/tests/e2e/utils/registry.ts @@ -63,7 +63,7 @@ export async function createNpmConfigForAuthentication( * _auth="dGVzdGluZzpzM2NyZXQ="` * ``` */ - scopedAuthentication: boolean, + scopedAuthentication = true, /** When true, an incorrect token is used. Use this to validate authentication failures. */ invalidToken = false, ): Promise {