Skip to content

fix(linter): multi-version support compliance for @nx/eslint and @nx/eslint-plugin#35811

Merged
leosvelperez merged 12 commits into
masterfrom
nxc-4387
May 29, 2026
Merged

fix(linter): multi-version support compliance for @nx/eslint and @nx/eslint-plugin#35811
leosvelperez merged 12 commits into
masterfrom
nxc-4387

Conversation

@polygraph-snapshot-app

Copy link
Copy Markdown
Contributor

Current Behavior

@nx/eslint and @nx/eslint-plugin have several multi-version support compliance gaps:

  • The bare @nx/eslint:init generator path lands fresh installs on EOL ESLint v8 (~8.57.0) even though the flat-config path already ships v9.
  • Local re-implementations of installed-version helpers in version-utils.ts and per-major version aliases (eslint9__*) in versions.ts drift from the shared @nx/devkit/internal helpers.
  • Generators do not assert the supported ESLint floor at their entry points — sub-floor workspaces silently get configs incompatible with their installed ESLint.
  • addDependenciesToPackageJson call sites in generators do not preserve user-pinned ESLint dependency versions; init's schema defaults keepExistingVersions to false.
  • The @nx/eslint:lint executor enforces a stale 7.6 floor with a hand-rolled Number(version[0]) check rather than the shared canonical helper.
  • Two ESLint migration generators (update-typescript-eslint-v8.13.0, add-file-extensions-to-overrides) lack requires gates, so they run on every workspace even when their target packages are absent or at unrelated versions.
  • @nx/eslint-plugin declares @typescript-eslint/parser: ^6.13.2 || ^7.0.0 || ^8.0.0 as a required peer but ships @typescript-eslint/utils / @typescript-eslint/type-utils pinned to ^8.0.0 — the peer claim is wider than the bundled runtime range, and users only linting JavaScript see an unmet-peer warning.

Expected Behavior

@nx/eslint:

  • Fresh installs default to ESLint v9 via the canonical versions(tree) route. Installed versions are respected through the version map (v8 → ~8.57.0 lane; v9/v10 → latestVersions, with v10 silently falling through — no above-ceiling throw).
  • versions.ts follows the bundle pattern; version-utils.ts delegates to @nx/devkit/internal helpers.
  • Every generators.json entry asserts the supported floor (8.0.0) at its working function's first statement via the canonical assertSupportedEslintVersion(tree) wrapper. A parameterized all-generators-enforce-floor.spec.ts pins this so a future generator added without the assert fails the spec.
  • All generator-side addDependenciesToPackageJson calls preserve user-pinned versions: init's schema defaults keepExistingVersions to true, and programmatic callers default via ?? true.
  • The @nx/eslint:lint executor uses the shared assertSupportedInstalledPackageVersion helper to enforce the 8.0.0 floor with the canonical Unsupported version of \eslint` detected` message.
  • The two migration generators are gated on @typescript-eslint/parser >=8.0.0 and eslint >=8.57.0 respectively (open upper bound so nx migrate --from <older> still applies them).

@nx/eslint-plugin:

  • @typescript-eslint/parser peer is tightened to ^8.0.0 (matching the bundled @typescript-eslint/utils / type-utils v8 runtime) and declared optional via peerDependenciesMeta — users linting only JavaScript no longer see unmet-peer warnings.

Implementation Details

Important

This PR includes a cherry-picked commit (feat(devkit): add assertSupportedInstalledPackageVersion to @nx/devkit/internal) that originates from #35806. Whichever of the two PRs merges first, the other will be rebased to drop the duplicate commit.


View session information ↗

@netlify

netlify Bot commented May 27, 2026

Copy link
Copy Markdown

Deploy Preview for nx-dev ready!

Name Link
🔨 Latest commit 38b7f63
🔍 Latest deploy log https://app.netlify.com/projects/nx-dev/deploys/6a19bd0d7058180008854511
😎 Deploy Preview https://deploy-preview-35811--nx-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented May 27, 2026

Copy link
Copy Markdown

Deploy Preview for nx-docs ready!

Name Link
🔨 Latest commit 38b7f63
🔍 Latest deploy log https://app.netlify.com/projects/nx-docs/deploys/6a19bd0b12d45e0008cd0bd0
😎 Deploy Preview https://deploy-preview-35811--nx-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@nx-cloud

