Conversation
…lint Co-authored-by: lirantal <316371+lirantal@users.noreply.github.com>
Review Summary by QodoBump Node.js engine to 22.13.0 and ignore util.styleText in eslint
WalkthroughsDescription• Bump minimum Node.js engine to 22.13.0 • Explicitly ignore util.styleText in eslint node-builtins rule • Resolves lint failures from backported API coverage gaps Diagramflowchart LR
A["Node.js engine requirement"] -->|"Update to 22.13.0"| B["package.json"]
C["ESLint node-builtins rule"] -->|"Add util.styleText ignore"| D["eslint.config.js"]
B -->|"Resolves"| E["Lint failures fixed"]
D -->|"Resolves"| E
File Changes1. package.json
|
Code Review by Qodo
1. Lint ignore masks runtime crash
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #88 +/- ##
=======================================
Coverage 80.34% 80.34%
=======================================
Files 9 9
Lines 1628 1628
Branches 96 96
=======================================
Hits 1308 1308
Misses 314 314
Partials 6 6 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
commit: |
| rules: { | ||
| 'n/no-process-exit': 'warn', | ||
| 'n/no-unsupported-features': 'off', | ||
| 'n/no-unsupported-features/node-builtins': ['error', { ignores: ['util.styleText'] }], |
There was a problem hiding this comment.
1. Lint ignore masks runtime crash 🐞 Bug ✓ Correctness
The new ESLint ignore allows util.styleText despite the package declaring an open-ended Node range; because the CLI statically imports styleText from node:util, any allowed Node version that lacks this export will crash at module load time.
Agent Prompt
## Issue description
`src/bin/cli.ts` statically imports `styleText` from `node:util`. If the running Node version does not export `styleText`, Node will fail to load the module (hard crash at startup). This PR suppresses the lint rule that was warning about exactly this risk, while `package.json` still declares an open-ended Node range.
## Issue Context
The intent is to fix CI lint failures caused by `eslint-plugin-n` doing a compatibility subset check across the engine range. Suppressing the rule removes the warning but doesn’t make runtime behavior safe.
## Fix Focus Areas
- Decide on one of the following:
- **Constrain engines** to versions that actually include `util.styleText` (e.g., exclude the known 23.0–23.4 gap), and then you likely won’t need the ignore.
- **Add a runtime fallback**: avoid static named import; access `util.styleText` dynamically with a safe fallback (e.g., identity function) so the CLI can run even if the API is missing.
- Optionally **extend CI matrix** to test the minimum supported Node and any declared majors.
### Code locations
- package.json[26-28]
- eslint.config.js[13-17]
- src/bin/cli.ts[1-6]
- src/bin/cli.ts[140-142]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
There was a problem hiding this comment.
@copilot you should likely not ignore it, we already added an engines rule, right?
There was a problem hiding this comment.
Code Implementation 🛠️
Implementation: Replace the ignores: ['util.styleText'] exception with an explicit Node.js version range for the node-builtins rule so util.styleText is only considered supported in versions where it actually exists.
| 'n/no-unsupported-features/node-builtins': ['error', { ignores: ['util.styleText'] }], | |
| 'n/no-unsupported-features/node-builtins': ['error', { version: '>=22.13.0 <23.0.0 || >=23.5.0' }], |
See review comment here
There was a problem hiding this comment.
The ignores is unfortunately still needed alongside the engines bump. The reason: >=22.13.0 is an open-ended range that includes Node.js 23.0–23.4, which lack util.styleText. The eslint-plugin-n rule uses a semver subset check — it verifies the entire configured version range is covered by the feature's supported versions (^22.13.0 || ^21.7.0 || ^20.12.0 || >=23.5.0). Since >=22.13.0 includes 23.0–23.4 which aren't in that set, the check fails even with the engines update.
I tested reverting the ignores while keeping only engines.node: ">=22.13.0" and lint still errors. The ignores: ['util.styleText'] is the surgical fix — it keeps the rule active for all other builtins while acknowledging that util.styleText is intentionally used within the supported LTS range.
There was a problem hiding this comment.
@copilot what if instead we used this rule though for the ignores:
'n/no-unsupported-features/node-builtins': ['error', { version: '>=22.13.0 <23.0.0 || >=23.5.0' }],
will it work?
There was a problem hiding this comment.
Ask❓
@copilot what if instead we used this rule though for the ignores: 'n/no-unsupported-features/node-builtins': ['error', { version: '>=22.13.0 <23.0.0 || >=23.5.0' }], will it work?
Answer:
Yes — that approach should work for ESLint (and is preferable to ignores) if eslint-plugin-n in your repo supports the version option for n/no-unsupported-features/node-builtins (it does in current versions).
What it does:
- The rule normally infers the Node range from
package.json#engines.node. - By providing
{ version: '...' }, you override the inferred engine range for this rule only, so the rule’s “subset” check no longer has to consider Node23.0–23.4, andutil.styleTextwon’t be flagged.
Suggested config (your snippet is basically right):
'n/no-unsupported-features/node-builtins': [
'error',
{ version: '>=22.13.0 <23.0.0 || >=23.5.0' }
],Two important caveats:
-
This only fixes linting, not runtime safety. If
package.jsonstill says"node": ">=22.13.0", users can run Node23.0–23.4and your CLI can still crash on startup if it statically importsstyleText. The lint rule override would just “look away” from that reality. -
Make sure the semver expression is accepted by the plugin’s semver parser (it should be; it’s a standard npm range with
||).
Recommendation:
- If the project truly does not support Node
23.0–23.4, the cleanest solution is to also changeengines.nodeto match the same range (>=22.13.0 <23.0.0 || >=23.5.0). Then you likely don’t needignores, and the lint rule and runtime contract are aligned. - If you want to keep an open-ended engine range, then you should add a runtime fallback (avoid static named import) rather than relying on lint configuration to paper over the gap.
There was a problem hiding this comment.
Tested it — unfortunately it doesn't work. Even with version: '>=22.13.0 <23.0.0 || >=23.5.0', eslint-plugin-n still errors:
The 'util.styleText' is still an experimental feature and is not supported until Node.js 23.5.0 (backported: ^22.13.0, ^21.7.0, ^20.12.0). The configured version range is '>=22.13.0 <23.0.0 || >=23.5.0'
The plugin classifies util.styleText as "experimental" in the 22.x backport range — it only considers it stable from 23.5.0. The version option narrows the semver range but doesn't change the plugin's experimental classification of the API, so it still fails.
The ignores: ['util.styleText'] is the only option that works here, explicitly opting out of the check for this specific backported API.
| rules: { | ||
| 'n/no-process-exit': 'warn', | ||
| 'n/no-unsupported-features': 'off', | ||
| 'n/no-unsupported-features/node-builtins': ['error', { ignores: ['util.styleText'] }], |
There was a problem hiding this comment.
@copilot you should likely not ignore it, we already added an engines rule, right?
| rules: { | ||
| 'n/no-process-exit': 'warn', | ||
| 'n/no-unsupported-features': 'off', | ||
| 'n/no-unsupported-features/node-builtins': ['error', { ignores: ['util.styleText'] }], |
There was a problem hiding this comment.
@copilot what if instead we used this rule though for the ignores:
'n/no-unsupported-features/node-builtins': ['error', { version: '>=22.13.0 <23.0.0 || >=23.5.0' }],
will it work?
util.styleTextwas backported to^22.13.0but the declared engine range>=22.0.0causedn/no-unsupported-features/node-builtinsto fail. Updating to>=22.13.0alone doesn't fully resolve it — the open-ended range includes23.0–23.4whereutil.styleTextis absent, making the plugin's subset check fail.Changes
package.json—engines.node:>=22.0.0→>=22.13.0eslint.config.js— Overriden/no-unsupported-features/node-builtinswithignores: ['util.styleText']to explicitly permit this backported API regardless of the gap in 23.x coverage🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.