diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml
new file mode 100644
index 000000000..bcd8ef593
--- /dev/null
+++ b/.github/workflows/claude.yml
@@ -0,0 +1,37 @@
+name: Claude Code
+
+on:
+ issue_comment:
+ types: [created]
+ pull_request_review_comment:
+ types: [created]
+ issues:
+ types: [opened, assigned]
+ pull_request_review:
+ types: [submitted]
+
+jobs:
+ claude:
+ if: |
+ (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
+ (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
+ (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
+ (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ pull-requests: read
+ issues: read
+ id-token: write
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 1
+
+ - name: Run Claude Code
+ id: claude
+ uses: anthropics/claude-code-action@beta
+ with:
+ anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
+
diff --git a/.gitignore b/.gitignore
index dddc42bd7..4aa9fa6cc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -119,4 +119,5 @@ tmp
.nx/workspace-data
*.tsbuildinfo
-
+.cursor/rules/nx-rules.mdc
+.github/instructions/nx.instructions.md
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 000000000..cb6541380
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,33 @@
+# Guidelines for Codex
+
+This repository uses Nx as the task runner. Nx Cloud requires internet access, which is not available in the Codex environment, so **all nx commands must be executed with `NX_NO_CLOUD=true`**.
+
+## Required checks
+
+When modifying rule implementations or documentation, run the following commands and ensure they pass (noting the comments that explain what to do if any of these checks fail):
+
+```bash
+pnpm format-check # run pnpm nx format and commit the result if this check fails
+pnpm nx sync:check # run pnpm nx sync and commit the result if this check fails
+NX_NO_CLOUD=true pnpm nx run-many -t check-rule-docs # run NX_NO_CLOUD=true pnpm nx run-many -t update-rule-docs and commit the result if this check fails
+NX_NO_CLOUD=true pnpm nx run-many -t check-rule-lists # run NX_NO_CLOUD=true pnpm nx run-many -t update-rule-lists and commit the result if this check fails
+NX_NO_CLOUD=true pnpm nx run-many -t check-rule-configs # run NX_NO_CLOUD=true pnpm nx run-many -t update-rule-configs and commit the result if this check fails
+```
+
+Additionally, run tests and lints for any affected project. For example, changes to `eslint-plugin-template` require:
+
+```bash
+NX_NO_CLOUD=true pnpm nx test eslint-plugin-template
+NX_NO_CLOUD=true pnpm nx lint eslint-plugin-template
+```
+
+If there are memory issues with jest tests, try passing `--runInBand` to the test command.
+
+## Commit conventions
+
+Use [Conventional Commits](https://www.conventionalcommits.org/) for commit messages and PR titles.
+
+- When a change affects a single project, include its name as the scope: `feat(eslint-plugin-template): add new rule`.
+- When multiple projects are affected, omit the scope: `fix: correct lint configuration`.
+
+By convention, if only updating a single rule within a single project, for example the `alt-text` rule within the `eslint-plugin-template` project, the commit message should be `fix(eslint-plugin-template): [alt-text] description of the change`.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b2ceeba88..44f4d6797 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,33 @@
+## 19.5.0 (2025-05-25)
+
+### π Features
+
+- **builder:** add stats option ([#2453](https://github.com/angular-eslint/angular-eslint/pull/2453))
+- **eslint-plugin:** introduce sort keys in type-decorator rule ([#2187](https://github.com/angular-eslint/angular-eslint/pull/2187))
+- **eslint-plugin-template:** [no-nested-tags] add rule ([#2398](https://github.com/angular-eslint/angular-eslint/pull/2398))
+- **eslint-plugin-template:** add rule prefer-at-empty ([#2352](https://github.com/angular-eslint/angular-eslint/pull/2352))
+- **schematics:** support --skip-install for ng-add ([#2451](https://github.com/angular-eslint/angular-eslint/pull/2451))
+
+### π©Ή Fixes
+
+- update dependency semver to v7.7.2 ([#2421](https://github.com/angular-eslint/angular-eslint/pull/2421))
+- update typescript-eslint packages to v8.32.1 ([#2422](https://github.com/angular-eslint/angular-eslint/pull/2422))
+- update dependency @angular/compiler to v19.2.13 ([#2438](https://github.com/angular-eslint/angular-eslint/pull/2438))
+- update dependency eslint to v9.27.0 ([#2431](https://github.com/angular-eslint/angular-eslint/pull/2431))
+- **builder:** correct option name in flat config error ([#2443](https://github.com/angular-eslint/angular-eslint/pull/2443))
+- **eslint-plugin-template:** [prefer-template-literal] handle parentheses in autofix ([#2418](https://github.com/angular-eslint/angular-eslint/pull/2418))
+- **eslint-plugin-template:** [alt-text] ensure multiple attributes do not cause false negatives ([#2441](https://github.com/angular-eslint/angular-eslint/pull/2441))
+- **eslint-plugin-template:** [cyclomatic-complexity] handle new control flow syntax ([#2447](https://github.com/angular-eslint/angular-eslint/pull/2447))
+- **eslint-plugin-template:** [prefer-at-empty] remove closing brace from @if when no longer needed ([#2450](https://github.com/angular-eslint/angular-eslint/pull/2450))
+
+### β€οΈ Thank You
+
+- Alexander von Weiss @sod
+- Benjamin SchΓ€ublin
+- Dave @reduckted
+- Guillaume DROUARD
+- James Henry @JamesHenry
+
## 19.4.0 (2025-05-08)
### π Features
diff --git a/docs/CONFIGURING_FLAT_CONFIG.md b/docs/CONFIGURING_FLAT_CONFIG.md
index b988977a1..c6cc1db3b 100644
--- a/docs/CONFIGURING_FLAT_CONFIG.md
+++ b/docs/CONFIGURING_FLAT_CONFIG.md
@@ -192,7 +192,8 @@ module.exports = tseslint.config([
// we already applied the rootConfig above which has them)
files: ['**/*.ts'],
extends: [prettierRecommended], // here we inherit from the recommended setup from eslint-plugin-prettier for TS
- rules: {
+ rules: {},
+ },
{
// Any project level overrides or additional rules for HTML files can go here
// (we don't need to extend from any angular-eslint configs because
diff --git a/docs/MIGRATING_FROM_TSLINT.md b/docs/MIGRATING_FROM_TSLINT.md
index 118f78256..c6ce557ad 100644
--- a/docs/MIGRATING_FROM_TSLINT.md
+++ b/docs/MIGRATING_FROM_TSLINT.md
@@ -42,7 +42,7 @@ If you just have a single project in your workspace you can just run:
ng g @angular-eslint/schematics:convert-tslint-to-eslint
```
-If you have a `projects/` directory or similar in your workspace, you will have multiple entries in your `projects` configuration and you will need to chose which one you want to migrate using the `convert-tslint-to-eslint` schematic:
+If you have a `projects/` directory or similar in your workspace, you will have multiple entries in your `projects` configuration and you will need to choose which one you want to migrate using the `convert-tslint-to-eslint` schematic:
```sh
ng g @angular-eslint/schematics:convert-tslint-to-eslint {{YOUR_PROJECT_NAME_GOES_HERE}}
diff --git a/e2e/src/__snapshots__/inline-template-fixer.test.ts.snap b/e2e/src/__snapshots__/inline-template-fixer.test.ts.snap
index 92fb75f40..907223b4f 100644
--- a/e2e/src/__snapshots__/inline-template-fixer.test.ts.snap
+++ b/e2e/src/__snapshots__/inline-template-fixer.test.ts.snap
@@ -22,7 +22,7 @@ exports[`inline-template-fixer should generate the expected inline template fixe
"@angular/compiler-cli": "^19.X.X",
"@types/jasmine": "~5.1.0",
"angular-eslint": "0.0.0-e2e",
- "eslint": "^9.26.0",
+ "eslint": "^9.27.0",
"jasmine-core": "~5.6.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
@@ -30,6 +30,6 @@ exports[`inline-template-fixer should generate the expected inline template fixe
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"typescript": "~5.X.X",
- "typescript-eslint": "8.32.0"
+ "typescript-eslint": "8.32.1"
}
`;
diff --git a/e2e/src/__snapshots__/new-workspace-create-application-false-ng-add-then-project.test.ts.snap b/e2e/src/__snapshots__/new-workspace-create-application-false-ng-add-then-project.test.ts.snap
index 63b0418df..9df6244be 100644
--- a/e2e/src/__snapshots__/new-workspace-create-application-false-ng-add-then-project.test.ts.snap
+++ b/e2e/src/__snapshots__/new-workspace-create-application-false-ng-add-then-project.test.ts.snap
@@ -7,7 +7,7 @@ exports[`new-workspace-create-application-false-ng-add-then-project should pass
"@angular/compiler-cli": "^19.X.X",
"@types/jasmine": "~5.1.0",
"angular-eslint": "0.0.0-e2e",
- "eslint": "^9.26.0",
+ "eslint": "^9.27.0",
"jasmine-core": "~5.6.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
@@ -15,7 +15,7 @@ exports[`new-workspace-create-application-false-ng-add-then-project should pass
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"typescript": "~5.X.X",
- "typescript-eslint": "8.32.0"
+ "typescript-eslint": "8.32.1"
}
`;
diff --git a/e2e/src/__snapshots__/new-workspace-create-application-false-project-then-ng-add.test.ts.snap b/e2e/src/__snapshots__/new-workspace-create-application-false-project-then-ng-add.test.ts.snap
index b9ee1500d..4212310fb 100644
--- a/e2e/src/__snapshots__/new-workspace-create-application-false-project-then-ng-add.test.ts.snap
+++ b/e2e/src/__snapshots__/new-workspace-create-application-false-project-then-ng-add.test.ts.snap
@@ -7,7 +7,7 @@ exports[`new-workspace-create-application-false-project-then-ng-add should pass
"@angular/compiler-cli": "^19.X.X",
"@types/jasmine": "~5.1.0",
"angular-eslint": "0.0.0-e2e",
- "eslint": "^9.26.0",
+ "eslint": "^9.27.0",
"jasmine-core": "~5.6.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
@@ -15,7 +15,7 @@ exports[`new-workspace-create-application-false-project-then-ng-add should pass
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"typescript": "~5.X.X",
- "typescript-eslint": "8.32.0"
+ "typescript-eslint": "8.32.1"
}
`;
diff --git a/e2e/src/__snapshots__/new-workspace-type-module.test.ts.snap b/e2e/src/__snapshots__/new-workspace-type-module.test.ts.snap
index cffb198ee..717107473 100644
--- a/e2e/src/__snapshots__/new-workspace-type-module.test.ts.snap
+++ b/e2e/src/__snapshots__/new-workspace-type-module.test.ts.snap
@@ -7,7 +7,7 @@ exports[`new-workspace-type-module should pass linting after creating a new work
"@angular/compiler-cli": "^19.X.X",
"@types/jasmine": "~5.1.0",
"angular-eslint": "0.0.0-e2e",
- "eslint": "^9.26.0",
+ "eslint": "^9.27.0",
"jasmine-core": "~5.6.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
@@ -16,7 +16,7 @@ exports[`new-workspace-type-module should pass linting after creating a new work
"karma-jasmine-html-reporter": "~2.1.0",
"ng-packagr": "^19.X.X",
"typescript": "~5.X.X",
- "typescript-eslint": "8.32.0"
+ "typescript-eslint": "8.32.1"
}
`;
diff --git a/e2e/src/__snapshots__/new-workspace.test.ts.snap b/e2e/src/__snapshots__/new-workspace.test.ts.snap
index 8b66528c8..9296c6367 100644
--- a/e2e/src/__snapshots__/new-workspace.test.ts.snap
+++ b/e2e/src/__snapshots__/new-workspace.test.ts.snap
@@ -7,7 +7,7 @@ exports[`new-workspace should pass linting after creating a new workspace from s
"@angular/compiler-cli": "^19.X.X",
"@types/jasmine": "~5.1.0",
"angular-eslint": "0.0.0-e2e",
- "eslint": "^9.26.0",
+ "eslint": "^9.27.0",
"jasmine-core": "~5.6.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
@@ -16,7 +16,7 @@ exports[`new-workspace should pass linting after creating a new workspace from s
"karma-jasmine-html-reporter": "~2.1.0",
"ng-packagr": "^19.X.X",
"typescript": "~5.X.X",
- "typescript-eslint": "8.32.0"
+ "typescript-eslint": "8.32.1"
}
`;
diff --git a/nx.json b/nx.json
index 2ee63d848..f702e5e30 100644
--- a/nx.json
+++ b/nx.json
@@ -1,6 +1,6 @@
{
"$schema": "./node_modules/nx/schemas/nx-schema.json",
- "nxCloudAccessToken": "NzNkMDZiM2MtMzVlOS00YzVlLWE1MGQtNWZlYzI3MjRkOTRmfHJlYWQ=",
+ "nxCloudId": "601e8ec60a30c421b31beed9",
"plugins": [
{
"plugin": "@nx/eslint/plugin",
diff --git a/package.json b/package.json
index 567b204b5..79939e490 100644
--- a/package.json
+++ b/package.json
@@ -3,9 +3,9 @@
"private": true,
"description": "The tooling which enables ESLint to work with Angular projects",
"volta": {
- "node": "20.19.1"
+ "node": "20.19.2"
},
- "packageManager": "pnpm@10.10.0",
+ "packageManager": "pnpm@10.11.0",
"contributors": [
"James Henry "
],
@@ -48,46 +48,46 @@
]
},
"devDependencies": {
- "@angular/cli": "19.2.11",
- "@angular/compiler": "19.2.10",
+ "@angular/cli": "19.2.13",
+ "@angular/compiler": "19.2.13",
"@commitlint/cli": "19.8.1",
"@commitlint/config-conventional": "19.8.1",
- "@mdn/browser-compat-data": "6.0.12",
- "@nx/devkit": "21.0.2",
- "@nx/esbuild": "21.0.2",
- "@nx/eslint": "21.0.2",
- "@nx/eslint-plugin": "21.0.2",
- "@nx/jest": "21.0.2",
- "@nx/js": "21.0.2",
- "@nx/plugin": "21.0.2",
- "@nx/workspace": "21.0.2",
- "@schematics/angular": "19.2.11",
+ "@mdn/browser-compat-data": "6.0.17",
+ "@nx/devkit": "21.1.2",
+ "@nx/esbuild": "21.1.2",
+ "@nx/eslint": "21.1.2",
+ "@nx/eslint-plugin": "21.1.2",
+ "@nx/jest": "21.1.2",
+ "@nx/js": "21.1.2",
+ "@nx/plugin": "21.1.2",
+ "@nx/workspace": "21.1.2",
+ "@schematics/angular": "19.2.13",
"@swc-node/register": "1.10.10",
- "@swc/cli": "0.7.5",
- "@swc/core": "1.11.24",
+ "@swc/cli": "0.7.7",
+ "@swc/core": "1.11.29",
"@swc/helpers": "0.5.17",
"@types/eslint": "9.6.1",
- "@types/eslint-scope": "3.7.7",
+ "@types/eslint-scope": "8.3.0",
"@types/jest": "29.5.14",
- "@types/node": "20.17.45",
+ "@types/node": "20.17.50",
"@types/semver": "^7.5.8",
"@types/yargs": "^17.0.33",
- "@typescript-eslint/rule-tester": "8.32.0",
- "@typescript-eslint/types": "8.32.0",
- "@typescript-eslint/utils": "8.32.0",
+ "@typescript-eslint/rule-tester": "8.32.1",
+ "@typescript-eslint/types": "8.32.1",
+ "@typescript-eslint/utils": "8.32.1",
"cz-conventional-changelog": "3.3.0",
"esbuild": "^0.25.0",
- "eslint": "9.26.0",
- "eslint-config-prettier": "10.1.3",
+ "eslint": "9.27.0",
+ "eslint-config-prettier": "10.1.5",
"execa": "5.1.1",
"husky": "9.1.7",
"jest": "29.7.0",
"json-schema-to-typescript": "15.0.4",
"json-schema-traverse": "1.0.0",
"jsonc-eslint-parser": "^2.1.0",
- "lint-staged": "15.5.2",
+ "lint-staged": "16.0.0",
"ncp": "2.0.0",
- "nx": "21.0.2",
+ "nx": "21.1.2",
"picocolors": "1.1.1",
"prettier": "3.5.3",
"prettier-v2-for-jest-inline-snapshots": "npm:prettier@^2",
@@ -98,7 +98,7 @@
"tslib": "^2.4.1",
"tsx": "^4.7.3",
"typescript": "5.8.3",
- "typescript-eslint": "8.32.0",
+ "typescript-eslint": "8.32.1",
"verdaccio": "6.1.2",
"yargs": "17.7.2"
},
diff --git a/packages/angular-eslint/CHANGELOG.md b/packages/angular-eslint/CHANGELOG.md
index ec32a79d7..a5dca3ec5 100644
--- a/packages/angular-eslint/CHANGELOG.md
+++ b/packages/angular-eslint/CHANGELOG.md
@@ -1,3 +1,17 @@
+## 19.5.0 (2025-05-25)
+
+### π Features
+
+- **eslint-plugin-template:** add rule prefer-at-empty ([#2352](https://github.com/angular-eslint/angular-eslint/pull/2352))
+- **eslint-plugin:** introduce sort keys in type-decorator rule ([#2187](https://github.com/angular-eslint/angular-eslint/pull/2187))
+- **eslint-plugin-template:** [no-nested-tags] add rule ([#2398](https://github.com/angular-eslint/angular-eslint/pull/2398))
+
+### β€οΈ Thank You
+
+- Alexander von Weiss @sod
+- Benjamin SchΓ€ublin
+- Dave @reduckted
+
## 19.4.0 (2025-05-08)
### π Features
diff --git a/packages/angular-eslint/package.json b/packages/angular-eslint/package.json
index 6c876df59..ba76b28e3 100644
--- a/packages/angular-eslint/package.json
+++ b/packages/angular-eslint/package.json
@@ -1,6 +1,6 @@
{
"name": "angular-eslint",
- "version": "19.4.0",
+ "version": "19.5.0",
"description": "The tooling which enables ESLint to work with Angular projects",
"license": "MIT",
"main": "dist/index.js",
diff --git a/packages/angular-eslint/src/configs/template-all.ts b/packages/angular-eslint/src/configs/template-all.ts
index 8598dd46b..82bd87454 100644
--- a/packages/angular-eslint/src/configs/template-all.ts
+++ b/packages/angular-eslint/src/configs/template-all.ts
@@ -37,7 +37,9 @@ export default (
'@angular-eslint/template/no-inline-styles': 'error',
'@angular-eslint/template/no-interpolation-in-attributes': 'error',
'@angular-eslint/template/no-negated-async': 'error',
+ '@angular-eslint/template/no-nested-tags': 'error',
'@angular-eslint/template/no-positive-tabindex': 'error',
+ '@angular-eslint/template/prefer-at-empty': 'error',
'@angular-eslint/template/prefer-contextual-for-variables': 'error',
'@angular-eslint/template/prefer-control-flow': 'error',
'@angular-eslint/template/prefer-ngsrc': 'error',
diff --git a/packages/angular-eslint/src/configs/ts-all.ts b/packages/angular-eslint/src/configs/ts-all.ts
index 2be622fa7..fa71b3684 100644
--- a/packages/angular-eslint/src/configs/ts-all.ts
+++ b/packages/angular-eslint/src/configs/ts-all.ts
@@ -50,6 +50,7 @@ export default (
'@angular-eslint/require-lifecycle-on-prototype': 'error',
'@angular-eslint/require-localize-metadata': 'error',
'@angular-eslint/runtime-localize': 'error',
+ '@angular-eslint/sort-keys-in-type-decorator': 'error',
'@angular-eslint/sort-lifecycle-methods': 'error',
'@angular-eslint/use-component-selector': 'error',
'@angular-eslint/use-component-view-encapsulation': 'error',
diff --git a/packages/builder/CHANGELOG.md b/packages/builder/CHANGELOG.md
index eab9ad61e..540698bae 100644
--- a/packages/builder/CHANGELOG.md
+++ b/packages/builder/CHANGELOG.md
@@ -1,3 +1,17 @@
+## 19.5.0 (2025-05-25)
+
+### π Features
+
+- **builder:** add stats option ([#2453](https://github.com/angular-eslint/angular-eslint/pull/2453))
+
+### π©Ή Fixes
+
+- **builder:** correct option name in flat config error ([#2443](https://github.com/angular-eslint/angular-eslint/pull/2443))
+
+### β€οΈ Thank You
+
+- James Henry @JamesHenry
+
## 19.4.0 (2025-05-08)
This was a version bump only for builder to align it with other projects, there were no code changes.
diff --git a/packages/builder/README.md b/packages/builder/README.md
index cbc81ec1e..f13dc172f 100644
--- a/packages/builder/README.md
+++ b/packages/builder/README.md
@@ -5,3 +5,13 @@ Please see https://github.com/angular-eslint/angular-eslint for full usage instr
The `@angular-eslint/builder` package is a custom Angular CLI builder that allows you to run ESLint on your Angular CLI projects.
It wraps the ESLint programmatic node API (https://eslint.org/docs/latest/integrate/nodejs-api) to provide a seamless experience via `ng lint` that is closely equivalent to using the `eslint` CLI directly.
+
+## Performance statistics
+
+You can profile rule execution times by enabling ESLint's stats output:
+
+```bash
+ng lint --stats
+```
+
+This option requires a flat ESLint configuration (`eslint.config.js/ts/mjs`). Using `--stats` with legacy `.eslintrc.*` files will cause an error.
diff --git a/packages/builder/package.json b/packages/builder/package.json
index 93cf90b9c..37cb62da2 100644
--- a/packages/builder/package.json
+++ b/packages/builder/package.json
@@ -1,6 +1,6 @@
{
"name": "@angular-eslint/builder",
- "version": "19.4.0",
+ "version": "19.5.0",
"description": "Angular CLI builder for ESLint",
"license": "MIT",
"main": "dist/index.js",
diff --git a/packages/builder/src/lint.impl.spec.ts b/packages/builder/src/lint.impl.spec.ts
index 8ea1e128c..cf344917a 100644
--- a/packages/builder/src/lint.impl.spec.ts
+++ b/packages/builder/src/lint.impl.spec.ts
@@ -83,6 +83,7 @@ function createValidRunBuilderOptions(
silent: false,
ignorePath: null,
outputFile: null,
+ stats: false,
noEslintrc: false,
rulesdir: [],
resolvePluginsRelativeTo: null,
@@ -171,6 +172,7 @@ describe('Linter Builder', () => {
format: 'stylish',
force: false,
silent: false,
+ stats: false,
maxWarnings: -1,
outputFile: null,
ignorePath: null,
@@ -195,6 +197,7 @@ describe('Linter Builder', () => {
format: 'stylish',
force: false,
silent: false,
+ stats: false,
useEslintrc: null,
maxWarnings: -1,
outputFile: null,
@@ -233,6 +236,7 @@ describe('Linter Builder', () => {
format: 'stylish',
force: false,
silent: false,
+ stats: false,
useEslintrc: null,
maxWarnings: -1,
outputFile: null,
@@ -271,6 +275,7 @@ describe('Linter Builder', () => {
format: 'stylish',
force: false,
silent: false,
+ stats: false,
useEslintrc: null,
maxWarnings: -1,
outputFile: null,
@@ -309,6 +314,7 @@ describe('Linter Builder', () => {
format: 'stylish',
force: false,
silent: false,
+ stats: false,
useEslintrc: null,
maxWarnings: -1,
outputFile: null,
@@ -760,4 +766,48 @@ describe('Linter Builder', () => {
mockFormatter.format(mockReports),
);
});
+
+ it('should pass stats option to resolveAndInstantiateESLint', async () => {
+ jest.spyOn(fs, 'existsSync').mockImplementation((path: any) => {
+ if (basename(path) === 'eslint.config.js') {
+ return true;
+ }
+ return false;
+ });
+
+ await runBuilder(
+ createValidRunBuilderOptions({
+ stats: true,
+ }),
+ );
+
+ expect(mockResolveAndInstantiateESLint).toHaveBeenCalledTimes(1);
+ expect(mockResolveAndInstantiateESLint).toHaveBeenCalledWith(
+ undefined,
+ {
+ stats: true, // stats pass through correctly
+ lintFilePatterns: [],
+ eslintConfig: null,
+ exclude: ['excludedFile1'],
+ fix: true,
+ quiet: false,
+ cache: true,
+ cacheLocation: `cacheLocation1${sep}??>`,
+ cacheStrategy: 'content',
+ format: 'stylish',
+ force: false,
+ silent: false,
+ useEslintrc: null,
+ maxWarnings: -1,
+ outputFile: null,
+ ignorePath: null,
+ noEslintrc: false,
+ noConfigLookup: null,
+ rulesdir: [],
+ resolvePluginsRelativeTo: null,
+ reportUnusedDisableDirectives: null,
+ },
+ true, // useFlatConfig
+ );
+ });
});
diff --git a/packages/builder/src/schema.d.ts b/packages/builder/src/schema.d.ts
index 3909d9884..f788fdb44 100644
--- a/packages/builder/src/schema.d.ts
+++ b/packages/builder/src/schema.d.ts
@@ -14,6 +14,7 @@ export interface Schema extends JsonObject {
eslintConfig: string | null;
ignorePath: string | null;
outputFile: string | null;
+ stats: boolean;
noEslintrc: boolean;
rulesdir: string[];
resolvePluginsRelativeTo: string | null;
diff --git a/packages/builder/src/schema.json b/packages/builder/src/schema.json
index c1fa862f2..38b97ff22 100644
--- a/packages/builder/src/schema.json
+++ b/packages/builder/src/schema.json
@@ -26,6 +26,11 @@
"type": "string",
"description": "File to write report to instead of the console."
},
+ "stats": {
+ "type": "boolean",
+ "description": "Output performance statistics for ESLint rules",
+ "default": false
+ },
"cacheStrategy": {
"type": "string",
"description": "Strategy to use for detecting changed files in the cache.",
diff --git a/packages/builder/src/utils/eslint-utils.spec.ts b/packages/builder/src/utils/eslint-utils.spec.ts
index bad04b7a7..9c591ba9d 100644
--- a/packages/builder/src/utils/eslint-utils.spec.ts
+++ b/packages/builder/src/utils/eslint-utils.spec.ts
@@ -2,7 +2,12 @@ jest.mock('eslint', () => ({
ESLint: jest.fn(),
}));
+jest.mock('eslint/use-at-your-own-risk', () => ({
+ FlatESLint: jest.fn(),
+}));
+
import { ESLint } from 'eslint';
+import { FlatESLint } from 'eslint/use-at-your-own-risk';
import { resolveAndInstantiateESLint } from './eslint-utils';
describe('eslint-utils', () => {
@@ -211,4 +216,35 @@ describe('eslint-utils', () => {
);
});
});
+
+ describe('stats option', () => {
+ it('should create the ESLint instance with "stats" set to true when using flat config', async () => {
+ await resolveAndInstantiateESLint(
+ './eslint.config.js',
+ {
+ stats: true,
+ } as any,
+ true,
+ );
+ expect(FlatESLint).toHaveBeenCalledWith({
+ cache: false,
+ cacheLocation: undefined,
+ cacheStrategy: undefined,
+ errorOnUnmatchedPattern: false,
+ fix: false,
+ overrideConfigFile: './eslint.config.js',
+ stats: true,
+ });
+ });
+
+ it('should throw when "stats" is used with eslintrc config', async () => {
+ await expect(
+ resolveAndInstantiateESLint(
+ './.eslintrc.json',
+ { stats: true } as any,
+ false,
+ ),
+ ).rejects.toThrow('The --stats option requires ESLint Flat Config');
+ });
+ });
});
diff --git a/packages/builder/src/utils/eslint-utils.ts b/packages/builder/src/utils/eslint-utils.ts
index 7e75ee105..3d3fe9e45 100644
--- a/packages/builder/src/utils/eslint-utils.ts
+++ b/packages/builder/src/utils/eslint-utils.ts
@@ -33,6 +33,9 @@ export async function resolveAndInstantiateESLint(
options: Schema,
useFlatConfig = false,
) {
+ if (options.stats && !useFlatConfig) {
+ throw new Error('The --stats option requires ESLint Flat Config');
+ }
if (
useFlatConfig &&
eslintConfigPath &&
@@ -63,6 +66,7 @@ export async function resolveAndInstantiateESLint(
};
if (useFlatConfig) {
+ eslintOptions.stats = !!options.stats;
if (typeof options.useEslintrc !== 'undefined') {
throw new Error(
'For Flat Config, the `useEslintrc` option is not applicable. See https://eslint.org/docs/latest/use/configure/configuration-files-new',
@@ -80,7 +84,7 @@ export async function resolveAndInstantiateESLint(
}
if (options.reportUnusedDisableDirectives) {
throw new Error(
- 'For Flat Config, ESLint removed `reportedUnusedDisableDirectives` and so it is not supported as an option. See https://eslint.org/docs/latest/use/configure/configuration-files-new',
+ 'For Flat Config, ESLint removed `reportUnusedDisableDirectives` and so it is not supported as an option. See https://eslint.org/docs/latest/use/configure/configuration-files-new',
);
}
diff --git a/packages/bundled-angular-compiler/CHANGELOG.md b/packages/bundled-angular-compiler/CHANGELOG.md
index fc51d5781..ea6ecdb1c 100644
--- a/packages/bundled-angular-compiler/CHANGELOG.md
+++ b/packages/bundled-angular-compiler/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 19.5.0 (2025-05-25)
+
+This was a version bump only for bundled-angular-compiler to align it with other projects, there were no code changes.
+
## 19.4.0 (2025-05-08)
This was a version bump only for bundled-angular-compiler to align it with other projects, there were no code changes.
diff --git a/packages/bundled-angular-compiler/package.json b/packages/bundled-angular-compiler/package.json
index e851e2f9c..1464184e2 100644
--- a/packages/bundled-angular-compiler/package.json
+++ b/packages/bundled-angular-compiler/package.json
@@ -1,6 +1,6 @@
{
"name": "@angular-eslint/bundled-angular-compiler",
- "version": "19.4.0",
+ "version": "19.5.0",
"description": "A CJS bundled version of @angular/compiler",
"license": "MIT",
"main": "dist/index.js",
diff --git a/packages/eslint-plugin-template/CHANGELOG.md b/packages/eslint-plugin-template/CHANGELOG.md
index c3adb7cd9..4b92162aa 100644
--- a/packages/eslint-plugin-template/CHANGELOG.md
+++ b/packages/eslint-plugin-template/CHANGELOG.md
@@ -1,3 +1,24 @@
+## 19.5.0 (2025-05-25)
+
+### π Features
+
+- **eslint-plugin-template:** add rule prefer-at-empty ([#2352](https://github.com/angular-eslint/angular-eslint/pull/2352))
+- **eslint-plugin-template:** [no-nested-tags] add rule ([#2398](https://github.com/angular-eslint/angular-eslint/pull/2398))
+
+### π©Ή Fixes
+
+- **eslint-plugin-template:** [prefer-at-empty] remove closing brace from @if when no longer needed ([#2450](https://github.com/angular-eslint/angular-eslint/pull/2450))
+- **eslint-plugin-template:** [cyclomatic-complexity] handle new control flow syntax ([#2447](https://github.com/angular-eslint/angular-eslint/pull/2447))
+- **eslint-plugin-template:** [alt-text] ensure multiple attributes do not cause false negatives ([#2441](https://github.com/angular-eslint/angular-eslint/pull/2441))
+- **eslint-plugin-template:** [prefer-template-literal] handle parentheses in autofix ([#2418](https://github.com/angular-eslint/angular-eslint/pull/2418))
+
+### β€οΈ Thank You
+
+- Alexander von Weiss @sod
+- Dave @reduckted
+- Guillaume DROUARD
+- James Henry @JamesHenry
+
## 19.4.0 (2025-05-08)
### π Features
diff --git a/packages/eslint-plugin-template/README.md b/packages/eslint-plugin-template/README.md
index f28cb7178..f49602f07 100644
--- a/packages/eslint-plugin-template/README.md
+++ b/packages/eslint-plugin-template/README.md
@@ -23,6 +23,7 @@ Please see https://github.com/angular-eslint/angular-eslint for full usage instr
| Rule | Description | :white_check_mark: | :wrench: | :bulb: | :accessibility: |
| --- | --- | --- | --- | --- | --- |
| [`no-duplicate-attributes`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/no-duplicate-attributes.md) | Ensures that there are no duplicate input properties or output event listeners | | | :bulb: | |
+| [`no-nested-tags`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/no-nested-tags.md) | Denies nesting of and tags. | | | | |
@@ -61,6 +62,7 @@ Please see https://github.com/angular-eslint/angular-eslint for full usage instr
| [`no-interpolation-in-attributes`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/no-interpolation-in-attributes.md) | Ensures that property-binding is used instead of interpolation in attributes. | | | | |
| [`no-negated-async`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/no-negated-async.md) | Ensures that async pipe results, as well as values used with the async pipe, are not negated | :white_check_mark: | | :bulb: | |
| [`no-positive-tabindex`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/no-positive-tabindex.md) | Ensures that the `tabindex` attribute is not positive | | | :bulb: | |
+| [`prefer-at-empty`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/prefer-at-empty.md) | Prefer using `@empty` with `@for` loops instead of a separate `@if` or `@else` block to reduce code and make it easier to read. | | :wrench: | | |
| [`prefer-contextual-for-variables`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/prefer-contextual-for-variables.md) | Ensures that contextual variables are used in @for blocks where possible instead of aliasing them. | | :wrench: | | |
| [`prefer-control-flow`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/prefer-control-flow.md) | Ensures that the built-in control flow is used. | | | | |
| [`prefer-ngsrc`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/prefer-ngsrc.md) | Ensures ngSrc is used instead of src for img elements | | | | |
diff --git a/packages/eslint-plugin-template/docs/rules/alt-text.md b/packages/eslint-plugin-template/docs/rules/alt-text.md
index 4da71cb96..b94efbf4b 100644
--- a/packages/eslint-plugin-template/docs/rules/alt-text.md
+++ b/packages/eslint-plugin-template/docs/rules/alt-text.md
@@ -408,6 +408,32 @@ The rule does not have any configuration options.
#### β
Valid Code
+```html
+
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/alt-text": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
```html
```
@@ -486,6 +512,32 @@ The rule does not have any configuration options.
#### β
Valid Code
+```html
+
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/alt-text": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
```html
```
@@ -568,6 +620,110 @@ The rule does not have any configuration options.
```
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/alt-text": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/alt-text": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/alt-text": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/alt-text": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+
+```
+
diff --git a/packages/eslint-plugin-template/docs/rules/cyclomatic-complexity.md b/packages/eslint-plugin-template/docs/rules/cyclomatic-complexity.md
index a8e048c67..931e74775 100644
--- a/packages/eslint-plugin-template/docs/rules/cyclomatic-complexity.md
+++ b/packages/eslint-plugin-template/docs/rules/cyclomatic-complexity.md
@@ -132,6 +132,42 @@ interface Options {
```
+
+
+---
+
+
+
+#### Custom Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/cyclomatic-complexity": [
+ "error",
+ {
+ "maxComplexity": 3
+ }
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (cond) {
+ @for (item of items; track item.id) {
+ @switch (item) {
+ @case ('a') {}
+ @default {}
+ }
+ }
+}
+```
+
@@ -241,6 +277,103 @@ interface Options {
```
+
+
+---
+
+
+
+#### Custom Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/cyclomatic-complexity": [
+ "error",
+ {
+ "maxComplexity": 1
+ }
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+@if (condition) {
+ Content
+} @else {
+ Other
+}
+```
+
+
+
+---
+
+
+
+#### Custom Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/cyclomatic-complexity": [
+ "error",
+ {
+ "maxComplexity": 1
+ }
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+@for (item of items; track item.id) {
+ {{ item }}
+}
+```
+
+
+
+---
+
+
+
+#### Custom Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/cyclomatic-complexity": [
+ "error",
+ {
+ "maxComplexity": 3
+ }
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+@switch (value) {
+ @case ('a') { A }
+ @case ('b') { B }
+ @default { Default }
+}
+```
+
diff --git a/packages/eslint-plugin-template/docs/rules/no-nested-tags.md b/packages/eslint-plugin-template/docs/rules/no-nested-tags.md
new file mode 100644
index 000000000..63acdb97d
--- /dev/null
+++ b/packages/eslint-plugin-template/docs/rules/no-nested-tags.md
@@ -0,0 +1,231 @@
+
+
+
+
+# `@angular-eslint/template/no-nested-tags`
+
+Denies nesting of and tags.
+
+- Type: problem
+
+
+
+## Rule Options
+
+The rule does not have any configuration options.
+
+
+
+## Usage Examples
+
+> The following examples are generated automatically from the actual unit tests within the plugin, so you can be assured that their behavior is accurate based on the current commit.
+
+
+
+
+β - Toggle examples of incorrect code for this rule
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/no-nested-tags": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+
+ ~~~~~~~
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/no-nested-tags": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+
@if(true) {
}
+ ~~~~~~~
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/no-nested-tags": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+
+```
+
+
+
+
+
+---
+
+
+
+
+β
- Toggle examples of correct code for this rule
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/no-nested-tags": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/no-nested-tags": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/no-nested-tags": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/no-nested-tags": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+
+```
+
+
+
+
diff --git a/packages/eslint-plugin-template/docs/rules/prefer-at-empty.md b/packages/eslint-plugin-template/docs/rules/prefer-at-empty.md
new file mode 100644
index 000000000..d2cf1cd95
--- /dev/null
+++ b/packages/eslint-plugin-template/docs/rules/prefer-at-empty.md
@@ -0,0 +1,1496 @@
+
+
+
+
+# `@angular-eslint/template/prefer-at-empty`
+
+Prefer using `@empty` with `@for` loops instead of a separate `@if` or `@else` block to reduce code and make it easier to read.
+
+- Type: suggestion
+- π§ Supports autofix (`--fix`)
+
+
+
+## Rule Options
+
+The rule does not have any configuration options.
+
+
+
+## Usage Examples
+
+> The following examples are generated automatically from the actual unit tests within the plugin, so you can be assured that their behavior is accurate based on the current commit.
+
+
+
+
+β - Toggle examples of incorrect code for this rule
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@for (item of items; track $index) {}
+@if (items.length === 0) {
+~~~~
+ No items
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@for (item of items; track $index) {}
+@if (items.length == 0) {
+~~~~
+ No items
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@for (item of items; track $index) {}
+@if (0 === items.length) {
+~~~~
+ No items
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@for (item of items; track $index) {}
+@if (0 == items.length) {
+~~~~
+ No items
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@for (item of items; track $index) {}
+@if (!items.length) {
+~~~~
+ No items
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (items.length === 0) {
+~~~~
+ No items
+}
+@for (item of items; track $index) {}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (items.length == 0) {
+~~~~
+ No items
+}
+@for (item of items; track $index) {}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (0 === items.length) {
+~~~~
+ No items
+}
+@for (item of items; track $index) {}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (0 == items.length) {
+~~~~
+ No items
+}
+@for (item of items; track $index) {}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (!items.length) {
+~~~~
+ No items
+}
+@for (item of items; track $index) {}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (items.length > 0) {
+~~~~
+ @for (item of items; track $index) {}
+} @else {
+ No items
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (items.length !== 0) {
+~~~~
+ @for (item of items; track $index) {}
+} @else {
+ No items
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (items.length != 0) {
+~~~~
+ @for (item of items; track $index) {}
+} @else {
+ No items
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (0 < items.length) {
+~~~~
+ @for (item of items; track $index) {}
+} @else {
+ No items
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (0 !== items.length) {
+~~~~
+ @for (item of items; track $index) {}
+} @else {
+ No items
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (0 != items.length) {
+~~~~
+ @for (item of items; track $index) {}
+} @else {
+ No items
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (items.length) {
+~~~~
+ @for (item of items; track $index) {}
+} @else {
+ No items
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (items.length === 0) {
+~~~~
+ No items
+} @else {
+ @for (item of items; track $index) {}
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (items.length == 0) {
+~~~~
+ No items
+} @else {
+ @for (item of items; track $index) {}
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (0 === items.length) {
+~~~~
+ No items
+} @else {
+ @for (item of items; track $index) {}
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (0 == items.length) {
+~~~~
+ No items
+} @else {
+ @for (item of items; track $index) {}
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (!items.length) {
+~~~~
+ No items
+} @else {
+ @for (item of items; track $index) {}
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (items.length > 0) {
+~~~~
+ @for (item of items; track $index) {}
+}
+@if (items.length === 0) {
+ No items
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (items.length === 0) {
+ No items
+}
+@if (items.length > 0) {
+~~~~
+ @for (item of items; track $index) {}
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (items.length > 0) {
+~~~~
+ @for (item of items; track $index) {}
+} @else if (condition) {
+ Condition is true
+} @else {
+ Condition is false
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@for (item of items; track $index) {}
+
+@if (items.length === 0) {
+~~~~
+ No items
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+
+@for (item of items; track $index) {}
+
+@if (items.length === 0) {
+~~~~
+ Not empty
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (items.length === 0) {
+~~~~
+ Not empty
+}
+@for (item of items; track $index) {}
+@empty {
+ Existing
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@for (item of items; track $index) {}
+@empty {
+ Existing
+}
+@if (items.length === 0) {
+~~~~
+ Not empty
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (items.length > 0) {
+~~~~
+ @for (item of items; track $index) {}
+ @empty {
+ Existing
+ }
+} @else {
+ Empty
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (items.length === 0) {
+~~~~
+ Empty
+} @else {
+ @for (item of items; track $index) {}
+ @empty {
+ Existing
+ }
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (items.length === 0) {
+~~~~
+ Empty
+} @else {
+ @for (item of items; track $index) {}
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (items.length > 0) {
+~~~~
+
+ @for (item of items; track $index) {}
+
+} @else {
+ Empty
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+@if (items.length === 0) {
+~~~~
+ Empty
+} @else {
+
+ @for (item of items; track $index) {}
+
+}
+```
+
+
+
+
+
+---
+
+
+
+
+β
- Toggle examples of correct code for this rule
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+@for (item of items; track $index) {}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+@for (item of items; track $index) {} @empty {}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+@if (alpha.length > 0) {
+ @for (item of beta; track $index) {}
+} @else {
+ No items
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+@if (items.length > 0) {
+ Items:
+ @for (item of items; track $index) {}
+} @else {
+ No items
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+@if (items.length === 0) {
+ No items
+} @else {
+ Items:
+ @for (item of items; track $index) {}
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+@if (items.length > 0) {
+ @for (item of items; track $index) {}
+ Total: {{ $count }}
+} @else {
+ No items
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+@if (items.length === 0) {
+ No items
+} @else {
+ @for (item of items; track $index) {}
+ Total: {{ $count }}
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+@if (items.length > 0) {
+ @for (item of items; track $index) {}
+}
+@if (items.length > 0) {
+ Not empty
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+@if (items.length > 0) {
+ @for (item of items; track $index) {}
+}
+---
+@if (items.length === 0) {
+ Not empty
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+@for (item of items; track $index) {}
+---
+@if (items.length === 0) {
+ Not empty
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+@for (item of items; track $index) {}
+@if (items.length > 0) {
+ Not empty
+}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+@if (items.length > 0) {
+ Not empty
+}
+@for (item of items; track $index) {}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-at-empty": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```html
+@if (beta.length > 0) {
+ @for (item of alpha; track $index) {}
+ @for (item of beta; track $index) {}
+} @else {
+ Empty
+}
+```
+
+
+
+
diff --git a/packages/eslint-plugin-template/docs/rules/prefer-template-literal.md b/packages/eslint-plugin-template/docs/rules/prefer-template-literal.md
index c8f23457f..998a28a25 100644
--- a/packages/eslint-plugin-template/docs/rules/prefer-template-literal.md
+++ b/packages/eslint-plugin-template/docs/rules/prefer-template-literal.md
@@ -541,6 +541,60 @@ The rule does not have any configuration options.
#### β Invalid Code
+```html
+{{ 'prefix-' + (condition ? 'true' : 'false') }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-template-literal": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+{{ 'prefix-' + ('value' | pipe) }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-template-literal": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
```html
{{ "prefix-" + 42 }}
~~~~~~~~~~~~~~
@@ -730,6 +784,60 @@ The rule does not have any configuration options.
#### β Invalid Code
+```html
+{{ 'prefix-' + (condition ? 'true' : 'false') }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-template-literal": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+{{ 'prefix-' + ('value' | pipe) }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-template-literal": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
```html
{{ `prefix-${value}-suffix` + 42 }}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -919,6 +1027,60 @@ The rule does not have any configuration options.
#### β Invalid Code
+```html
+{{ `prefix-${value}-suffix` + (condition ? 'true' : 'false') }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-template-literal": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+{{ `prefix-${value}-suffix` + ('value' | pipe) }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-template-literal": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
```html
{{ 42 + '-suffix' }}
~~~~~~~~~~~~~~
@@ -1135,6 +1297,60 @@ The rule does not have any configuration options.
#### β Invalid Code
+```html
+{{ (condition ? 'true' : 'false') + '-suffix' }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-template-literal": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+{{ ('value' | pipe) + '-suffix' }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-template-literal": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
```html
{{ 42 + "-suffix" }}
~~~~~~~~~~~~~~
@@ -1351,6 +1567,60 @@ The rule does not have any configuration options.
#### β Invalid Code
+```html
+{{ (condition ? 'true' : 'false') + "-suffix" }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-template-literal": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+{{ ('value' | pipe) + "-suffix" }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-template-literal": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
```html
{{ 42 + `prefix-${value}-suffix` }}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1518,6 +1788,60 @@ The rule does not have any configuration options.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-template-literal": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+{{ (condition ? 'true' : 'false') + `prefix-${value}-suffix` }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/template/prefer-template-literal": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```html
+{{ ('value' | pipe) + `prefix-${value}-suffix` }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+```
+
diff --git a/packages/eslint-plugin-template/package.json b/packages/eslint-plugin-template/package.json
index 683ff1c6b..710d8d19f 100644
--- a/packages/eslint-plugin-template/package.json
+++ b/packages/eslint-plugin-template/package.json
@@ -1,6 +1,6 @@
{
"name": "@angular-eslint/eslint-plugin-template",
- "version": "19.4.0",
+ "version": "19.5.0",
"description": "ESLint plugin for Angular Templates",
"license": "MIT",
"main": "dist/index.js",
diff --git a/packages/eslint-plugin-template/src/configs/all.json b/packages/eslint-plugin-template/src/configs/all.json
index 5fcd30d67..794598dec 100644
--- a/packages/eslint-plugin-template/src/configs/all.json
+++ b/packages/eslint-plugin-template/src/configs/all.json
@@ -23,7 +23,9 @@
"@angular-eslint/template/no-inline-styles": "error",
"@angular-eslint/template/no-interpolation-in-attributes": "error",
"@angular-eslint/template/no-negated-async": "error",
+ "@angular-eslint/template/no-nested-tags": "error",
"@angular-eslint/template/no-positive-tabindex": "error",
+ "@angular-eslint/template/prefer-at-empty": "error",
"@angular-eslint/template/prefer-contextual-for-variables": "error",
"@angular-eslint/template/prefer-control-flow": "error",
"@angular-eslint/template/prefer-ngsrc": "error",
diff --git a/packages/eslint-plugin-template/src/index.ts b/packages/eslint-plugin-template/src/index.ts
index 45db70eb0..ca708a9d7 100644
--- a/packages/eslint-plugin-template/src/index.ts
+++ b/packages/eslint-plugin-template/src/index.ts
@@ -58,12 +58,18 @@ import noInterpolationInAttributes, {
import noNegatedAsync, {
RULE_NAME as noNegatedAsyncRuleName,
} from './rules/no-negated-async';
+import noNestedTags, {
+ RULE_NAME as noNestedTagsRuleName,
+} from './rules/no-nested-tags';
import noPositiveTabindex, {
RULE_NAME as noPositiveTabindexRuleName,
} from './rules/no-positive-tabindex';
import preferNgsrc, {
RULE_NAME as preferNgsrcRuleName,
} from './rules/prefer-ngsrc';
+import preferAtEmpty, {
+ RULE_NAME as preferAtEmptyRuleName,
+} from './rules/prefer-at-empty';
import preferContextualForVariables, {
RULE_NAME as preferContextualForVariablesRuleName,
} from './rules/prefer-contextual-for-variables';
@@ -117,10 +123,12 @@ export = {
[noCallExpressionRuleName]: noCallExpression,
[noDistractingElementsRuleName]: noDistractingElements,
[noDuplicateAttributesRuleName]: noDuplicateAttributes,
+ [noNestedTagsRuleName]: noNestedTags,
[noInlineStylesRuleName]: noInlineStyles,
[noInterpolationInAttributesRuleName]: noInterpolationInAttributes,
[noNegatedAsyncRuleName]: noNegatedAsync,
[noPositiveTabindexRuleName]: noPositiveTabindex,
+ [preferAtEmptyRuleName]: preferAtEmpty,
[preferContextualForVariablesRuleName]: preferContextualForVariables,
[preferControlFlowRuleName]: preferControlFlow,
[preferSelfClosingTagsRuleName]: preferSelfClosingTags,
diff --git a/packages/eslint-plugin-template/src/rules/alt-text.ts b/packages/eslint-plugin-template/src/rules/alt-text.ts
index 7a5ceb791..dee5d1f11 100644
--- a/packages/eslint-plugin-template/src/rules/alt-text.ts
+++ b/packages/eslint-plugin-template/src/rules/alt-text.ts
@@ -81,8 +81,9 @@ function isValidObjectNode(node: TmplAstElement): boolean {
hasAriaLabelAttribute = false;
for (const attribute of node.attributes) {
- hasTitleAttribute = attribute.name === 'title';
- hasAriaLabelAttribute = isAriaLabel(attribute.name);
+ hasTitleAttribute = hasTitleAttribute || attribute.name === 'title';
+ hasAriaLabelAttribute =
+ hasAriaLabelAttribute || isAriaLabel(attribute.name);
}
// Note that we return "early" before looping through `element.inputs`.
@@ -96,8 +97,8 @@ function isValidObjectNode(node: TmplAstElement): boolean {
hasAriaLabelBinding = false;
for (const input of node.inputs) {
- hasTitleBinding = input.name === 'title';
- hasAriaLabelBinding = isAriaLabel(input.name);
+ hasTitleBinding = hasTitleBinding || input.name === 'title';
+ hasAriaLabelBinding = hasAriaLabelBinding || isAriaLabel(input.name);
}
if (hasTitleBinding || hasAriaLabelBinding) {
@@ -119,8 +120,9 @@ function isValidAreaNode(node: TmplAstElement): boolean {
hasAriaLabelAttribute = false;
for (const attribute of node.attributes) {
- hasAltAttribute = isAlt(attribute.name);
- hasAriaLabelAttribute = isAriaLabel(attribute.name);
+ hasAltAttribute = hasAltAttribute || isAlt(attribute.name);
+ hasAriaLabelAttribute =
+ hasAriaLabelAttribute || isAriaLabel(attribute.name);
}
// Note that we return "early" before looping through `element.inputs`.
@@ -134,8 +136,8 @@ function isValidAreaNode(node: TmplAstElement): boolean {
hasAriaLabelBinding = false;
for (const input of node.inputs) {
- hasAltBinding = isAlt(input.name);
- hasAriaLabelBinding = isAriaLabel(input.name);
+ hasAltBinding = hasAltBinding || isAlt(input.name);
+ hasAriaLabelBinding = hasAriaLabelBinding || isAriaLabel(input.name);
}
return hasAltBinding || hasAriaLabelBinding;
diff --git a/packages/eslint-plugin-template/src/rules/cyclomatic-complexity.ts b/packages/eslint-plugin-template/src/rules/cyclomatic-complexity.ts
index 733e3c9f7..1e7faf280 100644
--- a/packages/eslint-plugin-template/src/rules/cyclomatic-complexity.ts
+++ b/packages/eslint-plugin-template/src/rules/cyclomatic-complexity.ts
@@ -1,6 +1,11 @@
-import type {
+import {
+ Node,
TmplAstBoundAttribute,
TmplAstTextAttribute,
+ TmplAstIfBlock,
+ TmplAstForLoopBlock,
+ TmplAstSwitchBlockCase,
+ ParseSourceSpan,
} from '@angular-eslint/bundled-angular-compiler';
import { getTemplateParserServices } from '@angular-eslint/utils';
import { createESLintRule } from '../utils/create-eslint-rule';
@@ -40,21 +45,39 @@ export default createESLintRule({
let totalComplexity = 0;
const parserServices = getTemplateParserServices(context);
- return {
- 'BoundAttribute[name=/^(ngForOf|ngIf|ngSwitchCase)$/], TextAttribute[name="ngSwitchDefault"]'({
- sourceSpan,
- }: TmplAstBoundAttribute | TmplAstTextAttribute) {
- totalComplexity += 1;
+ function increment(node: { sourceSpan: ParseSourceSpan }): void {
+ totalComplexity += 1;
+
+ if (totalComplexity <= maxComplexity) return;
- if (totalComplexity <= maxComplexity) return;
+ const loc = parserServices.convertNodeSourceSpanToLoc(node.sourceSpan);
- const loc = parserServices.convertNodeSourceSpanToLoc(sourceSpan);
+ context.report({
+ messageId: 'cyclomaticComplexity',
+ loc,
+ data: { maxComplexity, totalComplexity },
+ });
+ }
- context.report({
- messageId: 'cyclomaticComplexity',
- loc,
- data: { maxComplexity, totalComplexity },
- });
+ return {
+ '*': (node: Node) => {
+ if (
+ node instanceof TmplAstBoundAttribute &&
+ /^(ngForOf|ngIf|ngSwitchCase)$/.test(node.name)
+ ) {
+ increment(node);
+ } else if (
+ node instanceof TmplAstTextAttribute &&
+ node.name === 'ngSwitchDefault'
+ ) {
+ increment(node);
+ } else if (
+ node instanceof TmplAstIfBlock ||
+ node instanceof TmplAstForLoopBlock ||
+ node instanceof TmplAstSwitchBlockCase
+ ) {
+ increment(node);
+ }
},
};
},
diff --git a/packages/eslint-plugin-template/src/rules/no-nested-tags.ts b/packages/eslint-plugin-template/src/rules/no-nested-tags.ts
new file mode 100644
index 000000000..a636d18a0
--- /dev/null
+++ b/packages/eslint-plugin-template/src/rules/no-nested-tags.ts
@@ -0,0 +1,64 @@
+import { TmplAstElement } from '@angular-eslint/bundled-angular-compiler';
+import { getTemplateParserServices } from '@angular-eslint/utils';
+import { createESLintRule } from '../utils/create-eslint-rule';
+
+export type Options = [];
+export type MessageIds = 'noNestedTags';
+export const RULE_NAME = 'no-nested-tags';
+
+type TmplAstElementWithAncestor = TmplAstElement & {
+ parent?: TmplAstElementWithAncestor;
+};
+
+export default createESLintRule({
+ name: RULE_NAME,
+ meta: {
+ type: 'problem',
+ docs: {
+ description: 'Denies nesting of and tags.',
+ },
+ schema: [],
+ messages: {
+ noNestedTags:
+ '<{{tag}}> elements must not be nested! This breaks angular incremental hydration as all browsers will convert "<{{tag}}>1<{{tag}}>2{{tag}}>3{{tag}}>" into "<{{tag}}>1{{tag}}><{{tag}}>2{{tag}}>3", creating a DOM mismatch between SSR and Angular',
+ },
+ },
+ defaultOptions: [],
+ create(context) {
+ const parserServices = getTemplateParserServices(context);
+
+ return {
+ 'Element[name=/^(p|a)$/]'(node: TmplAstElementWithAncestor) {
+ const hasInvalidNesting = hasAncestorOfSameType(node);
+
+ if (hasInvalidNesting) {
+ const loc = parserServices.convertElementSourceSpanToLoc(
+ context,
+ node,
+ );
+ context.report({
+ loc,
+ messageId: 'noNestedTags',
+ data: {
+ tag: node.name,
+ },
+ });
+ }
+ },
+ };
+ },
+});
+
+function hasAncestorOfSameType(node: TmplAstElementWithAncestor) {
+ let parent = node.parent;
+
+ while (parent) {
+ if (parent instanceof TmplAstElement && parent.name === node.name) {
+ return true;
+ }
+
+ parent = parent.parent;
+ }
+
+ return false;
+}
diff --git a/packages/eslint-plugin-template/src/rules/prefer-at-empty.ts b/packages/eslint-plugin-template/src/rules/prefer-at-empty.ts
new file mode 100644
index 000000000..589d88ee6
--- /dev/null
+++ b/packages/eslint-plugin-template/src/rules/prefer-at-empty.ts
@@ -0,0 +1,644 @@
+import {
+ AST,
+ ASTWithSource,
+ Binary,
+ LiteralPrimitive,
+ Node,
+ ParseSourceSpan,
+ PrefixNot,
+ PropertyRead,
+ TmplAstForLoopBlock,
+ TmplAstIfBlock,
+ TmplAstIfBlockBranch,
+ TmplAstText,
+} from '@angular-eslint/bundled-angular-compiler';
+import { getTemplateParserServices } from '@angular-eslint/utils';
+import { createESLintRule } from '../utils/create-eslint-rule';
+import { areEquivalentASTs } from '../utils/are-equivalent-asts';
+
+export type Options = [];
+export type MessageIds = 'preferAtEmpty';
+export const RULE_NAME = 'prefer-at-empty';
+
+export default createESLintRule({
+ name: RULE_NAME,
+ meta: {
+ type: 'suggestion',
+ fixable: 'code',
+ docs: {
+ description:
+ 'Prefer using `@empty` with `@for` loops instead of a separate `@if` or `@else` block to reduce code and make it easier to read.',
+ },
+ schema: [],
+ messages: {
+ preferAtEmpty: 'Prefer using `@for (...) {...} @empty {...}`.',
+ },
+ },
+ defaultOptions: [],
+ create(context) {
+ const parserServices = getTemplateParserServices(context);
+ const previousNodeStack: (NodeInfo | undefined)[] = [undefined];
+
+ function getOnlyForBlock(
+ node: TmplAstIfBlockBranch,
+ ): TmplAstForLoopBlock | undefined {
+ let forBlock: TmplAstForLoopBlock | undefined;
+
+ // Find the only `@for` block in the children,
+ // ignoring any text nodes that are only whitespace.
+ for (const child of node.children) {
+ if (child instanceof TmplAstForLoopBlock) {
+ if (forBlock) {
+ return undefined;
+ }
+ forBlock = child;
+ } else if (child instanceof TmplAstText) {
+ // The `value` property contains the HTML-decoded
+ // value, so we need to look at the raw source code
+ // to see if the content is only whitespace.
+ if (
+ context.sourceCode.text
+ .slice(child.sourceSpan.start.offset, child.sourceSpan.end.offset)
+ .trim() !== ''
+ ) {
+ return undefined;
+ }
+ } else {
+ return undefined;
+ }
+ }
+
+ return forBlock;
+ }
+
+ function checkFor(
+ forInfo: ForNodeInfo,
+ previous: NodeInfo | undefined,
+ ): void {
+ // If the `@for` block is immediately preceded by an "if empty"
+ // block for the same collection, then that `@if` block can
+ // be moved into the `@empty` block.
+ if (previous?.kind === 'if-empty') {
+ if (areEquivalentASTs(forInfo.collection, previous.collection)) {
+ const branch = previous.node.branches[0];
+ const branchEnd = branch.endSourceSpan;
+ context.report({
+ loc: parserServices.convertNodeSourceSpanToLoc(
+ previous.node.nameSpan,
+ ),
+ messageId: 'preferAtEmpty',
+ fix: branchEnd
+ ? function* (fixer) {
+ // Remove the entire `@if` block.
+ yield fixer.removeRange(toRange(previous.node.sourceSpan));
+
+ if (forInfo.node.empty) {
+ // There is already an `@empty` block. The contents of the
+ // `@if` block and the contents of the `@empty` block would
+ // both be shown in the collection is empty, so we need to
+ // combine the two blocks. The `@if` block would be rendered
+ // first, so it needs to be inserted before the existing
+ // contents of the `@empty` block.
+ yield fixer.insertTextAfterRange(
+ [
+ forInfo.node.empty.nameSpan.end.offset,
+ forInfo.node.empty.startSourceSpan.end.offset,
+ ],
+ context.sourceCode.text.slice(
+ branch.startSourceSpan.end.offset,
+ // The end offset is after the closing `}`, so we
+ // need to subtract one to ensure it's not included.
+ branchEnd.end.offset - 1,
+ ),
+ );
+ } else {
+ // Take the contents of the `@if` block and move
+ // it into an `@empty` block after the `@for` block.
+ yield fixer.insertTextAfterRange(
+ toRange(forInfo.node.sourceSpan),
+ ` @empty {${context.sourceCode.text.slice(
+ branch.startSourceSpan.end.offset,
+ branchEnd.end.offset,
+ )}`,
+ );
+ }
+ }
+ : undefined,
+ });
+ }
+ }
+ }
+
+ function checkIfEmpty(
+ ifInfo: IfNodeInfo,
+ previous: NodeInfo | undefined,
+ ): void {
+ if (!previous) {
+ return;
+ }
+
+ // If the `@if` block is immediately preceded by a `@for`
+ // block for the same collection, then that `@if` block
+ // can be moved into the `@empty` block.
+ switch (previous.kind) {
+ case 'for':
+ if (areEquivalentASTs(ifInfo.collection, previous.collection)) {
+ // The `@if` block can be moved into the `@for` block,
+ // so report the problem on the `@if` block.
+ context.report({
+ loc: parserServices.convertNodeSourceSpanToLoc(
+ ifInfo.node.nameSpan,
+ ),
+ messageId: 'preferAtEmpty',
+ fix: function* (fixer) {
+ if (previous.node.empty?.endSourceSpan) {
+ // There is already an `@empty` block. The contents of
+ // the `@empty` block and the `@if` block would both be
+ // rendered. The `@empty` block would appear first, so
+ // we need to move the contents of the `@if` block after
+ // the existing contents of the `@empty` block. This can
+ // easily be achieved by removing the closing brace of the
+ // `@empty` block and removing the `@if` statement.
+ yield fixer.removeRange(
+ toRange(previous.node.empty.endSourceSpan),
+ );
+ yield fixer.removeRange(toRange(ifInfo.node.startSourceSpan));
+ } else {
+ // There is not already an `@empty` block, so
+ // we can create one by replacing the entire
+ // `@if (...) {` segment with `@empty {`.
+ yield fixer.replaceTextRange(
+ toRange(ifInfo.node.startSourceSpan),
+ '@empty {',
+ );
+ }
+ },
+ });
+ }
+ break;
+
+ case 'if-not-empty':
+ if (areEquivalentASTs(ifInfo.collection, previous.collection)) {
+ const forBlock = getOnlyForBlock(previous.node.branches[0]);
+ if (
+ forBlock &&
+ areEquivalentASTs(ifInfo.collection, forBlock.expression.ast)
+ ) {
+ const previousIfBlockEnd = previous.node.endSourceSpan;
+
+ // The previous `@if` block can be removed and the current `@if`
+ // block moved into the `@for` block's `@empty` block, so report
+ // the problem on the previous `@if` block.
+ context.report({
+ loc: parserServices.convertNodeSourceSpanToLoc(
+ previous.node.nameSpan,
+ ),
+ messageId: 'preferAtEmpty',
+ fix: previousIfBlockEnd
+ ? (fixer) => [
+ // Remove the previous `@if` statement.
+ fixer.removeRange(toRange(previous.node.startSourceSpan)),
+
+ // Remove the closing brace from the previous `@if` block.
+ fixer.removeRange(toRange(previousIfBlockEnd)),
+
+ // Take the contents of the current `@if` block and move
+ // it into the `@empty` block of the previous `@for` block.
+ fixer.insertTextAfterRange(
+ toRange(forBlock.sourceSpan),
+ ` @empty {${context.sourceCode.text.slice(
+ ifInfo.node.startSourceSpan.end.offset,
+ // The end offset includes the closing brace.
+ ifInfo.node.sourceSpan.end.offset,
+ )}`,
+ ),
+
+ // Remove the entirety of the current `@if` block.
+ fixer.removeRange(toRange(ifInfo.node.sourceSpan)),
+ ]
+ : undefined,
+ });
+ }
+ }
+ }
+ }
+
+ function checkIfEmptyElse(info: IfNodeInfo): void {
+ // Look for an `@for` block in the `@else` branch.
+ const forBlock = getOnlyForBlock(info.node.branches[1]);
+ if (
+ forBlock &&
+ areEquivalentASTs(info.collection, forBlock.expression.ast)
+ ) {
+ const ifBranchEnd = info.node.branches[0].endSourceSpan;
+
+ // The contents of the `@if` block can be moved into an
+ // `@empty` block, so report the problem on the `@if` block.
+ context.report({
+ loc: parserServices.convertNodeSourceSpanToLoc(info.node.nameSpan),
+ messageId: 'preferAtEmpty',
+ fix: ifBranchEnd
+ ? function* (fixer) {
+ // Remove the entire `@if` branch through to the
+ // start of the body of the `@else` block.
+ yield fixer.removeRange([
+ info.node.sourceSpan.start.offset,
+ info.node.branches[1].startSourceSpan.end.offset,
+ ]);
+
+ // Take the contents of the `@if` branch and move
+ // it into an `@empty` block after the `@for` block.
+ const empty = context.sourceCode.text.slice(
+ info.node.startSourceSpan.end.offset,
+ ifBranchEnd.start.offset,
+ );
+ if (forBlock.empty?.endSourceSpan) {
+ // There is already an `@empty` block, but because the `@for`
+ // block was inside an `@else` block, the `@empty` block
+ // would never have be rendered, so we can replace its contents.
+ yield fixer.replaceTextRange(
+ [
+ forBlock.empty.startSourceSpan.end.offset,
+ forBlock.empty.endSourceSpan.start.offset,
+ ],
+ empty,
+ );
+
+ // Remove the closing brace from the end of the `@else` block.
+ if (info.node.endSourceSpan) {
+ yield fixer.removeRange([
+ info.node.endSourceSpan.start.offset,
+ info.node.endSourceSpan.end.offset,
+ ]);
+ }
+ } else {
+ // There isn't an existing `@empty` block, so we can create
+ // one. We don't need to include a closing brace, because
+ // we can reuse the one from the end of the @`if` block.
+ yield fixer.insertTextAfterRange(
+ toRange(forBlock.sourceSpan),
+ ` @empty {${empty}`,
+ );
+ }
+ }
+ : undefined,
+ });
+ }
+ }
+
+ function checkIfNotEmpty(
+ ifNotInfo: IfNodeInfo,
+ previous: NodeInfo | undefined,
+ ): void {
+ if (previous?.kind === 'if-empty') {
+ if (areEquivalentASTs(ifNotInfo.collection, previous.collection)) {
+ const forBlock = getOnlyForBlock(ifNotInfo.node.branches[0]);
+ if (
+ forBlock &&
+ areEquivalentASTs(ifNotInfo.collection, forBlock.expression.ast)
+ ) {
+ // The `@if` block can be removed and the contents of
+ // the `@else` block moved into an `@empty` block,
+ // so report the problem on the `@if` block.
+ context.report({
+ loc: parserServices.convertNodeSourceSpanToLoc(
+ ifNotInfo.node.nameSpan,
+ ),
+ messageId: 'preferAtEmpty',
+ fix: (fixer) => [
+ // Remove the entire previous `@if` block.
+ fixer.removeRange(toRange(previous.node.sourceSpan)),
+
+ // Remove the current `@if` statement.
+ fixer.removeRange(toRange(ifNotInfo.node.startSourceSpan)),
+
+ // Take the contents of the previous `@if` block and move
+ // it into the `@empty` block after the `@for` block.
+ fixer.insertTextAfterRange(
+ toRange(forBlock.sourceSpan),
+ ` @empty {${context.sourceCode.text.slice(
+ previous.node.startSourceSpan.end.offset,
+ // The end offset is after the closing `}`, so we
+ // need to subtract one to ensure it gets removed.
+ previous.node.sourceSpan.end.offset - 1,
+ )}`,
+ ),
+ ],
+ });
+ }
+ }
+ }
+ }
+
+ function checkIfNotEmptyElse(info: IfNodeInfo): void {
+ const forBlock = getOnlyForBlock(info.node.branches[0]);
+ if (
+ forBlock &&
+ areEquivalentASTs(info.collection, forBlock.expression.ast)
+ ) {
+ const ifBranchEnd = info.node.branches[0].endSourceSpan;
+ const ifEnd = info.node.endSourceSpan;
+
+ // The `@if` block can be removed and the contents of
+ // the `@else` block moved into an `@empty` block,
+ // so report the problem on the `@if` block.
+ context.report({
+ loc: parserServices.convertNodeSourceSpanToLoc(info.node.nameSpan),
+ messageId: 'preferAtEmpty',
+ fix:
+ ifBranchEnd && ifEnd
+ ? function* (fixer) {
+ if (forBlock.empty) {
+ // Because the `@for` block was inside an `@if`
+ // block, the `@empty` block would never be rendered,
+ // so we can remove it. We could try to replace it,
+ // but it's easier to remove it and create a new one.
+ yield fixer.removeRange(toRange(forBlock.empty.sourceSpan));
+ }
+
+ // Remove the entire `@if (...) {` segment.
+ yield fixer.removeRange(toRange(info.node.startSourceSpan));
+
+ const elseBranch = info.node.branches[1];
+ if (elseBranch.expression) {
+ // The second branch is an `@else if` branch. We
+ // need to turn it into its own `@if` block. Replace
+ // the `@else if` text with the start of the `@empty`
+ // block and the start of the `@if` block, then put
+ // a closing brace after the original `@if` block
+ // to close the `@empty` block.
+ yield fixer.replaceTextRange(
+ [
+ ifBranchEnd.end.offset - 1,
+ elseBranch.nameSpan.end.offset,
+ ],
+ '@empty { @if ',
+ );
+ yield fixer.insertTextAfterRange(toRange(ifEnd), '}');
+ } else {
+ // The second branch is just an `@else` branch, so we
+ // can replace from end of the `@if` branch through to
+ // the end of the `@else` statement with `@empty {`.
+ // The children of the `@else` branch, and the closing
+ // `}`, will become part of the `@empty` block.
+ yield fixer.replaceTextRange(
+ [
+ // The end offset is after the closing `}`, so we
+ // need to subtract one to ensure it gets removed.
+ ifBranchEnd.end.offset - 1,
+ elseBranch.startSourceSpan.end.offset,
+ ],
+ '@empty {',
+ );
+ }
+ }
+ : undefined,
+ });
+ }
+ }
+
+ return {
+ // We need to visit `@for` and `@if` blocks, but we
+ // also need to know if there are any nodes immediately
+ // before them, so we need to visit all nodes.
+ '*'(node: Node) {
+ const current = getNodeInfo(node);
+
+ if (current !== undefined) {
+ switch (current.kind) {
+ case 'for':
+ checkFor(current, previousNodeStack.at(-1));
+ break;
+
+ case 'if-empty':
+ checkIfEmpty(current, previousNodeStack.at(-1));
+ break;
+
+ case 'if-empty-else':
+ checkIfEmptyElse(current);
+ break;
+
+ case 'if-not-empty':
+ checkIfNotEmpty(current, previousNodeStack.at(-1));
+ break;
+
+ case 'if-not-empty-else':
+ checkIfNotEmptyElse(current);
+ break;
+ }
+ }
+
+ // Record this current node as the previous node so that
+ // we can get the info when we look at the next sibling.
+ previousNodeStack[previousNodeStack.length - 1] = current;
+
+ // We are about to visit the children of this node,
+ // so push a new "previous node info" onto the stack.
+ // The previous node of the first child is undefined.
+ previousNodeStack.push(undefined);
+ },
+ '*:exit'() {
+ // We've finished visiting the children of this node,
+ // so pop the "previous node info" off the stack.
+ previousNodeStack.pop();
+ },
+ };
+ },
+});
+
+function getNodeInfo(node: Node): NodeInfo | undefined {
+ if (node instanceof TmplAstForLoopBlock) {
+ return {
+ node,
+ kind: 'for',
+ collection: node.expression.ast,
+ };
+ }
+
+ if (node instanceof TmplAstIfBlock) {
+ if (node.branches.length === 0) {
+ return undefined;
+ }
+
+ if (!node.branches[0].expression) {
+ return undefined;
+ }
+
+ let collection = getNotEmptyTestCollection(node.branches[0].expression);
+ if (collection) {
+ // The block is either:
+ //
+ // @if (collection.length > 0) {
+ // }
+ //
+ // or:
+ //
+ // @if (collection.length > 0) {
+ // } @else {
+ // }
+ //
+ // or:
+ //
+ // @if (collection.length > 0) {
+ // } @else if (condition){
+ // }
+ //
+ // or:
+ //
+ // @if (collection.length > 0) {
+ // } @else if (condition) {
+ // } @else {
+ // }
+ //
+ // In any case, we treat this as one of the "if not empty"
+ // nodes, because if there is an `@for` block in the `@if`
+ // branch, then whatever is in the `@else if` or @else`
+ // branches, could be moved into the `@empty` block.
+ return {
+ node,
+ kind: node.branches.length === 1 ? 'if-not-empty' : 'if-not-empty-else',
+ collection,
+ };
+ }
+
+ collection = getEmptyTestCollection(node.branches[0].expression);
+ if (collection) {
+ // Unlike the "if not empty" cases, there are only two cases
+ // that could be considered an "if empty" case:
+ //
+ // @if (collection.length === 0) {
+ // }
+ //
+ // or:
+ //
+ // @if (collection.length > 0) {
+ // } @else {
+ // }
+ //
+ // If there is an `@else if`, then whatever is in the `@if`
+ // branch could not safely be moved into an `@empty` block
+ // because of the condition in the `@else if` branch.
+ if (node.branches.length === 1) {
+ return {
+ node,
+ kind: 'if-empty',
+ collection,
+ };
+ } else if (node.branches.length === 2 && !node.branches[1].expression) {
+ return {
+ node,
+ kind: 'if-empty-else',
+ collection,
+ };
+ }
+ }
+ }
+
+ return undefined;
+}
+
+function getNotEmptyTestCollection(node: AST): AST | undefined {
+ if (node instanceof ASTWithSource) {
+ node = node.ast;
+ }
+
+ if (isLengthRead(node)) {
+ // @if (collection.length)
+ return node.receiver;
+ }
+
+ if (node instanceof Binary) {
+ if (isLengthRead(node.left)) {
+ if (
+ node.operation === '!==' ||
+ node.operation === '>' ||
+ node.operation === '!='
+ ) {
+ if (isZero(node.right)) {
+ // @if (collection.length !== 0)
+ // @if (collection.length > 0)
+ // @if (collection.length != 0)
+ return node.left.receiver;
+ }
+ }
+ } else if (isZero(node.left)) {
+ if (
+ node.operation === '!==' ||
+ node.operation === '<' ||
+ node.operation === '!='
+ ) {
+ if (isLengthRead(node.right)) {
+ // @if (0 !== collection.length)
+ // @if (0 < collection.length)
+ // @if (0 != collection.length)
+ return node.right.receiver;
+ }
+ }
+ }
+ }
+
+ return undefined;
+}
+
+function getEmptyTestCollection(node: AST): AST | undefined {
+ if (node instanceof ASTWithSource) {
+ node = node.ast;
+ }
+
+ if (node instanceof PrefixNot) {
+ if (isLengthRead(node.expression)) {
+ // @if (!collection.length)
+ return node.expression.receiver;
+ }
+ } else if (node instanceof Binary) {
+ if (isLengthRead(node.left)) {
+ if (node.operation === '===' || node.operation === '==') {
+ if (isZero(node.right)) {
+ // @if (collection.length === 0)
+ // @if (collection.length == 0)
+ return node.left.receiver;
+ }
+ }
+ } else if (isZero(node.left)) {
+ if (node.operation === '===' || node.operation === '==') {
+ if (isLengthRead(node.right)) {
+ // @if (0 === collection.length)
+ // @if (0 == collection.length)
+ return node.right.receiver;
+ }
+ }
+ }
+ }
+
+ return undefined;
+}
+
+function isLengthRead(node: AST): node is PropertyRead {
+ return node instanceof PropertyRead && node.name === 'length';
+}
+
+function isZero(node: AST): boolean {
+ return node instanceof LiteralPrimitive && node.value === 0;
+}
+
+function toRange(span: ParseSourceSpan): [number, number] {
+ return [span.start.offset, span.end.offset];
+}
+
+interface ForNodeInfo {
+ readonly node: TmplAstForLoopBlock;
+ readonly kind: 'for';
+ readonly collection: AST;
+}
+
+interface IfNodeInfo {
+ readonly node: TmplAstIfBlock;
+ readonly kind:
+ | 'if-empty'
+ | 'if-empty-else'
+ | 'if-not-empty'
+ | 'if-not-empty-else';
+ readonly collection: AST;
+}
+
+type NodeInfo = ForNodeInfo | IfNodeInfo;
diff --git a/packages/eslint-plugin-template/src/rules/prefer-template-literal.ts b/packages/eslint-plugin-template/src/rules/prefer-template-literal.ts
index 22a896453..e82568357 100644
--- a/packages/eslint-plugin-template/src/rules/prefer-template-literal.ts
+++ b/packages/eslint-plugin-template/src/rules/prefer-template-literal.ts
@@ -69,6 +69,13 @@ export default createESLintRule({
return '`';
}
+ function hasParentheses(node: AST): boolean {
+ const { start, end } = node.sourceSpan;
+ const text = sourceCode.text.slice(start - 1, end + 1);
+
+ return text.startsWith('(') && text.endsWith(')');
+ }
+
context.report({
loc: {
start: sourceCode.getLocFromIndex(start),
@@ -88,19 +95,69 @@ export default createESLintRule({
);
}
- const fixes = new Array();
+ const fixes = Array();
+
+ const leftHasParentheses = hasParentheses(left);
+ const rightHasParentheses = hasParentheses(right);
+
+ // Remove the left first parenthesis if it exists
+ if (leftHasParentheses) {
+ fixes.push(
+ fixer.removeRange([
+ left.sourceSpan.start - 1,
+ left.sourceSpan.start,
+ ]),
+ );
+ }
// Fix the left side
fixes.push(...getLeftSideFixes(fixer, left));
+ // Remove the left last parenthesis if it exists
+ if (leftHasParentheses) {
+ fixes.push(
+ fixer.removeRange([
+ left.sourceSpan.end,
+ left.sourceSpan.end + 1,
+ ]),
+ );
+ }
+
// Remove the `+` sign
fixes.push(
- fixer.removeRange([left.sourceSpan.end, right.sourceSpan.start]),
+ fixer.removeRange([
+ leftHasParentheses
+ ? left.sourceSpan.end + 1
+ : left.sourceSpan.end,
+ rightHasParentheses
+ ? right.sourceSpan.start - 1
+ : right.sourceSpan.start,
+ ]),
);
+ // Remove the right first parenthesis if it exists
+ if (rightHasParentheses) {
+ fixes.push(
+ fixer.removeRange([
+ right.sourceSpan.start - 1,
+ right.sourceSpan.start,
+ ]),
+ );
+ }
+
// Fix the right side
fixes.push(...getRightSideFixes(fixer, right));
+ // Remove the right last parenthesis if it exists
+ if (rightHasParentheses) {
+ fixes.push(
+ fixer.removeRange([
+ right.sourceSpan.end,
+ right.sourceSpan.end + 1,
+ ]),
+ );
+ }
+
return fixes;
},
});
@@ -115,7 +172,9 @@ function getLeftSideFixes(fixer: RuleFixer, left: AST): readonly RuleFix[] {
if (left instanceof TemplateLiteral) {
// Remove the end ` sign from the left side
return [fixer.removeRange([end - 1, end])];
- } else if (isLiteralPrimitive(left)) {
+ }
+
+ if (isLiteralPrimitive(left)) {
// Transform left side to template literal
return [
fixer.replaceTextRange(
@@ -123,13 +182,13 @@ function getLeftSideFixes(fixer: RuleFixer, left: AST): readonly RuleFix[] {
`\`${getLiteralPrimitiveStringValue(left, '`')}`,
),
];
- } else {
- // Transform left side to template literal
- return [
- fixer.insertTextBeforeRange([start, end], '`${'),
- fixer.insertTextAfterRange([start, end], '}'),
- ];
}
+
+ // Transform left side to template literal
+ return [
+ fixer.insertTextBeforeRange([start, end], '`${'),
+ fixer.insertTextAfterRange([start, end], '}'),
+ ];
}
function getRightSideFixes(fixer: RuleFixer, right: AST): readonly RuleFix[] {
@@ -138,7 +197,9 @@ function getRightSideFixes(fixer: RuleFixer, right: AST): readonly RuleFix[] {
if (right instanceof TemplateLiteral) {
// Remove the start ` sign from the right side
return [fixer.removeRange([start, start + 1])];
- } else if (isLiteralPrimitive(right)) {
+ }
+
+ if (isLiteralPrimitive(right)) {
// Transform right side to template literal if it's a string
return [
fixer.replaceTextRange(
@@ -146,11 +207,11 @@ function getRightSideFixes(fixer: RuleFixer, right: AST): readonly RuleFix[] {
`${getLiteralPrimitiveStringValue(right, '`')}\``,
),
];
- } else {
- // Transform right side to template literal
- return [
- fixer.insertTextBeforeRange([start, end], '${'),
- fixer.insertTextAfterRange([start, end], '}`'),
- ];
}
+
+ // Transform right side to template literal
+ return [
+ fixer.insertTextBeforeRange([start, end], '${'),
+ fixer.insertTextAfterRange([start, end], '}`'),
+ ];
}
diff --git a/packages/eslint-plugin-template/tests/rules/alt-text/cases.ts b/packages/eslint-plugin-template/tests/rules/alt-text/cases.ts
index 4aac19c28..2859d50c7 100644
--- a/packages/eslint-plugin-template/tests/rules/alt-text/cases.ts
+++ b/packages/eslint-plugin-template/tests/rules/alt-text/cases.ts
@@ -16,13 +16,19 @@ export const valid: readonly (string | ValidTestCase)[] = [
'
+ ~~~~~~~
+ `,
+ data: { tag: 'a' },
+ }),
+ convertAnnotatedSourceToFailureCase({
+ messageId,
+ description: 'should fail on nested p tag',
+ annotatedSource: `
+
@if(true) {
}
+ ~~~~~~~
+ `,
+ data: { tag: 'p' },
+ }),
+ convertAnnotatedSourceToFailureCase({
+ messageId,
+ description: 'should fail on arbitrary depth',
+ annotatedSource: `
+ ${''.repeat(20)}
+
fail
+ ~~~~~~~~~~~
+ ${'
'.repeat(20)}
+ `,
+ data: { tag: 'a' },
+ }),
+];
diff --git a/packages/eslint-plugin-template/tests/rules/no-nested-tags/spec.ts b/packages/eslint-plugin-template/tests/rules/no-nested-tags/spec.ts
new file mode 100644
index 000000000..5a5499ca0
--- /dev/null
+++ b/packages/eslint-plugin-template/tests/rules/no-nested-tags/spec.ts
@@ -0,0 +1,14 @@
+import { RuleTester } from '@angular-eslint/test-utils';
+import rule, { RULE_NAME } from '../../../src/rules/no-nested-tags';
+import { invalid, valid } from './cases';
+
+const ruleTester = new RuleTester({
+ languageOptions: {
+ parser: require('@angular-eslint/template-parser'),
+ },
+});
+
+ruleTester.run(RULE_NAME, rule, {
+ valid,
+ invalid,
+});
diff --git a/packages/eslint-plugin-template/tests/rules/prefer-at-empty/cases.ts b/packages/eslint-plugin-template/tests/rules/prefer-at-empty/cases.ts
new file mode 100644
index 000000000..ed7f4049d
--- /dev/null
+++ b/packages/eslint-plugin-template/tests/rules/prefer-at-empty/cases.ts
@@ -0,0 +1,487 @@
+import { convertAnnotatedSourceToFailureCase } from '@angular-eslint/test-utils';
+import type {
+ InvalidTestCase,
+ ValidTestCase,
+} from '@typescript-eslint/rule-tester';
+import type { MessageIds, Options } from '../../../src/rules/prefer-at-empty';
+
+const messageId: MessageIds = 'preferAtEmpty';
+
+export const valid: readonly (string | ValidTestCase)[] = [
+ `@for (item of items; track $index) {}`,
+ `@for (item of items; track $index) {} @empty {}`,
+ `
+ @if (alpha.length > 0) {
+ @for (item of beta; track $index) {}
+ } @else {
+ No items
+ }
+ `,
+ `
+ @if (items.length > 0) {
+ Items:
+ @for (item of items; track $index) {}
+ } @else {
+ No items
+ }
+ `,
+ `
+ @if (items.length === 0) {
+ No items
+ } @else {
+ Items:
+ @for (item of items; track $index) {}
+ }
+ `,
+ `
+ @if (items.length > 0) {
+ @for (item of items; track $index) {}
+ Total: {{ $count }}
+ } @else {
+ No items
+ }
+ `,
+ `
+ @if (items.length === 0) {
+ No items
+ } @else {
+ @for (item of items; track $index) {}
+ Total: {{ $count }}
+ }
+ `,
+ `
+ @if (items.length > 0) {
+ @for (item of items; track $index) {}
+ }
+ @if (items.length > 0) {
+ Not empty
+ }
+ `,
+ `
+ @if (items.length > 0) {
+ @for (item of items; track $index) {}
+ }
+ ---
+ @if (items.length === 0) {
+ Not empty
+ }
+ `,
+ `
+ @for (item of items; track $index) {}
+ ---
+ @if (items.length === 0) {
+ Not empty
+ }
+ `,
+ `
+ @for (item of items; track $index) {}
+ @if (items.length > 0) {
+ Not empty
+ }
+ `,
+ `
+ @if (items.length > 0) {
+ Not empty
+ }
+ @for (item of items; track $index) {}
+ `,
+ `
+ @if (beta.length > 0) {
+ @for (item of alpha; track $index) {}
+ @for (item of beta; track $index) {}
+ } @else {
+ Empty
+ }
+ `,
+];
+
+export const invalid: readonly InvalidTestCase[] = [
+ ...[
+ 'items.length === 0',
+ 'items.length == 0',
+ '0 === items.length',
+ '0 == items.length',
+ '!items.length',
+ ].map(
+ (condition): InvalidTestCase =>
+ convertAnnotatedSourceToFailureCase({
+ description: `fails when '@for' block is followed by '@if (${condition})'`,
+ annotatedSource: `
+ @for (item of items; track $index) {}
+ @if (${condition}) {
+ ~~~~
+ No items
+ }
+ `,
+ messageId,
+ annotatedOutput: `
+ @for (item of items; track $index) {}
+ @empty {
+
+ No items
+ }
+ `,
+ }),
+ ),
+ ...[
+ 'items.length === 0',
+ 'items.length == 0',
+ '0 === items.length',
+ '0 == items.length',
+ '!items.length',
+ ].map(
+ (condition): InvalidTestCase =>
+ convertAnnotatedSourceToFailureCase({
+ description: `fails when '@for' block is followed by '@if (${condition})'`,
+ annotatedSource: `
+ @if (${condition}) {
+ ~~~~
+ No items
+ }
+ @for (item of items; track $index) {}
+ `,
+ messageId,
+ annotatedOutput: `
+
+ @for (item of items; track $index) {} @empty {
+
+ No items
+ }
+ `,
+ }),
+ ),
+ ...[
+ 'items.length > 0',
+ 'items.length !== 0',
+ 'items.length != 0',
+ '0 < items.length',
+ '0 !== items.length',
+ '0 != items.length',
+ 'items.length',
+ ].map(
+ (condition): InvalidTestCase =>
+ convertAnnotatedSourceToFailureCase({
+ description: `fails when '@for' block is in '@if (${condition})' block`,
+ annotatedSource: `
+ @if (${condition}) {
+ ~~~~
+ @for (item of items; track $index) {}
+ } @else {
+ No items
+ }
+ `,
+ messageId,
+ annotatedOutput: `
+
+
+ @for (item of items; track $index) {}
+ @empty {
+ No items
+ }
+ `,
+ }),
+ ),
+ ...[
+ 'items.length === 0',
+ 'items.length == 0',
+ '0 === items.length',
+ '0 == items.length',
+ '!items.length',
+ ].map(
+ (condition): InvalidTestCase =>
+ convertAnnotatedSourceToFailureCase({
+ description: `fails when '@for' block is in '@else' block of '@if (${condition})'`,
+ annotatedSource: `
+ @if (${condition}) {
+ ~~~~
+ No items
+ } @else {
+ @for (item of items; track $index) {}
+ }
+ `,
+ messageId,
+ annotatedOutput: `
+
+ @for (item of items; track $index) {} @empty {
+
+ No items
+
+ }
+ `,
+ }),
+ ),
+ convertAnnotatedSourceToFailureCase({
+ description: `fails when '@for' block is in '@if (items.length > 0)' and is followed by '@if (items.length === 0)'`,
+ annotatedSource: `
+ @if (items.length > 0) {
+ ~~~~
+ @for (item of items; track $index) {}
+ }
+ @if (items.length === 0) {
+ No items
+ }
+ `,
+ messageId,
+ annotatedOutput: `
+
+
+ @for (item of items; track $index) {} @empty {
+ No items
+ }
+
+
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ description: `fails when '@if (items.length === 0)' is followed by '@if (items.length > 0)' block that contains the '@for' block`,
+ annotatedSource: `
+ @if (items.length === 0) {
+ No items
+ }
+ @if (items.length > 0) {
+ ~~~~
+ @for (item of items; track $index) {}
+ }
+ `,
+ messageId,
+ annotatedOutput: `
+
+
+
+ @for (item of items; track $index) {} @empty {
+ No items
+
+ }
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ description: `fails when '@for' block inside '@if' block with '@else if' branch`,
+ annotatedSource: `
+ @if (items.length > 0) {
+ ~~~~
+ @for (item of items; track $index) {}
+ } @else if (condition) {
+ Condition is true
+ } @else {
+ Condition is false
+ }
+ `,
+ messageId,
+ annotatedOutput: `
+
+
+ @for (item of items; track $index) {}
+ @empty { @if (condition) {
+ Condition is true
+ } @else {
+ Condition is false
+ }}
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ description: `fails when comment separates '@for' block and '@if' block`,
+ annotatedSource: `
+ @for (item of items; track $index) {}
+
+ @if (items.length === 0) {
+ ~~~~
+ No items
+ }
+ `,
+ messageId,
+ annotatedOutput: `
+ @for (item of items; track $index) {}
+
+ @empty {
+
+ No items
+ }
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ description: `fails when '@for' block is separated from '@if' block by `,
+ annotatedSource: `
+
+ @for (item of items; track $index) {}
+
+ @if (items.length === 0) {
+ ~~~~
+ Not empty
+ }
+ `,
+ messageId,
+ annotatedOutput: `
+
+ @for (item of items; track $index) {}
+
+ @empty {
+
+ Not empty
+ }
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ description: `'@empty' block already exists and '@if' block is before it`,
+ annotatedSource: `
+ @if (items.length === 0) {
+ ~~~~
+ Not empty
+ }
+ @for (item of items; track $index) {}
+ @empty {
+ Existing
+ }
+ `,
+ messageId,
+ annotatedOutput: `
+
+ @for (item of items; track $index) {}
+ @empty {
+ ~~~~
+ Not empty
+
+ Existing
+ }
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ description: `'@empty' block already exists and '@if' block is after it`,
+ annotatedSource: `
+ @for (item of items; track $index) {}
+ @empty {
+ Existing
+ }
+ @if (items.length === 0) {
+ ~~~~
+ Not empty
+ }
+ `,
+ messageId,
+ annotatedOutput: `
+ @for (item of items; track $index) {}
+ @empty {
+ Existing
+
+
+
+ Not empty
+ }
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ description: `replaces '@empty' block when '@for' block is inside '@if' block`,
+ annotatedSource: `
+ @if (items.length > 0) {
+ ~~~~
+ @for (item of items; track $index) {}
+ @empty {
+ Existing
+ }
+ } @else {
+ Empty
+ }
+ `,
+ messageId,
+ annotatedOutput: `
+
+
+ @for (item of items; track $index) {}
+
+ @empty {
+ Empty
+ }
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ description: `replaces '@empty' block when '@for' block is inside '@else' block`,
+ annotatedSource: `
+ @if (items.length === 0) {
+ ~~~~
+ Empty
+ } @else {
+ @for (item of items; track $index) {}
+ @empty {
+ Existing
+ }
+ }
+ `,
+ messageId,
+ annotatedOutput: `
+
+ @for (item of items; track $index) {}
+ @empty {
+
+ Empty
+ }
+
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ description: `adds '@empty' block when '@for' block without '@empty' block is inside '@else' block`,
+ annotatedSource: `
+ @if (items.length === 0) {
+ ~~~~
+ Empty
+ } @else {
+ @for (item of items; track $index) {}
+ }
+ `,
+ messageId,
+ annotatedOutput: `
+
+ @for (item of items; track $index) {} @empty {
+
+ Empty
+
+ }
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ description: `comments around '@for' block in '@if' block are kept`,
+ annotatedSource: `
+ @if (items.length > 0) {
+ ~~~~
+
+ @for (item of items; track $index) {}
+
+ } @else {
+ Empty
+ }
+ `,
+ messageId,
+ annotatedOutput: `
+
+
+
+ @for (item of items; track $index) {}
+
+ @empty {
+ Empty
+ }
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ description: `comments around '@for' block in '@else' block are kept`,
+ annotatedSource: `
+ @if (items.length === 0) {
+ ~~~~
+ Empty
+ } @else {
+
+ @for (item of items; track $index) {}
+
+ }
+ `,
+ messageId,
+ annotatedOutput: `
+
+
+ @for (item of items; track $index) {} @empty {
+
+ Empty
+
+
+ }
+ `,
+ }),
+];
diff --git a/packages/eslint-plugin-template/tests/rules/prefer-at-empty/spec.ts b/packages/eslint-plugin-template/tests/rules/prefer-at-empty/spec.ts
new file mode 100644
index 000000000..60d89180a
--- /dev/null
+++ b/packages/eslint-plugin-template/tests/rules/prefer-at-empty/spec.ts
@@ -0,0 +1,14 @@
+import { RuleTester } from '@angular-eslint/test-utils';
+import rule, { RULE_NAME } from '../../../src/rules/prefer-at-empty';
+import { invalid, valid } from './cases';
+
+const ruleTester = new RuleTester({
+ languageOptions: {
+ parser: require('@angular-eslint/template-parser'),
+ },
+});
+
+ruleTester.run(RULE_NAME, rule, {
+ valid,
+ invalid,
+});
diff --git a/packages/eslint-plugin-template/tests/rules/prefer-template-literal/cases.ts b/packages/eslint-plugin-template/tests/rules/prefer-template-literal/cases.ts
index ed154e09a..d9a888132 100644
--- a/packages/eslint-plugin-template/tests/rules/prefer-template-literal/cases.ts
+++ b/packages/eslint-plugin-template/tests/rules/prefer-template-literal/cases.ts
@@ -266,6 +266,32 @@ export const invalid: readonly InvalidTestCase[] = [
`,
}),
+ convertAnnotatedSourceToFailureCase({
+ messageId,
+ description:
+ 'should fail concatenation (left: simple quote, right: ternary in parentheses)',
+ annotatedSource: `
+ {{ 'prefix-' + (condition ? 'true' : 'false') }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ `,
+ annotatedOutput: `
+ {{ \`prefix-\${condition ? 'true' : 'false'}\` }}
+
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ messageId,
+ description:
+ 'should fail concatenation (left: simple quote, right: pipe in parentheses)',
+ annotatedSource: `
+ {{ 'prefix-' + ('value' | pipe) }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ `,
+ annotatedOutput: `
+ {{ \`prefix-\${'value' | pipe}\` }}
+
+ `,
+ }),
// Left : double quote
convertAnnotatedSourceToFailureCase({
@@ -356,6 +382,32 @@ export const invalid: readonly InvalidTestCase[] = [
`,
}),
+ convertAnnotatedSourceToFailureCase({
+ messageId,
+ description:
+ 'should fail concatenation (left: double quote, right: ternary in parentheses)',
+ annotatedSource: `
+ {{ 'prefix-' + (condition ? 'true' : 'false') }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ `,
+ annotatedOutput: `
+ {{ \`prefix-\${condition ? 'true' : 'false'}\` }}
+
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ messageId,
+ description:
+ 'should fail concatenation (left: double quote, right: pipe in parentheses)',
+ annotatedSource: `
+ {{ 'prefix-' + ('value' | pipe) }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ `,
+ annotatedOutput: `
+ {{ \`prefix-\${'value' | pipe}\` }}
+
+ `,
+ }),
// Left : template
convertAnnotatedSourceToFailureCase({
@@ -443,6 +495,32 @@ export const invalid: readonly InvalidTestCase[] = [
`,
}),
+ convertAnnotatedSourceToFailureCase({
+ messageId,
+ description:
+ 'should fail concatenation (left: template, right: ternary in parentheses)',
+ annotatedSource: `
+ {{ \`prefix-\${value}-suffix\` + (condition ? 'true' : 'false') }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ `,
+ annotatedOutput: `
+ {{ \`prefix-\${value}-suffix\${condition ? 'true' : 'false'}\` }}
+
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ messageId,
+ description:
+ 'should fail concatenation (left: template, right: pipe in parentheses)',
+ annotatedSource: `
+ {{ \`prefix-\${value}-suffix\` + ('value' | pipe) }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ `,
+ annotatedOutput: `
+ {{ \`prefix-\${value}-suffix\${'value' | pipe}\` }}
+
+ `,
+ }),
// Right : simple quote
convertAnnotatedSourceToFailureCase({
@@ -546,6 +624,32 @@ export const invalid: readonly InvalidTestCase[] = [
`,
}),
+ convertAnnotatedSourceToFailureCase({
+ messageId,
+ description:
+ 'should fail concatenation (left: ternary in parentheses, right: simple quote)',
+ annotatedSource: `
+ {{ (condition ? 'true' : 'false') + '-suffix' }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ `,
+ annotatedOutput: `
+ {{ \`\${condition ? 'true' : 'false'}-suffix\` }}
+
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ messageId,
+ description:
+ 'should fail concatenation (left: pipe in parentheses, right: simple quote)',
+ annotatedSource: `
+ {{ ('value' | pipe) + '-suffix' }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ `,
+ annotatedOutput: `
+ {{ \`\${'value' | pipe}-suffix\` }}
+
+ `,
+ }),
// Right : double quote
convertAnnotatedSourceToFailureCase({
@@ -649,6 +753,32 @@ export const invalid: readonly InvalidTestCase[] = [
`,
}),
+ convertAnnotatedSourceToFailureCase({
+ messageId,
+ description:
+ 'should fail concatenation (left: ternary in parentheses, right: double quote)',
+ annotatedSource: `
+ {{ (condition ? 'true' : 'false') + "-suffix" }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ `,
+ annotatedOutput: `
+ {{ \`\${condition ? 'true' : 'false'}-suffix\` }}
+
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ messageId,
+ description:
+ 'should fail concatenation (left: pipe in parentheses, right: double quote)',
+ annotatedSource: `
+ {{ ('value' | pipe) + "-suffix" }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ `,
+ annotatedOutput: `
+ {{ \`\${'value' | pipe}-suffix\` }}
+
+ `,
+ }),
// Right : template
convertAnnotatedSourceToFailureCase({
@@ -736,4 +866,30 @@ export const invalid: readonly InvalidTestCase[] = [
`,
}),
+ convertAnnotatedSourceToFailureCase({
+ messageId,
+ description:
+ 'should fail concatenation (left: ternary in parentheses, right: template)',
+ annotatedSource: `
+ {{ (condition ? 'true' : 'false') + \`prefix-\${value}-suffix\` }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ `,
+ annotatedOutput: `
+ {{ \`\${condition ? 'true' : 'false'}prefix-\${value}-suffix\` }}
+
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ messageId,
+ description:
+ 'should fail concatenation (left: pipe in parentheses, right: template)',
+ annotatedSource: `
+ {{ ('value' | pipe) + \`prefix-\${value}-suffix\` }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ `,
+ annotatedOutput: `
+ {{ \`\${'value' | pipe}prefix-\${value}-suffix\` }}
+
+ `,
+ }),
];
diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md
index bba2f8782..b88f82c61 100644
--- a/packages/eslint-plugin/CHANGELOG.md
+++ b/packages/eslint-plugin/CHANGELOG.md
@@ -1,3 +1,13 @@
+## 19.5.0 (2025-05-25)
+
+### π Features
+
+- **eslint-plugin:** introduce sort keys in type-decorator rule ([#2187](https://github.com/angular-eslint/angular-eslint/pull/2187))
+
+### β€οΈ Thank You
+
+- Benjamin SchΓ€ublin
+
## 19.4.0 (2025-05-08)
### π Features
diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md
index 1058e5c6d..bade7d022 100644
--- a/packages/eslint-plugin/README.md
+++ b/packages/eslint-plugin/README.md
@@ -73,6 +73,7 @@ Please see https://github.com/angular-eslint/angular-eslint for full usage instr
| [`relative-url-prefix`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/relative-url-prefix.md) | The ./ and ../ prefix is standard syntax for relative URLs; don't depend on Angular's current ability to do without that prefix. See more at https://angular.dev/style-guide#style-05-04 | | | |
| [`require-localize-metadata`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/require-localize-metadata.md) | Ensures that $localize tagged messages contain helpful metadata to aid with translations. | | | |
| [`runtime-localize`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/runtime-localize.md) | Ensures that $localize tagged messages can use runtime-loaded translations. | | | |
+| [`sort-keys-in-type-decorator`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/sort-keys-in-type-decorator.md) | Ensures that keys in type decorators (Component, Directive, NgModule, Pipe) are sorted in a consistent order | | :wrench: | |
| [`use-component-selector`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/use-component-selector.md) | Component selector must be declared | | | |
| [`use-component-view-encapsulation`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/use-component-view-encapsulation.md) | Disallows using `ViewEncapsulation.None` | | | :bulb: |
| [`use-injectable-provided-in`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/use-injectable-provided-in.md) | Using the `providedIn` property makes `Injectables` tree-shakable | | | :bulb: |
diff --git a/packages/eslint-plugin/docs/rules/sort-keys-in-type-decorator.md b/packages/eslint-plugin/docs/rules/sort-keys-in-type-decorator.md
new file mode 100644
index 000000000..d4793e734
--- /dev/null
+++ b/packages/eslint-plugin/docs/rules/sort-keys-in-type-decorator.md
@@ -0,0 +1,917 @@
+
+
+
+
+# `@angular-eslint/sort-keys-in-type-decorator`
+
+Ensures that keys in type decorators (Component, Directive, NgModule, Pipe) are sorted in a consistent order
+
+- Type: suggestion
+- π§ Supports autofix (`--fix`)
+
+
+
+## Rule Options
+
+The rule accepts an options object with the following properties:
+
+```ts
+interface Options {
+ /**
+ * Default: `["selector","imports","standalone","templateUrl","template","styleUrl","styleUrls","styles","encapsulation","changeDetection"]`
+ */
+ Component?: string[];
+ /**
+ * Default: `["selector","standalone"]`
+ */
+ Directive?: string[];
+ /**
+ * Default: `["declarations","imports","exports","providers","bootstrap"]`
+ */
+ NgModule?: string[];
+ /**
+ * Default: `["name","standalone"]`
+ */
+ Pipe?: string[];
+}
+
+```
+
+
+
+## Usage Examples
+
+> The following examples are generated automatically from the actual unit tests within the plugin, so you can be assured that their behavior is accurate based on the current commit.
+
+
+
+
+β - Toggle examples of incorrect code for this rule
+
+
+
+#### Custom Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/sort-keys-in-type-decorator": [
+ "error",
+ {
+ "Component": [
+ "selector",
+ "imports",
+ "standalone",
+ "templateUrl",
+ "styleUrl",
+ "encapsulation",
+ "changeDetection"
+ ]
+ }
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```ts
+@Component({
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ selector: 'app-root',
+ imports: [CommonModule],
+ standalone: true,
+ templateUrl: './app.component.html',
+ styleUrl: './app.component.css',
+ encapsulation: ViewEncapsulation.None
+})
+class Test {
+}
+```
+
+
+
+---
+
+
+
+#### Custom Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/sort-keys-in-type-decorator": [
+ "error",
+ {
+ "Directive": [
+ "selector",
+ "standalone"
+ ]
+ }
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```ts
+@Directive({
+ standalone: true,
+ ~~~~~~~~~~~~~~~~
+ selector: '[app-test]'
+})
+class Test {
+}
+```
+
+
+
+---
+
+
+
+#### Custom Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/sort-keys-in-type-decorator": [
+ "error",
+ {
+ "NgModule": [
+ "declarations",
+ "imports"
+ ]
+ }
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```ts
+@NgModule({
+ imports: [CommonModule],
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ declarations: [AppComponent]
+})
+class Test {
+}
+```
+
+
+
+---
+
+
+
+#### Custom Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/sort-keys-in-type-decorator": [
+ "error",
+ {
+ "Pipe": [
+ "name",
+ "standalone"
+ ]
+ }
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```ts
+@Pipe({
+ standalone: true,
+ ~~~~~~~~~~~~~~~~
+ name: 'myPipe'
+})
+class Test {
+}
+```
+
+
+
+---
+
+
+
+#### Custom Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/sort-keys-in-type-decorator": [
+ "error",
+ {
+ "Component": [
+ "selector",
+ "imports",
+ "standalone",
+ "templateUrl",
+ "styleUrl",
+ "encapsulation",
+ "changeDetection"
+ ]
+ }
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```ts
+@Component({
+ styleUrl: './app.component.css',
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ selector: 'app-root',
+ templateUrl: './app.component.html'
+})
+class Test {
+}
+```
+
+
+
+---
+
+
+
+#### Custom Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/sort-keys-in-type-decorator": [
+ "error",
+ {
+ "NgModule": [
+ "declarations",
+ "imports",
+ "exports",
+ "providers",
+ "bootstrap"
+ ]
+ }
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```ts
+@NgModule({
+ exports: [AppComponent],
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ declarations: [AppComponent]
+})
+class Test {
+}
+```
+
+
+
+---
+
+
+
+#### Custom Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/sort-keys-in-type-decorator": [
+ "error",
+ {
+ "Component": [
+ "selector",
+ "styleUrl"
+ ]
+ }
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```ts
+@Component({
+ styleUrl: './app.component.css', // Inline comment for styleUrl
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ selector: 'app-root' // Inline comment for selector
+})
+class Test {}
+```
+
+
+
+---
+
+
+
+#### Custom Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/sort-keys-in-type-decorator": [
+ "error",
+ {
+ "Component": [
+ "selector",
+ "styleUrl"
+ ]
+ }
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```ts
+@Component({
+ // Comment above styleUrl
+ styleUrl: './app.component.css',
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // Comment above selector
+ selector: 'app-root'
+})
+class Test {}
+```
+
+
+
+---
+
+
+
+#### Custom Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/sort-keys-in-type-decorator": [
+ "error",
+ {
+ "Component": [
+ "selector",
+ "styleUrl"
+ ]
+ }
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```ts
+@Component({
+ /* This is a multi-line comment
+ above styleUrl property */
+ styleUrl: './app.component.css',
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ /* This is a multi-line comment
+ above selector property */
+ selector: 'app-root'
+})
+class Test {}
+```
+
+
+
+---
+
+
+
+#### Custom Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/sort-keys-in-type-decorator": [
+ "error",
+ {
+ "Component": [
+ "selector",
+ "imports",
+ "standalone",
+ "templateUrl",
+ "styleUrl",
+ "encapsulation",
+ "changeDetection"
+ ]
+ }
+ ]
+ }
+}
+```
+
+
+
+#### β Invalid Code
+
+```ts
+@Component({
+ // Comment above changeDetection
+ changeDetection: ChangeDetectionStrategy.OnPush, // Inline comment for changeDetection
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ /* Multi-line comment
+ above selector */
+ selector: 'app-root', /* Inline multi-line comment after selector */
+ // Comment above imports
+ imports: [
+ // Comment inside imports array
+ CommonModule, // Comment after CommonModule
+ FormsModule /* Comment after FormsModule */
+ ],
+ /* Comment above standalone */
+ standalone: true, // Comment after standalone
+ // Comment above templateUrl
+ templateUrl: './app.component.html',
+ /* Multi-line comment
+ above styleUrl */
+ styleUrl: './app.component.css',
+ // Comment above encapsulation
+ encapsulation: ViewEncapsulation.None /* Inline comment for encapsulation */
+})
+class Test {}
+```
+
+
+
+
+
+---
+
+
+
+
+β
- Toggle examples of correct code for this rule
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/sort-keys-in-type-decorator": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```ts
+@Type({
+ a: 'a',
+ b: 'b',
+ c: 'c'
+})
+class Test {}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/sort-keys-in-type-decorator": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```ts
+@Type({})
+class Test {}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/sort-keys-in-type-decorator": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```ts
+@Type({
+ a: 'a'
+})
+class Test {}
+```
+
+
+
+---
+
+
+
+#### Custom Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/sort-keys-in-type-decorator": [
+ "error",
+ {
+ "Component": [
+ "selector",
+ "imports",
+ "standalone",
+ "templateUrl",
+ "styleUrl",
+ "encapsulation",
+ "changeDetection"
+ ]
+ }
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```ts
+@Component({
+ selector: 'app-root',
+ imports: [CommonModule],
+ standalone: true,
+ templateUrl: './app.component.html',
+ styleUrl: './app.component.css',
+ encapsulation: ViewEncapsulation.None,
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+class Test {}
+```
+
+
+
+---
+
+
+
+#### Custom Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/sort-keys-in-type-decorator": [
+ "error",
+ {
+ "Directive": [
+ "selector",
+ "standalone"
+ ]
+ }
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```ts
+@Directive({
+ selector: '[app-test]',
+ standalone: true
+})
+class Test {}
+```
+
+
+
+---
+
+
+
+#### Custom Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/sort-keys-in-type-decorator": [
+ "error",
+ {
+ "NgModule": [
+ "declarations",
+ "imports"
+ ]
+ }
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```ts
+@NgModule({
+ declarations: [AppComponent],
+ imports: [CommonModule]
+})
+class Test {}
+```
+
+
+
+---
+
+
+
+#### Custom Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/sort-keys-in-type-decorator": [
+ "error",
+ {
+ "Pipe": [
+ "name",
+ "standalone"
+ ]
+ }
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```ts
+@Pipe({
+ name: 'myPipe',
+ standalone: true
+})
+class Test {}
+```
+
+
+
+---
+
+
+
+#### Custom Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/sort-keys-in-type-decorator": [
+ "error",
+ {
+ "Component": [
+ "selector",
+ "imports",
+ "standalone",
+ "templateUrl",
+ "styleUrl",
+ "encapsulation",
+ "changeDetection"
+ ]
+ }
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```ts
+@Component({
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrl: './app.component.css'
+})
+class Test {}
+```
+
+
+
+---
+
+
+
+#### Custom Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/sort-keys-in-type-decorator": [
+ "error",
+ {
+ "NgModule": [
+ "declarations",
+ "imports",
+ "exports",
+ "providers",
+ "bootstrap"
+ ]
+ }
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```ts
+@NgModule({
+ declarations: [AppComponent],
+ exports: [AppComponent]
+})
+class Test {}
+```
+
+
+
+---
+
+
+
+#### Custom Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/sort-keys-in-type-decorator": [
+ "error",
+ {
+ "Component": [
+ "selector",
+ "imports",
+ "standalone",
+ "templateUrl",
+ "styleUrl",
+ "encapsulation",
+ "changeDetection"
+ ]
+ }
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```ts
+@Component({
+ // Comment above selector
+ selector: 'app-root', // Inline comment for selector
+ /* Multi-line comment
+ above imports */
+ imports: [
+ CommonModule,
+ FormsModule
+ ], // Inline comment after imports
+ standalone: true,
+ templateUrl: './app.component.html',
+ styleUrl: './app.component.css',
+ // Comment above encapsulation
+ encapsulation: ViewEncapsulation.None,
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+class Test {}
+```
+
+
+
+---
+
+
+
+#### Custom Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/sort-keys-in-type-decorator": [
+ "error",
+ {
+ "NgModule": [
+ "declarations",
+ "imports",
+ "exports",
+ "providers",
+ "bootstrap"
+ ]
+ }
+ ]
+ }
+}
+```
+
+
+
+#### β
Valid Code
+
+```ts
+@NgModule({
+ // Leading comment for declarations
+ declarations: [
+ /* Component list comment */
+ AppComponent,
+ HeaderComponent
+ ],
+ imports: [
+ CommonModule, // Common module comment
+ RouterModule /* Router module comment */
+ ],
+ /* Multi-line export comment
+ with multiple lines
+ before the property */
+ exports: [AppComponent]
+})
+class Test {}
+```
+
+
+
+
diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json
index c43aad63f..200271483 100644
--- a/packages/eslint-plugin/package.json
+++ b/packages/eslint-plugin/package.json
@@ -1,6 +1,6 @@
{
"name": "@angular-eslint/eslint-plugin",
- "version": "19.4.0",
+ "version": "19.5.0",
"description": "ESLint plugin for Angular applications, following https://angular.dev/style-guide",
"license": "MIT",
"main": "dist/index.js",
diff --git a/packages/eslint-plugin/src/configs/all.json b/packages/eslint-plugin/src/configs/all.json
index 433f79d34..e34434e1a 100644
--- a/packages/eslint-plugin/src/configs/all.json
+++ b/packages/eslint-plugin/src/configs/all.json
@@ -36,6 +36,7 @@
"@angular-eslint/require-lifecycle-on-prototype": "error",
"@angular-eslint/require-localize-metadata": "error",
"@angular-eslint/runtime-localize": "error",
+ "@angular-eslint/sort-keys-in-type-decorator": "error",
"@angular-eslint/sort-lifecycle-methods": "error",
"@angular-eslint/use-component-selector": "error",
"@angular-eslint/use-component-view-encapsulation": "error",
diff --git a/packages/eslint-plugin/src/index.ts b/packages/eslint-plugin/src/index.ts
index 65c28d877..5c6b3824b 100644
--- a/packages/eslint-plugin/src/index.ts
+++ b/packages/eslint-plugin/src/index.ts
@@ -34,6 +34,9 @@ import noAttributeDecorator, {
import noConflictingLifecycle, {
RULE_NAME as noConflictingLifecycleRuleName,
} from './rules/no-conflicting-lifecycle';
+import noDuplicatesInMetadataArrays, {
+ RULE_NAME as noDuplicatesInMetadataArraysRuleName,
+} from './rules/no-duplicates-in-metadata-arrays';
import noEmptyLifecycleMethod, {
RULE_NAME as noEmptyLifecycleMethodRuleName,
} from './rules/no-empty-lifecycle-method';
@@ -100,6 +103,9 @@ import requireLocalizeMetadata, {
import runtimeLocalize, {
RULE_NAME as runtimeLocalizeRuleName,
} from './rules/runtime-localize';
+import sortKeysInTypeDecorator, {
+ RULE_NAME as sortKeysInTypeDecoratorRuleName,
+} from './rules/sort-keys-in-type-decorator';
import sortLifecycleMethods, {
RULE_NAME as sortLifecycleMethodsRuleName,
} from './rules/sort-lifecycle-methods';
@@ -118,9 +124,6 @@ import useLifecycleInterface, {
import usePipeTransformInterface, {
RULE_NAME as usePipeTransformInterfaceRuleName,
} from './rules/use-pipe-transform-interface';
-import noDuplicatesInMetadataArrays, {
- RULE_NAME as noDuplicatesInMetadataArraysRuleName,
-} from './rules/no-duplicates-in-metadata-arrays';
export = {
configs: {
@@ -163,6 +166,7 @@ export = {
[requireLifecycleOnPrototypeRuleName]: requireLifecycleOnPrototype,
[requireLocalizeMetadataRuleName]: requireLocalizeMetadata,
[runtimeLocalizeRuleName]: runtimeLocalize,
+ [sortKeysInTypeDecoratorRuleName]: sortKeysInTypeDecorator,
[sortLifecycleMethodsRuleName]: sortLifecycleMethods,
[useComponentSelectorRuleName]: useComponentSelector,
[useComponentViewEncapsulationRuleName]: useComponentViewEncapsulation,
diff --git a/packages/eslint-plugin/src/rules/sort-keys-in-type-decorator.ts b/packages/eslint-plugin/src/rules/sort-keys-in-type-decorator.ts
new file mode 100644
index 000000000..1048743c6
--- /dev/null
+++ b/packages/eslint-plugin/src/rules/sort-keys-in-type-decorator.ts
@@ -0,0 +1,256 @@
+import { ASTUtils, CommentUtils, Selectors } from '@angular-eslint/utils';
+import { TSESLint, TSESTree } from '@typescript-eslint/utils';
+import { createESLintRule } from '../utils/create-eslint-rule';
+
+export type Options = [
+ {
+ [key: string]: string[];
+ },
+];
+
+export type MessageIds = 'incorrectOrder';
+
+const DEFAULT_ORDER = {
+ Component: [
+ 'selector',
+ 'imports',
+ 'standalone',
+ 'templateUrl',
+ 'template',
+ 'styleUrl',
+ 'styleUrls',
+ 'styles',
+ 'encapsulation',
+ 'changeDetection',
+ ],
+ Directive: ['selector', 'standalone'],
+ NgModule: ['declarations', 'imports', 'exports', 'providers', 'bootstrap'],
+ Pipe: ['name', 'standalone'],
+};
+
+export const RULE_NAME = 'sort-keys-in-type-decorator';
+
+export default createESLintRule({
+ name: RULE_NAME,
+ meta: {
+ type: 'suggestion',
+ docs: {
+ description:
+ 'Ensures that keys in type decorators (Component, Directive, NgModule, Pipe) are sorted in a consistent order',
+ },
+ fixable: 'code',
+ schema: [
+ {
+ type: 'object',
+ properties: {
+ Component: {
+ type: 'array',
+ items: {
+ type: 'string',
+ },
+ },
+ Directive: {
+ type: 'array',
+ items: {
+ type: 'string',
+ },
+ },
+ NgModule: {
+ type: 'array',
+ items: {
+ type: 'string',
+ },
+ },
+ Pipe: {
+ type: 'array',
+ items: {
+ type: 'string',
+ },
+ },
+ },
+ additionalProperties: false,
+ },
+ ],
+ messages: {
+ incorrectOrder:
+ 'Keys in @{{decorator}} decorator should be ordered: {{expectedOrder}}',
+ },
+ },
+ defaultOptions: [DEFAULT_ORDER],
+ create(
+ context: Readonly>,
+ [orderConfig]: Readonly,
+ ) {
+ function checkContext(
+ node: TSESTree.Decorator,
+ decoratorName: string,
+ ): void {
+ const expectedOrder = orderConfig[decoratorName];
+ if (!expectedOrder) {
+ return;
+ }
+
+ const argument = ASTUtils.getDecoratorArgument(node);
+ if (!argument) {
+ return;
+ }
+
+ const properties = ASTUtils.getDecoratorProperties(node);
+ if (properties.length <= 1) {
+ return;
+ }
+
+ const firstConfiguredIndex = properties.findIndex(({ key }) =>
+ expectedOrder.includes((key as TSESTree.Identifier).name),
+ );
+ const lastNonConfiguredIndex = properties.findIndex(
+ ({ key }) => !expectedOrder.includes((key as TSESTree.Identifier).name),
+ );
+
+ if (
+ firstConfiguredIndex !== -1 &&
+ lastNonConfiguredIndex !== -1 &&
+ lastNonConfiguredIndex < firstConfiguredIndex
+ ) {
+ createInvalidSortRuleForDecorator(
+ context,
+ decoratorName,
+ expectedOrder,
+ properties,
+ properties[lastNonConfiguredIndex],
+ );
+ return;
+ }
+
+ const configuredProperties = properties.filter(({ key }) =>
+ expectedOrder.includes((key as TSESTree.Identifier).name),
+ );
+
+ if (configuredProperties.length) {
+ const actualConfiguredOrder = configuredProperties.map(
+ ({ key }) => (key as TSESTree.Identifier).name,
+ );
+ const expectedConfiguredOrder = expectedOrder.filter((key: string) =>
+ actualConfiguredOrder.includes(key),
+ );
+
+ if (
+ actualConfiguredOrder.length &&
+ JSON.stringify(actualConfiguredOrder) !==
+ JSON.stringify(expectedConfiguredOrder)
+ ) {
+ const firstOutOfOrderIndex = actualConfiguredOrder.findIndex(
+ (key, index) => key !== expectedConfiguredOrder[index],
+ );
+ const outOfOrderProperty = configuredProperties[firstOutOfOrderIndex];
+
+ createInvalidSortRuleForDecorator(
+ context,
+ decoratorName,
+ expectedOrder,
+ properties,
+ outOfOrderProperty,
+ );
+ }
+ }
+ }
+
+ return {
+ [Selectors.COMPONENT_CLASS_DECORATOR](node: TSESTree.Decorator) {
+ checkContext(node, ASTUtils.AngularClassDecorators.Component);
+ },
+ [Selectors.DIRECTIVE_CLASS_DECORATOR](node: TSESTree.Decorator) {
+ checkContext(node, ASTUtils.AngularClassDecorators.Directive);
+ },
+ [Selectors.INJECTABLE_CLASS_DECORATOR](node: TSESTree.Decorator) {
+ checkContext(node, ASTUtils.AngularClassDecorators.Injectable);
+ },
+ [Selectors.MODULE_CLASS_DECORATOR](node: TSESTree.Decorator) {
+ checkContext(node, ASTUtils.AngularClassDecorators.NgModule);
+ },
+ [Selectors.PIPE_CLASS_DECORATOR](node: TSESTree.Decorator) {
+ checkContext(node, ASTUtils.AngularClassDecorators.Pipe);
+ },
+ };
+ },
+});
+
+function createInvalidSortRuleForDecorator(
+ context: Readonly>,
+ decoratorName: string,
+ expectedOrder: string[],
+ properties: TSESTree.Property[],
+ node: TSESTree.Property,
+): void {
+ const presentProps = properties.map(
+ (prop) => (prop.key as TSESTree.Identifier).name,
+ );
+
+ const relevantExpectedOrder = expectedOrder.filter((propName) =>
+ presentProps.includes(propName),
+ );
+
+ const data = {
+ decorator: decoratorName,
+ expectedOrder: relevantExpectedOrder.join(', '),
+ };
+
+ reportAndFix(
+ context,
+ node,
+ 'incorrectOrder',
+ data,
+ properties,
+ expectedOrder,
+ node.parent as TSESTree.Expression,
+ );
+}
+
+function reportAndFix(
+ context: Readonly>,
+ node: TSESTree.Property,
+ messageId: MessageIds,
+ data: { decorator: string; expectedOrder: string },
+ properties: TSESTree.Property[],
+ expectedOrder: string[],
+ objectExpression: TSESTree.Expression,
+): void {
+ const sourceCode = context.sourceCode;
+
+ context.report({
+ node,
+ messageId,
+ data,
+ fix(fixer) {
+ const indentation = CommentUtils.getObjectIndentation(
+ sourceCode,
+ objectExpression,
+ );
+
+ const propNames = properties.map(
+ (p) => (p.key as TSESTree.Identifier).name,
+ );
+ const filteredOrder = expectedOrder.filter((name) =>
+ propNames.includes(name),
+ );
+
+ const propInfoMap = CommentUtils.extractPropertyComments(
+ sourceCode,
+ properties,
+ objectExpression,
+ indentation,
+ );
+
+ const sortedText = CommentUtils.buildSortedPropertiesWithComments(
+ filteredOrder,
+ propInfoMap,
+ indentation,
+ );
+
+ return fixer.replaceText(
+ objectExpression,
+ `{\n${sortedText}\n${indentation.slice(0, -2)}}`,
+ );
+ },
+ });
+}
diff --git a/packages/eslint-plugin/tests/rules/sort-keys-in-type-decorator/cases.ts b/packages/eslint-plugin/tests/rules/sort-keys-in-type-decorator/cases.ts
new file mode 100644
index 000000000..4201c14e2
--- /dev/null
+++ b/packages/eslint-plugin/tests/rules/sort-keys-in-type-decorator/cases.ts
@@ -0,0 +1,606 @@
+import { convertAnnotatedSourceToFailureCase } from '@angular-eslint/test-utils';
+import type {
+ InvalidTestCase,
+ ValidTestCase,
+} from '@typescript-eslint/rule-tester';
+import type {
+ MessageIds,
+ Options,
+} from '../../../src/rules/sort-keys-in-type-decorator';
+
+export const valid: readonly ValidTestCase[] = [
+ {
+ code: `
+ @Type({
+ a: 'a',
+ b: 'b',
+ c: 'c'
+ })
+ class Test {}
+ `,
+ },
+ {
+ code: `
+ @Type({})
+ class Test {}
+ `,
+ },
+ {
+ code: `
+ @Type({
+ a: 'a'
+ })
+ class Test {}
+ `,
+ },
+ {
+ code: `
+ @Component({
+ selector: 'app-root',
+ imports: [CommonModule],
+ standalone: true,
+ templateUrl: './app.component.html',
+ styleUrl: './app.component.css',
+ encapsulation: ViewEncapsulation.None,
+ changeDetection: ChangeDetectionStrategy.OnPush
+ })
+ class Test {}
+ `,
+ options: [
+ {
+ Component: [
+ 'selector',
+ 'imports',
+ 'standalone',
+ 'templateUrl',
+ 'styleUrl',
+ 'encapsulation',
+ 'changeDetection',
+ ],
+ },
+ ],
+ },
+ {
+ code: `
+ @Directive({
+ selector: '[app-test]',
+ standalone: true
+ })
+ class Test {}
+ `,
+ options: [
+ {
+ Directive: ['selector', 'standalone'],
+ },
+ ],
+ },
+ {
+ code: `
+ @NgModule({
+ declarations: [AppComponent],
+ imports: [CommonModule]
+ })
+ class Test {}
+ `,
+ options: [
+ {
+ NgModule: ['declarations', 'imports'],
+ },
+ ],
+ },
+ {
+ code: `
+ @Pipe({
+ name: 'myPipe',
+ standalone: true
+ })
+ class Test {}
+ `,
+ options: [
+ {
+ Pipe: ['name', 'standalone'],
+ },
+ ],
+ },
+ {
+ code: `
+ @Component({
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrl: './app.component.css'
+ })
+ class Test {}
+ `,
+ options: [
+ {
+ Component: [
+ 'selector',
+ 'imports',
+ 'standalone',
+ 'templateUrl',
+ 'styleUrl',
+ 'encapsulation',
+ 'changeDetection',
+ ],
+ },
+ ],
+ },
+ {
+ code: `
+ @NgModule({
+ declarations: [AppComponent],
+ exports: [AppComponent]
+ })
+ class Test {}
+ `,
+ options: [
+ {
+ NgModule: [
+ 'declarations',
+ 'imports',
+ 'exports',
+ 'providers',
+ 'bootstrap',
+ ],
+ },
+ ],
+ },
+ {
+ code: `
+ @Component({
+ // Comment above selector
+ selector: 'app-root', // Inline comment for selector
+ /* Multi-line comment
+ above imports */
+ imports: [
+ CommonModule,
+ FormsModule
+ ], // Inline comment after imports
+ standalone: true,
+ templateUrl: './app.component.html',
+ styleUrl: './app.component.css',
+ // Comment above encapsulation
+ encapsulation: ViewEncapsulation.None,
+ changeDetection: ChangeDetectionStrategy.OnPush
+ })
+ class Test {}
+ `,
+ options: [
+ {
+ Component: [
+ 'selector',
+ 'imports',
+ 'standalone',
+ 'templateUrl',
+ 'styleUrl',
+ 'encapsulation',
+ 'changeDetection',
+ ],
+ },
+ ],
+ },
+ {
+ code: `
+ @NgModule({
+ // Leading comment for declarations
+ declarations: [
+ /* Component list comment */
+ AppComponent,
+ HeaderComponent
+ ],
+ imports: [
+ CommonModule, // Common module comment
+ RouterModule /* Router module comment */
+ ],
+ /* Multi-line export comment
+ with multiple lines
+ before the property */
+ exports: [AppComponent]
+ })
+ class Test {}
+ `,
+ options: [
+ {
+ NgModule: [
+ 'declarations',
+ 'imports',
+ 'exports',
+ 'providers',
+ 'bootstrap',
+ ],
+ },
+ ],
+ },
+];
+
+export const invalid: readonly InvalidTestCase[] = [
+ convertAnnotatedSourceToFailureCase({
+ description:
+ 'should fail when Component decorator keys are not sorted according to specified order',
+ annotatedSource: `
+ @Component({
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ selector: 'app-root',
+ imports: [CommonModule],
+ standalone: true,
+ templateUrl: './app.component.html',
+ styleUrl: './app.component.css',
+ encapsulation: ViewEncapsulation.None
+ })
+ class Test {
+ }
+ `,
+ messageId: 'incorrectOrder',
+ data: {
+ decorator: 'Component',
+ expectedOrder:
+ 'selector, imports, standalone, templateUrl, styleUrl, encapsulation, changeDetection',
+ },
+ options: [
+ {
+ Component: [
+ 'selector',
+ 'imports',
+ 'standalone',
+ 'templateUrl',
+ 'styleUrl',
+ 'encapsulation',
+ 'changeDetection',
+ ],
+ },
+ ],
+ annotatedOutput: `
+ @Component({
+ selector: 'app-root',
+ imports: [CommonModule],
+ standalone: true,
+ templateUrl: './app.component.html',
+ styleUrl: './app.component.css',
+ encapsulation: ViewEncapsulation.None,
+ changeDetection: ChangeDetectionStrategy.OnPush
+ })
+ class Test {
+ }
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ description:
+ 'should fail when Directive decorator keys are not sorted according to specified order',
+ annotatedSource: `
+ @Directive({
+ standalone: true,
+ ~~~~~~~~~~~~~~~~
+ selector: '[app-test]'
+ })
+ class Test {
+ }
+ `,
+ messageId: 'incorrectOrder',
+ data: {
+ decorator: 'Directive',
+ expectedOrder: 'selector, standalone',
+ },
+ options: [
+ {
+ Directive: ['selector', 'standalone'],
+ },
+ ],
+ annotatedOutput: `
+ @Directive({
+ selector: '[app-test]',
+ standalone: true
+ })
+ class Test {
+ }
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ description:
+ 'should fail when NgModule decorator keys are not sorted according to specified order',
+ annotatedSource: `
+ @NgModule({
+ imports: [CommonModule],
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ declarations: [AppComponent]
+ })
+ class Test {
+ }
+ `,
+ messageId: 'incorrectOrder',
+ data: {
+ decorator: 'NgModule',
+ expectedOrder: 'declarations, imports',
+ },
+ options: [
+ {
+ NgModule: ['declarations', 'imports'],
+ },
+ ],
+ annotatedOutput: `
+ @NgModule({
+ declarations: [AppComponent],
+ imports: [CommonModule]
+ })
+ class Test {
+ }
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ description:
+ 'should fail when Pipe decorator keys are not sorted according to specified order',
+ annotatedSource: `
+ @Pipe({
+ standalone: true,
+ ~~~~~~~~~~~~~~~~
+ name: 'myPipe'
+ })
+ class Test {
+ }
+ `,
+ messageId: 'incorrectOrder',
+ data: {
+ decorator: 'Pipe',
+ expectedOrder: 'name, standalone',
+ },
+ options: [
+ {
+ Pipe: ['name', 'standalone'],
+ },
+ ],
+ annotatedOutput: `
+ @Pipe({
+ name: 'myPipe',
+ standalone: true
+ })
+ class Test {
+ }
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ description: 'should fail when partial properties are not in correct order',
+ annotatedSource: `
+ @Component({
+ styleUrl: './app.component.css',
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ selector: 'app-root',
+ templateUrl: './app.component.html'
+ })
+ class Test {
+ }
+ `,
+ messageId: 'incorrectOrder',
+ data: {
+ decorator: 'Component',
+ expectedOrder: 'selector, templateUrl, styleUrl',
+ },
+ options: [
+ {
+ Component: [
+ 'selector',
+ 'imports',
+ 'standalone',
+ 'templateUrl',
+ 'styleUrl',
+ 'encapsulation',
+ 'changeDetection',
+ ],
+ },
+ ],
+ annotatedOutput: `
+ @Component({
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrl: './app.component.css'
+ })
+ class Test {
+ }
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ description:
+ 'should fail when partial NgModule properties are not in correct order',
+ annotatedSource: `
+ @NgModule({
+ exports: [AppComponent],
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ declarations: [AppComponent]
+ })
+ class Test {
+ }
+ `,
+ messageId: 'incorrectOrder',
+ data: {
+ decorator: 'NgModule',
+ expectedOrder: 'declarations, exports',
+ },
+ options: [
+ {
+ NgModule: [
+ 'declarations',
+ 'imports',
+ 'exports',
+ 'providers',
+ 'bootstrap',
+ ],
+ },
+ ],
+ annotatedOutput: `
+ @NgModule({
+ declarations: [AppComponent],
+ exports: [AppComponent]
+ })
+ class Test {
+ }
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ description: 'should handle basic inline comments when sorting properties',
+ annotatedSource: `
+ @Component({
+ styleUrl: './app.component.css', // Inline comment for styleUrl
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ selector: 'app-root' // Inline comment for selector
+ })
+ class Test {}
+ `,
+ messageId: 'incorrectOrder',
+ data: {
+ decorator: 'Component',
+ expectedOrder: 'selector, styleUrl',
+ },
+ options: [
+ {
+ Component: ['selector', 'styleUrl'],
+ },
+ ],
+ annotatedOutput: `
+ @Component({
+ selector: 'app-root', // Inline comment for selector
+ styleUrl: './app.component.css' // Inline comment for styleUrl
+ })
+ class Test {}
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ description: 'should preserve leading comments when sorting properties',
+ annotatedSource: `
+ @Component({
+ // Comment above styleUrl
+ styleUrl: './app.component.css',
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // Comment above selector
+ selector: 'app-root'
+ })
+ class Test {}
+ `,
+ messageId: 'incorrectOrder',
+ data: {
+ decorator: 'Component',
+ expectedOrder: 'selector, styleUrl',
+ },
+ options: [
+ {
+ Component: ['selector', 'styleUrl'],
+ },
+ ],
+ annotatedOutput: `
+ @Component({
+ // Comment above selector
+ selector: 'app-root',
+ // Comment above styleUrl
+ styleUrl: './app.component.css'
+ })
+ class Test {}
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ description: 'should preserve multi-line comments when sorting properties',
+ annotatedSource: `
+ @Component({
+ /* This is a multi-line comment
+ above styleUrl property */
+ styleUrl: './app.component.css',
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ /* This is a multi-line comment
+ above selector property */
+ selector: 'app-root'
+ })
+ class Test {}
+ `,
+ messageId: 'incorrectOrder',
+ data: {
+ decorator: 'Component',
+ expectedOrder: 'selector, styleUrl',
+ },
+ options: [
+ {
+ Component: ['selector', 'styleUrl'],
+ },
+ ],
+ annotatedOutput: `
+ @Component({
+ /* This is a multi-line comment
+ above selector property */
+ selector: 'app-root',
+ /* This is a multi-line comment
+ above styleUrl property */
+ styleUrl: './app.component.css'
+ })
+ class Test {}
+ `,
+ }),
+ convertAnnotatedSourceToFailureCase({
+ description: 'should properly handle comments when sorting properties',
+ annotatedSource: `
+ @Component({
+ // Comment above changeDetection
+ changeDetection: ChangeDetectionStrategy.OnPush, // Inline comment for changeDetection
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ /* Multi-line comment
+ above selector */
+ selector: 'app-root', /* Inline multi-line comment after selector */
+ // Comment above imports
+ imports: [
+ // Comment inside imports array
+ CommonModule, // Comment after CommonModule
+ FormsModule /* Comment after FormsModule */
+ ],
+ /* Comment above standalone */
+ standalone: true, // Comment after standalone
+ // Comment above templateUrl
+ templateUrl: './app.component.html',
+ /* Multi-line comment
+ above styleUrl */
+ styleUrl: './app.component.css',
+ // Comment above encapsulation
+ encapsulation: ViewEncapsulation.None /* Inline comment for encapsulation */
+ })
+ class Test {}
+ `,
+ messageId: 'incorrectOrder',
+ data: {
+ decorator: 'Component',
+ expectedOrder:
+ 'selector, imports, standalone, templateUrl, styleUrl, encapsulation, changeDetection',
+ },
+ options: [
+ {
+ Component: [
+ 'selector',
+ 'imports',
+ 'standalone',
+ 'templateUrl',
+ 'styleUrl',
+ 'encapsulation',
+ 'changeDetection',
+ ],
+ },
+ ],
+ annotatedOutput: `
+ @Component({
+ /* Multi-line comment
+ above selector */
+ selector: 'app-root', /* Inline multi-line comment after selector */
+ // Comment above imports
+ imports: [
+ // Comment inside imports array
+ CommonModule, // Comment after CommonModule
+ FormsModule /* Comment after FormsModule */
+ ],
+ /* Comment above standalone */
+ standalone: true, // Comment after standalone
+ // Comment above templateUrl
+ templateUrl: './app.component.html',
+ /* Multi-line comment
+ above styleUrl */
+ styleUrl: './app.component.css',
+ // Comment above encapsulation
+ encapsulation: ViewEncapsulation.None, /* Inline comment for encapsulation */
+ // Comment above changeDetection
+ changeDetection: ChangeDetectionStrategy.OnPush // Inline comment for changeDetection
+ })
+ class Test {}
+ `,
+ }),
+];
diff --git a/packages/eslint-plugin/tests/rules/sort-keys-in-type-decorator/spec.ts b/packages/eslint-plugin/tests/rules/sort-keys-in-type-decorator/spec.ts
new file mode 100644
index 000000000..be8e7fb7d
--- /dev/null
+++ b/packages/eslint-plugin/tests/rules/sort-keys-in-type-decorator/spec.ts
@@ -0,0 +1,12 @@
+import { RuleTester } from '@angular-eslint/test-utils';
+import rule, {
+ RULE_NAME,
+} from '../../../src/rules/sort-keys-in-type-decorator';
+import { invalid, valid } from './cases';
+
+const ruleTester = new RuleTester();
+
+ruleTester.run(RULE_NAME, rule, {
+ valid,
+ invalid,
+});
diff --git a/packages/schematics/CHANGELOG.md b/packages/schematics/CHANGELOG.md
index 8492e09af..da5821382 100644
--- a/packages/schematics/CHANGELOG.md
+++ b/packages/schematics/CHANGELOG.md
@@ -1,3 +1,19 @@
+## 19.5.0 (2025-05-25)
+
+### π Features
+
+- **schematics:** support --skip-install for ng-add ([#2451](https://github.com/angular-eslint/angular-eslint/pull/2451))
+
+### π©Ή Fixes
+
+- update dependency eslint to v9.27.0 ([#2431](https://github.com/angular-eslint/angular-eslint/pull/2431))
+- update typescript-eslint packages to v8.32.1 ([#2422](https://github.com/angular-eslint/angular-eslint/pull/2422))
+- update dependency semver to v7.7.2 ([#2421](https://github.com/angular-eslint/angular-eslint/pull/2421))
+
+### β€οΈ Thank You
+
+- James Henry @JamesHenry
+
## 19.4.0 (2025-05-08)
### π©Ή Fixes
diff --git a/packages/schematics/README.md b/packages/schematics/README.md
index 1522b359f..130ccbf45 100644
--- a/packages/schematics/README.md
+++ b/packages/schematics/README.md
@@ -3,3 +3,13 @@
Please see https://github.com/angular-eslint/angular-eslint for full usage instructions and guidance.
The `@angular-eslint/schematics` package is a set of custom Angular CLI Schematics which are used to add and update dependencies and configuration files which are relevant for running ESLint on an Angular workspace.
+
+## Options
+
+### `--skip-install`
+
+Skips installing npm packages when running `ng add @angular-eslint/schematics`. This can be useful when the schematic is executed as part of a larger workflow that handles dependency installation separately.
+
+```
+ng add @angular-eslint/schematics --skip-install
+```
diff --git a/packages/schematics/package.json b/packages/schematics/package.json
index 213bc6e6f..2444d993a 100644
--- a/packages/schematics/package.json
+++ b/packages/schematics/package.json
@@ -1,6 +1,6 @@
{
"name": "@angular-eslint/schematics",
- "version": "19.4.0",
+ "version": "19.5.0",
"description": "Angular Schematics for angular-eslint",
"license": "MIT",
"main": "dist/index.js",
@@ -41,12 +41,12 @@
"@angular-eslint/eslint-plugin": "workspace:*",
"@angular-eslint/eslint-plugin-template": "workspace:*",
"ignore": "7.0.4",
- "semver": "7.7.1",
+ "semver": "7.7.2",
"strip-json-comments": "3.1.1"
},
"devDependencies": {
- "@typescript-eslint/utils": "8.32.0",
- "eslint": "9.26.0"
+ "@typescript-eslint/utils": "8.32.1",
+ "eslint": "9.27.0"
},
"gitHead": "e2006e5e9c99e5a943d1a999e0efa5247d29ec24"
}
diff --git a/packages/schematics/src/ng-add/index.ts b/packages/schematics/src/ng-add/index.ts
index 648c4e549..142701c7d 100644
--- a/packages/schematics/src/ng-add/index.ts
+++ b/packages/schematics/src/ng-add/index.ts
@@ -1,6 +1,7 @@
import type { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
import { chain, schematic } from '@angular-devkit/schematics';
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
+import type { Schema } from './schema';
import {
createRootESLintConfig,
createStringifiedRootESLintConfig,
@@ -21,6 +22,7 @@ const packageJSON = require('../../package.json');
function addAngularESLintPackages(
json: Record,
useFlatConfig: boolean,
+ options: Schema,
) {
return (host: Tree, context: SchematicContext) => {
if (!host.exists('package.json')) {
@@ -62,13 +64,21 @@ function addAngularESLintPackages(
json.devDependencies = sortObjectByKeys(json.devDependencies);
host.overwrite('package.json', JSON.stringify(json, null, 2));
- context.addTask(new NodePackageInstallTask());
+ if (!options.skipInstall) {
+ context.addTask(new NodePackageInstallTask({ allowScripts: false }));
- context.logger.info(`
+ context.logger.info(`
All angular-eslint dependencies have been successfully installed π
Please see https://github.com/angular-eslint/angular-eslint for how to add ESLint configuration to your project.
`);
+ } else {
+ context.logger.info(`
+All angular-eslint dependencies have been successfully added. Run your package manager install command to complete setup.
+
+Please see https://github.com/angular-eslint/angular-eslint for how to add ESLint configuration to your project.
+`);
+ }
return host;
};
@@ -212,7 +222,12 @@ Please see https://github.com/angular-eslint/angular-eslint for more information
};
}
-export default function (): Rule {
+/**
+ * Entry point for the ng-add schematic.
+ *
+ * @param options Configuration options passed to the schematic.
+ */
+export default function (options: Schema): Rule {
return (host: Tree, context: SchematicContext) => {
const workspacePackageJSON = (host.read('package.json') as Buffer).toString(
'utf-8',
@@ -221,7 +236,7 @@ export default function (): Rule {
const useFlatConfig = shouldUseFlatConfig(host, json);
return chain([
- addAngularESLintPackages(json, useFlatConfig),
+ addAngularESLintPackages(json, useFlatConfig, options),
applyESLintConfigIfSingleProjectWithNoExistingTSLint(useFlatConfig),
])(host, context);
};
diff --git a/packages/schematics/src/ng-add/schema.json b/packages/schematics/src/ng-add/schema.json
index bed495d4e..eb603ca20 100644
--- a/packages/schematics/src/ng-add/schema.json
+++ b/packages/schematics/src/ng-add/schema.json
@@ -3,6 +3,13 @@
"$id": "add-angular-eslint",
"title": "Add angular-eslint to an existing workspace",
"type": "object",
- "properties": {},
+ "properties": {
+ "skipInstall": {
+ "type": "boolean",
+ "description": "Skip package installation after adding dependencies",
+ "default": false,
+ "alias": "skip-install"
+ }
+ },
"required": []
}
diff --git a/packages/schematics/src/ng-add/schema.ts b/packages/schematics/src/ng-add/schema.ts
new file mode 100644
index 000000000..fa0abb11e
--- /dev/null
+++ b/packages/schematics/src/ng-add/schema.ts
@@ -0,0 +1,9 @@
+/**
+ * Options available to the ng-add schematic.
+ */
+export interface Schema {
+ /**
+ * Skip installing dependencies after modifying package.json.
+ */
+ skipInstall?: boolean;
+}
diff --git a/packages/template-parser/CHANGELOG.md b/packages/template-parser/CHANGELOG.md
index 81bfd014f..bbad5c345 100644
--- a/packages/template-parser/CHANGELOG.md
+++ b/packages/template-parser/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 19.5.0 (2025-05-25)
+
+This was a version bump only for template-parser to align it with other projects, there were no code changes.
+
## 19.4.0 (2025-05-08)
This was a version bump only for template-parser to align it with other projects, there were no code changes.
diff --git a/packages/template-parser/package.json b/packages/template-parser/package.json
index bba9a77b1..933048cdb 100644
--- a/packages/template-parser/package.json
+++ b/packages/template-parser/package.json
@@ -1,6 +1,6 @@
{
"name": "@angular-eslint/template-parser",
- "version": "19.4.0",
+ "version": "19.5.0",
"description": "Angular Template parser for ESLint",
"license": "MIT",
"main": "dist/index.js",
diff --git a/packages/template-parser/src/index.ts b/packages/template-parser/src/index.ts
index 615bc53c7..fa38d423f 100644
--- a/packages/template-parser/src/index.ts
+++ b/packages/template-parser/src/index.ts
@@ -250,7 +250,7 @@ function parseForESLint(
options: ParserOptions,
): {
ast: AST;
- scopeManager: ScopeManager;
+ scopeManager: InstanceType;
visitorKeys: VisitorKeys;
services: {
convertElementSourceSpanToLoc: typeof convertElementSourceSpanToLoc;
@@ -281,10 +281,7 @@ function parseForESLint(
value: code,
};
- // @ts-expect-error The types for ScopeManager seem to be wrong, it requires a configuration object or it will throw at runtime
const scopeManager = new ScopeManager({});
-
- // @ts-expect-error Create a global scope for the ScopeManager, the types for Scope also seem to be wrong
new Scope(scopeManager, 'module', null, ast, false);
preprocessNode(ast);
diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md
index 8cc5df289..7f0665eb6 100644
--- a/packages/test-utils/CHANGELOG.md
+++ b/packages/test-utils/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 19.5.0 (2025-05-25)
+
+This was a version bump only for @angular-eslint/test-utils to align it with other projects, there were no code changes.
+
## 19.4.0 (2025-05-08)
This was a version bump only for @angular-eslint/test-utils to align it with other projects, there were no code changes.
diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json
index 0bad5023b..f88b9518b 100644
--- a/packages/test-utils/package.json
+++ b/packages/test-utils/package.json
@@ -1,6 +1,6 @@
{
"name": "@angular-eslint/test-utils",
- "version": "19.4.0",
+ "version": "19.5.0",
"license": "MIT",
"main": "dist/index.js",
"types": "dist/index.d.ts",
diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md
index 89660e978..80dc755a2 100644
--- a/packages/utils/CHANGELOG.md
+++ b/packages/utils/CHANGELOG.md
@@ -1,3 +1,13 @@
+## 19.5.0 (2025-05-25)
+
+### π Features
+
+- **eslint-plugin:** introduce sort keys in type-decorator rule ([#2187](https://github.com/angular-eslint/angular-eslint/pull/2187))
+
+### β€οΈ Thank You
+
+- Benjamin SchΓ€ublin
+
## 19.4.0 (2025-05-08)
This was a version bump only for @angular-eslint/utils to align it with other projects, there were no code changes.
diff --git a/packages/utils/package.json b/packages/utils/package.json
index 200f725a1..a90c8e969 100644
--- a/packages/utils/package.json
+++ b/packages/utils/package.json
@@ -1,6 +1,6 @@
{
"name": "@angular-eslint/utils",
- "version": "19.4.0",
+ "version": "19.5.0",
"license": "MIT",
"main": "dist/index.js",
"types": "dist/index.d.ts",
diff --git a/packages/utils/src/eslint-plugin/ast-utils.ts b/packages/utils/src/eslint-plugin/ast-utils.ts
index 24af11c0b..e5f375b96 100644
--- a/packages/utils/src/eslint-plugin/ast-utils.ts
+++ b/packages/utils/src/eslint-plugin/ast-utils.ts
@@ -442,13 +442,19 @@ export function getPropertyDefinitionName({
);
}
+export const getDecoratorProperties = (
+ decorator: TSESTree.Decorator,
+): TSESTree.Property[] => {
+ return getDecoratorArgument(decorator)?.properties.filter(isProperty) ?? [];
+};
+
export const getDecoratorProperty = (
decorator: TSESTree.Decorator,
name: string,
): TSESTree.Property | undefined => {
- return getDecoratorArgument(decorator)
- ?.properties.filter(isProperty)
- .find(({ key }) => ASTUtils.isIdentifier(key) && key.name === name);
+ return getDecoratorProperties(decorator).find(
+ ({ key }) => ASTUtils.isIdentifier(key) && key.name === name,
+ );
};
export const getDecoratorPropertyValue = (
diff --git a/packages/utils/src/eslint-plugin/comment-utils.ts b/packages/utils/src/eslint-plugin/comment-utils.ts
new file mode 100644
index 000000000..e303fda31
--- /dev/null
+++ b/packages/utils/src/eslint-plugin/comment-utils.ts
@@ -0,0 +1,128 @@
+import type { TSESLint, TSESTree } from '@typescript-eslint/utils';
+
+export interface PropInfo {
+ name: string;
+ leadingComments: string[];
+ value: string;
+ trailingComments: string[];
+}
+
+export function extractPropertyComments(
+ sourceCode: Readonly,
+ properties: TSESTree.Property[],
+ objectExpression: TSESTree.Expression,
+ indentation: string,
+): Map {
+ const allComments = sourceCode.getAllComments();
+ const processedCommentRanges = new Set();
+ const propInfoMap = new Map();
+ const commentLineMap = new Map();
+
+ for (const comment of allComments) {
+ const line = sourceCode.getLocFromIndex(comment.range[0]).line;
+ if (!commentLineMap.has(line)) {
+ commentLineMap.set(line, []);
+ }
+ commentLineMap.get(line)?.push(comment);
+ }
+
+ const makeRangeKey = (start: number, end: number) => `${start}-${end}`;
+
+ for (let i = 0; i < properties.length; i++) {
+ const prop = properties[i];
+ const name = (prop.key as TSESTree.Identifier).name;
+ const propRange = prop.range;
+ const leadingComments: string[] = [];
+ const prevPropEnd =
+ i > 0 ? properties[i - 1].range[1] : objectExpression.range[0] + 1;
+
+ for (const comment of allComments) {
+ const rangeKey = makeRangeKey(comment.range[0], comment.range[1]);
+ if (
+ comment.range[0] > prevPropEnd &&
+ comment.range[0] < propRange[0] &&
+ !processedCommentRanges.has(rangeKey)
+ ) {
+ leadingComments.push(indentation + sourceCode.getText(comment));
+ processedCommentRanges.add(rangeKey);
+ }
+ }
+
+ const propText = sourceCode.getText(prop).replace(/,\s*$/, '');
+ const trailingComments: string[] = [];
+ const propEndLine = sourceCode.getLocFromIndex(propRange[1]).line;
+
+ if (commentLineMap.has(propEndLine)) {
+ const commentsOnLine = commentLineMap.get(propEndLine) || [];
+ for (const comment of commentsOnLine) {
+ const rangeKey = makeRangeKey(comment.range[0], comment.range[1]);
+ if (
+ comment.range[0] > propRange[1] &&
+ !processedCommentRanges.has(rangeKey)
+ ) {
+ const spaceBefore = sourceCode
+ .getText()
+ .substring(propRange[1], comment.range[0])
+ .replace(/,/g, '');
+
+ trailingComments.push(spaceBefore + sourceCode.getText(comment));
+ processedCommentRanges.add(rangeKey);
+ }
+ }
+ }
+
+ propInfoMap.set(name, {
+ name,
+ leadingComments,
+ value: propText,
+ trailingComments,
+ });
+ }
+
+ return propInfoMap;
+}
+
+export function buildSortedPropertiesWithComments(
+ filteredOrder: string[],
+ propInfoMap: Map,
+ indentation: string,
+): string {
+ const sortedParts: string[] = [];
+
+ for (let i = 0; i < filteredOrder.length; i++) {
+ const propName = filteredOrder[i];
+ const info = propInfoMap.get(propName);
+
+ if (info) {
+ if (info.leadingComments.length > 0) {
+ sortedParts.push(...info.leadingComments);
+ }
+
+ const isLast = i === filteredOrder.length - 1;
+ let finalPropText = indentation + info.value;
+
+ if (!isLast) {
+ finalPropText += ',';
+ }
+
+ if (info.trailingComments.length > 0) {
+ info.trailingComments.forEach((comment) => {
+ finalPropText += comment;
+ });
+ }
+
+ sortedParts.push(finalPropText);
+ }
+ }
+
+ return sortedParts.join('\n');
+}
+
+export function getObjectIndentation(
+ sourceCode: Readonly,
+ objectExpression: TSESTree.Expression,
+): string {
+ const objectExpressionText = sourceCode.getText(objectExpression);
+ const lines = objectExpressionText.split('\n');
+ return lines[1] ? lines[1].match(/^\s*/)?.[0] || '' : '';
+}
diff --git a/packages/utils/src/eslint-plugin/get-native-event-names.ts b/packages/utils/src/eslint-plugin/get-native-event-names.ts
index 3642c4ae5..01d6acb5f 100644
--- a/packages/utils/src/eslint-plugin/get-native-event-names.ts
+++ b/packages/utils/src/eslint-plugin/get-native-event-names.ts
@@ -9,7 +9,7 @@ let nativeEventNames: ReadonlySet | null = null;
/**
* Check MDN events page for details https://developer.mozilla.org/en-US/docs/Web/Events
*
- * Event names sourced from @mdn/browser-compat-data@6.0.12
+ * Event names sourced from @mdn/browser-compat-data@6.0.17
*/
export function getNativeEventNames(): ReadonlySet {
return (
diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts
index 5b494d11c..34060cea3 100644
--- a/packages/utils/src/index.ts
+++ b/packages/utils/src/index.ts
@@ -12,6 +12,7 @@ export { getAriaAttributeKeys } from './eslint-plugin/get-aria-attribute-keys';
export { getNativeEventNames } from './eslint-plugin/get-native-event-names';
export * as ASTUtils from './eslint-plugin/ast-utils';
+export * as CommentUtils from './eslint-plugin/comment-utils';
export * as RuleFixes from './eslint-plugin/rule-fixes';
export * as Selectors from './eslint-plugin/selectors';
export * as SelectorUtils from './eslint-plugin/selector-utils';
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index c7adcfa9a..c9eb169c3 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -5,9 +5,9 @@ settings:
excludeLinksFromLockfile: false
overrides:
- '@typescript-eslint/parser': 8.32.0
- '@typescript-eslint/rule-tester': 8.32.0
- '@typescript-eslint/utils': 8.32.0
+ '@typescript-eslint/parser': 8.32.1
+ '@typescript-eslint/rule-tester': 8.32.1
+ '@typescript-eslint/utils': 8.32.1
patchedDependencies:
'@typescript-eslint/rule-tester':
@@ -19,56 +19,56 @@ importers:
.:
devDependencies:
'@angular/cli':
- specifier: 19.2.11
- version: 19.2.11(@types/node@20.17.45)
+ specifier: 19.2.13
+ version: 19.2.13(@types/node@20.17.50)
'@angular/compiler':
- specifier: 19.2.10
- version: 19.2.10
+ specifier: 19.2.13
+ version: 19.2.13
'@commitlint/cli':
specifier: 19.8.1
- version: 19.8.1(@types/node@20.17.45)(typescript@5.8.3)
+ version: 19.8.1(@types/node@20.17.50)(typescript@5.8.3)
'@commitlint/config-conventional':
specifier: 19.8.1
version: 19.8.1
'@mdn/browser-compat-data':
- specifier: 6.0.12
- version: 6.0.12
+ specifier: 6.0.17
+ version: 6.0.17
'@nx/devkit':
- specifier: 21.0.2
- version: 21.0.2(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))
+ specifier: 21.1.2
+ version: 21.1.2(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
'@nx/esbuild':
- specifier: 21.0.2
- version: 21.0.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))(esbuild@0.25.4)(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
+ specifier: 21.1.2
+ version: 21.1.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(esbuild@0.25.4)(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
'@nx/eslint':
- specifier: 21.0.2
- version: 21.0.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.26.0(jiti@2.4.2))(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
+ specifier: 21.1.2
+ version: 21.1.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.27.0(jiti@2.4.2))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
'@nx/eslint-plugin':
- specifier: 21.0.2
- version: 21.0.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))(@typescript-eslint/parser@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3))(eslint-config-prettier@10.1.3(eslint@9.26.0(jiti@2.4.2)))(eslint@9.26.0(jiti@2.4.2))(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))(typescript@5.8.3)(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
+ specifier: 21.1.2
+ version: 21.1.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@typescript-eslint/parser@8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3))(eslint-config-prettier@10.1.5(eslint@9.27.0(jiti@2.4.2)))(eslint@9.27.0(jiti@2.4.2))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(typescript@5.8.3)(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
'@nx/jest':
- specifier: 21.0.2
- version: 21.0.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(babel-plugin-macros@3.1.0)(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))(ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
+ specifier: 21.1.2
+ version: 21.1.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(babel-plugin-macros@3.1.0)(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
'@nx/js':
- specifier: 21.0.2
- version: 21.0.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
+ specifier: 21.1.2
+ version: 21.1.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
'@nx/plugin':
- specifier: 21.0.2
- version: 21.0.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.26.0(jiti@2.4.2))(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))(ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
+ specifier: 21.1.2
+ version: 21.1.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.27.0(jiti@2.4.2))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
'@nx/workspace':
- specifier: 21.0.2
- version: 21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))
+ specifier: 21.1.2
+ version: 21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))
'@schematics/angular':
- specifier: 19.2.11
- version: 19.2.11
+ specifier: 19.2.13
+ version: 19.2.13
'@swc-node/register':
specifier: 1.10.10
- version: 1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3)
+ version: 1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3)
'@swc/cli':
- specifier: 0.7.5
- version: 0.7.5(@swc/core@1.11.24(@swc/helpers@0.5.17))
+ specifier: 0.7.7
+ version: 0.7.7(@swc/core@1.11.29(@swc/helpers@0.5.17))
'@swc/core':
- specifier: 1.11.24
- version: 1.11.24(@swc/helpers@0.5.17)
+ specifier: 1.11.29
+ version: 1.11.29(@swc/helpers@0.5.17)
'@swc/helpers':
specifier: 0.5.17
version: 0.5.17
@@ -76,14 +76,14 @@ importers:
specifier: 9.6.1
version: 9.6.1
'@types/eslint-scope':
- specifier: 3.7.7
- version: 3.7.7
+ specifier: 8.3.0
+ version: 8.3.0
'@types/jest':
specifier: 29.5.14
version: 29.5.14
'@types/node':
- specifier: 20.17.45
- version: 20.17.45
+ specifier: 20.17.50
+ version: 20.17.50
'@types/semver':
specifier: ^7.5.8
version: 7.7.0
@@ -91,26 +91,26 @@ importers:
specifier: ^17.0.33
version: 17.0.33
'@typescript-eslint/rule-tester':
- specifier: 8.32.0
- version: 8.32.0(patch_hash=0395d56159bca55b94596b2ce1a79005dd964f4b648c29e0c04c6dfcb85e13cf)(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
+ specifier: 8.32.1
+ version: 8.32.1(patch_hash=0395d56159bca55b94596b2ce1a79005dd964f4b648c29e0c04c6dfcb85e13cf)(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
'@typescript-eslint/types':
- specifier: 8.32.0
- version: 8.32.0
+ specifier: 8.32.1
+ version: 8.32.1
'@typescript-eslint/utils':
- specifier: 8.32.0
- version: 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
+ specifier: 8.32.1
+ version: 8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
cz-conventional-changelog:
specifier: 3.3.0
- version: 3.3.0(@types/node@20.17.45)(typescript@5.8.3)
+ version: 3.3.0(@types/node@20.17.50)(typescript@5.8.3)
esbuild:
specifier: ^0.25.0
version: 0.25.4
eslint:
- specifier: 9.26.0
- version: 9.26.0(jiti@2.4.2)
+ specifier: 9.27.0
+ version: 9.27.0(jiti@2.4.2)
eslint-config-prettier:
- specifier: 10.1.3
- version: 10.1.3(eslint@9.26.0(jiti@2.4.2))
+ specifier: 10.1.5
+ version: 10.1.5(eslint@9.27.0(jiti@2.4.2))
execa:
specifier: 5.1.1
version: 5.1.1
@@ -119,7 +119,7 @@ importers:
version: 9.1.7
jest:
specifier: 29.7.0
- version: 29.7.0(@types/node@20.17.45)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3))
+ version: 29.7.0(@types/node@20.17.50)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3))
json-schema-to-typescript:
specifier: 15.0.4
version: 15.0.4
@@ -130,14 +130,14 @@ importers:
specifier: ^2.1.0
version: 2.4.0
lint-staged:
- specifier: 15.5.2
- version: 15.5.2
+ specifier: 16.0.0
+ version: 16.0.0
ncp:
specifier: 2.0.0
version: 2.0.0
nx:
- specifier: 21.0.2
- version: 21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))
+ specifier: 21.1.2
+ version: 21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))
picocolors:
specifier: 1.1.1
version: 1.1.1
@@ -152,13 +152,13 @@ importers:
version: 5.0.10
semver:
specifier: ^7.6.2
- version: 7.7.1
+ version: 7.7.2
tree-kill:
specifier: 1.2.2
version: 1.2.2
ts-jest:
specifier: 29.2.4
- version: 29.2.4(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(esbuild@0.25.4)(jest@29.7.0(@types/node@20.17.45)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3)))(typescript@5.8.3)
+ version: 29.2.4(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(esbuild@0.25.4)(jest@29.7.0(@types/node@20.17.50)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3)))(typescript@5.8.3)
tslib:
specifier: ^2.4.1
version: 2.8.1
@@ -169,8 +169,8 @@ importers:
specifier: 5.8.3
version: 5.8.3
typescript-eslint:
- specifier: 8.32.0
- version: 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
+ specifier: 8.32.1
+ version: 8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
verdaccio:
specifier: 6.1.2
version: 6.1.2(encoding@0.1.13)(typanion@3.14.0)
@@ -182,10 +182,10 @@ importers:
dependencies:
'@angular-devkit/core':
specifier: '>= 19.0.0 < 20.0.0'
- version: 19.2.11
+ version: 19.2.13
'@angular-devkit/schematics':
specifier: '>= 19.0.0 < 20.0.0'
- version: 19.2.11
+ version: 19.2.13
'@angular-eslint/builder':
specifier: workspace:*
version: link:../builder
@@ -203,31 +203,31 @@ importers:
version: link:../template-parser
'@typescript-eslint/types':
specifier: ^8.0.0
- version: 8.32.0
+ version: 8.32.1
'@typescript-eslint/utils':
- specifier: 8.32.0
- version: 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
+ specifier: 8.32.1
+ version: 8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
eslint:
specifier: ^8.57.0 || ^9.0.0
- version: 9.26.0(jiti@2.4.2)
+ version: 9.27.0(jiti@2.4.2)
typescript:
specifier: '*'
version: 5.8.3
typescript-eslint:
specifier: ^8.0.0
- version: 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
+ version: 8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
packages/builder:
dependencies:
'@angular-devkit/architect':
specifier: '>= 0.1900.0 < 0.2000.0'
- version: 0.1902.11
+ version: 0.1902.13
'@angular-devkit/core':
specifier: '>= 19.0.0 < 20.0.0'
- version: 19.2.11
+ version: 19.2.13
eslint:
specifier: ^8.57.0 || ^9.0.0
- version: 9.26.0(jiti@2.4.2)
+ version: 9.27.0(jiti@2.4.2)
typescript:
specifier: '*'
version: 5.8.3
@@ -243,11 +243,11 @@ importers:
specifier: workspace:*
version: link:../utils
'@typescript-eslint/utils':
- specifier: 8.32.0
- version: 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
+ specifier: 8.32.1
+ version: 8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
eslint:
specifier: ^8.57.0 || ^9.0.0
- version: 9.26.0(jiti@2.4.2)
+ version: 9.27.0(jiti@2.4.2)
typescript:
specifier: '*'
version: 5.8.3
@@ -266,10 +266,10 @@ importers:
version: link:../utils
'@typescript-eslint/types':
specifier: ^7.11.0 || ^8.0.0
- version: 8.32.0
+ version: 8.32.1
'@typescript-eslint/utils':
- specifier: 8.32.0
- version: 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
+ specifier: 8.32.1
+ version: 8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
aria-query:
specifier: 5.3.2
version: 5.3.2
@@ -278,7 +278,7 @@ importers:
version: 4.1.0
eslint:
specifier: ^8.57.0 || ^9.0.0
- version: 9.26.0(jiti@2.4.2)
+ version: 9.27.0(jiti@2.4.2)
typescript:
specifier: '*'
version: 5.8.3
@@ -299,10 +299,10 @@ importers:
dependencies:
'@angular-devkit/core':
specifier: '>= 19.0.0 < 20.0.0'
- version: 19.2.11
+ version: 19.2.13
'@angular-devkit/schematics':
specifier: '>= 19.0.0 < 20.0.0'
- version: 19.2.11
+ version: 19.2.13
'@angular-eslint/eslint-plugin':
specifier: workspace:*
version: link:../eslint-plugin
@@ -313,18 +313,18 @@ importers:
specifier: 7.0.4
version: 7.0.4
semver:
- specifier: 7.7.1
- version: 7.7.1
+ specifier: 7.7.2
+ version: 7.7.2
strip-json-comments:
specifier: 3.1.1
version: 3.1.1
devDependencies:
'@typescript-eslint/utils':
- specifier: 8.32.0
- version: 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
+ specifier: 8.32.1
+ version: 8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
eslint:
- specifier: 9.26.0
- version: 9.26.0(jiti@2.4.2)
+ specifier: 9.27.0
+ version: 9.27.0(jiti@2.4.2)
packages/template-parser:
dependencies:
@@ -333,7 +333,7 @@ importers:
version: link:../bundled-angular-compiler
eslint:
specifier: ^8.57.0 || ^9.0.0
- version: 9.26.0(jiti@2.4.2)
+ version: 9.27.0(jiti@2.4.2)
eslint-scope:
specifier: ^8.0.2
version: 8.3.0
@@ -347,17 +347,17 @@ importers:
specifier: workspace:*
version: link:../template-parser
'@typescript-eslint/parser':
- specifier: 8.32.0
- version: 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
+ specifier: 8.32.1
+ version: 8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
'@typescript-eslint/rule-tester':
- specifier: 8.32.0
- version: 8.32.0(patch_hash=0395d56159bca55b94596b2ce1a79005dd964f4b648c29e0c04c6dfcb85e13cf)(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
+ specifier: 8.32.1
+ version: 8.32.1(patch_hash=0395d56159bca55b94596b2ce1a79005dd964f4b648c29e0c04c6dfcb85e13cf)(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
'@typescript-eslint/utils':
- specifier: 8.32.0
- version: 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
+ specifier: 8.32.1
+ version: 8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
eslint:
specifier: ^8.57.0 || ^9.0.0
- version: 9.26.0(jiti@2.4.2)
+ version: 9.27.0(jiti@2.4.2)
typescript:
specifier: '*'
version: 5.8.3
@@ -368,11 +368,11 @@ importers:
specifier: workspace:*
version: link:../bundled-angular-compiler
'@typescript-eslint/utils':
- specifier: 8.32.0
- version: 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
+ specifier: 8.32.1
+ version: 8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
eslint:
specifier: ^8.57.0 || ^9.0.0
- version: 9.26.0(jiti@2.4.2)
+ version: 9.27.0(jiti@2.4.2)
typescript:
specifier: '*'
version: 5.8.3
@@ -383,12 +383,12 @@ packages:
resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
engines: {node: '>=6.0.0'}
- '@angular-devkit/architect@0.1902.11':
- resolution: {integrity: sha512-Zz/4ySZ4i8WXU4U4WwUGQm8wjwAyrMo5kjFt7O2SGmHQx7L/hChvcMLCGVkpHr27Xdsmrl//OXfbjkPgb6DFBg==}
+ '@angular-devkit/architect@0.1902.13':
+ resolution: {integrity: sha512-ZMj+PjK22Ph2U8usG6L7LqEfvWlbaOvmiWXSrEt9YiC9QJt6rsumCkOgUIsmHQtucm/lK+9CMtyYdwH2fYycjg==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
- '@angular-devkit/core@19.2.11':
- resolution: {integrity: sha512-hXacCEbLbVo/PYPHBhaU2LThFm0Q1tIGTsWSkQjtsQpW8e4xqgSnFIWaHdsPiiGryxtdtvNE2cr9qa0ddAJOnA==}
+ '@angular-devkit/core@19.2.13':
+ resolution: {integrity: sha512-iq73hE5Uvms1w3uMUSk4i4NDXDMQ863VAifX8LOTadhG6U0xISjNJ11763egVCxQmaKmg7zbG4rda88wHJATzA==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
peerDependencies:
chokidar: ^4.0.0
@@ -396,17 +396,17 @@ packages:
chokidar:
optional: true
- '@angular-devkit/schematics@19.2.11':
- resolution: {integrity: sha512-R5g18xBhMHRtti5kDd2tlEMMxfRi8gQZ6LoT5xbox3w2kGSt7NtkSa3SUoF7Ns7JfPLrKsTQbVLFd5AggBLbHQ==}
+ '@angular-devkit/schematics@19.2.13':
+ resolution: {integrity: sha512-NhSPz3lI9njEo8eMUlZVGtlXl12UcNZv5lWTBZY/FGWUu6P5ciD/9iJINbc1jiaDH5E/DLEicUNuai0Q91X4Nw==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
- '@angular/cli@19.2.11':
- resolution: {integrity: sha512-U+Sapv4S1v+LEywyCImhQf12c6vmhuJhBS58nBxWDUVn1kmYzdUCAKNDDgMQqWQmg/Dek1YI88XYDToUvEdD1g==}
+ '@angular/cli@19.2.13':
+ resolution: {integrity: sha512-dDRCS73/lrItWx9j4SmwHR56GiZsW8ObNi2q9l/1ny813CG9K43STYFG/wJvGS7ZF3y5hvjIiJOwBx2YIouOIw==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
hasBin: true
- '@angular/compiler@19.2.10':
- resolution: {integrity: sha512-XI4VVaTHIsvDu25b/hOqFBIub4RoEVqVrBYo1rKRF9NI+mxg2Wy30qyJ7rYGbF7qUPomC54pen0qQgw359YhMA==}
+ '@angular/compiler@19.2.13':
+ resolution: {integrity: sha512-xAj1peVrQtb65NsULmz8ocH4QZ4ESG5YiiVzJ0tLz8t280xY+QhJiM6C0+jaCVHLXvZp0c7GEzsYjL6x1HmabQ==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0}
'@apidevtools/json-schema-ref-parser@11.7.2':
@@ -1304,24 +1304,24 @@ packages:
resolution: {integrity: sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@eslint/core@0.13.0':
- resolution: {integrity: sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==}
+ '@eslint/core@0.14.0':
+ resolution: {integrity: sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/eslintrc@3.3.1':
resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@eslint/js@9.26.0':
- resolution: {integrity: sha512-I9XlJawFdSMvWjDt6wksMCrgns5ggLNfFwFvnShsleWruvXM514Qxk8V246efTw+eo9JABvVz+u3q2RiAowKxQ==}
+ '@eslint/js@9.27.0':
+ resolution: {integrity: sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/object-schema@2.1.6':
resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@eslint/plugin-kit@0.2.8':
- resolution: {integrity: sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==}
+ '@eslint/plugin-kit@0.3.1':
+ resolution: {integrity: sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@humanfs/core@0.19.1':
@@ -1581,12 +1581,8 @@ packages:
peerDependencies:
'@inquirer/prompts': '>= 3 < 8'
- '@mdn/browser-compat-data@6.0.12':
- resolution: {integrity: sha512-lQ6p212jKeJBG+L7UYRKchTCcnQbp6yOj5swKxGLjvuW4SmbgWgd/WyA1Dxq1GGT86C7jVTEaKry36LmsBp8SQ==}
-
- '@modelcontextprotocol/sdk@1.11.0':
- resolution: {integrity: sha512-k/1pb70eD638anoi0e8wUGAlbMJXyvdV4p62Ko+EZ7eBe1xMx8Uhak1R5DgfoofsK5IBBnRwsYGTaLZl+6/+RQ==}
- engines: {node: '>=18'}
+ '@mdn/browser-compat-data@6.0.17':
+ resolution: {integrity: sha512-yBMooSEtOoVz6vUP5OeGUnq4JBVMyE4vWsGalbrOLoGaXXNwA3YAE2mkgT4YPcOhGuPosSIk901PQI9pSMzgVg==}
'@napi-rs/nice-android-arm-eabi@1.0.1':
resolution: {integrity: sha512-5qpvOu5IGwDo7MEKVqqyAxF90I6aLj4n07OzpARdgDRfz8UbBztTByBp0RC59r3J1Ij8uzYi6jI7r5Lws7nn6w==}
@@ -1751,30 +1747,30 @@ packages:
resolution: {integrity: sha512-q9C0uHrb6B6cm3qXVM32UmpqTKuFGbtP23O2K5sLvPMz2hilKd0ptqGXSpuunOuOmPQb/aT5F/kCXFc1P2gO/A==}
engines: {node: ^18.17.0 || >=20.5.0}
- '@nx/devkit@21.0.2':
- resolution: {integrity: sha512-FF1+CYkqRmNUznAj9kWiRHZT91KrpZkLYmAoP5RlaXwSxgiiBTXL3FOIp0/LcHUlOUHur3079beBwreApfbvBA==}
+ '@nx/devkit@21.1.2':
+ resolution: {integrity: sha512-1dgjwSsNDdp/VXydZnSfzfVwySEB3C9yjzeIw6+3+nRvZfH16a7ggZE7MF5sJTq4d+01hAgIDz3KyvGa6Jf73g==}
peerDependencies:
- nx: 21.0.2
+ nx: 21.1.2
- '@nx/esbuild@21.0.2':
- resolution: {integrity: sha512-muxyNOW253izBdXSU6LYfrMTBJi5lZpX6SS+ghBWvvZhgw+kcRwGdNwSCrPLuILTTXRMYUoAJcAXXp0UFz8orQ==}
+ '@nx/esbuild@21.1.2':
+ resolution: {integrity: sha512-6h3f8mC/5e2JxFAJaE4kLALkaoAs0nVB3aFBV+nd3+0mwywbcnMQ+dibvGCrBz2EPYlWczo43upAFEvvqpdUag==}
peerDependencies:
- esbuild: ^0.19.2
+ esbuild: '>=0.19.2 <1.0.0'
peerDependenciesMeta:
esbuild:
optional: true
- '@nx/eslint-plugin@21.0.2':
- resolution: {integrity: sha512-LbLq4WewxZ7nqw6rgg+ik0CXHCS+dkUN7Mew5z058IzBoB9XytkWdpv0I9r1Ry0qE/ZGEtGYfvT6PROUPQL8wA==}
+ '@nx/eslint-plugin@21.1.2':
+ resolution: {integrity: sha512-kwhwe6e8dZ0pf5CYPq4OBck15NEJrfuivCEGRTIDZWu3WDYJIw7OvhfyCdGuoZLeHGoCVRjIU6xV5hOzkD9RSw==}
peerDependencies:
- '@typescript-eslint/parser': 8.32.0
+ '@typescript-eslint/parser': 8.32.1
eslint-config-prettier: ^10.0.0
peerDependenciesMeta:
eslint-config-prettier:
optional: true
- '@nx/eslint@21.0.2':
- resolution: {integrity: sha512-uZwzaqiMWXFaF+A86HK3K4AQIIOuGA3UAgnS6PUk6c7vUuLkJw1FLdFbdCA5LdyHoVu8BHdsinshxbiVl5tn2Q==}
+ '@nx/eslint@21.1.2':
+ resolution: {integrity: sha512-Mp8u0RlkhxYtZ47d2ou6t8XIpRy7N/n23OzikqMro4Wt/DK1irGyShSoNIqdGdwalAE5MG1OFXspttXB+y/wOQ==}
peerDependencies:
'@zkochan/js-yaml': 0.0.7
eslint: ^8.0.0 || ^9.0.0
@@ -1782,72 +1778,72 @@ packages:
'@zkochan/js-yaml':
optional: true
- '@nx/jest@21.0.2':
- resolution: {integrity: sha512-k9jJHHOE7OK9V6NOMc92AOw/Y0a5rpq3bYVs3wkRRo8F/230wQK+ea+ftsJ25rghJoCzqRnGVZe0cZcd4gBNDQ==}
+ '@nx/jest@21.1.2':
+ resolution: {integrity: sha512-y4VZita9LFb6XajulRIwjMcqHU6/f73C4SNSH6IM5BYmkN68ovICmzTGvoaL7wGTaYrA4Moh/WoKwEwQWKxRPQ==}
- '@nx/js@21.0.2':
- resolution: {integrity: sha512-AhqAUkqu2YDbMXqr0g/5Qhlm/ERV1FockmpK6ltYHRDaQu/yW/VKIPQtj0ndrSAKfZ74pjt8koyhFdGZjt9cMg==}
+ '@nx/js@21.1.2':
+ resolution: {integrity: sha512-ZF6Zf4Ys+RBvH0GoQHio94C/0N07Px/trAvseMuQ8PKc0tSkXycu/EBc1uAZQvgJThR5o3diAKtIQug77pPYMQ==}
peerDependencies:
verdaccio: ^6.0.5
peerDependenciesMeta:
verdaccio:
optional: true
- '@nx/nx-darwin-arm64@21.0.2':
- resolution: {integrity: sha512-C2A94y4TJpAsxbyAZufCzcWNDFKvHNcGCxSwdMxyaDBHXOxDasSYH6KsUTj95sZtjMiHvMn9J4xforTwF/tE7w==}
+ '@nx/nx-darwin-arm64@21.1.2':
+ resolution: {integrity: sha512-9dO32jd+h7SrvQafJph6b7Bsmp2IotTE0w7dAGb4MGBQni3JWCXaxlMMpWUZXWW1pM5uIkFJO5AASW4UOI7w2w==}
cpu: [arm64]
os: [darwin]
- '@nx/nx-darwin-x64@21.0.2':
- resolution: {integrity: sha512-eWHM0gmOZBuqFw0QrO6h/ku0+LxbjmTYaWFJerPjqfAyOHKI9CEY/nPWHuJRkq7algUQdlgX5Utf+oQ+6aJlTQ==}
+ '@nx/nx-darwin-x64@21.1.2':
+ resolution: {integrity: sha512-5sf+4PRVg9pDVgD53NE1hoPz4lC8Ni34UovQsOrZgDvwU5mqPbIhTzVYRDH86i/086AcCvjT5tEt7rEcuRwlKw==}
cpu: [x64]
os: [darwin]
- '@nx/nx-freebsd-x64@21.0.2':
- resolution: {integrity: sha512-k9bPYiHscJhinxlWC/iZTObpZo6SEBqEaObvgBH4csZpirQ5sQSy/tHB0H1pPKzDwLqkRtUHn3Z6hdWwjF1hdQ==}
+ '@nx/nx-freebsd-x64@21.1.2':
+ resolution: {integrity: sha512-E5HR44fimXlQuAgn/tP9esmvxbzt/92AIl0PBT6L3Juh/xYiXKWhda63H4+UNT8AcLRxVXwfZrGPuGCDs+7y/Q==}
cpu: [x64]
os: [freebsd]
- '@nx/nx-linux-arm-gnueabihf@21.0.2':
- resolution: {integrity: sha512-4u9TIfaeG+H9p8+LWXkBMJzqEVqfae0SMB06r7WB4RDRRe5elkU7sOtJK1LRs2MogBpTC6AErShFHXGEgQhSIQ==}
+ '@nx/nx-linux-arm-gnueabihf@21.1.2':
+ resolution: {integrity: sha512-V4n6DE+r12gwJHFjZs+e2GmWYZdhpgA2DYWbsYWRYb1XQCNUg4vPzt+YFzWZ+K2o91k93EBnlLfrag7CqxUslw==}
cpu: [arm]
os: [linux]
- '@nx/nx-linux-arm64-gnu@21.0.2':
- resolution: {integrity: sha512-415Rj9nXUUyqFB/YwkK1Ag41jgymn0BNAqTZ/9sv1NZR1K/B5hA938Cc8eqFmrk5tFbLzqIwr5EA3QGrGZKN9Q==}
+ '@nx/nx-linux-arm64-gnu@21.1.2':
+ resolution: {integrity: sha512-NFhsp27O+mS3r7PWLmJgyZy42WQ72c2pTQSpYfhaBbZPTI5DqBHdANa0sEPmV+ON24qkl5CZKvsmhzjsNmyW6A==}
cpu: [arm64]
os: [linux]
- '@nx/nx-linux-arm64-musl@21.0.2':
- resolution: {integrity: sha512-gkA/TzOY4/sNHQF0k4EeLR6Pt79c1/PiVOmVN5tdjgljOzTkbrPzeeaBWlS/JH/e005+tkZZmceAZmXYEP9vGw==}
+ '@nx/nx-linux-arm64-musl@21.1.2':
+ resolution: {integrity: sha512-BgS9npARwcnw+hoaRsbas6vdBAJRBAj5qSeL57LO8Dva+e/6PYqoNyVJ0BgJ98xPXDpzM/NnpeRsndQGpLyhDw==}
cpu: [arm64]
os: [linux]
- '@nx/nx-linux-x64-gnu@21.0.2':
- resolution: {integrity: sha512-F7PT9gJCdtUmVXecVOjU6kRbN8vs3FPI4G0Kuuh9n5OQ+y8uqTMIrSD8//yyn0S4tfz4Esd/UjtWB9Inw1WMgQ==}
+ '@nx/nx-linux-x64-gnu@21.1.2':
+ resolution: {integrity: sha512-tjBINbymQgxnIlNK/m6B0P5eiGRSHSYPNkFdh3+sra80AP/ymHGLRxxZy702Ga2xg8RVr9zEvuXYHI+QBa1YmA==}
cpu: [x64]
os: [linux]
- '@nx/nx-linux-x64-musl@21.0.2':
- resolution: {integrity: sha512-a/qEWf7E7xjnh3XonnPKbzBbIhmCset7pJuDAWHyaoMRfjdYI3/uxs8mvRUZAMwThg7KMwmxx5QLAqEcMRgoyw==}
+ '@nx/nx-linux-x64-musl@21.1.2':
+ resolution: {integrity: sha512-+0V0YAOWMh1wvpQZuayQ7y+sj2MhE3l7z0JMD9SX/4xv9zLOWGv+EiUmN/fGoU/mwsSkH2wTCo6G6quKF1E8jQ==}
cpu: [x64]
os: [linux]
- '@nx/nx-win32-arm64-msvc@21.0.2':
- resolution: {integrity: sha512-vZIv4/fS30WZ2yQA8tq2oQeyq3Pq9stx6NA7VW/Vtw2/Uv9QY0kXKysf7/pBY81h3pKNGi8FNaOOAgoT/+dz9w==}
+ '@nx/nx-win32-arm64-msvc@21.1.2':
+ resolution: {integrity: sha512-E+ECMQIMJ6R47BMW5YpDyOhTqczvFaL8k24umRkcvlRh3SraczyxBVPkYHDukDp7tCeIszc5EvdWc83C3W8U4w==}
cpu: [arm64]
os: [win32]
- '@nx/nx-win32-x64-msvc@21.0.2':
- resolution: {integrity: sha512-GJFjODSuNhcEjSm1sBHJ8GZ4quE299nnuWADoZYpXkkAhjCElyZJME/nuOpbh8r2E7cCFRbv04qTbkA/73UcFw==}
+ '@nx/nx-win32-x64-msvc@21.1.2':
+ resolution: {integrity: sha512-J9rNTBOS7Ld6CybU/cou1Fg52AHSYsiwpZISM2RNM0XIoVSDk3Jsvh4OJgS2rvV0Sp/cgDg3ieOMAreekH+TKw==}
cpu: [x64]
os: [win32]
- '@nx/plugin@21.0.2':
- resolution: {integrity: sha512-FPhCGiJnYQdfP1EjP/r6Vx0MyJrBgHp7veCbAIHtvA6cQbRnqvciYE2i1kAvPHZtsjvKN4hvsX5Hd2NWvmoHLg==}
+ '@nx/plugin@21.1.2':
+ resolution: {integrity: sha512-+iiyI5/JiIyWAwdmXe6kkLYH+8tFLlkvzzr5XcWY3pyW3RjW6XuMRa56K1t4IU9DkQt3gEFBiYWV/8NlX929Lw==}
- '@nx/workspace@21.0.2':
- resolution: {integrity: sha512-E1luDXSflU8Ix9z8xTsfCS9LHALCqn8kFkuPACexUPlQRB5P2eF2j+vIUHf7zw3a4xUvgjsik+ed3jfL8Q/GJg==}
+ '@nx/workspace@21.1.2':
+ resolution: {integrity: sha512-I4e/X/GN0Vx3FDZv/7bFYmXfOPmcMI3cDO/rg+TqudsuxVM7tJ7+8jtwdpU4I2IEpI6oU9FZ7Fu9R2uNqL5rrQ==}
'@oxc-resolver/binding-darwin-arm64@5.2.0':
resolution: {integrity: sha512-3v2eS1swAUZ/OPrBpTB5Imn4Xhbz4zKPa/mugnYCAC4pVt/miBQLBNciBRZG8oyHiGmLtjw/qanZC36uB6MITQ==}
@@ -1923,8 +1919,8 @@ packages:
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
- '@schematics/angular@19.2.11':
- resolution: {integrity: sha512-Xkqur8OJrrfR5CeMXj2FqdiqGp//w9cZ7q9RBfRr3lZgW5QUiZw7iJNQHUIDNsCBKK5yFpPIDckpdVx8jLGclg==}
+ '@schematics/angular@19.2.13':
+ resolution: {integrity: sha512-SOpK4AwH0isXo7Y2SkgXLyGLMw4GxWPAun6sCLiprmop4KlqKGGALn4xIW0yjq0s5GS0Vx0FFjz8bBfPkgnawA==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
'@sec-ant/readable-stream@0.4.1':
@@ -1983,8 +1979,8 @@ packages:
'@swc-node/sourcemap-support@0.5.1':
resolution: {integrity: sha512-JxIvIo/Hrpv0JCHSyRpetAdQ6lB27oFYhv0PKCNf1g2gUXOjpeR1exrXccRxLMuAV5WAmGFBwRnNOJqN38+qtg==}
- '@swc/cli@0.7.5':
- resolution: {integrity: sha512-RlUYAxOhsecBB7qFVdDXhXXW3GDVxXpJx90q8Tlj+KuJVUPXViI7tNAvu54u3hbIZAL3LtrQKZHBWF6O5cXxZQ==}
+ '@swc/cli@0.7.7':
+ resolution: {integrity: sha512-j4yYm9bx3pxWofaJKX1BFwj/3ngUDynN4UIQ2Xd2h0h/7Gt7zkReBTpDN7g5S13mgAYxacaTHTOUsz18097E8w==}
engines: {node: '>= 16.14.0'}
hasBin: true
peerDependencies:
@@ -1994,68 +1990,68 @@ packages:
chokidar:
optional: true
- '@swc/core-darwin-arm64@1.11.24':
- resolution: {integrity: sha512-dhtVj0PC1APOF4fl5qT2neGjRLgHAAYfiVP8poJelhzhB/318bO+QCFWAiimcDoyMgpCXOhTp757gnoJJrheWA==}
+ '@swc/core-darwin-arm64@1.11.29':
+ resolution: {integrity: sha512-whsCX7URzbuS5aET58c75Dloby3Gtj/ITk2vc4WW6pSDQKSPDuONsIcZ7B2ng8oz0K6ttbi4p3H/PNPQLJ4maQ==}
engines: {node: '>=10'}
cpu: [arm64]
os: [darwin]
- '@swc/core-darwin-x64@1.11.24':
- resolution: {integrity: sha512-H/3cPs8uxcj2Fe3SoLlofN5JG6Ny5bl8DuZ6Yc2wr7gQFBmyBkbZEz+sPVgsID7IXuz7vTP95kMm1VL74SO5AQ==}
+ '@swc/core-darwin-x64@1.11.29':
+ resolution: {integrity: sha512-S3eTo/KYFk+76cWJRgX30hylN5XkSmjYtCBnM4jPLYn7L6zWYEPajsFLmruQEiTEDUg0gBEWLMNyUeghtswouw==}
engines: {node: '>=10'}
cpu: [x64]
os: [darwin]
- '@swc/core-linux-arm-gnueabihf@1.11.24':
- resolution: {integrity: sha512-PHJgWEpCsLo/NGj+A2lXZ2mgGjsr96ULNW3+T3Bj2KTc8XtMUkE8tmY2Da20ItZOvPNC/69KroU7edyo1Flfbw==}
+ '@swc/core-linux-arm-gnueabihf@1.11.29':
+ resolution: {integrity: sha512-o9gdshbzkUMG6azldHdmKklcfrcMx+a23d/2qHQHPDLUPAN+Trd+sDQUYArK5Fcm7TlpG4sczz95ghN0DMkM7g==}
engines: {node: '>=10'}
cpu: [arm]
os: [linux]
- '@swc/core-linux-arm64-gnu@1.11.24':
- resolution: {integrity: sha512-C2FJb08+n5SD4CYWCTZx1uR88BN41ZieoHvI8A55hfVf2woT8+6ZiBzt74qW2g+ntZ535Jts5VwXAKdu41HpBg==}
+ '@swc/core-linux-arm64-gnu@1.11.29':
+ resolution: {integrity: sha512-sLoaciOgUKQF1KX9T6hPGzvhOQaJn+3DHy4LOHeXhQqvBgr+7QcZ+hl4uixPKTzxk6hy6Hb0QOvQEdBAAR1gXw==}
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
- '@swc/core-linux-arm64-musl@1.11.24':
- resolution: {integrity: sha512-ypXLIdszRo0re7PNNaXN0+2lD454G8l9LPK/rbfRXnhLWDBPURxzKlLlU/YGd2zP98wPcVooMmegRSNOKfvErw==}
+ '@swc/core-linux-arm64-musl@1.11.29':
+ resolution: {integrity: sha512-PwjB10BC0N+Ce7RU/L23eYch6lXFHz7r3NFavIcwDNa/AAqywfxyxh13OeRy+P0cg7NDpWEETWspXeI4Ek8otw==}
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
- '@swc/core-linux-x64-gnu@1.11.24':
- resolution: {integrity: sha512-IM7d+STVZD48zxcgo69L0yYptfhaaE9cMZ+9OoMxirNafhKKXwoZuufol1+alEFKc+Wbwp+aUPe/DeWC/Lh3dg==}
+ '@swc/core-linux-x64-gnu@1.11.29':
+ resolution: {integrity: sha512-i62vBVoPaVe9A3mc6gJG07n0/e7FVeAvdD9uzZTtGLiuIfVfIBta8EMquzvf+POLycSk79Z6lRhGPZPJPYiQaA==}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
- '@swc/core-linux-x64-musl@1.11.24':
- resolution: {integrity: sha512-DZByJaMVzSfjQKKQn3cqSeqwy6lpMaQDQQ4HPlch9FWtDx/dLcpdIhxssqZXcR2rhaQVIaRQsCqwV6orSDGAGw==}
+ '@swc/core-linux-x64-musl@1.11.29':
+ resolution: {integrity: sha512-YER0XU1xqFdK0hKkfSVX1YIyCvMDI7K07GIpefPvcfyNGs38AXKhb2byySDjbVxkdl4dycaxxhRyhQ2gKSlsFQ==}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
- '@swc/core-win32-arm64-msvc@1.11.24':
- resolution: {integrity: sha512-Q64Ytn23y9aVDKN5iryFi8mRgyHw3/kyjTjT4qFCa8AEb5sGUuSj//AUZ6c0J7hQKMHlg9do5Etvoe61V98/JQ==}
+ '@swc/core-win32-arm64-msvc@1.11.29':
+ resolution: {integrity: sha512-po+WHw+k9g6FAg5IJ+sMwtA/fIUL3zPQ4m/uJgONBATCVnDDkyW6dBA49uHNVtSEvjvhuD8DVWdFP847YTcITw==}
engines: {node: '>=10'}
cpu: [arm64]
os: [win32]
- '@swc/core-win32-ia32-msvc@1.11.24':
- resolution: {integrity: sha512-9pKLIisE/Hh2vJhGIPvSoTK4uBSPxNVyXHmOrtdDot4E1FUUI74Vi8tFdlwNbaj8/vusVnb8xPXsxF1uB0VgiQ==}
+ '@swc/core-win32-ia32-msvc@1.11.29':
+ resolution: {integrity: sha512-h+NjOrbqdRBYr5ItmStmQt6x3tnhqgwbj9YxdGPepbTDamFv7vFnhZR0YfB3jz3UKJ8H3uGJ65Zw1VsC+xpFkg==}
engines: {node: '>=10'}
cpu: [ia32]
os: [win32]
- '@swc/core-win32-x64-msvc@1.11.24':
- resolution: {integrity: sha512-sybnXtOsdB+XvzVFlBVGgRHLqp3yRpHK7CrmpuDKszhj/QhmsaZzY/GHSeALlMtLup13M0gqbcQvsTNlAHTg3w==}
+ '@swc/core-win32-x64-msvc@1.11.29':
+ resolution: {integrity: sha512-Q8cs2BDV9wqDvqobkXOYdC+pLUSEpX/KvI0Dgfun1F+LzuLotRFuDhrvkU9ETJA6OnD2+Fn/ieHgloiKA/Mn/g==}
engines: {node: '>=10'}
cpu: [x64]
os: [win32]
- '@swc/core@1.11.24':
- resolution: {integrity: sha512-MaQEIpfcEMzx3VWWopbofKJvaraqmL6HbLlw2bFZ7qYqYw3rkhM0cQVEgyzbHtTWwCwPMFZSC2DUbhlZgrMfLg==}
+ '@swc/core@1.11.29':
+ resolution: {integrity: sha512-g4mThMIpWbNhV8G2rWp5a5/Igv8/2UFRJx2yImrLGMgrDDYZIopqZ/z0jZxDgqNA1QDx93rpwNF7jGsxVWcMlA==}
engines: {node: '>=10'}
peerDependencies:
'@swc/helpers': '>=0.5.17'
@@ -2120,8 +2116,8 @@ packages:
'@types/conventional-commits-parser@5.0.1':
resolution: {integrity: sha512-7uz5EHdzz2TqoMfV7ee61Egf5y6NkcO4FB/1iCCQnbeiI1F3xzv3vK5dBCXUCLQgGYS+mUeigK1iKQzvED+QnQ==}
- '@types/eslint-scope@3.7.7':
- resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==}
+ '@types/eslint-scope@8.3.0':
+ resolution: {integrity: sha512-FaY/QEfIyGJzJdkObuvtaROKv7A0zArw+be0tgXfWd1s1/AqPzEbyf7eyK0Pg0YezUpKrSwK4kgBn/kjzQOjtQ==}
'@types/eslint@9.6.1':
resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==}
@@ -2153,8 +2149,8 @@ packages:
'@types/lodash@4.17.13':
resolution: {integrity: sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg==}
- '@types/node@20.17.45':
- resolution: {integrity: sha512-vO9+E1smq+149wsmmLdM8SKVW7gRzLjfo0mU7kiykhV6rL+GEUhUmW7VywJNSxJHQzt9QBIHEo+3SG4MrFTqbA==}
+ '@types/node@20.17.50':
+ resolution: {integrity: sha512-Mxiq0ULv/zo1OzOhwPqOA13I81CV/W3nvd3ChtQZRT5Cwz3cr0FKo/wMSsbTqL3EXpaBAEQhva2B8ByRkOIh9A==}
'@types/parse-json@4.0.2':
resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==}
@@ -2171,78 +2167,57 @@ packages:
'@types/yargs@17.0.33':
resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==}
- '@typescript-eslint/eslint-plugin@8.32.0':
- resolution: {integrity: sha512-/jU9ettcntkBFmWUzzGgsClEi2ZFiikMX5eEQsmxIAWMOn4H3D4rvHssstmAHGVvrYnaMqdWWWg0b5M6IN/MTQ==}
+ '@typescript-eslint/eslint-plugin@8.32.1':
+ resolution: {integrity: sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
- '@typescript-eslint/parser': 8.32.0
+ '@typescript-eslint/parser': 8.32.1
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.9.0'
- '@typescript-eslint/parser@8.32.0':
- resolution: {integrity: sha512-B2MdzyWxCE2+SqiZHAjPphft+/2x2FlO9YBx7eKE1BCb+rqBlQdhtAEhzIEdozHd55DXPmxBdpMygFJjfjjA9A==}
+ '@typescript-eslint/parser@8.32.1':
+ resolution: {integrity: sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.9.0'
- '@typescript-eslint/rule-tester@8.32.0':
- resolution: {integrity: sha512-kfR6D4RdosBZiwa3/fuuRggzg3YPlMKaEdohVjv5nSyu9ZFD5fr6E/kydvMt0nkM1PLNzMAEtODriEz7RI/cqw==}
+ '@typescript-eslint/rule-tester@8.32.1':
+ resolution: {integrity: sha512-XUCGJUbBBn6HNFnihX2bm50F4J1LndwdzTlw7kfSnqukXoRkW/SEwMIhDLSiTcSPXZPVbO8R/Aw35J9zm4kD4w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
- '@typescript-eslint/scope-manager@8.32.0':
- resolution: {integrity: sha512-jc/4IxGNedXkmG4mx4nJTILb6TMjL66D41vyeaPWvDUmeYQzF3lKtN15WsAeTr65ce4mPxwopPSo1yUUAWw0hQ==}
+ '@typescript-eslint/scope-manager@8.32.1':
+ resolution: {integrity: sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@typescript-eslint/type-utils@8.31.0':
- resolution: {integrity: sha512-DJ1N1GdjI7IS7uRlzJuEDCgDQix3ZVYVtgeWEyhyn4iaoitpMBX6Ndd488mXSx0xah/cONAkEaYyylDyAeHMHg==}
+ '@typescript-eslint/type-utils@8.32.1':
+ resolution: {integrity: sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.9.0'
- '@typescript-eslint/type-utils@8.32.0':
- resolution: {integrity: sha512-t2vouuYQKEKSLtJaa5bB4jHeha2HJczQ6E5IXPDPgIty9EqcJxpr1QHQ86YyIPwDwxvUmLfP2YADQ5ZY4qddZg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: ^8.57.0 || ^9.0.0
- typescript: '>=4.8.4 <5.9.0'
-
- '@typescript-eslint/types@8.31.0':
- resolution: {integrity: sha512-Ch8oSjVyYyJxPQk8pMiP2FFGYatqXQfQIaMp+TpuuLlDachRWpUAeEu1u9B/v/8LToehUIWyiKcA/w5hUFRKuQ==}
+ '@typescript-eslint/types@8.32.1':
+ resolution: {integrity: sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@typescript-eslint/types@8.32.0':
- resolution: {integrity: sha512-O5Id6tGadAZEMThM6L9HmVf5hQUXNSxLVKeGJYWNhhVseps/0LddMkp7//VDkzwJ69lPL0UmZdcZwggj9akJaA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@typescript-eslint/typescript-estree@8.31.0':
- resolution: {integrity: sha512-xLmgn4Yl46xi6aDSZ9KkyfhhtnYI15/CvHbpOy/eR5NWhK/BK8wc709KKwhAR0m4ZKRP7h07bm4BWUYOCuRpQQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- typescript: '>=4.8.4 <5.9.0'
-
- '@typescript-eslint/typescript-estree@8.32.0':
- resolution: {integrity: sha512-pU9VD7anSCOIoBFnhTGfOzlVFQIA1XXiQpH/CezqOBaDppRwTglJzCC6fUQGpfwey4T183NKhF1/mfatYmjRqQ==}
+ '@typescript-eslint/typescript-estree@8.32.1':
+ resolution: {integrity: sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <5.9.0'
- '@typescript-eslint/utils@8.32.0':
- resolution: {integrity: sha512-8S9hXau6nQ/sYVtC3D6ISIDoJzS1NsCK+gluVhLN2YkBPX+/1wkwyUiDKnxRh15579WoOIyVWnoyIf3yGI9REw==}
+ '@typescript-eslint/utils@8.32.1':
+ resolution: {integrity: sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.9.0'
- '@typescript-eslint/visitor-keys@8.31.0':
- resolution: {integrity: sha512-QcGHmlRHWOl93o64ZUMNewCdwKGU6WItOU52H0djgNmn1EOrhVudrDzXz4OycCRSCPwFCDrE2iIt5vmuUdHxuQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@typescript-eslint/visitor-keys@8.32.0':
- resolution: {integrity: sha512-1rYQTCLFFzOI5Nl0c8LUpJT8HxpwVRn9E4CkMsYfuN6ctmQqExjSTzzSk0Tz2apmXy7WU6/6fyaZVVA/thPN+w==}
+ '@typescript-eslint/visitor-keys@8.32.1':
+ resolution: {integrity: sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@verdaccio/auth@8.0.0-next-8.15':
@@ -2387,10 +2362,6 @@ packages:
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
engines: {node: '>= 0.6'}
- accepts@2.0.0:
- resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==}
- engines: {node: '>= 0.6'}
-
acorn-jsx@5.3.2:
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
peerDependencies:
@@ -2634,10 +2605,6 @@ packages:
resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
- body-parser@2.2.0:
- resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==}
- engines: {node: '>=18'}
-
brace-expansion@1.1.11:
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
@@ -2880,10 +2847,6 @@ packages:
resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==}
engines: {node: '>= 0.6'}
- content-disposition@1.0.0:
- resolution: {integrity: sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==}
- engines: {node: '>= 0.6'}
-
content-type@1.0.5:
resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
engines: {node: '>= 0.6'}
@@ -2910,10 +2873,6 @@ packages:
cookie-signature@1.0.6:
resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==}
- cookie-signature@1.2.2:
- resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==}
- engines: {node: '>=6.6.0'}
-
cookie@0.7.1:
resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==}
engines: {node: '>= 0.6'}
@@ -3223,8 +3182,8 @@ packages:
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
engines: {node: '>=10'}
- eslint-config-prettier@10.1.3:
- resolution: {integrity: sha512-vDo4d9yQE+cS2tdIT4J02H/16veRvkHgiLDRpej+WL67oCfbOb97itZXn8wMPJ/GsiEBVjrjs//AVNw2Cp1EcA==}
+ eslint-config-prettier@10.1.5:
+ resolution: {integrity: sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==}
hasBin: true
peerDependencies:
eslint: '>=7.0.0'
@@ -3241,8 +3200,8 @@ packages:
resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- eslint@9.26.0:
- resolution: {integrity: sha512-Hx0MOjPh6uK9oq9nVsATZKE/Wlbai7KFjfCuw9UHaguDW3x+HF0O5nIi3ud39TWgrTjTO5nHxmL3R1eANinWHQ==}
+ eslint@9.27.0:
+ resolution: {integrity: sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
hasBin: true
peerDependencies:
@@ -3295,22 +3254,10 @@ packages:
resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
engines: {node: '>=0.8.x'}
- eventsource-parser@3.0.1:
- resolution: {integrity: sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==}
- engines: {node: '>=18.0.0'}
-
- eventsource@3.0.6:
- resolution: {integrity: sha512-l19WpE2m9hSuyP06+FbuUUf1G+R0SFLrtQfbRb9PRr+oimOfxQhgGCbVaXg5IvZyyTThJsxh6L/srkMiCeBPDA==}
- engines: {node: '>=18.0.0'}
-
execa@5.1.1:
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
engines: {node: '>=10'}
- execa@8.0.1:
- resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
- engines: {node: '>=16.17'}
-
exit@0.1.2:
resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==}
engines: {node: '>= 0.8.0'}
@@ -3329,20 +3276,10 @@ packages:
express-rate-limit@5.5.1:
resolution: {integrity: sha512-MTjE2eIbHv5DyfuFz4zLYWxpqVhEhkTiwFGuB74Q9CSou2WHO52nlE5y3Zlg6SIsiYUIPj6ifFxnkPz6O3sIUg==}
- express-rate-limit@7.5.0:
- resolution: {integrity: sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==}
- engines: {node: '>= 16'}
- peerDependencies:
- express: ^4.11 || 5 || ^5.0.0-beta.1
-
express@4.21.2:
resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==}
engines: {node: '>= 0.10.0'}
- express@5.1.0:
- resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==}
- engines: {node: '>= 18'}
-
ext-list@2.2.2:
resolution: {integrity: sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==}
engines: {node: '>=0.10.0'}
@@ -3438,10 +3375,6 @@ packages:
resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==}
engines: {node: '>= 0.8'}
- finalhandler@2.1.0:
- resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==}
- engines: {node: '>= 0.8'}
-
find-node-modules@2.1.3:
resolution: {integrity: sha512-UC2I2+nx1ZuOBclWVNdcnbDR5dlrOdVb7xNjmT/lHE+LsgztWks3dG7boJ37yTS/venXw84B/mAW9uHVoC5QRg==}
@@ -3511,10 +3444,6 @@ packages:
resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
engines: {node: '>= 0.6'}
- fresh@2.0.0:
- resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==}
- engines: {node: '>= 0.8'}
-
front-matter@4.0.2:
resolution: {integrity: sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==}
@@ -3576,10 +3505,6 @@ packages:
resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
engines: {node: '>=10'}
- get-stream@8.0.1:
- resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==}
- engines: {node: '>=16'}
-
get-stream@9.0.1:
resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==}
engines: {node: '>=18'}
@@ -3743,10 +3668,6 @@ packages:
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
engines: {node: '>=10.17.0'}
- human-signals@5.0.0:
- resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
- engines: {node: '>=16.17.0'}
-
husky@9.1.7:
resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==}
engines: {node: '>=18'}
@@ -3897,17 +3818,10 @@ packages:
is-promise@2.2.2:
resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==}
- is-promise@4.0.0:
- resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==}
-
is-stream@2.0.1:
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
engines: {node: '>=8'}
- is-stream@3.0.0:
- resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
-
is-stream@4.0.1:
resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==}
engines: {node: '>=18'}
@@ -4234,15 +4148,19 @@ packages:
resolution: {integrity: sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
- lint-staged@15.5.2:
- resolution: {integrity: sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==}
- engines: {node: '>=18.12.0'}
+ lint-staged@16.0.0:
+ resolution: {integrity: sha512-sUCprePs6/rbx4vKC60Hez6X10HPkpDJaGcy3D1NdwR7g1RcNkWL8q9mJMreOqmHBTs+1sNFp+wOiX9fr+hoOQ==}
+ engines: {node: '>=20.18'}
hasBin: true
listr2@8.2.5:
resolution: {integrity: sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==}
engines: {node: '>=18.0.0'}
+ listr2@8.3.3:
+ resolution: {integrity: sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==}
+ engines: {node: '>=18.0.0'}
+
locate-path@5.0.0:
resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
engines: {node: '>=8'}
@@ -4374,10 +4292,6 @@ packages:
resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
engines: {node: '>= 0.6'}
- media-typer@1.1.0:
- resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==}
- engines: {node: '>= 0.8'}
-
meow@12.1.1:
resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==}
engines: {node: '>=16.10'}
@@ -4385,10 +4299,6 @@ packages:
merge-descriptors@1.0.3:
resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==}
- merge-descriptors@2.0.0:
- resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==}
- engines: {node: '>=18'}
-
merge-stream@2.0.0:
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
@@ -4423,10 +4333,6 @@ packages:
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
engines: {node: '>= 0.6'}
- mime-types@3.0.1:
- resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==}
- engines: {node: '>= 0.6'}
-
mime@1.6.0:
resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
engines: {node: '>=4'}
@@ -4446,10 +4352,6 @@ packages:
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
engines: {node: '>=6'}
- mimic-fn@4.0.0:
- resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
- engines: {node: '>=12'}
-
mimic-function@5.0.1:
resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==}
engines: {node: '>=18'}
@@ -4561,6 +4463,10 @@ packages:
resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==}
engines: {node: ^18.17.0 || >=20.5.0}
+ nano-spawn@1.0.1:
+ resolution: {integrity: sha512-BfcvzBlUTxSDWfT+oH7vd6CbUV+rThLLHCIym/QO6GGLBsyVXleZs00fto2i2jzC/wPiBYk5jyOmpXWg4YopiA==}
+ engines: {node: '>=20.18'}
+
natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
@@ -4659,13 +4565,8 @@ packages:
resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
engines: {node: '>=8'}
- npm-run-path@5.3.0:
- resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
-
- nx@21.0.2:
- resolution: {integrity: sha512-Kkf7d4XgQH5KglwuWxtjY0scHClEf3G3I3wZpBWRdUd52t/a1kxUPL4lDcJ7hwkW+FWgSxFB+jmp/kMbroMXOg==}
- engines: {node: ^20.19.0 || ^22.12.0}
+ nx@21.1.2:
+ resolution: {integrity: sha512-oczAEOOkQHElxCXs2g2jXDRabDRsmub/h5SAgqAUDSJ2CRnYGVVlgZX7l+o+A9kSqfONyLy5FlJ1pSWlvPuG4w==}
hasBin: true
peerDependencies:
'@swc-node/register': ^1.8.0
@@ -4703,10 +4604,6 @@ packages:
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
engines: {node: '>=6'}
- onetime@6.0.0:
- resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==}
- engines: {node: '>=12'}
-
onetime@7.0.0:
resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==}
engines: {node: '>=18'}
@@ -4817,10 +4714,6 @@ packages:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'}
- path-key@4.0.0:
- resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==}
- engines: {node: '>=12'}
-
path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
@@ -4831,10 +4724,6 @@ packages:
path-to-regexp@0.1.12:
resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==}
- path-to-regexp@8.2.0:
- resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==}
- engines: {node: '>=16'}
-
path-type@4.0.0:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
@@ -4892,10 +4781,6 @@ packages:
piscina@4.7.0:
resolution: {integrity: sha512-b8hvkpp9zS0zsfa939b/jXbe64Z2gZv0Ha7FYPNUiDIB1y2AtxcOZdfP8xN8HFjUaqQiT9gRlfjAsoL8vdJ1Iw==}
- pkce-challenge@5.0.0:
- resolution: {integrity: sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==}
- engines: {node: '>=16.20.0'}
-
pkg-dir@4.2.0:
resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==}
engines: {node: '>=8'}
@@ -5012,10 +4897,6 @@ packages:
resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==}
engines: {node: '>= 0.8'}
- raw-body@3.0.0:
- resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==}
- engines: {node: '>= 0.8'}
-
react-is@18.3.1:
resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
@@ -5124,10 +5005,6 @@ packages:
resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==}
hasBin: true
- router@2.2.0:
- resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==}
- engines: {node: '>= 18'}
-
run-async@2.4.1:
resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==}
engines: {node: '>=0.12.0'}
@@ -5177,22 +5054,19 @@ packages:
engines: {node: '>=10'}
hasBin: true
+ semver@7.7.2:
+ resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==}
+ engines: {node: '>=10'}
+ hasBin: true
+
send@0.19.0:
resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==}
engines: {node: '>= 0.8.0'}
- send@1.2.0:
- resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==}
- engines: {node: '>= 18'}
-
serve-static@1.16.2:
resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==}
engines: {node: '>= 0.8.0'}
- serve-static@2.2.0:
- resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==}
- engines: {node: '>= 18'}
-
set-function-length@1.2.2:
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
engines: {node: '>= 0.4'}
@@ -5398,10 +5272,6 @@ packages:
resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
engines: {node: '>=6'}
- strip-final-newline@3.0.0:
- resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==}
- engines: {node: '>=12'}
-
strip-json-comments@3.1.1:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
@@ -5602,12 +5472,8 @@ packages:
resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
engines: {node: '>= 0.6'}
- type-is@2.0.1:
- resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==}
- engines: {node: '>= 0.6'}
-
- typescript-eslint@8.32.0:
- resolution: {integrity: sha512-UMq2kxdXCzinFFPsXc9o2ozIpYCCOiEC46MG3yEh5Vipq6BO27otTtEBZA1fQ66DulEUgE97ucQ/3YY66CPg0A==}
+ typescript-eslint@8.32.1:
+ resolution: {integrity: sha512-D7el+eaDHAmXvrZBy1zpzSNIRqnCOrkwTgZxTu3MUqRWk8k0q9m9Ho4+vPf7iHtgUfrK/o8IZaEApsxPlHTFCg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
@@ -5831,8 +5697,8 @@ packages:
resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
engines: {node: '>= 6'}
- yaml@2.7.0:
- resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==}
+ yaml@2.7.1:
+ resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==}
engines: {node: '>= 14'}
hasBin: true
@@ -5864,14 +5730,6 @@ packages:
resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==}
engines: {node: '>=18'}
- zod-to-json-schema@3.24.5:
- resolution: {integrity: sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==}
- peerDependencies:
- zod: ^3.24.1
-
- zod@3.24.4:
- resolution: {integrity: sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==}
-
snapshots:
'@ampproject/remapping@2.3.0':
@@ -5879,14 +5737,14 @@ snapshots:
'@jridgewell/gen-mapping': 0.3.5
'@jridgewell/trace-mapping': 0.3.25
- '@angular-devkit/architect@0.1902.11':
+ '@angular-devkit/architect@0.1902.13':
dependencies:
- '@angular-devkit/core': 19.2.11
+ '@angular-devkit/core': 19.2.13
rxjs: 7.8.1
transitivePeerDependencies:
- chokidar
- '@angular-devkit/core@19.2.11':
+ '@angular-devkit/core@19.2.13':
dependencies:
ajv: 8.17.1
ajv-formats: 3.0.1(ajv@8.17.1)
@@ -5895,9 +5753,9 @@ snapshots:
rxjs: 7.8.1
source-map: 0.7.4
- '@angular-devkit/schematics@19.2.11':
+ '@angular-devkit/schematics@19.2.13':
dependencies:
- '@angular-devkit/core': 19.2.11
+ '@angular-devkit/core': 19.2.13
jsonc-parser: 3.3.1
magic-string: 0.30.17
ora: 5.4.1
@@ -5905,14 +5763,14 @@ snapshots:
transitivePeerDependencies:
- chokidar
- '@angular/cli@19.2.11(@types/node@20.17.45)':
+ '@angular/cli@19.2.13(@types/node@20.17.50)':
dependencies:
- '@angular-devkit/architect': 0.1902.11
- '@angular-devkit/core': 19.2.11
- '@angular-devkit/schematics': 19.2.11
- '@inquirer/prompts': 7.3.2(@types/node@20.17.45)
- '@listr2/prompt-adapter-inquirer': 2.0.18(@inquirer/prompts@7.3.2(@types/node@20.17.45))
- '@schematics/angular': 19.2.11
+ '@angular-devkit/architect': 0.1902.13
+ '@angular-devkit/core': 19.2.13
+ '@angular-devkit/schematics': 19.2.13
+ '@inquirer/prompts': 7.3.2(@types/node@20.17.50)
+ '@listr2/prompt-adapter-inquirer': 2.0.18(@inquirer/prompts@7.3.2(@types/node@20.17.50))
+ '@schematics/angular': 19.2.13
'@yarnpkg/lockfile': 1.1.0
ini: 5.0.0
jsonc-parser: 3.3.1
@@ -5930,7 +5788,7 @@ snapshots:
- chokidar
- supports-color
- '@angular/compiler@19.2.10':
+ '@angular/compiler@19.2.13':
dependencies:
tslib: 2.8.1
@@ -6727,11 +6585,11 @@ snapshots:
'@bcoe/v8-coverage@0.2.3': {}
- '@commitlint/cli@19.8.1(@types/node@20.17.45)(typescript@5.8.3)':
+ '@commitlint/cli@19.8.1(@types/node@20.17.50)(typescript@5.8.3)':
dependencies:
'@commitlint/format': 19.8.1
'@commitlint/lint': 19.8.1
- '@commitlint/load': 19.8.1(@types/node@20.17.45)(typescript@5.8.3)
+ '@commitlint/load': 19.8.1(@types/node@20.17.50)(typescript@5.8.3)
'@commitlint/read': 19.8.1
'@commitlint/types': 19.8.1
tinyexec: 1.0.1
@@ -6778,7 +6636,7 @@ snapshots:
'@commitlint/is-ignored@19.8.1':
dependencies:
'@commitlint/types': 19.8.1
- semver: 7.7.1
+ semver: 7.7.2
'@commitlint/lint@19.8.1':
dependencies:
@@ -6787,7 +6645,7 @@ snapshots:
'@commitlint/rules': 19.8.1
'@commitlint/types': 19.8.1
- '@commitlint/load@19.5.0(@types/node@20.17.45)(typescript@5.8.3)':
+ '@commitlint/load@19.5.0(@types/node@20.17.50)(typescript@5.8.3)':
dependencies:
'@commitlint/config-validator': 19.5.0
'@commitlint/execute-rule': 19.5.0
@@ -6795,7 +6653,7 @@ snapshots:
'@commitlint/types': 19.8.0
chalk: 5.4.1
cosmiconfig: 9.0.0(typescript@5.8.3)
- cosmiconfig-typescript-loader: 5.1.0(@types/node@20.17.45)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3)
+ cosmiconfig-typescript-loader: 5.1.0(@types/node@20.17.50)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3)
lodash.isplainobject: 4.0.6
lodash.merge: 4.6.2
lodash.uniq: 4.5.0
@@ -6804,7 +6662,7 @@ snapshots:
- typescript
optional: true
- '@commitlint/load@19.8.1(@types/node@20.17.45)(typescript@5.8.3)':
+ '@commitlint/load@19.8.1(@types/node@20.17.50)(typescript@5.8.3)':
dependencies:
'@commitlint/config-validator': 19.8.1
'@commitlint/execute-rule': 19.8.1
@@ -6812,7 +6670,7 @@ snapshots:
'@commitlint/types': 19.8.1
chalk: 5.4.1
cosmiconfig: 9.0.0(typescript@5.8.3)
- cosmiconfig-typescript-loader: 6.1.0(@types/node@20.17.45)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3)
+ cosmiconfig-typescript-loader: 6.1.0(@types/node@20.17.50)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3)
lodash.isplainobject: 4.0.6
lodash.merge: 4.6.2
lodash.uniq: 4.5.0
@@ -6993,14 +6851,14 @@ snapshots:
'@esbuild/win32-x64@0.25.4':
optional: true
- '@eslint-community/eslint-utils@4.4.1(eslint@9.26.0(jiti@2.4.2))':
+ '@eslint-community/eslint-utils@4.4.1(eslint@9.27.0(jiti@2.4.2))':
dependencies:
- eslint: 9.26.0(jiti@2.4.2)
+ eslint: 9.27.0(jiti@2.4.2)
eslint-visitor-keys: 3.4.3
- '@eslint-community/eslint-utils@4.7.0(eslint@9.26.0(jiti@2.4.2))':
+ '@eslint-community/eslint-utils@4.7.0(eslint@9.27.0(jiti@2.4.2))':
dependencies:
- eslint: 9.26.0(jiti@2.4.2)
+ eslint: 9.27.0(jiti@2.4.2)
eslint-visitor-keys: 3.4.3
'@eslint-community/regexpp@4.12.1': {}
@@ -7015,7 +6873,7 @@ snapshots:
'@eslint/config-helpers@0.2.1': {}
- '@eslint/core@0.13.0':
+ '@eslint/core@0.14.0':
dependencies:
'@types/json-schema': 7.0.15
@@ -7033,13 +6891,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@eslint/js@9.26.0': {}
+ '@eslint/js@9.27.0': {}
'@eslint/object-schema@2.1.6': {}
- '@eslint/plugin-kit@0.2.8':
+ '@eslint/plugin-kit@0.3.1':
dependencies:
- '@eslint/core': 0.13.0
+ '@eslint/core': 0.14.0
levn: 0.4.1
'@humanfs/core@0.19.1': {}
@@ -7055,27 +6913,27 @@ snapshots:
'@humanwhocodes/retry@0.4.2': {}
- '@inquirer/checkbox@4.1.2(@types/node@20.17.45)':
+ '@inquirer/checkbox@4.1.2(@types/node@20.17.50)':
dependencies:
- '@inquirer/core': 10.1.7(@types/node@20.17.45)
+ '@inquirer/core': 10.1.7(@types/node@20.17.50)
'@inquirer/figures': 1.0.10
- '@inquirer/type': 3.0.4(@types/node@20.17.45)
+ '@inquirer/type': 3.0.4(@types/node@20.17.50)
ansi-escapes: 4.3.2
yoctocolors-cjs: 2.1.2
optionalDependencies:
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
- '@inquirer/confirm@5.1.6(@types/node@20.17.45)':
+ '@inquirer/confirm@5.1.6(@types/node@20.17.50)':
dependencies:
- '@inquirer/core': 10.1.7(@types/node@20.17.45)
- '@inquirer/type': 3.0.4(@types/node@20.17.45)
+ '@inquirer/core': 10.1.7(@types/node@20.17.50)
+ '@inquirer/type': 3.0.4(@types/node@20.17.50)
optionalDependencies:
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
- '@inquirer/core@10.1.7(@types/node@20.17.45)':
+ '@inquirer/core@10.1.7(@types/node@20.17.50)':
dependencies:
'@inquirer/figures': 1.0.10
- '@inquirer/type': 3.0.4(@types/node@20.17.45)
+ '@inquirer/type': 3.0.4(@types/node@20.17.50)
ansi-escapes: 4.3.2
cli-width: 4.1.0
mute-stream: 2.0.0
@@ -7083,97 +6941,97 @@ snapshots:
wrap-ansi: 6.2.0
yoctocolors-cjs: 2.1.2
optionalDependencies:
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
- '@inquirer/editor@4.2.7(@types/node@20.17.45)':
+ '@inquirer/editor@4.2.7(@types/node@20.17.50)':
dependencies:
- '@inquirer/core': 10.1.7(@types/node@20.17.45)
- '@inquirer/type': 3.0.4(@types/node@20.17.45)
+ '@inquirer/core': 10.1.7(@types/node@20.17.50)
+ '@inquirer/type': 3.0.4(@types/node@20.17.50)
external-editor: 3.1.0
optionalDependencies:
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
- '@inquirer/expand@4.0.9(@types/node@20.17.45)':
+ '@inquirer/expand@4.0.9(@types/node@20.17.50)':
dependencies:
- '@inquirer/core': 10.1.7(@types/node@20.17.45)
- '@inquirer/type': 3.0.4(@types/node@20.17.45)
+ '@inquirer/core': 10.1.7(@types/node@20.17.50)
+ '@inquirer/type': 3.0.4(@types/node@20.17.50)
yoctocolors-cjs: 2.1.2
optionalDependencies:
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
'@inquirer/figures@1.0.10': {}
- '@inquirer/input@4.1.6(@types/node@20.17.45)':
+ '@inquirer/input@4.1.6(@types/node@20.17.50)':
dependencies:
- '@inquirer/core': 10.1.7(@types/node@20.17.45)
- '@inquirer/type': 3.0.4(@types/node@20.17.45)
+ '@inquirer/core': 10.1.7(@types/node@20.17.50)
+ '@inquirer/type': 3.0.4(@types/node@20.17.50)
optionalDependencies:
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
- '@inquirer/number@3.0.9(@types/node@20.17.45)':
+ '@inquirer/number@3.0.9(@types/node@20.17.50)':
dependencies:
- '@inquirer/core': 10.1.7(@types/node@20.17.45)
- '@inquirer/type': 3.0.4(@types/node@20.17.45)
+ '@inquirer/core': 10.1.7(@types/node@20.17.50)
+ '@inquirer/type': 3.0.4(@types/node@20.17.50)
optionalDependencies:
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
- '@inquirer/password@4.0.9(@types/node@20.17.45)':
+ '@inquirer/password@4.0.9(@types/node@20.17.50)':
dependencies:
- '@inquirer/core': 10.1.7(@types/node@20.17.45)
- '@inquirer/type': 3.0.4(@types/node@20.17.45)
+ '@inquirer/core': 10.1.7(@types/node@20.17.50)
+ '@inquirer/type': 3.0.4(@types/node@20.17.50)
ansi-escapes: 4.3.2
optionalDependencies:
- '@types/node': 20.17.45
-
- '@inquirer/prompts@7.3.2(@types/node@20.17.45)':
- dependencies:
- '@inquirer/checkbox': 4.1.2(@types/node@20.17.45)
- '@inquirer/confirm': 5.1.6(@types/node@20.17.45)
- '@inquirer/editor': 4.2.7(@types/node@20.17.45)
- '@inquirer/expand': 4.0.9(@types/node@20.17.45)
- '@inquirer/input': 4.1.6(@types/node@20.17.45)
- '@inquirer/number': 3.0.9(@types/node@20.17.45)
- '@inquirer/password': 4.0.9(@types/node@20.17.45)
- '@inquirer/rawlist': 4.0.9(@types/node@20.17.45)
- '@inquirer/search': 3.0.9(@types/node@20.17.45)
- '@inquirer/select': 4.0.9(@types/node@20.17.45)
+ '@types/node': 20.17.50
+
+ '@inquirer/prompts@7.3.2(@types/node@20.17.50)':
+ dependencies:
+ '@inquirer/checkbox': 4.1.2(@types/node@20.17.50)
+ '@inquirer/confirm': 5.1.6(@types/node@20.17.50)
+ '@inquirer/editor': 4.2.7(@types/node@20.17.50)
+ '@inquirer/expand': 4.0.9(@types/node@20.17.50)
+ '@inquirer/input': 4.1.6(@types/node@20.17.50)
+ '@inquirer/number': 3.0.9(@types/node@20.17.50)
+ '@inquirer/password': 4.0.9(@types/node@20.17.50)
+ '@inquirer/rawlist': 4.0.9(@types/node@20.17.50)
+ '@inquirer/search': 3.0.9(@types/node@20.17.50)
+ '@inquirer/select': 4.0.9(@types/node@20.17.50)
optionalDependencies:
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
- '@inquirer/rawlist@4.0.9(@types/node@20.17.45)':
+ '@inquirer/rawlist@4.0.9(@types/node@20.17.50)':
dependencies:
- '@inquirer/core': 10.1.7(@types/node@20.17.45)
- '@inquirer/type': 3.0.4(@types/node@20.17.45)
+ '@inquirer/core': 10.1.7(@types/node@20.17.50)
+ '@inquirer/type': 3.0.4(@types/node@20.17.50)
yoctocolors-cjs: 2.1.2
optionalDependencies:
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
- '@inquirer/search@3.0.9(@types/node@20.17.45)':
+ '@inquirer/search@3.0.9(@types/node@20.17.50)':
dependencies:
- '@inquirer/core': 10.1.7(@types/node@20.17.45)
+ '@inquirer/core': 10.1.7(@types/node@20.17.50)
'@inquirer/figures': 1.0.10
- '@inquirer/type': 3.0.4(@types/node@20.17.45)
+ '@inquirer/type': 3.0.4(@types/node@20.17.50)
yoctocolors-cjs: 2.1.2
optionalDependencies:
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
- '@inquirer/select@4.0.9(@types/node@20.17.45)':
+ '@inquirer/select@4.0.9(@types/node@20.17.50)':
dependencies:
- '@inquirer/core': 10.1.7(@types/node@20.17.45)
+ '@inquirer/core': 10.1.7(@types/node@20.17.50)
'@inquirer/figures': 1.0.10
- '@inquirer/type': 3.0.4(@types/node@20.17.45)
+ '@inquirer/type': 3.0.4(@types/node@20.17.50)
ansi-escapes: 4.3.2
yoctocolors-cjs: 2.1.2
optionalDependencies:
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
'@inquirer/type@1.5.5':
dependencies:
mute-stream: 1.0.0
- '@inquirer/type@3.0.4(@types/node@20.17.45)':
+ '@inquirer/type@3.0.4(@types/node@20.17.50)':
optionalDependencies:
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
'@isaacs/cliui@8.0.2':
dependencies:
@@ -7201,27 +7059,27 @@ snapshots:
'@jest/console@29.7.0':
dependencies:
'@jest/types': 29.6.3
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
chalk: 4.1.2
jest-message-util: 29.7.0
jest-util: 29.7.0
slash: 3.0.0
- '@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3))':
+ '@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3))':
dependencies:
'@jest/console': 29.7.0
'@jest/reporters': 29.7.0
'@jest/test-result': 29.7.0
'@jest/transform': 29.7.0
'@jest/types': 29.6.3
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
ansi-escapes: 4.3.2
chalk: 4.1.2
ci-info: 3.9.0
exit: 0.1.2
graceful-fs: 4.2.11
jest-changed-files: 29.7.0
- jest-config: 29.7.0(@types/node@20.17.45)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3))
+ jest-config: 29.7.0(@types/node@20.17.50)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3))
jest-haste-map: 29.7.0
jest-message-util: 29.7.0
jest-regex-util: 29.6.3
@@ -7246,7 +7104,7 @@ snapshots:
dependencies:
'@jest/fake-timers': 29.7.0
'@jest/types': 29.6.3
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
jest-mock: 29.7.0
'@jest/expect-utils@29.7.0':
@@ -7264,7 +7122,7 @@ snapshots:
dependencies:
'@jest/types': 29.6.3
'@sinonjs/fake-timers': 10.3.0
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
jest-message-util: 29.7.0
jest-mock: 29.7.0
jest-util: 29.7.0
@@ -7286,7 +7144,7 @@ snapshots:
'@jest/transform': 29.7.0
'@jest/types': 29.6.3
'@jridgewell/trace-mapping': 0.3.25
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
chalk: 4.1.2
collect-v8-coverage: 1.0.2
exit: 0.1.2
@@ -7356,7 +7214,7 @@ snapshots:
'@jest/schemas': 29.6.3
'@types/istanbul-lib-coverage': 2.0.6
'@types/istanbul-reports': 3.0.4
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
'@types/yargs': 17.0.33
chalk: 4.1.2
@@ -7385,27 +7243,12 @@ snapshots:
'@jsdevtools/ono@7.1.3': {}
- '@listr2/prompt-adapter-inquirer@2.0.18(@inquirer/prompts@7.3.2(@types/node@20.17.45))':
+ '@listr2/prompt-adapter-inquirer@2.0.18(@inquirer/prompts@7.3.2(@types/node@20.17.50))':
dependencies:
- '@inquirer/prompts': 7.3.2(@types/node@20.17.45)
+ '@inquirer/prompts': 7.3.2(@types/node@20.17.50)
'@inquirer/type': 1.5.5
- '@mdn/browser-compat-data@6.0.12': {}
-
- '@modelcontextprotocol/sdk@1.11.0':
- dependencies:
- content-type: 1.0.5
- cors: 2.8.5
- cross-spawn: 7.0.6
- eventsource: 3.0.6
- express: 5.1.0
- express-rate-limit: 7.5.0(express@5.1.0)
- pkce-challenge: 5.0.0
- raw-body: 3.0.0
- zod: 3.24.4
- zod-to-json-schema: 3.24.5(zod@3.24.4)
- transitivePeerDependencies:
- - supports-color
+ '@mdn/browser-compat-data@6.0.17': {}
'@napi-rs/nice-android-arm-eabi@1.0.1':
optional: true
@@ -7522,11 +7365,11 @@ snapshots:
'@npmcli/fs@3.1.1':
dependencies:
- semver: 7.7.1
+ semver: 7.7.2
'@npmcli/fs@4.0.0':
dependencies:
- semver: 7.7.1
+ semver: 7.7.2
'@npmcli/git@6.0.1':
dependencies:
@@ -7537,7 +7380,7 @@ snapshots:
proc-log: 5.0.0
promise-inflight: 1.0.1
promise-retry: 2.0.1
- semver: 7.7.1
+ semver: 7.7.2
which: 5.0.0
transitivePeerDependencies:
- bluebird
@@ -7557,7 +7400,7 @@ snapshots:
json-parse-even-better-errors: 4.0.0
normalize-package-data: 7.0.0
proc-log: 5.0.0
- semver: 7.7.1
+ semver: 7.7.2
transitivePeerDependencies:
- bluebird
@@ -7579,22 +7422,22 @@ snapshots:
- bluebird
- supports-color
- '@nx/devkit@21.0.2(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))':
+ '@nx/devkit@21.1.2(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))':
dependencies:
ejs: 3.1.10
enquirer: 2.3.6
ignore: 5.3.2
minimatch: 9.0.3
- nx: 21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))
- semver: 7.7.1
+ nx: 21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))
+ semver: 7.7.2
tmp: 0.2.3
tslib: 2.8.1
yargs-parser: 21.1.1
- '@nx/esbuild@21.0.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))(esbuild@0.25.4)(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))':
+ '@nx/esbuild@21.1.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(esbuild@0.25.4)(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))':
dependencies:
- '@nx/devkit': 21.0.2(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))
- '@nx/js': 21.0.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
+ '@nx/devkit': 21.1.2(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+ '@nx/js': 21.1.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
picocolors: 1.1.1
tinyglobby: 0.2.12
tsconfig-paths: 4.2.0
@@ -7610,21 +7453,21 @@ snapshots:
- supports-color
- verdaccio
- '@nx/eslint-plugin@21.0.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))(@typescript-eslint/parser@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3))(eslint-config-prettier@10.1.3(eslint@9.26.0(jiti@2.4.2)))(eslint@9.26.0(jiti@2.4.2))(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))(typescript@5.8.3)(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))':
+ '@nx/eslint-plugin@21.1.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@typescript-eslint/parser@8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3))(eslint-config-prettier@10.1.5(eslint@9.27.0(jiti@2.4.2)))(eslint@9.27.0(jiti@2.4.2))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(typescript@5.8.3)(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))':
dependencies:
- '@nx/devkit': 21.0.2(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))
- '@nx/js': 21.0.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
- '@typescript-eslint/parser': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
- '@typescript-eslint/type-utils': 8.31.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
- '@typescript-eslint/utils': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
+ '@nx/devkit': 21.1.2(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+ '@nx/js': 21.1.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
+ '@typescript-eslint/parser': 8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
+ '@typescript-eslint/type-utils': 8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
+ '@typescript-eslint/utils': 8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
chalk: 4.1.2
confusing-browser-globals: 1.0.11
globals: 15.12.0
jsonc-eslint-parser: 2.4.0
- semver: 7.7.1
+ semver: 7.7.2
tslib: 2.8.1
optionalDependencies:
- eslint-config-prettier: 10.1.3(eslint@9.26.0(jiti@2.4.2))
+ eslint-config-prettier: 10.1.5(eslint@9.27.0(jiti@2.4.2))
transitivePeerDependencies:
- '@babel/traverse'
- '@swc-node/register'
@@ -7636,12 +7479,12 @@ snapshots:
- typescript
- verdaccio
- '@nx/eslint@21.0.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.26.0(jiti@2.4.2))(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))':
+ '@nx/eslint@21.1.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.27.0(jiti@2.4.2))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))':
dependencies:
- '@nx/devkit': 21.0.2(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))
- '@nx/js': 21.0.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
- eslint: 9.26.0(jiti@2.4.2)
- semver: 7.7.1
+ '@nx/devkit': 21.1.2(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+ '@nx/js': 21.1.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
+ eslint: 9.27.0(jiti@2.4.2)
+ semver: 7.7.2
tslib: 2.8.1
typescript: 5.7.3
optionalDependencies:
@@ -7655,21 +7498,21 @@ snapshots:
- supports-color
- verdaccio
- '@nx/jest@21.0.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(babel-plugin-macros@3.1.0)(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))(ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))':
+ '@nx/jest@21.1.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(babel-plugin-macros@3.1.0)(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))':
dependencies:
'@jest/reporters': 29.7.0
'@jest/test-result': 29.7.0
- '@nx/devkit': 21.0.2(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))
- '@nx/js': 21.0.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
+ '@nx/devkit': 21.1.2(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+ '@nx/js': 21.1.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
'@phenomnomnominal/tsquery': 5.0.1(typescript@5.8.3)
identity-obj-proxy: 3.0.0
- jest-config: 29.7.0(@types/node@20.17.45)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3))
+ jest-config: 29.7.0(@types/node@20.17.50)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3))
jest-resolve: 29.7.0
jest-util: 29.7.0
minimatch: 9.0.3
picocolors: 1.1.1
resolve.exports: 2.0.3
- semver: 7.7.1
+ semver: 7.7.2
tslib: 2.8.1
yargs-parser: 21.1.1
transitivePeerDependencies:
@@ -7686,7 +7529,7 @@ snapshots:
- typescript
- verdaccio
- '@nx/js@21.0.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))':
+ '@nx/js@21.1.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))':
dependencies:
'@babel/core': 7.26.0
'@babel/plugin-proposal-decorators': 7.25.9(@babel/core@7.26.0)
@@ -7695,8 +7538,8 @@ snapshots:
'@babel/preset-env': 7.26.0(@babel/core@7.26.0)
'@babel/preset-typescript': 7.26.0(@babel/core@7.26.0)
'@babel/runtime': 7.26.0
- '@nx/devkit': 21.0.2(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))
- '@nx/workspace': 21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))
+ '@nx/devkit': 21.1.2(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+ '@nx/workspace': 21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))
'@zkochan/js-yaml': 0.0.7
babel-plugin-const-enum: 1.2.0(@babel/core@7.26.0)
babel-plugin-macros: 3.1.0
@@ -7713,7 +7556,7 @@ snapshots:
ora: 5.3.0
picocolors: 1.1.1
picomatch: 4.0.2
- semver: 7.7.1
+ semver: 7.7.2
source-map-support: 0.5.19
tinyglobby: 0.2.12
tslib: 2.8.1
@@ -7727,42 +7570,42 @@ snapshots:
- nx
- supports-color
- '@nx/nx-darwin-arm64@21.0.2':
+ '@nx/nx-darwin-arm64@21.1.2':
optional: true
- '@nx/nx-darwin-x64@21.0.2':
+ '@nx/nx-darwin-x64@21.1.2':
optional: true
- '@nx/nx-freebsd-x64@21.0.2':
+ '@nx/nx-freebsd-x64@21.1.2':
optional: true
- '@nx/nx-linux-arm-gnueabihf@21.0.2':
+ '@nx/nx-linux-arm-gnueabihf@21.1.2':
optional: true
- '@nx/nx-linux-arm64-gnu@21.0.2':
+ '@nx/nx-linux-arm64-gnu@21.1.2':
optional: true
- '@nx/nx-linux-arm64-musl@21.0.2':
+ '@nx/nx-linux-arm64-musl@21.1.2':
optional: true
- '@nx/nx-linux-x64-gnu@21.0.2':
+ '@nx/nx-linux-x64-gnu@21.1.2':
optional: true
- '@nx/nx-linux-x64-musl@21.0.2':
+ '@nx/nx-linux-x64-musl@21.1.2':
optional: true
- '@nx/nx-win32-arm64-msvc@21.0.2':
+ '@nx/nx-win32-arm64-msvc@21.1.2':
optional: true
- '@nx/nx-win32-x64-msvc@21.0.2':
+ '@nx/nx-win32-x64-msvc@21.1.2':
optional: true
- '@nx/plugin@21.0.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.26.0(jiti@2.4.2))(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))(ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))':
+ '@nx/plugin@21.1.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.27.0(jiti@2.4.2))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))':
dependencies:
- '@nx/devkit': 21.0.2(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))
- '@nx/eslint': 21.0.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.26.0(jiti@2.4.2))(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
- '@nx/jest': 21.0.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(babel-plugin-macros@3.1.0)(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))(ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
- '@nx/js': 21.0.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
+ '@nx/devkit': 21.1.2(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+ '@nx/eslint': 21.1.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.27.0(jiti@2.4.2))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
+ '@nx/jest': 21.1.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(babel-plugin-macros@3.1.0)(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
+ '@nx/js': 21.1.2(@babel/traverse@7.25.9)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(verdaccio@6.1.2(encoding@0.1.13)(typanion@3.14.0))
tslib: 2.8.1
transitivePeerDependencies:
- '@babel/traverse'
@@ -7780,13 +7623,13 @@ snapshots:
- typescript
- verdaccio
- '@nx/workspace@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))':
+ '@nx/workspace@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))':
dependencies:
- '@nx/devkit': 21.0.2(nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)))
+ '@nx/devkit': 21.1.2(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
'@zkochan/js-yaml': 0.0.7
chalk: 4.1.2
enquirer: 2.3.6
- nx: 21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17))
+ nx: 21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))
picomatch: 4.0.2
tslib: 2.8.1
yargs-parser: 21.1.1
@@ -7844,10 +7687,10 @@ snapshots:
'@pkgjs/parseargs@0.11.0':
optional: true
- '@schematics/angular@19.2.11':
+ '@schematics/angular@19.2.13':
dependencies:
- '@angular-devkit/core': 19.2.11
- '@angular-devkit/schematics': 19.2.11
+ '@angular-devkit/core': 19.2.13
+ '@angular-devkit/schematics': 19.2.13
jsonc-parser: 3.3.1
transitivePeerDependencies:
- chokidar
@@ -7898,16 +7741,16 @@ snapshots:
dependencies:
'@sinonjs/commons': 3.0.1
- '@swc-node/core@1.13.3(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)':
+ '@swc-node/core@1.13.3(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)':
dependencies:
- '@swc/core': 1.11.24(@swc/helpers@0.5.17)
+ '@swc/core': 1.11.29(@swc/helpers@0.5.17)
'@swc/types': 0.1.21
- '@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3)':
+ '@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3)':
dependencies:
- '@swc-node/core': 1.13.3(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)
+ '@swc-node/core': 1.13.3(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)
'@swc-node/sourcemap-support': 0.5.1
- '@swc/core': 1.11.24(@swc/helpers@0.5.17)
+ '@swc/core': 1.11.29(@swc/helpers@0.5.17)
colorette: 2.0.20
debug: 4.4.0
oxc-resolver: 5.2.0
@@ -7923,64 +7766,64 @@ snapshots:
source-map-support: 0.5.21
tslib: 2.8.1
- '@swc/cli@0.7.5(@swc/core@1.11.24(@swc/helpers@0.5.17))':
+ '@swc/cli@0.7.7(@swc/core@1.11.29(@swc/helpers@0.5.17))':
dependencies:
- '@swc/core': 1.11.24(@swc/helpers@0.5.17)
+ '@swc/core': 1.11.29(@swc/helpers@0.5.17)
'@swc/counter': 0.1.3
'@xhmikosr/bin-wrapper': 13.0.5
commander: 8.3.0
fast-glob: 3.3.3
minimatch: 9.0.5
piscina: 4.7.0
- semver: 7.7.1
+ semver: 7.7.2
slash: 3.0.0
source-map: 0.7.4
- '@swc/core-darwin-arm64@1.11.24':
+ '@swc/core-darwin-arm64@1.11.29':
optional: true
- '@swc/core-darwin-x64@1.11.24':
+ '@swc/core-darwin-x64@1.11.29':
optional: true
- '@swc/core-linux-arm-gnueabihf@1.11.24':
+ '@swc/core-linux-arm-gnueabihf@1.11.29':
optional: true
- '@swc/core-linux-arm64-gnu@1.11.24':
+ '@swc/core-linux-arm64-gnu@1.11.29':
optional: true
- '@swc/core-linux-arm64-musl@1.11.24':
+ '@swc/core-linux-arm64-musl@1.11.29':
optional: true
- '@swc/core-linux-x64-gnu@1.11.24':
+ '@swc/core-linux-x64-gnu@1.11.29':
optional: true
- '@swc/core-linux-x64-musl@1.11.24':
+ '@swc/core-linux-x64-musl@1.11.29':
optional: true
- '@swc/core-win32-arm64-msvc@1.11.24':
+ '@swc/core-win32-arm64-msvc@1.11.29':
optional: true
- '@swc/core-win32-ia32-msvc@1.11.24':
+ '@swc/core-win32-ia32-msvc@1.11.29':
optional: true
- '@swc/core-win32-x64-msvc@1.11.24':
+ '@swc/core-win32-x64-msvc@1.11.29':
optional: true
- '@swc/core@1.11.24(@swc/helpers@0.5.17)':
+ '@swc/core@1.11.29(@swc/helpers@0.5.17)':
dependencies:
'@swc/counter': 0.1.3
'@swc/types': 0.1.21
optionalDependencies:
- '@swc/core-darwin-arm64': 1.11.24
- '@swc/core-darwin-x64': 1.11.24
- '@swc/core-linux-arm-gnueabihf': 1.11.24
- '@swc/core-linux-arm64-gnu': 1.11.24
- '@swc/core-linux-arm64-musl': 1.11.24
- '@swc/core-linux-x64-gnu': 1.11.24
- '@swc/core-linux-x64-musl': 1.11.24
- '@swc/core-win32-arm64-msvc': 1.11.24
- '@swc/core-win32-ia32-msvc': 1.11.24
- '@swc/core-win32-x64-msvc': 1.11.24
+ '@swc/core-darwin-arm64': 1.11.29
+ '@swc/core-darwin-x64': 1.11.29
+ '@swc/core-linux-arm-gnueabihf': 1.11.29
+ '@swc/core-linux-arm64-gnu': 1.11.29
+ '@swc/core-linux-arm64-musl': 1.11.29
+ '@swc/core-linux-x64-gnu': 1.11.29
+ '@swc/core-linux-x64-musl': 1.11.29
+ '@swc/core-win32-arm64-msvc': 1.11.29
+ '@swc/core-win32-ia32-msvc': 1.11.29
+ '@swc/core-win32-x64-msvc': 1.11.29
'@swc/helpers': 0.5.17
'@swc/counter@0.1.3': {}
@@ -8047,9 +7890,9 @@ snapshots:
'@types/conventional-commits-parser@5.0.1':
dependencies:
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
- '@types/eslint-scope@3.7.7':
+ '@types/eslint-scope@8.3.0':
dependencies:
'@types/eslint': 9.6.1
'@types/estree': 1.0.6
@@ -8063,7 +7906,7 @@ snapshots:
'@types/graceful-fs@4.1.9':
dependencies:
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
'@types/http-cache-semantics@4.0.4': {}
@@ -8086,7 +7929,7 @@ snapshots:
'@types/lodash@4.17.13': {}
- '@types/node@20.17.45':
+ '@types/node@20.17.50':
dependencies:
undici-types: 6.19.8
@@ -8102,127 +7945,95 @@ snapshots:
dependencies:
'@types/yargs-parser': 21.0.3
- '@typescript-eslint/eslint-plugin@8.32.0(@typescript-eslint/parser@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)':
+ '@typescript-eslint/eslint-plugin@8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
'@eslint-community/regexpp': 4.12.1
- '@typescript-eslint/parser': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
- '@typescript-eslint/scope-manager': 8.32.0
- '@typescript-eslint/type-utils': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
- '@typescript-eslint/utils': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
- '@typescript-eslint/visitor-keys': 8.32.0
- eslint: 9.26.0(jiti@2.4.2)
+ '@typescript-eslint/parser': 8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
+ '@typescript-eslint/scope-manager': 8.32.1
+ '@typescript-eslint/type-utils': 8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
+ '@typescript-eslint/utils': 8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
+ '@typescript-eslint/visitor-keys': 8.32.1
+ eslint: 9.27.0(jiti@2.4.2)
graphemer: 1.4.0
- ignore: 5.3.2
+ ignore: 7.0.4
natural-compare: 1.4.0
ts-api-utils: 2.1.0(typescript@5.8.3)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)':
+ '@typescript-eslint/parser@8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
- '@typescript-eslint/scope-manager': 8.32.0
- '@typescript-eslint/types': 8.32.0
- '@typescript-eslint/typescript-estree': 8.32.0(typescript@5.8.3)
- '@typescript-eslint/visitor-keys': 8.32.0
+ '@typescript-eslint/scope-manager': 8.32.1
+ '@typescript-eslint/types': 8.32.1
+ '@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3)
+ '@typescript-eslint/visitor-keys': 8.32.1
debug: 4.4.0
- eslint: 9.26.0(jiti@2.4.2)
+ eslint: 9.27.0(jiti@2.4.2)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/rule-tester@8.32.0(patch_hash=0395d56159bca55b94596b2ce1a79005dd964f4b648c29e0c04c6dfcb85e13cf)(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)':
+ '@typescript-eslint/rule-tester@8.32.1(patch_hash=0395d56159bca55b94596b2ce1a79005dd964f4b648c29e0c04c6dfcb85e13cf)(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
- '@typescript-eslint/parser': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
- '@typescript-eslint/typescript-estree': 8.32.0(typescript@5.8.3)
- '@typescript-eslint/utils': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
+ '@typescript-eslint/parser': 8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
+ '@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3)
+ '@typescript-eslint/utils': 8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
ajv: 6.12.6
- eslint: 9.26.0(jiti@2.4.2)
+ eslint: 9.27.0(jiti@2.4.2)
json-stable-stringify-without-jsonify: 1.0.1
lodash.merge: 4.6.2
- semver: 7.7.1
+ semver: 7.7.2
transitivePeerDependencies:
- supports-color
- typescript
- '@typescript-eslint/scope-manager@8.32.0':
+ '@typescript-eslint/scope-manager@8.32.1':
dependencies:
- '@typescript-eslint/types': 8.32.0
- '@typescript-eslint/visitor-keys': 8.32.0
+ '@typescript-eslint/types': 8.32.1
+ '@typescript-eslint/visitor-keys': 8.32.1
- '@typescript-eslint/type-utils@8.31.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)':
+ '@typescript-eslint/type-utils@8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
- '@typescript-eslint/typescript-estree': 8.31.0(typescript@5.8.3)
- '@typescript-eslint/utils': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
+ '@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3)
+ '@typescript-eslint/utils': 8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
debug: 4.4.0
- eslint: 9.26.0(jiti@2.4.2)
+ eslint: 9.27.0(jiti@2.4.2)
ts-api-utils: 2.1.0(typescript@5.8.3)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/type-utils@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)':
- dependencies:
- '@typescript-eslint/typescript-estree': 8.32.0(typescript@5.8.3)
- '@typescript-eslint/utils': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
- debug: 4.4.0
- eslint: 9.26.0(jiti@2.4.2)
- ts-api-utils: 2.1.0(typescript@5.8.3)
- typescript: 5.8.3
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/types@8.31.0': {}
+ '@typescript-eslint/types@8.32.1': {}
- '@typescript-eslint/types@8.32.0': {}
-
- '@typescript-eslint/typescript-estree@8.31.0(typescript@5.8.3)':
+ '@typescript-eslint/typescript-estree@8.32.1(typescript@5.8.3)':
dependencies:
- '@typescript-eslint/types': 8.31.0
- '@typescript-eslint/visitor-keys': 8.31.0
+ '@typescript-eslint/types': 8.32.1
+ '@typescript-eslint/visitor-keys': 8.32.1
debug: 4.4.0
fast-glob: 3.3.3
is-glob: 4.0.3
minimatch: 9.0.5
- semver: 7.7.1
+ semver: 7.7.2
ts-api-utils: 2.1.0(typescript@5.8.3)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/typescript-estree@8.32.0(typescript@5.8.3)':
+ '@typescript-eslint/utils@8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
- '@typescript-eslint/types': 8.32.0
- '@typescript-eslint/visitor-keys': 8.32.0
- debug: 4.4.0
- fast-glob: 3.3.3
- is-glob: 4.0.3
- minimatch: 9.0.5
- semver: 7.7.1
- ts-api-utils: 2.1.0(typescript@5.8.3)
+ '@eslint-community/eslint-utils': 4.7.0(eslint@9.27.0(jiti@2.4.2))
+ '@typescript-eslint/scope-manager': 8.32.1
+ '@typescript-eslint/types': 8.32.1
+ '@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3)
+ eslint: 9.27.0(jiti@2.4.2)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)':
+ '@typescript-eslint/visitor-keys@8.32.1':
dependencies:
- '@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0(jiti@2.4.2))
- '@typescript-eslint/scope-manager': 8.32.0
- '@typescript-eslint/types': 8.32.0
- '@typescript-eslint/typescript-estree': 8.32.0(typescript@5.8.3)
- eslint: 9.26.0(jiti@2.4.2)
- typescript: 5.8.3
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/visitor-keys@8.31.0':
- dependencies:
- '@typescript-eslint/types': 8.31.0
- eslint-visitor-keys: 4.2.0
-
- '@typescript-eslint/visitor-keys@8.32.0':
- dependencies:
- '@typescript-eslint/types': 8.32.0
+ '@typescript-eslint/types': 8.32.1
eslint-visitor-keys: 4.2.0
'@verdaccio/auth@8.0.0-next-8.15':
@@ -8467,11 +8278,6 @@ snapshots:
mime-types: 2.1.35
negotiator: 0.6.3
- accepts@2.0.0:
- dependencies:
- mime-types: 3.0.1
- negotiator: 1.0.0
-
acorn-jsx@5.3.2(acorn@8.14.0):
dependencies:
acorn: 8.14.0
@@ -8722,7 +8528,7 @@ snapshots:
bin-version-check@5.1.0:
dependencies:
bin-version: 6.0.0
- semver: 7.7.1
+ semver: 7.7.2
semver-truncate: 3.0.0
bin-version@6.0.0:
@@ -8753,20 +8559,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- body-parser@2.2.0:
- dependencies:
- bytes: 3.1.2
- content-type: 1.0.5
- debug: 4.4.0
- http-errors: 2.0.0
- iconv-lite: 0.6.3
- on-finished: 2.4.1
- qs: 6.14.0
- raw-body: 3.0.0
- type-is: 2.0.1
- transitivePeerDependencies:
- - supports-color
-
brace-expansion@1.1.11:
dependencies:
balanced-match: 1.0.2
@@ -8982,10 +8774,10 @@ snapshots:
commander@8.3.0: {}
- commitizen@4.3.1(@types/node@20.17.45)(typescript@5.8.3):
+ commitizen@4.3.1(@types/node@20.17.50)(typescript@5.8.3):
dependencies:
cachedir: 2.3.0
- cz-conventional-changelog: 3.3.0(@types/node@20.17.45)(typescript@5.8.3)
+ cz-conventional-changelog: 3.3.0(@types/node@20.17.50)(typescript@5.8.3)
dedent: 0.7.0
detect-indent: 6.1.0
find-node-modules: 2.1.3
@@ -9031,10 +8823,6 @@ snapshots:
dependencies:
safe-buffer: 5.2.1
- content-disposition@1.0.0:
- dependencies:
- safe-buffer: 5.2.1
-
content-type@1.0.5: {}
conventional-changelog-angular@7.0.0:
@@ -9058,8 +8846,6 @@ snapshots:
cookie-signature@1.0.6: {}
- cookie-signature@1.2.2: {}
-
cookie@0.7.1: {}
core-js-compat@3.39.0:
@@ -9077,17 +8863,17 @@ snapshots:
object-assign: 4.1.1
vary: 1.1.2
- cosmiconfig-typescript-loader@5.1.0(@types/node@20.17.45)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3):
+ cosmiconfig-typescript-loader@5.1.0(@types/node@20.17.50)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3):
dependencies:
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
cosmiconfig: 9.0.0(typescript@5.8.3)
jiti: 1.21.6
typescript: 5.8.3
optional: true
- cosmiconfig-typescript-loader@6.1.0(@types/node@20.17.45)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3):
+ cosmiconfig-typescript-loader@6.1.0(@types/node@20.17.50)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3):
dependencies:
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
cosmiconfig: 9.0.0(typescript@5.8.3)
jiti: 2.4.2
typescript: 5.8.3
@@ -9109,13 +8895,13 @@ snapshots:
optionalDependencies:
typescript: 5.8.3
- create-jest@29.7.0(@types/node@20.17.45)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3)):
+ create-jest@29.7.0(@types/node@20.17.50)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3)):
dependencies:
'@jest/types': 29.6.3
chalk: 4.1.2
exit: 0.1.2
graceful-fs: 4.2.11
- jest-config: 29.7.0(@types/node@20.17.45)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3))
+ jest-config: 29.7.0(@types/node@20.17.50)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3))
jest-util: 29.7.0
prompts: 2.4.2
transitivePeerDependencies:
@@ -9133,16 +8919,16 @@ snapshots:
shebang-command: 2.0.0
which: 2.0.2
- cz-conventional-changelog@3.3.0(@types/node@20.17.45)(typescript@5.8.3):
+ cz-conventional-changelog@3.3.0(@types/node@20.17.50)(typescript@5.8.3):
dependencies:
chalk: 2.4.2
- commitizen: 4.3.1(@types/node@20.17.45)(typescript@5.8.3)
+ commitizen: 4.3.1(@types/node@20.17.50)(typescript@5.8.3)
conventional-commit-types: 3.0.0
lodash.map: 4.6.0
longest: 2.0.1
word-wrap: 1.2.5
optionalDependencies:
- '@commitlint/load': 19.5.0(@types/node@20.17.45)(typescript@5.8.3)
+ '@commitlint/load': 19.5.0(@types/node@20.17.50)(typescript@5.8.3)
transitivePeerDependencies:
- '@types/node'
- typescript
@@ -9350,9 +9136,9 @@ snapshots:
escape-string-regexp@4.0.0: {}
- eslint-config-prettier@10.1.3(eslint@9.26.0(jiti@2.4.2)):
+ eslint-config-prettier@10.1.5(eslint@9.27.0(jiti@2.4.2)):
dependencies:
- eslint: 9.26.0(jiti@2.4.2)
+ eslint: 9.27.0(jiti@2.4.2)
eslint-scope@8.3.0:
dependencies:
@@ -9363,20 +9149,19 @@ snapshots:
eslint-visitor-keys@4.2.0: {}
- eslint@9.26.0(jiti@2.4.2):
+ eslint@9.27.0(jiti@2.4.2):
dependencies:
- '@eslint-community/eslint-utils': 4.4.1(eslint@9.26.0(jiti@2.4.2))
+ '@eslint-community/eslint-utils': 4.4.1(eslint@9.27.0(jiti@2.4.2))
'@eslint-community/regexpp': 4.12.1
'@eslint/config-array': 0.20.0
'@eslint/config-helpers': 0.2.1
- '@eslint/core': 0.13.0
+ '@eslint/core': 0.14.0
'@eslint/eslintrc': 3.3.1
- '@eslint/js': 9.26.0
- '@eslint/plugin-kit': 0.2.8
+ '@eslint/js': 9.27.0
+ '@eslint/plugin-kit': 0.3.1
'@humanfs/node': 0.16.6
'@humanwhocodes/module-importer': 1.0.1
'@humanwhocodes/retry': 0.4.2
- '@modelcontextprotocol/sdk': 1.11.0
'@types/estree': 1.0.6
'@types/json-schema': 7.0.15
ajv: 6.12.6
@@ -9401,7 +9186,6 @@ snapshots:
minimatch: 3.1.2
natural-compare: 1.4.0
optionator: 0.9.4
- zod: 3.24.4
optionalDependencies:
jiti: 2.4.2
transitivePeerDependencies:
@@ -9441,12 +9225,6 @@ snapshots:
events@3.3.0: {}
- eventsource-parser@3.0.1: {}
-
- eventsource@3.0.6:
- dependencies:
- eventsource-parser: 3.0.1
-
execa@5.1.1:
dependencies:
cross-spawn: 7.0.6
@@ -9459,18 +9237,6 @@ snapshots:
signal-exit: 3.0.7
strip-final-newline: 2.0.0
- execa@8.0.1:
- dependencies:
- cross-spawn: 7.0.6
- get-stream: 8.0.1
- human-signals: 5.0.0
- is-stream: 3.0.0
- merge-stream: 2.0.0
- npm-run-path: 5.3.0
- onetime: 6.0.0
- signal-exit: 4.1.0
- strip-final-newline: 3.0.0
-
exit@0.1.2: {}
expand-tilde@2.0.2:
@@ -9489,10 +9255,6 @@ snapshots:
express-rate-limit@5.5.1: {}
- express-rate-limit@7.5.0(express@5.1.0):
- dependencies:
- express: 5.1.0
-
express@4.21.2:
dependencies:
accepts: 1.3.8
@@ -9529,41 +9291,9 @@ snapshots:
transitivePeerDependencies:
- supports-color
- express@5.1.0:
- dependencies:
- accepts: 2.0.0
- body-parser: 2.2.0
- content-disposition: 1.0.0
- content-type: 1.0.5
- cookie: 0.7.1
- cookie-signature: 1.2.2
- debug: 4.4.0
- encodeurl: 2.0.0
- escape-html: 1.0.3
- etag: 1.8.1
- finalhandler: 2.1.0
- fresh: 2.0.0
- http-errors: 2.0.0
- merge-descriptors: 2.0.0
- mime-types: 3.0.1
- on-finished: 2.4.1
- once: 1.4.0
- parseurl: 1.3.3
- proxy-addr: 2.0.7
- qs: 6.14.0
- range-parser: 1.2.1
- router: 2.2.0
- send: 1.2.0
- serve-static: 2.2.0
- statuses: 2.0.1
- type-is: 2.0.1
- vary: 1.1.2
- transitivePeerDependencies:
- - supports-color
-
ext-list@2.2.2:
dependencies:
- mime-db: 1.53.0
+ mime-db: 1.54.0
ext-name@5.0.0:
dependencies:
@@ -9657,17 +9387,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- finalhandler@2.1.0:
- dependencies:
- debug: 4.4.0
- encodeurl: 2.0.0
- escape-html: 1.0.3
- on-finished: 2.4.1
- parseurl: 1.3.3
- statuses: 2.0.1
- transitivePeerDependencies:
- - supports-color
-
find-node-modules@2.1.3:
dependencies:
findup-sync: 4.0.0
@@ -9732,8 +9451,6 @@ snapshots:
fresh@0.5.2: {}
- fresh@2.0.0: {}
-
front-matter@4.0.2:
dependencies:
js-yaml: 3.14.1
@@ -9798,8 +9515,6 @@ snapshots:
get-stream@6.0.1: {}
- get-stream@8.0.1: {}
-
get-stream@9.0.1:
dependencies:
'@sec-ant/readable-stream': 0.4.1
@@ -9993,8 +9708,6 @@ snapshots:
human-signals@2.1.0: {}
- human-signals@5.0.0: {}
-
husky@9.1.7: {}
iconv-lite@0.4.24:
@@ -10004,6 +9717,7 @@ snapshots:
iconv-lite@0.6.3:
dependencies:
safer-buffer: 2.1.2
+ optional: true
identity-obj-proxy@3.0.0:
dependencies:
@@ -10117,12 +9831,8 @@ snapshots:
is-promise@2.2.2: {}
- is-promise@4.0.0: {}
-
is-stream@2.0.1: {}
- is-stream@3.0.0: {}
-
is-stream@4.0.1: {}
is-text-path@2.0.0:
@@ -10167,7 +9877,7 @@ snapshots:
'@babel/parser': 7.26.2
'@istanbuljs/schema': 0.1.3
istanbul-lib-coverage: 3.2.2
- semver: 7.7.1
+ semver: 7.7.2
transitivePeerDependencies:
- supports-color
@@ -10215,7 +9925,7 @@ snapshots:
'@jest/expect': 29.7.0
'@jest/test-result': 29.7.0
'@jest/types': 29.6.3
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
chalk: 4.1.2
co: 4.6.0
dedent: 1.5.3(babel-plugin-macros@3.1.0)
@@ -10235,16 +9945,16 @@ snapshots:
- babel-plugin-macros
- supports-color
- jest-cli@29.7.0(@types/node@20.17.45)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3)):
+ jest-cli@29.7.0(@types/node@20.17.50)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3)):
dependencies:
- '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3))
+ '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3))
'@jest/test-result': 29.7.0
'@jest/types': 29.6.3
chalk: 4.1.2
- create-jest: 29.7.0(@types/node@20.17.45)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3))
+ create-jest: 29.7.0(@types/node@20.17.50)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3))
exit: 0.1.2
import-local: 3.2.0
- jest-config: 29.7.0(@types/node@20.17.45)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3))
+ jest-config: 29.7.0(@types/node@20.17.50)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3))
jest-util: 29.7.0
jest-validate: 29.7.0
yargs: 17.7.2
@@ -10254,7 +9964,7 @@ snapshots:
- supports-color
- ts-node
- jest-config@29.7.0(@types/node@20.17.45)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3)):
+ jest-config@29.7.0(@types/node@20.17.50)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3)):
dependencies:
'@babel/core': 7.26.0
'@jest/test-sequencer': 29.7.0
@@ -10279,8 +9989,8 @@ snapshots:
slash: 3.0.0
strip-json-comments: 3.1.1
optionalDependencies:
- '@types/node': 20.17.45
- ts-node: 10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3)
+ '@types/node': 20.17.50
+ ts-node: 10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3)
transitivePeerDependencies:
- babel-plugin-macros
- supports-color
@@ -10309,7 +10019,7 @@ snapshots:
'@jest/environment': 29.7.0
'@jest/fake-timers': 29.7.0
'@jest/types': 29.6.3
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
jest-mock: 29.7.0
jest-util: 29.7.0
@@ -10319,7 +10029,7 @@ snapshots:
dependencies:
'@jest/types': 29.6.3
'@types/graceful-fs': 4.1.9
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
anymatch: 3.1.3
fb-watchman: 2.0.2
graceful-fs: 4.2.11
@@ -10358,7 +10068,7 @@ snapshots:
jest-mock@29.7.0:
dependencies:
'@jest/types': 29.6.3
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
jest-util: 29.7.0
jest-pnp-resolver@1.2.3(jest-resolve@29.7.0):
@@ -10393,7 +10103,7 @@ snapshots:
'@jest/test-result': 29.7.0
'@jest/transform': 29.7.0
'@jest/types': 29.6.3
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
chalk: 4.1.2
emittery: 0.13.1
graceful-fs: 4.2.11
@@ -10421,7 +10131,7 @@ snapshots:
'@jest/test-result': 29.7.0
'@jest/transform': 29.7.0
'@jest/types': 29.6.3
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
chalk: 4.1.2
cjs-module-lexer: 1.4.1
collect-v8-coverage: 1.0.2
@@ -10460,14 +10170,14 @@ snapshots:
jest-util: 29.7.0
natural-compare: 1.4.0
pretty-format: 29.7.0
- semver: 7.7.1
+ semver: 7.7.2
transitivePeerDependencies:
- supports-color
jest-util@29.7.0:
dependencies:
'@jest/types': 29.6.3
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
chalk: 4.1.2
ci-info: 3.9.0
graceful-fs: 4.2.11
@@ -10486,7 +10196,7 @@ snapshots:
dependencies:
'@jest/test-result': 29.7.0
'@jest/types': 29.6.3
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
ansi-escapes: 4.3.2
chalk: 4.1.2
emittery: 0.13.1
@@ -10495,17 +10205,17 @@ snapshots:
jest-worker@29.7.0:
dependencies:
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
jest-util: 29.7.0
merge-stream: 2.0.0
supports-color: 8.1.1
- jest@29.7.0(@types/node@20.17.45)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3)):
+ jest@29.7.0(@types/node@20.17.50)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3)):
dependencies:
- '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3))
+ '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3))
'@jest/types': 29.6.3
import-local: 3.2.0
- jest-cli: 29.7.0(@types/node@20.17.45)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3))
+ jest-cli: 29.7.0(@types/node@20.17.50)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3))
transitivePeerDependencies:
- '@types/node'
- babel-plugin-macros
@@ -10569,7 +10279,7 @@ snapshots:
acorn: 8.14.0
eslint-visitor-keys: 3.4.3
espree: 9.6.1
- semver: 7.7.1
+ semver: 7.7.2
jsonc-parser@3.2.0: {}
@@ -10594,7 +10304,7 @@ snapshots:
lodash.isstring: 4.0.1
lodash.once: 4.1.1
ms: 2.1.3
- semver: 7.7.1
+ semver: 7.7.2
jsprim@2.0.2:
dependencies:
@@ -10635,18 +10345,18 @@ snapshots:
lines-and-columns@2.0.3: {}
- lint-staged@15.5.2:
+ lint-staged@16.0.0:
dependencies:
chalk: 5.4.1
commander: 13.1.0
debug: 4.4.0
- execa: 8.0.1
lilconfig: 3.1.3
- listr2: 8.2.5
+ listr2: 8.3.3
micromatch: 4.0.8
+ nano-spawn: 1.0.1
pidtree: 0.6.0
string-argv: 0.3.2
- yaml: 2.7.0
+ yaml: 2.7.1
transitivePeerDependencies:
- supports-color
@@ -10659,6 +10369,15 @@ snapshots:
rfdc: 1.4.1
wrap-ansi: 9.0.0
+ listr2@8.3.3:
+ dependencies:
+ cli-truncate: 4.0.0
+ colorette: 2.0.20
+ eventemitter3: 5.0.1
+ log-update: 6.1.0
+ rfdc: 1.4.1
+ wrap-ansi: 9.0.0
+
locate-path@5.0.0:
dependencies:
p-locate: 4.1.0
@@ -10752,7 +10471,7 @@ snapshots:
make-dir@4.0.0:
dependencies:
- semver: 7.7.1
+ semver: 7.7.2
make-error@1.3.6: {}
@@ -10797,14 +10516,10 @@ snapshots:
media-typer@0.3.0: {}
- media-typer@1.1.0: {}
-
meow@12.1.1: {}
merge-descriptors@1.0.3: {}
- merge-descriptors@2.0.0: {}
-
merge-stream@2.0.0: {}
merge2@1.4.1: {}
@@ -10828,10 +10543,6 @@ snapshots:
dependencies:
mime-db: 1.52.0
- mime-types@3.0.1:
- dependencies:
- mime-db: 1.54.0
-
mime@1.6.0: {}
mime@2.6.0: {}
@@ -10840,8 +10551,6 @@ snapshots:
mimic-fn@2.1.0: {}
- mimic-fn@4.0.0: {}
-
mimic-function@5.0.1: {}
mimic-response@3.1.0: {}
@@ -10938,6 +10647,8 @@ snapshots:
mute-stream@2.0.0: {}
+ nano-spawn@1.0.1: {}
+
natural-compare@1.4.0: {}
ncp@2.0.0: {}
@@ -10965,7 +10676,7 @@ snapshots:
make-fetch-happen: 13.0.1
nopt: 7.2.1
proc-log: 4.2.0
- semver: 7.7.1
+ semver: 7.7.2
tar: 6.2.1
which: 4.0.0
transitivePeerDependencies:
@@ -10984,7 +10695,7 @@ snapshots:
normalize-package-data@7.0.0:
dependencies:
hosted-git-info: 8.0.2
- semver: 7.7.1
+ semver: 7.7.2
validate-npm-package-license: 3.0.4
normalize-path@3.0.0: {}
@@ -10997,7 +10708,7 @@ snapshots:
npm-install-checks@7.1.1:
dependencies:
- semver: 7.7.1
+ semver: 7.7.2
npm-normalize-package-bin@4.0.0: {}
@@ -11005,14 +10716,14 @@ snapshots:
dependencies:
hosted-git-info: 7.0.2
proc-log: 3.0.0
- semver: 7.7.1
+ semver: 7.7.2
validate-npm-package-name: 5.0.1
npm-package-arg@12.0.2:
dependencies:
hosted-git-info: 8.0.2
proc-log: 5.0.0
- semver: 7.7.1
+ semver: 7.7.2
validate-npm-package-name: 6.0.0
npm-packlist@9.0.0:
@@ -11024,7 +10735,7 @@ snapshots:
npm-install-checks: 7.1.1
npm-normalize-package-bin: 4.0.0
npm-package-arg: 12.0.2
- semver: 7.7.1
+ semver: 7.7.2
npm-registry-fetch@18.0.2:
dependencies:
@@ -11043,11 +10754,7 @@ snapshots:
dependencies:
path-key: 3.1.1
- npm-run-path@5.3.0:
- dependencies:
- path-key: 4.0.0
-
- nx@21.0.2(@swc-node/register@1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.24(@swc/helpers@0.5.17)):
+ nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)):
dependencies:
'@napi-rs/wasm-runtime': 0.2.4
'@yarnpkg/lockfile': 1.1.0
@@ -11074,29 +10781,29 @@ snapshots:
open: 8.4.2
ora: 5.3.0
resolve.exports: 2.0.3
- semver: 7.7.1
+ semver: 7.7.2
string-width: 4.2.3
tar-stream: 2.2.0
tmp: 0.2.3
tree-kill: 1.2.2
tsconfig-paths: 4.2.0
tslib: 2.8.1
- yaml: 2.7.0
+ yaml: 2.7.1
yargs: 17.7.2
yargs-parser: 21.1.1
optionalDependencies:
- '@nx/nx-darwin-arm64': 21.0.2
- '@nx/nx-darwin-x64': 21.0.2
- '@nx/nx-freebsd-x64': 21.0.2
- '@nx/nx-linux-arm-gnueabihf': 21.0.2
- '@nx/nx-linux-arm64-gnu': 21.0.2
- '@nx/nx-linux-arm64-musl': 21.0.2
- '@nx/nx-linux-x64-gnu': 21.0.2
- '@nx/nx-linux-x64-musl': 21.0.2
- '@nx/nx-win32-arm64-msvc': 21.0.2
- '@nx/nx-win32-x64-msvc': 21.0.2
- '@swc-node/register': 1.10.10(@swc/core@1.11.24(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3)
- '@swc/core': 1.11.24(@swc/helpers@0.5.17)
+ '@nx/nx-darwin-arm64': 21.1.2
+ '@nx/nx-darwin-x64': 21.1.2
+ '@nx/nx-freebsd-x64': 21.1.2
+ '@nx/nx-linux-arm-gnueabihf': 21.1.2
+ '@nx/nx-linux-arm64-gnu': 21.1.2
+ '@nx/nx-linux-arm64-musl': 21.1.2
+ '@nx/nx-linux-x64-gnu': 21.1.2
+ '@nx/nx-linux-x64-musl': 21.1.2
+ '@nx/nx-win32-arm64-msvc': 21.1.2
+ '@nx/nx-win32-x64-msvc': 21.1.2
+ '@swc-node/register': 1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3)
+ '@swc/core': 1.11.29(@swc/helpers@0.5.17)
transitivePeerDependencies:
- debug
@@ -11120,10 +10827,6 @@ snapshots:
dependencies:
mimic-fn: 2.1.0
- onetime@6.0.0:
- dependencies:
- mimic-fn: 4.0.0
-
onetime@7.0.0:
dependencies:
mimic-function: 5.0.1
@@ -11268,8 +10971,6 @@ snapshots:
path-key@3.1.1: {}
- path-key@4.0.0: {}
-
path-parse@1.0.7: {}
path-scurry@1.11.1:
@@ -11279,8 +10980,6 @@ snapshots:
path-to-regexp@0.1.12: {}
- path-to-regexp@8.2.0: {}
-
path-type@4.0.0: {}
peek-readable@5.3.1: {}
@@ -11336,8 +11035,6 @@ snapshots:
optionalDependencies:
'@napi-rs/nice': 1.0.1
- pkce-challenge@5.0.0: {}
-
pkg-dir@4.2.0:
dependencies:
find-up: 4.1.0
@@ -11429,13 +11126,6 @@ snapshots:
iconv-lite: 0.4.24
unpipe: 1.0.0
- raw-body@3.0.0:
- dependencies:
- bytes: 3.1.2
- http-errors: 2.0.0
- iconv-lite: 0.6.3
- unpipe: 1.0.0
-
react-is@18.3.1: {}
readable-stream@2.3.8:
@@ -11544,16 +11234,6 @@ snapshots:
dependencies:
glob: 10.4.5
- router@2.2.0:
- dependencies:
- debug: 4.4.0
- depd: 2.0.0
- is-promise: 4.0.0
- parseurl: 1.3.3
- path-to-regexp: 8.2.0
- transitivePeerDependencies:
- - supports-color
-
run-async@2.4.1: {}
run-parallel@1.2.0:
@@ -11580,7 +11260,7 @@ snapshots:
semver-truncate@3.0.0:
dependencies:
- semver: 7.7.1
+ semver: 7.7.2
semver@6.3.1: {}
@@ -11588,6 +11268,8 @@ snapshots:
semver@7.7.1: {}
+ semver@7.7.2: {}
+
send@0.19.0:
dependencies:
debug: 2.6.9
@@ -11606,22 +11288,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- send@1.2.0:
- dependencies:
- debug: 4.4.0
- encodeurl: 2.0.0
- escape-html: 1.0.3
- etag: 1.8.1
- fresh: 2.0.0
- http-errors: 2.0.0
- mime-types: 3.0.1
- ms: 2.1.3
- on-finished: 2.4.1
- range-parser: 1.2.1
- statuses: 2.0.1
- transitivePeerDependencies:
- - supports-color
-
serve-static@1.16.2:
dependencies:
encodeurl: 2.0.0
@@ -11631,15 +11297,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- serve-static@2.2.0:
- dependencies:
- encodeurl: 2.0.0
- escape-html: 1.0.3
- parseurl: 1.3.3
- send: 1.2.0
- transitivePeerDependencies:
- - supports-color
-
set-function-length@1.2.2:
dependencies:
define-data-property: 1.1.4
@@ -11883,8 +11540,6 @@ snapshots:
strip-final-newline@2.0.0: {}
- strip-final-newline@3.0.0: {}
-
strip-json-comments@3.1.1: {}
strtok3@9.1.1:
@@ -12010,17 +11665,17 @@ snapshots:
dependencies:
typescript: 5.8.3
- ts-jest@29.2.4(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(esbuild@0.25.4)(jest@29.7.0(@types/node@20.17.45)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3)))(typescript@5.8.3):
+ ts-jest@29.2.4(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(esbuild@0.25.4)(jest@29.7.0(@types/node@20.17.50)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3)))(typescript@5.8.3):
dependencies:
bs-logger: 0.2.6
ejs: 3.1.10
fast-json-stable-stringify: 2.1.0
- jest: 29.7.0(@types/node@20.17.45)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3))
+ jest: 29.7.0(@types/node@20.17.50)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3))
jest-util: 29.7.0
json5: 2.2.3
lodash.memoize: 4.1.2
make-error: 1.3.6
- semver: 7.7.1
+ semver: 7.7.2
typescript: 5.8.3
yargs-parser: 21.1.1
optionalDependencies:
@@ -12030,14 +11685,14 @@ snapshots:
babel-jest: 29.7.0(@babel/core@7.26.0)
esbuild: 0.25.4
- ts-node@10.9.1(@swc/core@1.11.24(@swc/helpers@0.5.17))(@types/node@20.17.45)(typescript@5.8.3):
+ ts-node@10.9.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@20.17.50)(typescript@5.8.3):
dependencies:
'@cspotcode/source-map-support': 0.8.1
'@tsconfig/node10': 1.0.11
'@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.4
- '@types/node': 20.17.45
+ '@types/node': 20.17.50
acorn: 8.14.1
acorn-walk: 8.3.4
arg: 4.1.3
@@ -12048,7 +11703,7 @@ snapshots:
v8-compile-cache-lib: 3.0.1
yn: 3.1.1
optionalDependencies:
- '@swc/core': 1.11.24(@swc/helpers@0.5.17)
+ '@swc/core': 1.11.29(@swc/helpers@0.5.17)
optional: true
tsconfig-paths@4.2.0:
@@ -12095,18 +11750,12 @@ snapshots:
media-typer: 0.3.0
mime-types: 2.1.35
- type-is@2.0.1:
- dependencies:
- content-type: 1.0.5
- media-typer: 1.1.0
- mime-types: 3.0.1
-
- typescript-eslint@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3):
+ typescript-eslint@8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3):
dependencies:
- '@typescript-eslint/eslint-plugin': 8.32.0(@typescript-eslint/parser@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
- '@typescript-eslint/parser': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
- '@typescript-eslint/utils': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
- eslint: 9.26.0(jiti@2.4.2)
+ '@typescript-eslint/eslint-plugin': 8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
+ '@typescript-eslint/parser': 8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
+ '@typescript-eslint/utils': 8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
+ eslint: 9.27.0(jiti@2.4.2)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
@@ -12347,7 +11996,7 @@ snapshots:
yaml@1.10.2: {}
- yaml@2.7.0: {}
+ yaml@2.7.1: {}
yargs-parser@21.1.1: {}
@@ -12374,9 +12023,3 @@ snapshots:
yocto-queue@1.1.1: {}
yoctocolors-cjs@2.1.2: {}
-
- zod-to-json-schema@3.24.5(zod@3.24.4):
- dependencies:
- zod: 3.24.4
-
- zod@3.24.4: {}