Update
This commit is contained in:
200
src/basic.ts
200
src/basic.ts
@ -1,38 +1,56 @@
|
||||
// @ts-check
|
||||
import type { ESLintConfig } from 'eslint-define-config';
|
||||
|
||||
function unique<T>(arr: T[]): T[] {
|
||||
return [...new Set(arr)];
|
||||
}
|
||||
|
||||
const error = 'error';
|
||||
const warn = 'warn';
|
||||
const off = 'off';
|
||||
|
||||
export function extendConfig({
|
||||
plugins,
|
||||
settings,
|
||||
rules,
|
||||
...config
|
||||
extends: _extends,
|
||||
...rest
|
||||
}: ESLintConfig): ESLintConfig {
|
||||
return {
|
||||
const hasReact = plugins?.includes('react');
|
||||
const hasUnicorn = plugins?.includes('unicorn');
|
||||
|
||||
const result: ESLintConfig = {
|
||||
root: true,
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['@typescript-eslint', 'import', ...(plugins ?? [])],
|
||||
env: { node: true, browser: true },
|
||||
plugins: unique(['@typescript-eslint', 'import', ...(plugins ?? [])]),
|
||||
env: { node: true, browser: true, es2023: true },
|
||||
reportUnusedDisableDirectives: true,
|
||||
parserOptions: { project: ['./tsconfig.json'] },
|
||||
extends: [
|
||||
parserOptions: {
|
||||
project: ['./tsconfig.json'],
|
||||
},
|
||||
extends: unique([
|
||||
'eslint:recommended',
|
||||
'prettier',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:@typescript-eslint/recommended-type-checked',
|
||||
'plugin:import/errors',
|
||||
'plugin:import/typescript',
|
||||
'plugin:react/recommended',
|
||||
'plugin:react-hooks/recommended',
|
||||
'plugin:jsx-a11y/recommended',
|
||||
],
|
||||
...(hasReact
|
||||
? [
|
||||
'plugin:react/recommended',
|
||||
'plugin:react-hooks/recommended',
|
||||
'plugin:jsx-a11y/recommended',
|
||||
]
|
||||
: []),
|
||||
...(hasUnicorn ? ['plugin:unicorn/recommended'] : []),
|
||||
...(_extends ?? []),
|
||||
]),
|
||||
settings: {
|
||||
'import/parsers': {
|
||||
'@typescript-eslint/parser': ['.ts', '.tsx'],
|
||||
'@typescript-eslint/parser': ['.ts', '.tsx', '.mts', '.cts'],
|
||||
},
|
||||
'import/core-modules': ['node:test'],
|
||||
'import/resolver': {
|
||||
typescript: {
|
||||
alwaysTryTypes: true,
|
||||
project: './tsconfig.json',
|
||||
},
|
||||
},
|
||||
react: {
|
||||
@ -41,9 +59,9 @@ export function extendConfig({
|
||||
...settings,
|
||||
},
|
||||
rules: {
|
||||
'no-duplicate-imports': 'error',
|
||||
'no-duplicate-imports': error,
|
||||
'no-restricted-imports': [
|
||||
'error',
|
||||
error,
|
||||
{
|
||||
paths: [
|
||||
{
|
||||
@ -54,78 +72,104 @@ export function extendConfig({
|
||||
],
|
||||
},
|
||||
],
|
||||
'no-restricted-globals': ['error', 'event', 'name'],
|
||||
'@typescript-eslint/ban-ts-comment': 'off',
|
||||
'@typescript-eslint/consistent-type-imports': [
|
||||
'error',
|
||||
{ disallowTypeAnnotations: false, fixStyle: 'inline-type-imports' },
|
||||
],
|
||||
'@typescript-eslint/ban-types': [
|
||||
'error',
|
||||
'no-restricted-globals': [error, 'event', 'name', 'length'],
|
||||
'@typescript-eslint/ban-ts-comment': [
|
||||
error,
|
||||
{
|
||||
extendDefaults: false,
|
||||
types: {
|
||||
String: { message: 'Use string instead', fixWith: 'string' },
|
||||
Number: { message: 'Use number instead', fixWith: 'number' },
|
||||
Boolean: { message: 'Use boolean instead', fixWith: 'boolean' },
|
||||
Symbol: { message: 'Use symbol instead', fixWith: 'symbol' },
|
||||
},
|
||||
'ts-expect-error': 'allow-with-description',
|
||||
'ts-check': false,
|
||||
'ts-ignore': 'allow-with-description',
|
||||
'ts-nocheck': 'allow-with-description',
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-namespace': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
'@typescript-eslint/no-use-before-define': 'off',
|
||||
'@typescript-eslint/no-var-requires': 'off',
|
||||
'@typescript-eslint/triple-slash-reference': 'off',
|
||||
'@typescript-eslint/no-empty-interface': 'off',
|
||||
'@typescript-eslint/no-unnecessary-type-assertion': 'error',
|
||||
'@typescript-eslint/consistent-type-imports': [
|
||||
error,
|
||||
{ disallowTypeAnnotations: false, fixStyle: 'inline-type-imports' },
|
||||
],
|
||||
'@typescript-eslint/ban-types': [error, { extendDefaults: true }],
|
||||
'@typescript-eslint/no-empty-interface': [error, { allowSingleExtends: true }],
|
||||
'@typescript-eslint/no-explicit-any': off,
|
||||
'@typescript-eslint/no-extraneous-class': error,
|
||||
'@typescript-eslint/no-namespace': off,
|
||||
'@typescript-eslint/no-unnecessary-type-assertion': error,
|
||||
'@typescript-eslint/no-unsafe-argument': off,
|
||||
'@typescript-eslint/no-unsafe-assignment': off,
|
||||
'@typescript-eslint/no-unsafe-member-access': off,
|
||||
'@typescript-eslint/no-unsafe-call': off,
|
||||
'@typescript-eslint/no-unsafe-return': off,
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
error,
|
||||
{ ignoreRestSiblings: true, varsIgnorePattern: '^_' },
|
||||
],
|
||||
'arrow-body-style': ['error', 'as-needed'],
|
||||
'class-methods-use-this': 'off',
|
||||
complexity: ['warn', { max: 100 }],
|
||||
curly: ['error', 'multi-line', 'consistent'],
|
||||
eqeqeq: ['error', 'smart'],
|
||||
'no-async-promise-executor': 'off',
|
||||
'no-case-declarations': 'off',
|
||||
'no-console': 'warn',
|
||||
'no-constant-condition': ['error', { checkLoops: false }],
|
||||
'no-debugger': 'off',
|
||||
'no-empty': ['error', { allowEmptyCatch: true }],
|
||||
'no-inner-declarations': 'off',
|
||||
'no-lonely-if': 'error',
|
||||
'no-template-curly-in-string': 'error',
|
||||
'no-var': 'error',
|
||||
'import/export': 'off',
|
||||
'import/order': ['error', { groups: ['builtin', 'external'] }],
|
||||
'object-shorthand': ['error', 'always', { ignoreConstructors: true }],
|
||||
'one-var': ['error', { var: 'never', let: 'never' }],
|
||||
'prefer-arrow-callback': 'error',
|
||||
'prefer-const': ['error', { destructuring: 'all' }],
|
||||
'@typescript-eslint/no-use-before-define': off,
|
||||
'@typescript-eslint/no-var-requires': off,
|
||||
'@typescript-eslint/unbound-method': off,
|
||||
'@typescript-eslint/triple-slash-reference': off,
|
||||
'arrow-body-style': [error, 'as-needed'],
|
||||
'class-methods-use-this': off,
|
||||
complexity: [warn, { max: 100 }],
|
||||
curly: [error, 'multi-line', 'consistent'],
|
||||
eqeqeq: [error, 'smart'],
|
||||
'no-async-promise-executor': off,
|
||||
'no-case-declarations': off,
|
||||
'no-console': warn,
|
||||
'no-constant-condition': [error, { checkLoops: false }],
|
||||
'no-debugger': warn,
|
||||
'no-empty': [error, { allowEmptyCatch: true }],
|
||||
'no-inner-declarations': off,
|
||||
'no-lonely-if': error,
|
||||
'no-template-curly-in-string': error,
|
||||
'no-var': error,
|
||||
'import/export': off,
|
||||
'import/order': [error, { groups: ['builtin', 'external'] }],
|
||||
'object-shorthand': [error, 'always', { ignoreConstructors: true }],
|
||||
'one-var': [error, { var: 'never', let: 'never' }],
|
||||
'prefer-arrow-callback': error,
|
||||
'prefer-const': [error, { destructuring: 'all' }],
|
||||
'prefer-destructuring': [
|
||||
'warn',
|
||||
warn,
|
||||
{ AssignmentExpression: { array: false, object: false } },
|
||||
],
|
||||
'prefer-object-spread': 'error',
|
||||
'prefer-rest-params': 'warn',
|
||||
'prefer-spread': 'warn',
|
||||
'quote-props': ['error', 'as-needed'],
|
||||
'spaced-comment': ['error', 'always', { markers: ['/'] }],
|
||||
'sort-imports': ['warn', { ignoreDeclarationSort: true }],
|
||||
yoda: ['error', 'never', { exceptRange: true }],
|
||||
'react/display-name': 'off',
|
||||
'react/no-children-prop': 'error',
|
||||
'react/prop-types': 'off',
|
||||
'react/react-in-jsx-scope': 'off',
|
||||
'react/no-unknown-property': ['error', { ignore: ['css'] }],
|
||||
'prefer-object-spread': error,
|
||||
'prefer-rest-params': warn,
|
||||
'prefer-spread': warn,
|
||||
'quote-props': [error, 'as-needed'],
|
||||
'spaced-comment': [error, 'always', { markers: ['/'] }],
|
||||
'sort-imports': [warn, { ignoreDeclarationSort: true }],
|
||||
yoda: [error, 'never', { exceptRange: true }],
|
||||
...(hasReact
|
||||
? {
|
||||
'react/display-name': off,
|
||||
'react/no-children-prop': error,
|
||||
'react/prop-types': off,
|
||||
'react/react-in-jsx-scope': off,
|
||||
'react/no-unknown-property': [error, { ignore: ['css'] }],
|
||||
}
|
||||
: {}),
|
||||
...(hasUnicorn
|
||||
? {
|
||||
'unicorn/no-abusive-eslint-disable': off,
|
||||
'unicorn/no-array-callback-reference': off,
|
||||
'unicorn/no-array-for-each': warn,
|
||||
'unicorn/no-array-reduce': off,
|
||||
'unicorn/no-await-expression-member': off,
|
||||
'unicorn/no-empty-file': off,
|
||||
'unicorn/no-negated-condition': warn,
|
||||
'unicorn/no-new-array': off,
|
||||
'unicorn/no-null': off,
|
||||
'unicorn/no-process-exit': off,
|
||||
'unicorn/no-this-assignment': off,
|
||||
'unicorn/prefer-module': off,
|
||||
'unicorn/prefer-string-replace-all': off,
|
||||
'unicorn/prefer-top-level-await': off,
|
||||
'unicorn/throw-new-error': off,
|
||||
'unicorn/no-unnecessary-await': off,
|
||||
}
|
||||
: {}),
|
||||
...rules,
|
||||
},
|
||||
...config,
|
||||
...rest,
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
import type { Rule } from 'eslint';
|
||||
|
||||
import noImportDot from "./no-import-dot";
|
||||
import requireNodePrefix from "./require-node-prefix"
|
||||
import noImportDot from "./no-import-dot"
|
||||
|
||||
export const rules: Record<string, Rule.RuleModule> = {
|
||||
"no-import-dot": noImportDot,
|
||||
"require-node-prefix": requireNodePrefix
|
||||
"no-import-dot": noImportDot
|
||||
};
|
@ -1,36 +0,0 @@
|
||||
// @ts-check
|
||||
import { builtinModules } from "node:module";
|
||||
import type { Rule } from "eslint";
|
||||
|
||||
const rule: Rule.RuleModule = {
|
||||
meta: {
|
||||
type: "problem",
|
||||
docs: {
|
||||
description:
|
||||
"Disallow imports of built-in Node.js modules without the `node:` prefix",
|
||||
category: "Best Practices",
|
||||
recommended: true,
|
||||
},
|
||||
fixable: "code",
|
||||
schema: [],
|
||||
},
|
||||
create: context => ({
|
||||
ImportDeclaration(node) {
|
||||
const { source } = node;
|
||||
|
||||
if (source?.type === "Literal" && typeof source.value === "string") {
|
||||
const moduleName = source.value;
|
||||
|
||||
if (builtinModules.includes(moduleName) && !moduleName.startsWith("node:")) {
|
||||
context.report({
|
||||
node: source,
|
||||
message: `Import of built-in Node.js module "${moduleName}" must use the "node:" prefix.`,
|
||||
fix: fixer => fixer.replaceText(source, `"node:${moduleName}"`),
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
export default rule;
|
Reference in New Issue
Block a user