Skip to content

Commit 70d2371

Browse files
committed
feat: support type-aware rules, fix #499
1 parent afc42f9 commit 70d2371

File tree

8 files changed

+66
-14
lines changed

8 files changed

+66
-14
lines changed

docs/content/1.packages/1.config.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,18 @@ export default createConfigForNuxt({
133133
```
134134

135135
Learn more about all the available options in the [ESLint Stylistic documentation](https://eslint.style/guide/config-presets#configuration-factory).
136+
137+
## Type Aware Rules
138+
139+
This config also provides type-aware rules for TypeScript and Vue. You can enable them by setting `features.typescript` to an object with `tsconfigPath` the path to your `tsconfig.json` file.
140+
```js [eslint.config.mjs]
141+
import { createConfigForNuxt } from '@nuxt/eslint-config'
142+
143+
export default createConfigForNuxt({
144+
features: {
145+
typescript: {
146+
tsconfigPath: './tsconfig.json'
147+
}
148+
}
149+
})
150+
```

eslint.config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ export default createConfigForNuxt({
88
stylistic: true,
99
tooling: true,
1010
formatters: true,
11+
// typescript: {
12+
// tsconfigPath: 'tsconfig.json',
13+
// },
1114
},
1215
dirs: {
1316
src: [

packages/eslint-config/src/configs/stylistic.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ import type { Linter } from 'eslint'
55
export default (options?: StylisticCustomizeOptions): Linter.Config => {
66
return {
77
name: 'nuxt/stylistic',
8-
...stylistic.configs.customize(options) as Linter.Config,
8+
...stylistic.configs.customize(options) as Linter,
99
}
1010
}

packages/eslint-config/src/configs/typescript.ts

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@ import { resolveOptions } from '../utils'
66

77
export { parserTs, pluginTs }
88

9+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
10+
const getRulesFromConfigs = (config: any) => {
11+
const array = Array.isArray(config) ? config : [config]
12+
const object = array.reduce((acc, item) => {
13+
return { ...acc, ...item.rules }
14+
}, {})
15+
return object
16+
}
17+
918
export default function typescript(options: NuxtESLintConfigOptions): Linter.Config[] {
1019
const resolved = resolveOptions(options)
1120

@@ -14,6 +23,8 @@ export default function typescript(options: NuxtESLintConfigOptions): Linter.Con
1423
}
1524

1625
const tsOptions = resolved.features.typescript === true ? {} : resolved.features.typescript
26+
const strict = tsOptions.strict === false ? false : true
27+
const tsconfigPath = tsOptions.tsconfigPath || undefined
1728

1829
return [
1930
{
@@ -28,14 +39,34 @@ export default function typescript(options: NuxtESLintConfigOptions): Linter.Con
2839
files: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts', '**/*.vue'],
2940
languageOptions: {
3041
parser: parserTs,
42+
parserOptions: {
43+
extraFileExtensions: ['.vue'],
44+
sourceType: 'module',
45+
...tsconfigPath
46+
? {
47+
projectService: {
48+
allowDefaultProject: ['./*.js'],
49+
defaultProject: tsconfigPath,
50+
},
51+
tsconfigRootDir: process.cwd(),
52+
}
53+
: {},
54+
},
3155
},
3256
rules: {
33-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
34-
...pluginTs.configs['eslint-recommended'].overrides![0].rules as any,
35-
...pluginTs.configs.recommended.rules,
36-
...(tsOptions.strict === false
37-
? {}
38-
: pluginTs.configs.strict.rules),
57+
...getRulesFromConfigs(pluginTs.configs['flat/recommended']),
58+
59+
// Type-aware rules
60+
...(tsconfigPath
61+
? getRulesFromConfigs(pluginTs.configs['flat/recommended-type-checked-only'])
62+
: {}),
63+
64+
// Strict rules
65+
...(strict
66+
? tsconfigPath
67+
? getRulesFromConfigs(pluginTs.configs['flat/strict-type-checked-only'])
68+
: getRulesFromConfigs(pluginTs.configs['flat/strict'])
69+
: {}),
3970

4071
// Include typescript eslint rules in *.vue files
4172
// https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/configs/eslint-recommended.ts

packages/eslint-config/src/configs/vue.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,9 @@ export default async function vue(options: NuxtESLintConfigOptions): Promise<Lin
8080
rules: {
8181
...pluginVue.configs.base.rules,
8282

83-
...pluginVue.configs['flat/essential'].map(c => c.rules).reduce((acc, c) => ({ ...acc, ...c }), {}) as Linter.Config['rules'],
84-
...pluginVue.configs['flat/strongly-recommended'].map(c => c.rules).reduce((acc, c) => ({ ...acc, ...c }), {}) as Linter.Config['rules'],
85-
...pluginVue.configs['flat/recommended'].map(c => c.rules).reduce((acc, c) => ({ ...acc, ...c }), {}) as Linter.Config['rules'],
83+
...pluginVue.configs['flat/essential'].map(c => c.rules).reduce((acc, c) => ({ ...acc, ...c }), {}),
84+
...pluginVue.configs['flat/strongly-recommended'].map(c => c.rules).reduce((acc, c) => ({ ...acc, ...c }), {}),
85+
...pluginVue.configs['flat/recommended'].map(c => c.rules).reduce((acc, c) => ({ ...acc, ...c }), {}),
8686

8787
// Deprecated in favor of 'vue/block-order'
8888
'vue/component-tags-order': undefined,

packages/eslint-config/src/index.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import type { ResolvableFlatConfig, FlatConfigComposer } from 'eslint-flat-config-utils'
22
import { composer } from 'eslint-flat-config-utils'
33
import gitignore from 'eslint-config-flat-gitignore'
4-
import type { Linter } from 'eslint'
54
import type { NuxtESLintConfigOptions } from './types'
65
import disables from './configs/disables'
76
import nuxt from './configs/nuxt'
@@ -21,7 +20,7 @@ export { resolveOptions }
2120
*/
2221
export function defineFlatConfigs(
2322
...configs: ResolvableFlatConfig[]
24-
): FlatConfigComposer<Linter.Config> {
23+
): FlatConfigComposer {
2524
return composer(...configs)
2625
}
2726

@@ -35,7 +34,7 @@ export function defineFlatConfigs(
3534
export function createConfigForNuxt(
3635
options: NuxtESLintConfigOptions = {},
3736
...userConfigs: ResolvableFlatConfig[]
38-
): FlatConfigComposer<Linter.Config> {
37+
): FlatConfigComposer {
3938
const c = composer()
4039

4140
const resolved = resolveOptions(options)

packages/eslint-config/src/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ export interface NuxtESLintFeaturesOptions {
8484
* @default true
8585
*/
8686
strict?: boolean
87+
/**
88+
* Path to the tsconfig file, when this is provide, type-aware rules will be enabled.
89+
*/
90+
tsconfigPath?: string
8791
}
8892
}
8993

packages/eslint-config/src/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const parserPlain = {
2525
}
2626

2727
export async function ensurePackages(packages: (string | undefined)[]): Promise<void> {
28-
if (process.env.CI || process.stdout.isTTY === false)
28+
if (process.env.CI || !process.stdout.isTTY)
2929
return
3030

3131
const nonExistingPackages = packages.filter(i => i && !isPackageExists(i)) as string[]

0 commit comments

Comments
 (0)