// ESLint 9+ flat config // TypeScript configuration import tsParser from '@typescript-eslint/parser'; import tsPlugin from '@typescript-eslint/eslint-plugin'; export default [ { // TypeScript files files: ['**/*.{ts,tsx}'], languageOptions: { parser: tsParser, parserOptions: { ecmaVersion: 2022, sourceType: 'module', project: './tsconfig.json', }, globals: { // Node.js globals process: 'readonly', console: 'readonly', Buffer: 'readonly', __dirname: 'readonly', __filename: 'readonly', global: 'readonly', module: 'readonly', require: 'readonly', exports: 'writable', // Common test globals describe: 'readonly', it: 'readonly', test: 'readonly', expect: 'readonly', beforeEach: 'readonly', afterEach: 'readonly', beforeAll: 'readonly', afterAll: 'readonly', vi: 'readonly', }, }, plugins: { '@typescript-eslint': tsPlugin, }, rules: { // Possible errors 'no-console': 'off', // Allow console in Node.js 'no-debugger': 'warn', 'no-dupe-keys': 'error', 'no-duplicate-case': 'error', 'no-empty': ['error', { allowEmptyCatch: true }], 'no-ex-assign': 'error', 'no-extra-boolean-cast': 'error', 'no-func-assign': 'error', 'no-irregular-whitespace': 'error', 'no-unreachable': 'error', 'valid-typeof': 'error', // Best practices 'curly': ['error', 'all'], 'eqeqeq': ['error', 'always', { null: 'ignore' }], 'no-eval': 'error', 'no-implied-eval': 'error', 'no-return-await': 'off', // Disabled in favor of TS version '@typescript-eslint/return-await': 'error', 'no-throw-literal': 'error', 'no-unused-expressions': 'error', 'no-useless-concat': 'error', 'no-useless-return': 'error', 'prefer-promise-reject-errors': 'error', // Variables - use TypeScript versions 'no-undef': 'off', // TypeScript handles this 'no-unused-vars': 'off', // Use TypeScript version '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_', }], // TypeScript specific '@typescript-eslint/no-explicit-any': 'warn', '@typescript-eslint/no-non-null-assertion': 'warn', '@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off', // Stylistic (basic only, prefer Prettier for formatting) 'indent': ['error', 2, { SwitchCase: 1 }], 'quotes': ['error', 'single', { avoidEscape: true }], 'semi': ['error', 'always'], 'comma-dangle': ['error', 'always-multiline'], 'no-trailing-spaces': 'error', 'eol-last': ['error', 'always'], }, }, { // JavaScript files (no TypeScript parser) files: ['**/*.{js,mjs,cjs}'], languageOptions: { ecmaVersion: 2022, sourceType: 'module', globals: { // Node.js globals process: 'readonly', console: 'readonly', Buffer: 'readonly', __dirname: 'readonly', __filename: 'readonly', global: 'readonly', module: 'readonly', require: 'readonly', exports: 'writable', // Browser globals (for gateway/ui) window: 'readonly', document: 'readonly', fetch: 'readonly', WebSocket: 'readonly', location: 'readonly', URLSearchParams: 'readonly', navigator: 'readonly', alert: 'readonly', confirm: 'readonly', setTimeout: 'readonly', setInterval: 'readonly', clearTimeout: 'readonly', clearInterval: 'readonly', }, }, rules: { // Possible errors 'no-console': 'off', 'no-debugger': 'warn', 'no-dupe-keys': 'error', 'no-duplicate-case': 'error', 'no-empty': ['error', { allowEmptyCatch: true }], 'no-ex-assign': 'error', 'no-extra-boolean-cast': 'error', 'no-func-assign': 'error', 'no-irregular-whitespace': 'error', 'no-unreachable': 'error', 'valid-typeof': 'error', // Best practices 'curly': ['error', 'all'], 'eqeqeq': ['error', 'always', { null: 'ignore' }], 'no-eval': 'error', 'no-implied-eval': 'error', 'no-throw-literal': 'error', 'no-unused-expressions': 'error', 'no-useless-concat': 'error', 'no-useless-return': 'error', // Variables 'no-undef': 'error', 'no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_', }], // Stylistic 'indent': ['error', 2, { SwitchCase: 1 }], 'quotes': ['error', 'single', { avoidEscape: true }], 'semi': ['error', 'always'], 'comma-dangle': ['error', 'always-multiline'], 'no-trailing-spaces': 'error', 'eol-last': ['error', 'always'], }, }, { // Ignore patterns ignores: [ 'dist/**', 'node_modules/**', '**/*.d.ts', 'coverage/**', '.pnpm-store/**', ], }, ];