Skip to content

Commit

Permalink
feat: add flat config presets (#122)
Browse files Browse the repository at this point in the history
Co-authored-by: Sukka <[email protected]>
  • Loading branch information
michaelfaith and SukkaW authored Aug 26, 2024
1 parent f37dc29 commit cd52e86
Show file tree
Hide file tree
Showing 14 changed files with 253 additions and 23 deletions.
14 changes: 14 additions & 0 deletions .changeset/great-dodos-dream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
"eslint-plugin-import-x": minor
---

Add ESLint flat configuration presets. You can access them with:

```ts
import eslintPluginImportX from 'eslint-plugin-import-x';

eslintPluginImportX.flatConfigs.recommended;
eslintPluginImportX.flatConfigs.react;
eslintPluginImportX.flatConfigs.typescript;
eslintPluginImportX.flatConfigs.electron;
```
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"codesandbox:install": "yarn --ignore-engines",
"lint": "run-p lint:*",
"lint:docs": "yarn update:eslint-docs --check",
"lint:es": "ESLINT_USE_FLAT_CONFIG=false eslint . --cache",
"lint:es": "cross-env ESLINT_USE_FLAT_CONFIG=false eslint . --cache",
"lint:tsc": "tsc -p tsconfig.base.json --noEmit",
"prepare": "patch-package",
"release": "changeset publish",
Expand Down
10 changes: 10 additions & 0 deletions src/config/flat/electron.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { PluginFlatConfig } from '../../types'

/**
* Default settings for Electron applications.
*/
export default {
settings: {
'import-x/core-modules': ['electron'],
},
} satisfies PluginFlatConfig
15 changes: 15 additions & 0 deletions src/config/flat/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { PluginFlatConfig } from '../../types'

/**
* unopinionated config. just the things that are necessarily runtime errors
* waiting to happen.
*/
export default {
rules: {
'import-x/no-unresolved': 2,
'import-x/named': 2,
'import-x/namespace': 2,
'import-x/default': 2,
'import-x/export': 2,
},
} satisfies PluginFlatConfig
15 changes: 15 additions & 0 deletions src/config/flat/react-native.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { PluginFlatBaseConfig } from '../../types'

/**
* adds platform extensions to Node resolver
*/
export default {
settings: {
'import-x/resolver': {
node: {
// Note: will not complain if only _one_ of these files exists.
extensions: ['.js', '.web.js', '.ios.js', '.android.js'],
},
},
},
} satisfies PluginFlatBaseConfig
21 changes: 21 additions & 0 deletions src/config/flat/react.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { PluginFlatBaseConfig } from '../../types'

/**
* Adds `.jsx` as an extension, and enables JSX parsing.
*
* Even if _you_ aren't using JSX (or .jsx) directly, if your dependencies
* define jsnext:main and have JSX internally, you may run into problems
* if you don't enable these settings at the top level.
*/
export default {
settings: {
'import-x/extensions': ['.js', '.jsx', '.mjs', '.cjs'],
},
languageOptions: {
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
} satisfies PluginFlatBaseConfig
27 changes: 27 additions & 0 deletions src/config/flat/recommended.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { PluginFlatBaseConfig } from '../../types'

/**
* The basics.
*/
export default {
rules: {
// analysis/correctness
'import-x/no-unresolved': 'error',
'import-x/named': 'error',
'import-x/namespace': 'error',
'import-x/default': 'error',
'import-x/export': 'error',

// red flags (thus, warnings)
'import-x/no-named-as-default': 'warn',
'import-x/no-named-as-default-member': 'warn',
'import-x/no-duplicates': 'warn',
},

// need all these for parsing dependencies (even if _your_ code doesn't need
// all of them)
languageOptions: {
ecmaVersion: 2018,
sourceType: 'module',
},
} satisfies PluginFlatBaseConfig
12 changes: 12 additions & 0 deletions src/config/flat/stage-0.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { PluginFlatBaseConfig } from '../../types'

/**
* Rules in progress.
*
* Do not expect these to adhere to semver across releases.
*/
export default {
rules: {
'import-x/no-deprecated': 1,
},
} satisfies PluginFlatBaseConfig
41 changes: 41 additions & 0 deletions src/config/flat/typescript.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { PluginFlatBaseConfig } from '../../types'

/**
* This config:
* 1) adds `.jsx`, `.ts`, `.cts`, `.mts`, and `.tsx` as an extension
* 2) enables JSX/TSX parsing
*/

// Omit `.d.ts` because 1) TypeScript compilation already confirms that
// types are resolved, and 2) it would mask an unresolved
// `.ts`/`.tsx`/`.js`/`.jsx` implementation.
const typeScriptExtensions = ['.ts', '.tsx', '.cts', '.mts'] as const

const allExtensions = [
...typeScriptExtensions,
'.js',
'.jsx',
'.cjs',
'.mjs',
] as const

export default {
settings: {
'import-x/extensions': allExtensions,
'import-x/external-module-folders': ['node_modules', 'node_modules/@types'],
'import-x/parsers': {
'@typescript-eslint/parser': [...typeScriptExtensions],
},
'import-x/resolver': {
node: {
extensions: allExtensions,
},
},
},
rules: {
// analysis/correctness

// TypeScript compilation already ensures that named imports exist in the referenced module
'import-x/named': 'off',
},
} satisfies PluginFlatBaseConfig
12 changes: 12 additions & 0 deletions src/config/flat/warnings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { PluginFlatBaseConfig } from '../../types'

/**
* more opinionated config.
*/
export default {
rules: {
'import-x/no-named-as-default': 1,
'import-x/no-named-as-default-member': 1,
'import-x/no-duplicates': 1,
},
} satisfies PluginFlatBaseConfig
12 changes: 9 additions & 3 deletions src/config/typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,22 @@ import type { PluginConfig } from '../types'
// Omit `.d.ts` because 1) TypeScript compilation already confirms that
// types are resolved, and 2) it would mask an unresolved
// `.ts`/`.tsx`/`.js`/`.jsx` implementation.
const typeScriptExtensions = ['.ts', '.tsx'] as const
const typeScriptExtensions = ['.ts', '.tsx', '.cts', '.mts'] as const

const allExtensions = [...typeScriptExtensions, '.js', '.jsx'] as const
const allExtensions = [
...typeScriptExtensions,
'.js',
'.jsx',
'.cjs',
'.mjs',
] as const

export = {
settings: {
'import-x/extensions': allExtensions,
'import-x/external-module-folders': ['node_modules', 'node_modules/@types'],
'import-x/parsers': {
'@typescript-eslint/parser': [...typeScriptExtensions, '.cts', '.mts'],
'@typescript-eslint/parser': [...typeScriptExtensions],
},
'import-x/resolver': {
node: {
Expand Down
84 changes: 66 additions & 18 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
import type { TSESLint } from '@typescript-eslint/utils'

// rules
import { name, version } from '../package.json'

import electron from './config/electron'
import errors from './config/errors'
import electronFlat from './config/flat/electron'
import errorsFlat from './config/flat/errors'
import reactFlat from './config/flat/react'
import reactNativeFlat from './config/flat/react-native'
import recommendedFlat from './config/flat/recommended'
import stage0Flat from './config/flat/stage-0'
import typescriptFlat from './config/flat/typescript'
import warningsFlat from './config/flat/warnings'
import react from './config/react'
import reactNative from './config/react-native'
import recommended from './config/recommended'
import stage0 from './config/stage-0'
import typescript from './config/typescript'
import warnings from './config/warnings'

Check failure on line 20 in src/index.ts

View workflow job for this annotation

GitHub Actions / Lint and Test with Node.js 20 and ESLint 8 on macos-latest

There should be no empty line within import group

Check failure on line 20 in src/index.ts

View workflow job for this annotation

GitHub Actions / Lint and Test with Node.js 20 and ESLint 8.56 on ubuntu-latest

There should be no empty line within import group

Check failure on line 20 in src/index.ts

View workflow job for this annotation

GitHub Actions / Lint and Test with Node.js 20 and ESLint 8 on ubuntu-latest

There should be no empty line within import group

Check failure on line 20 in src/index.ts

View workflow job for this annotation

GitHub Actions / Lint and Test with Node.js 20 and ESLint 9 on ubuntu-latest

There should be no empty line within import group

// rules
import consistentTypeSpecifierStyle from './rules/consistent-type-specifier-style'
import default_ from './rules/default'
import dynamicImportChunkname from './rules/dynamic-import-chunkname'
Expand Down Expand Up @@ -55,23 +66,11 @@ import order from './rules/order'
import preferDefaultExport from './rules/prefer-default-export'
import unambiguous from './rules/unambiguous'
// configs
import type { PluginConfig } from './types'

const configs = {
recommended,

errors,
warnings,

// shhhh... work in progress "secret" rules
'stage-0': stage0,

// useful stuff for folks using various environments
react,
'react-native': reactNative,
electron,
typescript,
} satisfies Record<string, PluginConfig>
import type {
PluginConfig,
PluginFlatBaseConfig,
PluginFlatConfig,
} from './types'

const rules = {
'no-unresolved': noUnresolved,
Expand Down Expand Up @@ -129,7 +128,56 @@ const rules = {
'imports-first': importsFirst,
} satisfies Record<string, TSESLint.RuleModule<string, readonly unknown[]>>

const configs = {
recommended,

errors,
warnings,

// shhhh... work in progress "secret" rules
'stage-0': stage0,

// useful stuff for folks using various environments
react,
'react-native': reactNative,
electron,
typescript,
} satisfies Record<string, PluginConfig>

// Base Plugin Object
const plugin = {
meta: { name, version },
rules,
}

// Create flat configs (Only ones that declare plugins and parser options need to be different from the legacy config)
const createFlatConfig = (
baseConfig: PluginFlatBaseConfig,
configName: string,
): PluginFlatConfig => ({
...baseConfig,
name: `import-x/${configName}`,
plugins: { 'import-x': plugin },
})

const flatConfigs = {
recommended: createFlatConfig(recommendedFlat, 'recommended'),

errors: createFlatConfig(errorsFlat, 'errors'),
warnings: createFlatConfig(warningsFlat, 'warnings'),

// shhhh... work in progress "secret" rules
'stage-0': createFlatConfig(stage0Flat, 'stage-0'),

// useful stuff for folks using various environments
react: reactFlat,
'react-native': reactNativeFlat,
electron: electronFlat,
typescript: typescriptFlat,
} satisfies Record<string, PluginFlatConfig>

export = {
configs,
flatConfigs,

This comment has been minimized.

Copy link
@kuoruan
rules,
}
9 changes: 9 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ export type PluginConfig = {
rules?: Record<`${PluginName}/${string}`, TSESLint.Linter.RuleEntry>
} & TSESLint.Linter.ConfigType

export type PluginFlatBaseConfig = {
settings?: PluginSettings
rules?: Record<`${PluginName}/${string}`, TSESLint.FlatConfig.RuleEntry>
} & TSESLint.FlatConfig.Config

export type PluginFlatConfig = PluginFlatBaseConfig & {
name?: `${PluginName}/${string}`
}

export type RuleContext<
TMessageIds extends string = string,
TOptions extends readonly unknown[] = readonly unknown[],
Expand Down
2 changes: 1 addition & 1 deletion src/utils/ignore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function validExtensions(context: ChildContext | RuleContext) {
export function getFileExtensions(settings: PluginSettings) {
// start with explicit JS-parsed extensions
const exts = new Set<FileExtension>(
settings['import-x/extensions'] || ['.js'],
settings['import-x/extensions'] || ['.js', '.mjs', '.cjs'],
)

// all alternate parser extensions are also valid
Expand Down

0 comments on commit cd52e86

Please sign in to comment.