nx-cloud Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor

View your CI Pipeline Execution ↗ for commit 12c53d0

Command Status Duration Result
nx affected --targets=lint,test,build,e2e,e2e-c... ✅ Succeeded 12m 8s View ↗
nx run-many -t check-imports check-lock-files c... ✅ Succeeded 4s View ↗
nx-cloud record -- pnpm nx-cloud conformance:check ✅ Succeeded 15s View ↗
nx build workspace-plugin ✅ Succeeded <1s View ↗
nx-cloud record -- nx sync:check ✅ Succeeded 19s View ↗
nx-cloud record -- nx format:check ✅ Succeeded 7s View ↗

☁️ Nx Cloud last updated this comment at 2026-05-29 16:37:59 UTC

@leosvelperez leosvelperez self-assigned this May 27, 2026
@socket-security

socket-security Bot commented May 27, 2026

Copy link
Copy Markdown

No dependency changes detected. Learn more about Socket for GitHub.

👍 No dependency changes detected in pull request

nx-cloud[bot]

This comment was marked as outdated.

nx-cloud[bot]

This comment was marked as outdated.

nx-cloud[bot]

This comment was marked as outdated.

@leosvelperez leosvelperez marked this pull request as ready for review May 28, 2026 08:00
@leosvelperez leosvelperez requested a review from a team as a code owner May 28, 2026 08:00
@leosvelperez leosvelperez requested a review from MaxKless May 28, 2026 08:00
…fresh installs to v9

Restructure `packages/eslint/src/utils/versions.ts` into the canonical
versionMap bundle pattern: top-level `eslintVersion` and
`typescriptESLintVersion` hold the latest supported (^9.8.0 / ^8.40.0);
the v8 lane lives in `versionMap[8]`. Add `minSupportedEslintVersion`
and a 7-line `assert-supported-eslint-version.ts` wrapper around
`@nx/devkit/internal`'s `assertSupportedPackageVersion`. Move
`getInstalledEslintVersion` / `getInstalledEslintMajorVersion` here per
the cypress canonical pattern.

Drop the local re-implementation of `getInstalledPackageVersion` in
`version-utils.ts` in favor of `@nx/devkit/internal`'s shared
`getInstalledPackageVersion` / `getDeclaredPackageVersion` helpers,
which centralize dist-tag handling and pnpm catalog resolution.

Route every consumer through `versions(tree)`: `init`, `init-migration`,
`setup-root-eslint`, `convert-to-flat-config`, `workspace-rule`, and
the `update-typescript-eslint-v8-13-0` migration. The bare
`@nx/eslint:init` path now lands fresh installs on `^9.8.0` instead of
the previous `~8.57.0`, aligning with the flat-config path that already
shipped v9. Installed versions are respected via the version map; v10
falls through to `latestVersions` (no above-ceiling throw).

Replace `gte(eslintVersion, '9.0.0')` in `eslint-file.ts` with a
numeric major comparison (`getInstalledEslintMajorVersion(tree) ?? 9`).
The previous code would have crashed if the fallback path ever fired
(`gte('^9.8.0', ...)` throws on the range).

Switch the `addExtendsToLintConfig` specs from mocking
`readModulePackageJson` to declaring `eslint` in the tree's
`package.json`, matching the canonical generator-time read pattern.

Rename `@nx/eslint/internal`'s `eslint9__typescriptESLintVersion`
export to `typescriptESLintVersion`, and update the lone external
consumer in `@nx/angular`'s `add-angular-eslint-dependencies.ts`.
Call `assertSupportedEslintVersion(tree)` as the first statement of
every working function backing a `generators.json` entry — `initEsLint`,
`lintWorkspaceRulesProjectGenerator`, `lintWorkspaceRuleGenerator`,
`convertToFlatConfigGenerator`, and `convertToInferred`. Workspaces
declaring `eslint` below the supported floor (`8.0.0`) now fail fast
with the canonical `Unsupported version of` error before any tree
mutations, instead of silently writing configs incompatible with the
installed ESLint major.

The `lintInitGenerator` wrapper does not assert itself — it delegates
to `initEsLint`, which carries the assert (canonical
wrapper/internal-split pattern).
…enerators

