Loading workspace insights... Statistics interval
7 days30 daysLatest CI Pipeline Executions
e84989fe fix(linter): improve convert-to-flat-config output fidelity (#35330)
## Current Behavior
Running `@nx/eslint:convert-to-flat-config` against a workspace with
legacy `.eslintrc` configs produces flat configs that don't faithfully
reflect the source, and leaves stale references to the deleted files
behind:
- Every converted config — root and leaves — gets an unconditional `{
ignores: ['**/dist', '**/out-tsc'] }` block prepended, even when the
legacy config never ignored those paths.
- Leaves whose only compat-looking field was a custom `parser` (e.g.
`jsonc-eslint-parser` for `package.json`) get a full `@eslint/eslintrc`
FlatCompat scaffold — `FlatCompat` import, `dirname`, `fileURLToPath`,
`js`, the `const compat = new FlatCompat({...})` block — that's never
referenced.
- Rule option values that embedded legacy filenames (most notably
`@nx/dependency-checks`'s `ignoredFiles`) keep pointing at
`.eslintrc.json` / `.eslintrc.base.json` / `.eslintignore` after those
files are deleted.
- `nx.json` gets the new `eslint.config.<fmt>` entry added to the lint
target and `production` named input, but legacy `.eslintrc.json` /
`.eslintignore` entries stay in place. Other `targetDefaults` inputs and
`namedInputs` are never rewritten.
- `project.json` files aren't touched at all — every `targets[*].inputs`
or `namedInputs[*]` that referenced the deleted files stays stale.
- Configs with `extends: '../../.eslintrc'` (extensionless — ESLint's
JSON-by-convention form) aren't supported: the source file isn't
converted, and if a leaf extends one that was converted elsewhere the
leaf ends up with `...compat.extends('../../.eslintrc')` pointing at
nothing.
- Legacy `ignorePatterns` entries that started with `!` were being
dropped wholesale, destroying real un-ignores like `['dist/**',
'!dist/keep.js']` that flat config still honors.
- `files` / `excludedFiles` arrays with source-side duplicates (e.g.
`package.json`, `./generators.json`, `./executors.json` repeated in the
same override) are emitted with the duplicates intact.
## Expected Behavior
Conversion preserves the semantics and intent of the legacy config,
rewrites everything that referred to the deleted files, and drops noise
that serves no purpose in flat config:
- The implicit `**/dist` / `**/out-tsc` ignore block is no longer added.
If the legacy config didn't ignore those paths, the converted one
doesn't either — migration stays faithful to the source. (`lint-project`
still adds them for fresh scaffolding, where there's no source intent to
preserve.)
- Parser-only overrides emit a clean flat entry with a hoisted static
parser import and no unused FlatCompat scaffold. Leaf configs shed the
dead boilerplate.
- Rule option values that embed `.eslintrc[.base].json` or
`.eslintignore` are rewritten to the flat-config equivalent.
Accidentally collapsed duplicates inside string arrays are deduped.
- `nx.json` is swept generically — every `targetDefaults[*].inputs` and
`namedInputs[*]` gets legacy filenames rewritten, with dedup so the
rewrite doesn't collide with freshly-added entries. `{ fileset }` shapes
are handled; non-path shapes (`runtime`, `env`, `externalDependencies`,
`dependentTasksOutputFiles`, named-input refs) are left untouched.
- Every project's `project.json` receives the same sweep across
`targets[*].inputs` and `namedInputs[*]`.
- Extensionless `.eslintrc` is now a convertible source, and `extends`
paths that point at `../../.eslintrc` (or `.eslintrc.base`) are
rewritten to the generated base config and imported as `baseConfig`.
- Real negated `ignorePatterns` like `!dist/keep.js` survive the
conversion; only the legacy `**/*` / `!**/*` / `node_modules` catch-alls
are dropped.
- `files` / `excludedFiles` arrays are deduped after glob mapping, so
source-side duplicates and glob-normalization collisions collapse. e84989fe fix(linter): improve convert-to-flat-config output fidelity (#35330)
## Current Behavior
Running `@nx/eslint:convert-to-flat-config` against a workspace with
legacy `.eslintrc` configs produces flat configs that don't faithfully
reflect the source, and leaves stale references to the deleted files
behind:
- Every converted config — root and leaves — gets an unconditional `{
ignores: ['**/dist', '**/out-tsc'] }` block prepended, even when the
legacy config never ignored those paths.
- Leaves whose only compat-looking field was a custom `parser` (e.g.
`jsonc-eslint-parser` for `package.json`) get a full `@eslint/eslintrc`
FlatCompat scaffold — `FlatCompat` import, `dirname`, `fileURLToPath`,
`js`, the `const compat = new FlatCompat({...})` block — that's never
referenced.
- Rule option values that embedded legacy filenames (most notably
`@nx/dependency-checks`'s `ignoredFiles`) keep pointing at
`.eslintrc.json` / `.eslintrc.base.json` / `.eslintignore` after those
files are deleted.
- `nx.json` gets the new `eslint.config.<fmt>` entry added to the lint
target and `production` named input, but legacy `.eslintrc.json` /
`.eslintignore` entries stay in place. Other `targetDefaults` inputs and
`namedInputs` are never rewritten.
- `project.json` files aren't touched at all — every `targets[*].inputs`
or `namedInputs[*]` that referenced the deleted files stays stale.
- Configs with `extends: '../../.eslintrc'` (extensionless — ESLint's
JSON-by-convention form) aren't supported: the source file isn't
converted, and if a leaf extends one that was converted elsewhere the
leaf ends up with `...compat.extends('../../.eslintrc')` pointing at
nothing.
- Legacy `ignorePatterns` entries that started with `!` were being
dropped wholesale, destroying real un-ignores like `['dist/**',
'!dist/keep.js']` that flat config still honors.
- `files` / `excludedFiles` arrays with source-side duplicates (e.g.
`package.json`, `./generators.json`, `./executors.json` repeated in the
same override) are emitted with the duplicates intact.
## Expected Behavior
Conversion preserves the semantics and intent of the legacy config,
rewrites everything that referred to the deleted files, and drops noise
that serves no purpose in flat config:
- The implicit `**/dist` / `**/out-tsc` ignore block is no longer added.
If the legacy config didn't ignore those paths, the converted one
doesn't either — migration stays faithful to the source. (`lint-project`
still adds them for fresh scaffolding, where there's no source intent to
preserve.)
- Parser-only overrides emit a clean flat entry with a hoisted static
parser import and no unused FlatCompat scaffold. Leaf configs shed the
dead boilerplate.
- Rule option values that embed `.eslintrc[.base].json` or
`.eslintignore` are rewritten to the flat-config equivalent.
Accidentally collapsed duplicates inside string arrays are deduped.
- `nx.json` is swept generically — every `targetDefaults[*].inputs` and
`namedInputs[*]` gets legacy filenames rewritten, with dedup so the
rewrite doesn't collide with freshly-added entries. `{ fileset }` shapes
are handled; non-path shapes (`runtime`, `env`, `externalDependencies`,
`dependentTasksOutputFiles`, named-input refs) are left untouched.
- Every project's `project.json` receives the same sweep across
`targets[*].inputs` and `namedInputs[*]`.
- Extensionless `.eslintrc` is now a convertible source, and `extends`
paths that point at `../../.eslintrc` (or `.eslintrc.base`) are
rewritten to the generated base config and imported as `baseConfig`.
- Real negated `ignorePatterns` like `!dist/keep.js` survive the
conversion; only the legacy `**/*` / `!**/*` / `node_modules` catch-alls
are dropped.
- `files` / `excludedFiles` arrays are deduped after glob mapping, so
source-side duplicates and glob-normalization collisions collapse. e84989fe fix(linter): improve convert-to-flat-config output fidelity (#35330)
## Current Behavior
Running `@nx/eslint:convert-to-flat-config` against a workspace with
legacy `.eslintrc` configs produces flat configs that don't faithfully
reflect the source, and leaves stale references to the deleted files
behind:
- Every converted config — root and leaves — gets an unconditional `{
ignores: ['**/dist', '**/out-tsc'] }` block prepended, even when the
legacy config never ignored those paths.
- Leaves whose only compat-looking field was a custom `parser` (e.g.
`jsonc-eslint-parser` for `package.json`) get a full `@eslint/eslintrc`
FlatCompat scaffold — `FlatCompat` import, `dirname`, `fileURLToPath`,
`js`, the `const compat = new FlatCompat({...})` block — that's never
referenced.
- Rule option values that embedded legacy filenames (most notably
`@nx/dependency-checks`'s `ignoredFiles`) keep pointing at
`.eslintrc.json` / `.eslintrc.base.json` / `.eslintignore` after those
files are deleted.
- `nx.json` gets the new `eslint.config.<fmt>` entry added to the lint
target and `production` named input, but legacy `.eslintrc.json` /
`.eslintignore` entries stay in place. Other `targetDefaults` inputs and
`namedInputs` are never rewritten.
- `project.json` files aren't touched at all — every `targets[*].inputs`
or `namedInputs[*]` that referenced the deleted files stays stale.
- Configs with `extends: '../../.eslintrc'` (extensionless — ESLint's
JSON-by-convention form) aren't supported: the source file isn't
converted, and if a leaf extends one that was converted elsewhere the
leaf ends up with `...compat.extends('../../.eslintrc')` pointing at
nothing.
- Legacy `ignorePatterns` entries that started with `!` were being
dropped wholesale, destroying real un-ignores like `['dist/**',
'!dist/keep.js']` that flat config still honors.
- `files` / `excludedFiles` arrays with source-side duplicates (e.g.
`package.json`, `./generators.json`, `./executors.json` repeated in the
same override) are emitted with the duplicates intact.
## Expected Behavior
Conversion preserves the semantics and intent of the legacy config,
rewrites everything that referred to the deleted files, and drops noise
that serves no purpose in flat config:
- The implicit `**/dist` / `**/out-tsc` ignore block is no longer added.
If the legacy config didn't ignore those paths, the converted one
doesn't either — migration stays faithful to the source. (`lint-project`
still adds them for fresh scaffolding, where there's no source intent to
preserve.)
- Parser-only overrides emit a clean flat entry with a hoisted static
parser import and no unused FlatCompat scaffold. Leaf configs shed the
dead boilerplate.
- Rule option values that embed `.eslintrc[.base].json` or
`.eslintignore` are rewritten to the flat-config equivalent.
Accidentally collapsed duplicates inside string arrays are deduped.
- `nx.json` is swept generically — every `targetDefaults[*].inputs` and
`namedInputs[*]` gets legacy filenames rewritten, with dedup so the
rewrite doesn't collide with freshly-added entries. `{ fileset }` shapes
are handled; non-path shapes (`runtime`, `env`, `externalDependencies`,
`dependentTasksOutputFiles`, named-input refs) are left untouched.
- Every project's `project.json` receives the same sweep across
`targets[*].inputs` and `namedInputs[*]`.
- Extensionless `.eslintrc` is now a convertible source, and `extends`
paths that point at `../../.eslintrc` (or `.eslintrc.base`) are
rewritten to the generated base config and imported as `baseConfig`.
- Real negated `ignorePatterns` like `!dist/keep.js` survive the
conversion; only the legacy `**/*` / `!**/*` / `node_modules` catch-alls
are dropped.
- `files` / `excludedFiles` arrays are deduped after glob mapping, so
source-side duplicates and glob-normalization collisions collapse. aa091aef fix(angular-rspack): exclude eslint config from tailwind v4 source scan (#35663)
## Current Behavior
In `examples-angular-rspack-csr-tailwind:build`, Tailwind v4's automatic
source-detection scanner (`@tailwindcss/oxide`) walks the project root
and reads every file with a known extension (`.html`, `.js`, `.mjs`,
`.cjs`, `.ts`, `.tsx`, `.vue`, …) honoring `.gitignore`.
`eslint.config.mjs` sits at the project root with a scanned extension,
so Tailwind reads it looking for utility class names. The Nx build
target excludes `eslint.config.@(js|cjs|mjs|ts|cts|mts)` from its
inputs, so the read shows up as an undeclared-read sandbox violation:
```
examples/angular-rspack/csr-tailwind/eslint.config.mjs
```
Other root-level files Tailwind also scans (e.g. `rspack.config.js`)
don't trigger violations because they are declared as inputs by their
respective plugins. `eslint.config.mjs` is unique in being both scanned
and excluded.
## Expected Behavior
Tailwind should not scan eslint config. Adding `@source not
"../eslint.config.mjs";` to `src/styles.css` tells Tailwind to skip that
file during its scan. No more sandbox violation; the eslint config
exclusion in the build inputs stays correct (eslint config has no effect
on build output).
## Related Issue(s)
N/A — sandbox-report finding, not a tracked issue. aa091aef fix(angular-rspack): exclude eslint config from tailwind v4 source scan (#35663)
## Current Behavior
In `examples-angular-rspack-csr-tailwind:build`, Tailwind v4's automatic
source-detection scanner (`@tailwindcss/oxide`) walks the project root
and reads every file with a known extension (`.html`, `.js`, `.mjs`,
`.cjs`, `.ts`, `.tsx`, `.vue`, …) honoring `.gitignore`.
`eslint.config.mjs` sits at the project root with a scanned extension,
so Tailwind reads it looking for utility class names. The Nx build
target excludes `eslint.config.@(js|cjs|mjs|ts|cts|mts)` from its
inputs, so the read shows up as an undeclared-read sandbox violation:
```
examples/angular-rspack/csr-tailwind/eslint.config.mjs
```
Other root-level files Tailwind also scans (e.g. `rspack.config.js`)
don't trigger violations because they are declared as inputs by their
respective plugins. `eslint.config.mjs` is unique in being both scanned
and excluded.
## Expected Behavior
Tailwind should not scan eslint config. Adding `@source not
"../eslint.config.mjs";` to `src/styles.css` tells Tailwind to skip that
file during its scan. No more sandbox violation; the eslint config
exclusion in the build inputs stays correct (eslint config has no effect
on build output).
## Related Issue(s)
N/A — sandbox-report finding, not a tracked issue. 99d3f8f6 feat(core): add --mode and --multi-major-mode flags to nx migrate (#35497)
## Current Behavior
`nx migrate <target>` processes every entry in the resolved
`packageJsonUpdates`, including third-party packages outside the
target's `nx.packageGroup`. There is no way to scope a run to Nx itself,
no safety rail when jumping multiple major versions, and the cascade can
propose downgrades for deps that have already been bumped past the
historical pin.
## Expected Behavior
Adds two new flags to `nx migrate`, plus a downgrade-prevention
safeguard and a bare-invocation default.
### `--mode={first-party|third-party|all}`
Scope which packages get migrated. Only valid when the target is the
canonical Nx package (`nx`, or `@nx/workspace` as an era-aware alias).
- **`first-party`** — bumps Nx and the packages in its
`nx.packageGroup`; third-party deps are left untouched.
- **`third-party`** — anchors at the installed Nx version and walks
`--from=nx@0.0.0 --exclude-applied-migrations` internally, surfacing
third-party catch-up that earlier first-party-only runs left behind.
- **`all`** (default) — everything; matches existing behavior.
Defaults to `all` outside a TTY; prompts in an interactive terminal when
the target is canonical Nx. Rejects `--from`,
`--exclude-applied-migrations`, and out-of-bounds `--to nx@…` (or a
higher `nx@…` positional) when `mode=third-party` — those already imply
going past the installed version.
### `--multi-major-mode={direct|gradual}`
Handles the case where the target jumps two or more major versions from
installed.
- **Interactive (TTY):** prompts with the smallest-step recommendations
— `latest in current major` (when at least a minor ahead of installed),
`next major`, and `migrate directly to <target>`. The smallest available
step is tagged `[recommended]`.
- **Non-interactive:** warns and proceeds with the requested target.
- **`--multi-major-mode=direct`** (or `NX_MULTI_MAJOR_MODE=direct`) —
skip the prompt/warn and migrate directly to the requested target.
- **`--multi-major-mode=gradual`** (or `NX_MULTI_MAJOR_MODE=gradual`) —
skip the prompt and pick the smallest recommended step automatically;
re-run `nx migrate` to continue toward the originally requested target.
Falls back silently to the requested target when no stepwise option is
available.
### Downgrade prevention
`packageJsonUpdates` entries that would move a workspace dep backwards
from its current pin are now dropped from the proposed updates. Common
case: a workspace that manually bumped a dep past the version a
historical `packageJsonUpdates` entry pins.
### Bare invocation
`nx migrate` with no positional now defaults to `nx@latest` instead of
erroring, then runs through the mode + multi-major flow.
---------
Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>