@@ -4,7 +4,10 @@ import eslint from '@eslint/js';
44import eslintConfigPrettier from 'eslint-config-prettier' ;
55import nodePlugin from 'eslint-plugin-n' ;
66import pluginPromise from 'eslint-plugin-promise' ;
7+ import security from 'eslint-plugin-security' ;
8+ import sonarjs from 'eslint-plugin-sonarjs' ;
79import eslintPluginUnicorn from 'eslint-plugin-unicorn' ;
10+ import unusedImports from 'eslint-plugin-unused-imports' ;
811import globals from 'globals' ;
912import path from 'node:path' ;
1013import { fileURLToPath } from 'node:url' ;
@@ -15,16 +18,24 @@ const __dirname = path.dirname(__filename);
1518const gitignorePath = path . resolve ( __dirname , '.gitignore' ) ;
1619
1720export default tseslint . config (
21+ // Base configurations
1822 eslint . configs . recommended ,
1923 ...tseslint . configs . strict ,
2024 ...tseslint . configs . stylistic ,
25+
26+ // Plugin configurations
2127 nodePlugin . configs [ 'flat/recommended' ] ,
22- eslintPluginUnicorn . configs [ 'flat/ recommended' ] ,
28+ eslintPluginUnicorn . configs [ 'recommended' ] ,
2329 pluginPromise . configs [ 'flat/recommended' ] ,
30+ security . configs [ 'recommended' ] ,
31+ sonarjs . configs [ 'recommended' ] ,
32+
33+ // Global language options
2434 {
35+ name : 'Global Language Options' ,
2536 languageOptions : {
2637 parser : tseslint . parser ,
27- ecmaVersion : 2022 ,
38+ ecmaVersion : 2024 ,
2839 sourceType : 'module' ,
2940 globals : {
3041 ...globals . node ,
@@ -34,61 +45,134 @@ export default tseslint.config(
3445 {
3546 name : 'Global Ignores' ,
3647 ignores : [
37- ...includeIgnoreFile ( gitignorePath ) . ignores ,
48+ ...( includeIgnoreFile ( gitignorePath ) . ignores ?? [ ] ) ,
3849 '/.cache' ,
3950 '/.git' ,
4051 '/.husky' ,
4152 '/.yarn' ,
53+ 'dist/**' ,
54+ 'build/**' ,
55+ 'coverage/**' ,
4256 '.dependency-cruiser.js' ,
4357 'cucumber.setup.js' ,
4458 'eslint.config.mjs' ,
59+ '**/*.d.ts' ,
4560 ] ,
4661 } ,
4762 {
48- files : [ '**/*.ts' ] ,
63+ plugins : {
64+ 'unused-imports' : unusedImports ,
65+ } ,
4966 rules : {
50- '@typescript-eslint/ban-ts-ignore' : 'off' ,
51- '@typescript-eslint/consistent-type-definitions' : 'off' ,
52- '@typescript-eslint/explicit-function-return-type' : 'off' ,
53- '@typescript-eslint/explicit-member-accessibility' : 'off' ,
54- '@typescript-eslint/explicit-module-boundary-types' : 'off' ,
55- '@typescript-eslint/indent' : 'off' ,
56- '@typescript-eslint/member-delimiter-style' : 'off' ,
57- '@typescript-eslint/no-empty-interface' : 'off' ,
67+ 'no-unused-vars' : 'off' ,
68+ 'unused-imports/no-unused-imports' : 'error' ,
69+ 'unused-imports/no-unused-vars' : [
70+ 'warn' ,
71+ {
72+ vars : 'all' ,
73+ varsIgnorePattern : '^_' ,
74+ args : 'after-used' ,
75+ argsIgnorePattern : '^_' ,
76+ } ,
77+ ] ,
78+ } ,
79+ } ,
80+ {
81+ name : 'Security and Code Quality' ,
82+ rules : {
83+ // Security rules - important for backend APIs
84+ 'security/detect-object-injection' : 'off' ,
85+ 'security/detect-non-literal-regexp' : 'warn' ,
86+ 'security/detect-unsafe-regex' : 'error' ,
87+ 'security/detect-buffer-noassert' : 'error' ,
88+ 'security/detect-child-process' : 'warn' ,
89+ 'security/detect-disable-mustache-escape' : 'error' ,
90+ 'security/detect-eval-with-expression' : 'error' ,
91+ 'security/detect-new-buffer' : 'error' ,
92+ 'security/detect-no-csrf-before-method-override' : 'error' ,
93+ 'security/detect-possible-timing-attacks' : 'warn' ,
94+ 'security/detect-pseudoRandomBytes' : 'error' ,
95+
96+ // SonarJS rules - code quality and bug prevention
97+ 'sonarjs/cognitive-complexity' : [ 'warn' , 15 ] ,
98+ 'sonarjs/no-duplicate-string' : [ 'warn' , { threshold : 3 } ] ,
99+ 'sonarjs/no-duplicated-branches' : 'error' ,
100+ 'sonarjs/no-identical-functions' : 'error' ,
101+ 'sonarjs/no-small-switch' : 'error' ,
102+ 'sonarjs/prefer-immediate-return' : 'warn' ,
103+ 'sonarjs/prefer-object-literal' : 'warn' ,
104+ 'sonarjs/prefer-single-boolean-return' : 'warn' ,
105+ 'sonarjs/no-nested-template-literals' : 'warn' ,
106+ 'sonarjs/no-redundant-boolean' : 'error' ,
107+ 'sonarjs/no-unused-collection' : 'error' ,
108+ 'sonarjs/no-useless-catch' : 'error' ,
109+ 'sonarjs/todo-tag' : 'off' ,
110+ 'sonarjs/no-commented-code' : 'off' ,
111+ 'sonarjs/function-return-type' : 'off' ,
112+ 'sonarjs/no-empty-test-file' : 'off' ,
113+ 'sonarjs/no-alphabetical-sort' : 'off' ,
114+ } ,
115+ } ,
116+ {
117+ name : 'TypeScript Rules' ,
118+ files : [ '**/*.ts' , '**/*.tsx' ] ,
119+ languageOptions : {
120+ parserOptions : {
121+ project : true ,
122+ tsconfigRootDir : __dirname ,
123+ } ,
124+ } ,
125+ rules : {
126+ '@typescript-eslint/no-unused-vars' : 'off' ,
127+ 'no-undef' : 'off' ,
58128 '@typescript-eslint/no-explicit-any' : 'off' ,
59129 '@typescript-eslint/no-floating-promises' : 'off' ,
60- '@typescript-eslint/no-object-literal-type-assertion' : 'off' ,
61- '@typescript-eslint/no-unsafe-argument' : 'off' ,
62- '@typescript-eslint/no-unsafe-assignment' : 'off' ,
63- '@typescript-eslint/no-unsafe-call' : 'off' ,
64- '@typescript-eslint/no-unsafe-member-access' : 'off' ,
65- '@typescript-eslint/no-unsafe-return' : 'off' ,
66- '@typescript-eslint/no-var-requires' : 'off' ,
130+ '@typescript-eslint/await-thenable' : 'error' ,
131+ '@typescript-eslint/prefer-nullish-coalescing' : 'warn' ,
132+ '@typescript-eslint/prefer-optional-chain' : 'warn' ,
133+ '@typescript-eslint/explicit-function-return-type' : 'off' ,
134+ '@typescript-eslint/explicit-module-boundary-types' : 'off' ,
67135 '@typescript-eslint/require-await' : 'off' ,
68- '@typescript-eslint/prefer-nullish-coalescing' : 'off' ,
69- '@typescript-eslint/unbound-method' : 'off' ,
70- '@typescript-eslint/no-empty-object-type' : 'off' ,
136+ '@typescript-eslint/no-unnecessary-condition' : 'off' ,
71137 'n/no-missing-import' : 'off' ,
72138 'n/no-unpublished-import' : 'off' ,
73- 'import/extensions' : 'off' ,
74- 'import/no-cycle' : 'off' ,
75- 'import/no-extraneous-dependencies' : 'off' ,
76- 'import/order' : 'off' ,
77- 'import/prefer-default-export' : 'off' ,
78- 'no-restricted-exports' : 'off' ,
79- 'no-undef' : 'off' ,
80- 'func-names' : 'off' ,
81- 'no-unused-vars' : 'off' ,
82- 'no-use-before-define' : 'off' ,
83- 'promise/always-return' : 'off' ,
84- 'promise/catch-or-return' : 'off' ,
139+ 'n/prefer-global/process' : 'error' ,
140+ 'n/prefer-global/buffer' : 'error' ,
141+ 'n/prefer-promises/dns' : 'error' ,
142+ 'n/prefer-promises/fs' : 'error' ,
143+ 'promise/prefer-await-to-then' : 'warn' ,
144+ 'promise/prefer-await-to-callbacks' : 'warn' ,
145+ 'unicorn/no-array-callback-reference' : 'off' ,
85146 'unicorn/filename-case' : 'off' ,
147+ 'unicorn/no-null' : 'off' ,
148+ 'unicorn/consistent-function-scoping' : 'off' ,
86149 'unicorn/prefer-module' : 'off' ,
87- 'unicorn/prefer-top-level-await' : 'off' ,
88150 'unicorn/prevent-abbreviations' : 'off' ,
151+ 'unicorn/prefer-top-level-await' : 'off' ,
89152 'unicorn/no-array-reduce' : 'off' ,
90- 'unicorn/no-abusive-eslint-disable' : 'off' ,
91- 'unicorn/no-array-callback-reference' : 'off' ,
153+ } ,
154+ } ,
155+ {
156+ name : 'Test Files' ,
157+ files : [
158+ '**/*.test.ts' ,
159+ '**/*.spec.ts' ,
160+ '**/test/**/*.ts' ,
161+ '**/tests/**/*.ts' ,
162+ ] ,
163+ rules : {
164+ 'sonarjs/no-duplicate-string' : 'off' ,
165+ '@typescript-eslint/no-explicit-any' : 'off' ,
166+ '@typescript-eslint/no-non-null-assertion' : 'off' ,
167+ 'unicorn/no-null' : 'off' ,
168+ } ,
169+ } ,
170+ {
171+ name : 'Configuration Files' ,
172+ files : [ '*.config.{js,ts,mjs}' , '.*.{js,ts,mjs}' , './scripts/**/*' ] ,
173+ rules : {
174+ 'unicorn/prefer-module' : 'off' ,
175+ '@typescript-eslint/no-var-requires' : 'off' ,
92176 } ,
93177 } ,
94178 eslintConfigPrettier ,
0 commit comments