Flip the default of `keepExistingVersions` to `true` on
`@nx/eslint:init`'s schema, and pass `true` (or
`keepExistingVersions ?? true` where the option is propagated from a
caller) to every generator-side `addDependenciesToPackageJson` call —
`setup-root-eslint` legacy and flat-config paths, the
`convert-to-flat-config` post-conversion dependency block,
`workspace-rule`, `workspace-rules-project`, and `init-migration`'s
`@eslint/js` and `@nx/eslint-plugin` writes.

Generators that previously overwrote installed ESLint, typescript-eslint,
and related dependency pins on re-run now leave user-pinned versions
intact. Bumping remains the responsibility of migrations, which are
explicitly exempt and not modified.
…SLint 8

Replace the ad-hoc `Number(version[0]) < 7 || ...` floor check and
inlined `ESLint must be version 7.6 or higher.` throw in
`packages/eslint/src/executors/lint/lint.impl.ts` with the shared
`assertSupportedInstalledPackageVersion('eslint', minSupportedEslintVersion)`
helper from `@nx/devkit/internal`. The floor moves from the stale
`7.6` to `8.0.0` (matching the declared `eslint` peer range), and the
thrown message now matches the canonical
`Unsupported version of \`eslint\` detected` format used across plugin
floor asserts.

Update the executor spec to mock `readModulePackageJson` (the FS read
backing `getInstalledPackageVersion`) for the sub-floor case via
`mockReturnValueOnce`, so the mock applies only to the targeted test
and other tests run against the actual installed `eslint`.
Add `requires` blocks to two migration generators in
`packages/eslint/migrations.json` so they only run on workspaces where
their target package is actually present at a relevant version:

* `update-typescript-eslint-v8.13.0` is now gated on
  `@typescript-eslint/parser: >=8.0.0`. Workspaces below v8 are skipped
  by the migrate runner instead of running the migration body and
  silently no-opping. The migration body keeps its per-package
  `gte('8.0.0') && lt('8.13.0')` guard, which covers the
  lockstep-broken case where one of the four typescript-eslint packages
  drifts to a different major than the parser; a comment in the
  migration documents the split.
* `add-file-extensions-to-overrides` is now gated on
  `eslint: >=8.57.0`. Workspaces without ESLint (or below the
  flat-config-compat baseline) no longer run the migration body.

Both gates are intentionally open at the upper bound — migration
generators should remain runnable via `nx migrate --from <older>` even
once newer Nx versions ship.

The `eslint-config-prettier` cross-major bump in `packageJsonUpdates`
`20.7.0` is left ungated: v10's `eslint >=7.0.0` peer covers the entire
supported ESLint window, `@nx/eslint-plugin` itself peers
`eslint-config-prettier: ^10.0.0` via the catalog, and there are no
codemods between v8/v9/v10 — the bump is corrective for sub-v10
workspaces, not a footgun.
…s enforce the floor

Add `packages/eslint/src/utils/all-generators-enforce-floor.spec.ts`
using the shared `assertGeneratorsEnforceVersionFloor` from
`@nx/devkit/internal-testing-utils`. The spec iterates every entry in
`@nx/eslint`'s `generators.json` and verifies it throws the canonical
`Unsupported version of` error on a sub-floor (`~7.32.0`) workspace.

This pins the floor-assert behavior at the suite level, so a future
generator added to `generators.json` without an assert in its working
function fails this spec — matching the canonical shape now used by
`@nx/cypress`, `@nx/playwright`, `@nx/angular`, `@nx/js`, and
`@nx/rsbuild`.
… to ^8

Restrict the `@typescript-eslint/parser` peer in
`packages/eslint-plugin/package.json` from
`^6.13.2 || ^7.0.0 || ^8.0.0` to `^8.0.0` so the declared peer matches
the plugin's actually-bundled runtime dependencies. The plugin ships
`@typescript-eslint/utils` and `@typescript-eslint/type-utils` pinned
to `^8.0.0` via the `catalog:eslint` entry, and workspaces previously
on `@typescript-eslint/parser@^6` or `^7` silently ran the plugin's
rules against v8 internals — risking AST-shape drift on rules that
walk TSESTree nodes.

The plugin does not directly invoke `@typescript-eslint/parser` (only
the user's ESLint config does, when configured to parse TypeScript
files), so the peer is declared as optional via
`peerDependenciesMeta`. Users who only lint JavaScript no longer see
an unmet-peer warning. This matches the canonical optional-peer
pattern used by `@playwright/test`, `cypress`, `vitest`, etc.

