chore: strengthen backend eslint profile
This commit is contained in:
+77
-33
@@ -1,31 +1,71 @@
|
||||
// @ts-check
|
||||
import nest from '@darraghor/eslint-plugin-nestjs-typed';
|
||||
import eslint from '@eslint/js';
|
||||
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
|
||||
import stylistic from '@stylistic/eslint-plugin';
|
||||
import { createTypeScriptImportResolver } from 'eslint-import-resolver-typescript';
|
||||
import { importX } from 'eslint-plugin-import-x';
|
||||
import jest from 'eslint-plugin-jest';
|
||||
import node from 'eslint-plugin-n';
|
||||
import perfectionist from 'eslint-plugin-perfectionist';
|
||||
import regexp from 'eslint-plugin-regexp';
|
||||
import security from 'eslint-plugin-security';
|
||||
import sonarjs from 'eslint-plugin-sonarjs';
|
||||
import { defineConfig, globalIgnores } from 'eslint/config';
|
||||
import globals from 'globals';
|
||||
import tseslint from 'typescript-eslint';
|
||||
|
||||
export default tseslint.config(
|
||||
const tests = ['**/*.spec.ts', 'test/**/*.ts'];
|
||||
|
||||
export default defineConfig(
|
||||
globalIgnores(['dist/**', 'dist-dev/**', 'build/**', 'generated/**', 'coverage/**', 'node_modules/**']),
|
||||
{
|
||||
ignores: ['eslint.config.mjs', 'dist/', 'generated/'],
|
||||
},
|
||||
eslint.configs.recommended,
|
||||
...tseslint.configs.recommendedTypeChecked,
|
||||
eslintPluginPrettierRecommended,
|
||||
{
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node,
|
||||
...globals.jest,
|
||||
},
|
||||
sourceType: 'commonjs',
|
||||
parserOptions: {
|
||||
projectService: true,
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
files: ['**/*.{ts,js,cjs,mjs}'],
|
||||
extends: [
|
||||
eslint.configs.recommended,
|
||||
node.configs['flat/recommended'],
|
||||
importX.flatConfigs.recommended,
|
||||
sonarjs.configs.recommended,
|
||||
regexp.configs['flat/recommended'],
|
||||
security.configs.recommended,
|
||||
perfectionist.configs['recommended-natural'],
|
||||
stylistic.configs.customize({ indent: 2, quotes: 'single', semi: true, jsx: false }),
|
||||
],
|
||||
languageOptions: { globals: globals.node },
|
||||
linterOptions: { reportUnusedDisableDirectives: 'error' },
|
||||
settings: {
|
||||
'import-x/resolver-next': [createTypeScriptImportResolver()],
|
||||
'node': { tryExtensions: ['.ts', '.js', '.json', '.node'], version: '24.21.0' },
|
||||
},
|
||||
rules: {
|
||||
'curly': ['error', 'multi-line'],
|
||||
// This private application is deployed as a whole, never published to npm.
|
||||
'n/no-unpublished-import': 'off',
|
||||
'n/no-unpublished-require': 'off',
|
||||
// Decorator execution and object insertion order can be observable at runtime.
|
||||
'perfectionist/sort-decorators': 'off',
|
||||
'perfectionist/sort-objects': 'off',
|
||||
'perfectionist/sort-modules': 'off',
|
||||
'perfectionist/sort-classes': 'off',
|
||||
'@stylistic/brace-style': ['error', '1tbs', { allowSingleLine: false }],
|
||||
'@stylistic/arrow-parens': ['error', 'always'],
|
||||
'@stylistic/operator-linebreak': ['error', 'after'],
|
||||
'import-x/no-duplicates': ['error', { 'prefer-inline': true }],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.mjs'],
|
||||
extends: [node.configs['flat/recommended-module']],
|
||||
},
|
||||
{
|
||||
files: ['**/*.ts'],
|
||||
extends: [tseslint.configs.recommendedTypeChecked, importX.flatConfigs.typescript],
|
||||
languageOptions: {
|
||||
sourceType: 'module',
|
||||
parserOptions: { projectService: true, tsconfigRootDir: import.meta.dirname },
|
||||
},
|
||||
rules: {
|
||||
// TypeScript resolves source imports; import-x checks them with the TS resolver.
|
||||
'n/no-missing-import': 'off',
|
||||
'no-magic-numbers': 'off',
|
||||
'@typescript-eslint/no-magic-numbers': [
|
||||
'error',
|
||||
@@ -63,24 +103,28 @@ export default tseslint.config(
|
||||
enforceConst: true,
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'error',
|
||||
'no-restricted-syntax': [
|
||||
'error',
|
||||
{
|
||||
selector:
|
||||
'PropertyDefinition[definite=true], VariableDeclarator[definite=true]',
|
||||
message:
|
||||
'Definite assignment assertions are forbidden. Initialize owned values; use declare only for externally populated DTO fields.',
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/no-floating-promises': 'warn',
|
||||
'@typescript-eslint/no-unsafe-argument': 'warn',
|
||||
'prettier/prettier': ['error', { endOfLine: 'auto' }],
|
||||
'no-restricted-syntax': ['error', {
|
||||
selector: 'PropertyDefinition[definite=true], VariableDeclarator[definite=true]',
|
||||
message: 'Definite assignment assertions are forbidden. Initialize owned values; use declare only for externally populated DTO fields.',
|
||||
}],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.spec.ts', 'test/**/*.ts'],
|
||||
rules: { '@typescript-eslint/no-magic-numbers': 'off' },
|
||||
files: ['src/**/*.ts'],
|
||||
ignores: tests,
|
||||
extends: [nest.configs.flatRecommended],
|
||||
rules: {
|
||||
// Domain string unions are validated with IsIn rather than runtime TS enums.
|
||||
'@darraghor/nestjs-typed/validated-non-primitive-property-needs-type-decorator': ['error', { additionalTypeDecorators: ['IsIn'] }],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: tests,
|
||||
extends: [jest.configs['flat/recommended']],
|
||||
rules: {
|
||||
'@typescript-eslint/no-magic-numbers': 'off',
|
||||
'jest/expect-expect': ['error', { assertFunctionNames: ['expect', '**.expect'] }],
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user