import eslint from '@eslint/js' import tseslint from 'typescript-eslint' import prettierConfig from 'eslint-config-prettier' import pluginNode from 'eslint-plugin-n' import pluginSecurity from 'eslint-plugin-security' export default tseslint.config( { ignores: [ '**/node_modules/**', '**/dist/**', '**/build/**', '**/.git/**', '**/coverage/**', '**/*.config.js', '**/*.config.mjs', 'prisma/migrations/**', ], }, eslint.configs.recommended, ...tseslint.configs.strictTypeChecked, ...tseslint.configs.stylisticTypeChecked, { files: ['**/*.ts', '**/*.js', '**/*.mjs'], plugins: { '@typescript-eslint': tseslint.plugin, n: pluginNode, security: pluginSecurity, }, languageOptions: { parser: tseslint.parser, parserOptions: { project: './tsconfig.json', tsconfigRootDir: import.meta.dirname, ecmaVersion: 'latest', sourceType: 'module', }, globals: { // Node.js ć…šć±€ć˜é‡ console: 'readonly', process: 'readonly', Buffer: 'readonly', __dirname: 'readonly', __filename: 'readonly', }, }, rules: { 'n/no-process-exit': 'error', 'n/no-deprecated-api': 'error', 'n/no-unpublished-import': [ 'error', { allowModules: [ 'fastify', '@fastify/autoload', '@fastify/cors', '@fastify/jwt', '@fastify/sensible', 'prisma', '@prisma/client', 'vitest', 'tsx', ], }, ], 'n/prefer-global/buffer': ['error', 'always'], 'n/prefer-global/console': ['error', 'always'], 'n/prefer-global/process': ['error', 'always'], 'no-console': ['warn', { allow: ['warn', 'error', 'info'] }], 'no-await-in-loop': 'warn', 'no-return-await': 'off', '@typescript-eslint/no-floating-promises': 'error', '@typescript-eslint/require-await': 'warn', '@typescript-eslint/no-misused-promises': 'error', '@typescript-eslint/await-thenable': 'error', '@typescript-eslint/return-await': ['error', 'in-try-catch'], '@typescript-eslint/no-unused-vars': [ 'error', { argsIgnorePattern: '^_|^reply|^request', varsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_', }, ], '@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off', '@typescript-eslint/no-explicit-any': 'warn', '@typescript-eslint/consistent-type-imports': [ 'error', { prefer: 'type-imports', fixStyle: 'separate-type-imports', }, ], '@typescript-eslint/no-unnecessary-type-assertion': 'error', '@typescript-eslint/prefer-nullish-coalescing': 'warn', '@typescript-eslint/prefer-optional-chain': 'warn', '@typescript-eslint/no-non-null-assertion': 'warn', 'no-throw-literal': 'off', '@typescript-eslint/only-throw-error': 'error', '@typescript-eslint/prefer-promise-reject-errors': 'error', 'security/detect-object-injection': 'warn', 'security/detect-non-literal-regexp': 'warn', 'security/detect-unsafe-regex': 'error', 'security/detect-buffer-noassert': 'error', 'security/detect-eval-with-expression': 'error', 'security/detect-non-literal-fs-filename': 'warn', 'security/detect-possible-timing-attacks': 'warn', 'no-nested-ternary': 'warn', 'max-depth': ['warn', 4], 'max-lines-per-function': [ 'warn', { max: 150, skipBlankLines: true, skipComments: true, }, ], complexity: ['warn', 15], 'sort-imports': [ 'error', { ignoreCase: true, ignoreDeclarationSort: true, }, ], '@typescript-eslint/no-confusing-void-expression': ['error', { ignoreArrowShorthand: true }], '@typescript-eslint/promise-function-async': 'error', }, }, { files: ['**/*.test.ts', '**/*.spec.ts', '**/tests/**/*.ts'], rules: { '@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/no-non-null-assertion': 'off', '@typescript-eslint/no-unsafe-assignment': 'off', '@typescript-eslint/no-unsafe-member-access': 'off', 'max-lines-per-function': 'off', 'n/no-unpublished-import': 'off', }, }, { files: ['*.config.js', '*.config.mjs', '*.config.ts'], rules: { 'n/no-unpublished-import': 'off', '@typescript-eslint/no-var-requires': 'off', '@typescript-eslint/no-require-imports': 'off', }, }, prettierConfig )