`@typescript-eslint/utils` and `@typescript-eslint/type-utils` remain
in `dependencies` — the plugin self-contains its runtime utils rather
than peering on the user's installation.
… to ^8

Restrict the `@typescript-eslint/parser` peer in
`packages/eslint-plugin/package.json` from
`^6.13.2 || ^7.0.0 || ^8.0.0` to `^8.0.0` so the declared peer matches
the plugin's actually-bundled runtime dependencies. The plugin ships
`@typescript-eslint/utils` and `@typescript-eslint/type-utils` pinned
to `^8.0.0` via the `catalog:eslint` entry, and workspaces previously
on `@typescript-eslint/parser@^6` or `^7` silently ran the plugin's
rules against v8 internals — risking AST-shape drift on rules that
walk TSESTree nodes.

The plugin does not directly invoke `@typescript-eslint/parser` (only
the user's ESLint config does, when configured to parse TypeScript
files), so the peer is declared as optional via
`peerDependenciesMeta`. Users who only lint JavaScript no longer see
an unmet-peer warning. This matches the canonical optional-peer
pattern used by `@playwright/test`, `cypress`, `vitest`, etc.

`@typescript-eslint/utils` and `@typescript-eslint/type-utils` remain
in `dependencies` — the plugin self-contains its runtime utils rather
than peering on the user's installation.
Honor the user's flat-config preference when picking the fresh-install
lane in `packages/eslint/src/utils/versions.ts`. When `useFlatConfig`
returns `false` (typically via `ESLINT_USE_FLAT_CONFIG=false`), install
the v8 ESLint + typescript-eslint v7 lane so the workspace remains
internally consistent: ESLint v9 with eslintrc is supported for runtime
linting, but `@typescript-eslint/rule-tester` v8 dropped eslintrc
support entirely and v7 rule-tester is pinned to ESLint v8 — so legacy
workspaces with a v9 + typescript-eslint v8 stack break the
`workspace-rule` generator's emitted spec.

`convert-to-flat-config` is an opt-in upgrade: after conversion the
workspace is on the v9 flat-config-ready stack, so the generator now
writes the latest `eslintVersion` / `typescriptESLintVersion`
constants directly rather than routing through `versions(tree)` (which
would pick the v8/v7 lane based on pre-conversion eslintrc state) and
drops the `keepExistingVersions` flag (this generator is meant to bump
existing pre-conversion pins).

The `@nx/vue` library snapshot is updated to reflect the v9 flat-config
defaults the vue library generator now produces.
…versions(tree) directly

`packages/eslint/src/utils/version-utils.ts` was a two-function file
whose entries (`getInstalledEslintVersion`, `getTypeScriptEslintVersionToInstall`)
were one-line indirections over what `versions.ts` already exposes. Drop
the file and route every consumer through `versions(tree)` directly:

* `packages/eslint/internal.ts` re-exports `getInstalledEslintVersion`,
  `typescriptESLintVersion`, and now also `versions` directly from
  `./src/utils/versions`.
* `packages/eslint/src/generators/workspace-rules-project/workspace-rules-project.ts`
  reads `versions(tree).typescriptESLintVersion` inline.
* `packages/vue/src/utils/add-linting.ts` swaps to the same call shape.

`packages/vue/src/generators/library/library.spec.ts` adds a per-test
`ESLINT_USE_FLAT_CONFIG=true` override for the "should add vue and vitest
to package.json when non-buildable" case. Jest's pnpm hoisting can
resolve `require('eslint')` to a v8 copy in the workspace store, which
would otherwise make `useFlatConfig` route the fresh-install lane
through the v8/v7 stack and not match the v9 flat-config snapshot. The
snapshot is refreshed to capture what real flat-config users actually
see (`@eslint/js`, `typescript-eslint` umbrella package, no
`@typescript-eslint/eslint-plugin`).

No production behavior change.
The legacy install lane (no flat config) paired ESLint v8 with
typescript-eslint v7, which pins `@typescript-eslint/parser` to v7.
With `@nx/eslint-plugin`'s parser peer tightened to `^8.0.0`,
`npm install` fails with ERESOLVE in fresh workspaces that pull in
`@nx/eslint-plugin` (e.g. `nx g @nx/remix:app --linter=eslint`).

