-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
feat: add support for flat configs #7935
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Thanks for the PR, @bradzacher! typescript-eslint is a 100% community driven project, and we are incredibly grateful that you are contributing to that community. The core maintainers work on this in their personal time, so please understand that it may not be possible for them to review your work immediately. Thanks again! 🙏 Please, if you or your company is finding typescript-eslint valuable, help us sustain the project by sponsoring it transparently on https://opencollective.com/typescript-eslint. |
✅ Deploy Preview for typescript-eslint ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
40ecd25
to
072c888
Compare
packages/core/src/index.ts
Outdated
rules: pluginBase.rules, | ||
}; | ||
|
||
function flatConfig(...config: FlatConfig.ConfigArray): FlatConfig.ConfigArray { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe just config
? Cleaner to say & write, and after a year or so most new projects should only/primarily think about flat configs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the problem with calling it config
is that you then have both config
and configs
exported from the package.
It does make things a little confusing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm yeah never mind... 🤔 a tough naming situation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eh it works fine enough - I added it as is. People will deal with it it's not THAT bad.
Status update: this PR is blocked on eslint/eslint#17820. We're waiting for that to be resolved. eslint/eslint#17906 looks very promising and we'll try it out. Note that once we're unblocked, we'll have to limit flat config support to versions of ESLint with that fix in them. Edit: the fix was merged but only into the v9 alphas. See #7935 (comment). |
072c888
to
4430fde
Compare
This comment was marked as off-topic.
This comment was marked as off-topic.
Yeah we're trying to work with them to backport the fix we're waiting for to v8. Once we have it working on v8 then we can start to think about v9. |
This comment was marked as off-topic.
This comment was marked as off-topic.
Filed eslint/eslint#17966 - we shall have to wait and see. |
This comment was marked as off-topic.
This comment was marked as off-topic.
packages/core/src/index.ts
Outdated
function flatConfig(...config: FlatConfig.ConfigArray): FlatConfig.ConfigArray { | ||
return config; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question:
What do we think about making this utility enforce a canonical name for plugins?
For example imagine like:
// eslint.config.js
import * as tseslint from '@typescript-eslint/core';
export default tseslint.config(
{
'@typescript-eslint': tseslint.plugin,
// ...
},
{
},
);
Then within the util we could rewrite all configs so that any references to the plugin use the defined namespace, and we rewrite it with pseudocode like:
for config in configs {
const pair = config.plugins.entries().find(plugin.value)
if pair && pair.key !== plugin.key {
pair.key = plugin.key
config.rules.keys().replace(`${pair.key}/`, `${plugin.key}/`)
}
}
Pros: fixes the "multiple namespace problem"
Cons: rewrites user configs, includes some complexity.
WDYT?
Alternate forms:
- more explicit object form like
config({ plugins: { ... }, configs: [ ... ] })
- a util function form like
config.withPlugins({ ..plugins.. })(..configs[])
(whereconfig(..configs[])
acts without explicit enforcement)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea at first glance, but suspect it should be done in a follow-up issue so that the ESLint folks can provide input too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on the discussions we've had (eslint/eslint#17766) - this is fully intended behaviour and it doesn't look like they intend to change that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I mean more on input for direction of the checking.
Plus splitting it out will make it easier to reference it when complaining about the name aliasing being allowed 😄
@bradzacher, just want to make sure you saw eslint/eslint#17820 (comment):
|
4430fde
to
a891a37
Compare
ad7e3c0
to
ee587e3
Compare
errorOnUnmatchedPattern: false, | ||
- reportUnusedDisableDirectives: options.reportUnusedDisableDirectives || undefined, | ||
+ // https://github.com/nrwl/nx/pull/21405 | ||
+ // reportUnusedDisableDirectives: options.reportUnusedDisableDirectives || undefined, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JoshuaKGoldberg - this is now truly ready for review (passing ci!!!) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoohoo!! 🥳
This looks great to me. There are a few points that could be taken as followups (docs, tests, a bit of style) but nothing IMO that should block this being merged. Awesome job!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Docs] This should be added to sidebar.base.js
so it shows up & has a sidebar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UGH. We should automate this somehow.
); | ||
} else { | ||
flatCode.push( | ||
`export default (_plugin: FlatConfig.Plugin, _parser: FlatConfig.Parser): FlatConfig.Config => (${flatConfigJson});`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Style] If they're unused, why bother including them?
`export default (_plugin: FlatConfig.Plugin, _parser: FlatConfig.Parser): FlatConfig.Config => (${flatConfigJson});`, | |
`export default (): FlatConfig.Config => (${flatConfigJson});`, |
Here, and the unused import above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cos it sets things up to have a consistent API shape - which is nice in case we do change things in future.
I.e. it means we can blindly write
configs: {
all: allConfig(plugin, parser),
base: baseConfig(plugin, parser),
disableTypeChecked: disableTypeCheckedConfig(plugin, parser),
eslintRecommended: eslintRecommendedConfig(plugin, parser),
recommended: recommendedConfig(plugin, parser),
recommendedTypeChecked: recommendedTypeCheckedConfig(plugin, parser),
strict: strictConfig(plugin, parser),
strictTypeChecked: strictTypeCheckedConfig(plugin, parser),
stylistic: stylisticConfig(plugin, parser),
stylisticTypeChecked: stylisticTypeCheckedConfig(plugin, parser),
}
rather than having to maintain which ones get args and which don't.
packages/typescript-eslint/LICENSE
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Non-Actionable] Heh, good catch...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DAMN YOU AMERICANS SPELLING THINGS WRONG
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IT'S NOT OUR FAULT WE DON'T HAVE AUSTRALIAN COFFEE
PR Checklist
Overview
This PR builds out support for Flat Configs for our project.
Unfortunately supporting both classic and flat configs from the plugin is a bit of a mess, so I took this opportunity to introduce something that we've always wanted - a single entrypoint package for linting users.
The beauty of this new package is that it means that linting users only need to install, update, and think about one package now - which is a big win.
This new package is
typescript-eslint
and it currently exports the following:parser
- an alias for@typescript-eslint/parser
.plugin
- an alias for@typescript-eslint/eslint-plugin
.configs
- flat config versions of the configs in@typescript-eslint/eslint-plugin
.config
- a utility function to make it dead simple to use types in flat config files.Consuming our tooling in a flat config will look something like this:
With this PR we are also dogfooding the package as I have migrated our config to a flat config. We're pretty light on shared configs so it's been pretty straight-forward and mostly "compat free". I have a few open TODOs in the config which are marked.
With this new tooling
TODO:
@typescript-eslint/
(the current approach in this PR)typescript-eslint/
typescript/
ts-eslint/
ts/