typescript-eslint v8 supports ESLint v8.57+ and still works with
eslintrc, so the v8 lane can ship typescript-eslint v8. The only
sub-package that dropped eslintrc is `@typescript-eslint/rule-tester`,
which `@nx/eslint` only installs in the flat-config lane.

@nx-cloud nx-cloud Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nx Cloud has identified a flaky task in your failed CI:

🔂 Since the failure was identified as flaky, we triggered a CI rerun by adding an empty commit to this branch.

Nx Cloud View detailed reasoning in Nx Cloud ↗


🎓 Learn more about Self-Healing CI on nx.dev

@leosvelperez leosvelperez enabled auto-merge (squash) May 29, 2026 16:35
@leosvelperez leosvelperez merged commit b7fc1c5 into master May 29, 2026
18 checks passed
@leosvelperez leosvelperez deleted the nxc-4387 branch May 29, 2026 16:39
jaysoo pushed a commit that referenced this pull request May 29, 2026
…eslint-plugin (#35811)

## Current Behavior

`@nx/eslint` and `@nx/eslint-plugin` have several multi-version support
compliance gaps:

- The bare `@nx/eslint:init` generator path lands fresh installs on EOL
ESLint v8 (`~8.57.0`) even though the flat-config path already ships v9.
- Local re-implementations of installed-version helpers in
`version-utils.ts` and per-major version aliases (`eslint9__*`) in
`versions.ts` drift from the shared `@nx/devkit/internal` helpers.
- Generators do not assert the supported ESLint floor at their entry
points — sub-floor workspaces silently get configs incompatible with
their installed ESLint.
- `addDependenciesToPackageJson` call sites in generators do not
preserve user-pinned ESLint dependency versions; `init`'s schema
defaults `keepExistingVersions` to `false`.
- The `@nx/eslint:lint` executor enforces a stale `7.6` floor with a
hand-rolled `Number(version[0])` check rather than the shared canonical
helper.
- Two ESLint migration generators (`update-typescript-eslint-v8.13.0`,
`add-file-extensions-to-overrides`) lack `requires` gates, so they run
on every workspace even when their target packages are absent or at
unrelated versions.
- `@nx/eslint-plugin` declares `@typescript-eslint/parser: ^6.13.2 ||
^7.0.0 || ^8.0.0` as a required peer but ships
`@typescript-eslint/utils` / `@typescript-eslint/type-utils` pinned to
`^8.0.0` — the peer claim is wider than the bundled runtime range, and
users only linting JavaScript see an unmet-peer warning.

## Expected Behavior

`@nx/eslint`:

- Fresh installs default to ESLint v9 via the canonical `versions(tree)`
route. Installed versions are respected through the version map (v8 →
`~8.57.0` lane; v9/v10 → `latestVersions`, with v10 silently falling
through — no above-ceiling throw).
- `versions.ts` follows the bundle pattern; `version-utils.ts` delegates
to `@nx/devkit/internal` helpers.
- Every `generators.json` entry asserts the supported floor (`8.0.0`) at
its working function's first statement via the canonical
`assertSupportedEslintVersion(tree)` wrapper. A parameterized
`all-generators-enforce-floor.spec.ts` pins this so a future generator
added without the assert fails the spec.
- All generator-side `addDependenciesToPackageJson` calls preserve
user-pinned versions: `init`'s schema defaults `keepExistingVersions` to
`true`, and programmatic callers default via `?? true`.
- The `@nx/eslint:lint` executor uses the shared
`assertSupportedInstalledPackageVersion` helper to enforce the `8.0.0`
floor with the canonical `Unsupported version of \`eslint\` detected`
message.
- The two migration generators are gated on `@typescript-eslint/parser
>=8.0.0` and `eslint >=8.57.0` respectively (open upper bound so `nx
migrate --from <older>` still applies them).

`@nx/eslint-plugin`:

- `@typescript-eslint/parser` peer is tightened to `^8.0.0` (matching
the bundled `@typescript-eslint/utils` / `type-utils` v8 runtime) and
declared optional via `peerDependenciesMeta` — users linting only
JavaScript no longer see unmet-peer warnings.

## Implementation Details

> [!IMPORTANT]
> This PR includes a cherry-picked commit (`feat(devkit): add
assertSupportedInstalledPackageVersion to @nx/devkit/internal`) that
originates from #35806. Whichever of the two PRs merges first, the other
will be rebased to drop the duplicate commit.

<!-- polygraph-session-start -->
---
[View session information
↗](https://snapshot.app.trypolygraph.com/orgs/69cdc268b6aa527e4129c2b4/sessions/nxc-4387-fa5e84db)
<!-- polygraph-session-end -->

---------

Co-authored-by: Leosvel Pérez Espinosa <leosvel.perez.espinosa@gmail.com>
Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>
vrxj81 pushed a commit to vrxj81/nx that referenced this pull request Jun 7, 2026
…eslint-plugin (nrwl#35811)

## Current Behavior

`@nx/eslint` and `@nx/eslint-plugin` have several multi-version support
compliance gaps:

- The bare `@nx/eslint:init` generator path lands fresh installs on EOL
ESLint v8 (`~8.57.0`) even though the flat-config path already ships v9.
- Local re-implementations of installed-version helpers in
`version-utils.ts` and per-major version aliases (`eslint9__*`) in
`versions.ts` drift from the shared `@nx/devkit/internal` helpers.
- Generators do not assert the supported ESLint floor at their entry
points — sub-floor workspaces silently get configs incompatible with
their installed ESLint.
- `addDependenciesToPackageJson` call sites in generators do not
preserve user-pinned ESLint dependency versions; `init`'s schema
defaults `keepExistingVersions` to `false`.
- The `@nx/eslint:lint` executor enforces a stale `7.6` floor with a
hand-rolled `Number(version[0])` check rather than the shared canonical
helper.
- Two ESLint migration generators (`update-typescript-eslint-v8.13.0`,
`add-file-extensions-to-overrides`) lack `requires` gates, so they run
on every workspace even when their target packages are absent or at
unrelated versions.
- `@nx/eslint-plugin` declares `@typescript-eslint/parser: ^6.13.2 ||
^7.0.0 || ^8.0.0` as a required peer but ships
`@typescript-eslint/utils` / `@typescript-eslint/type-utils` pinned to
`^8.0.0` — the peer claim is wider than the bundled runtime range, and
users only linting JavaScript see an unmet-peer warning.

## Expected Behavior

`@nx/eslint`:

- Fresh installs default to ESLint v9 via the canonical `versions(tree)`
route. Installed versions are respected through the version map (v8 →
`~8.57.0` lane; v9/v10 → `latestVersions`, with v10 silently falling
through — no above-ceiling throw).
- `versions.ts` follows the bundle pattern; `version-utils.ts` delegates
to `@nx/devkit/internal` helpers.
- Every `generators.json` entry asserts the supported floor (`8.0.0`) at
its working function's first statement via the canonical
`assertSupportedEslintVersion(tree)` wrapper. A parameterized
`all-generators-enforce-floor.spec.ts` pins this so a future generator
added without the assert fails the spec.
- All generator-side `addDependenciesToPackageJson` calls preserve
user-pinned versions: `init`'s schema defaults `keepExistingVersions` to
`true`, and programmatic callers default via `?? true`.
- The `@nx/eslint:lint` executor uses the shared
`assertSupportedInstalledPackageVersion` helper to enforce the `8.0.0`
floor with the canonical `Unsupported version of \`eslint\` detected`
message.
- The two migration generators are gated on `@typescript-eslint/parser
>=8.0.0` and `eslint >=8.57.0` respectively (open upper bound so `nx
migrate --from <older>` still applies them).

`@nx/eslint-plugin`:

- `@typescript-eslint/parser` peer is tightened to `^8.0.0` (matching
the bundled `@typescript-eslint/utils` / `type-utils` v8 runtime) and
declared optional via `peerDependenciesMeta` — users linting only
JavaScript no longer see unmet-peer warnings.

## Implementation Details

> [!IMPORTANT]
> This PR includes a cherry-picked commit (`feat(devkit): add
assertSupportedInstalledPackageVersion to @nx/devkit/internal`) that
originates from nrwl#35806. Whichever of the two PRs merges first, the other
will be rebased to drop the duplicate commit.

<!-- polygraph-session-start -->
---
[View session information
↗](https://snapshot.app.trypolygraph.com/orgs/69cdc268b6aa527e4129c2b4/sessions/nxc-4387-fa5e84db)
<!-- polygraph-session-end -->

---------

Co-authored-by: Leosvel Pérez Espinosa <leosvel.perez.espinosa@gmail.com>
Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants