321 lines
9.0 KiB
JavaScript
321 lines
9.0 KiB
JavaScript
import js from '@eslint/js';
|
|
import { defineConfig } from 'eslint/config';
|
|
import tseslint from 'typescript-eslint';
|
|
import prettierConfig from 'eslint-config-prettier';
|
|
import prettierPlugin from 'eslint-plugin-prettier';
|
|
import react from 'eslint-plugin-react';
|
|
import reactHooks from 'eslint-plugin-react-hooks';
|
|
import globals from 'globals';
|
|
import path from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
|
const reactPackageRules = {
|
|
// TypeScript rules
|
|
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
'@typescript-eslint/no-explicit-any': 'warn',
|
|
'@typescript-eslint/no-unused-vars': [
|
|
'error',
|
|
{
|
|
argsIgnorePattern: '^_',
|
|
varsIgnorePattern: '^_',
|
|
},
|
|
],
|
|
'@typescript-eslint/no-non-null-assertion': 'warn',
|
|
'@typescript-eslint/strict-boolean-expressions': 'off',
|
|
'@typescript-eslint/no-floating-promises': 'error',
|
|
'@typescript-eslint/no-misused-promises': 'error',
|
|
'@typescript-eslint/await-thenable': 'error',
|
|
'@typescript-eslint/require-await': 'error',
|
|
|
|
// Naming conventions
|
|
'@typescript-eslint/naming-convention': [
|
|
'error',
|
|
// Variables and parameters - camelCase
|
|
{
|
|
selector: ['parameter', 'function'],
|
|
format: ['camelCase', 'PascalCase'],
|
|
leadingUnderscore: 'allow',
|
|
trailingUnderscore: 'forbid',
|
|
},
|
|
// Types, interfaces, type parameters, classes - PascalCase
|
|
{
|
|
selector: ['typeLike', 'class'],
|
|
format: ['PascalCase'],
|
|
},
|
|
// Enum members - UPPER_CASE
|
|
{
|
|
selector: 'enumMember',
|
|
format: ['UPPER_CASE'],
|
|
},
|
|
// React components (functions starting with capital letter) - PascalCase
|
|
{
|
|
selector: 'variable',
|
|
format: ['camelCase', 'PascalCase', 'UPPER_CASE'],
|
|
leadingUnderscore: 'allow',
|
|
},
|
|
],
|
|
|
|
// React rules
|
|
'react/react-in-jsx-scope': 'off',
|
|
'react/prop-types': 'off',
|
|
'react/jsx-uses-react': 'off',
|
|
'react/jsx-uses-vars': 'error',
|
|
'react/jsx-no-duplicate-props': 'error',
|
|
'react/jsx-no-undef': 'error',
|
|
'react/jsx-pascal-case': 'error',
|
|
'react/no-children-prop': 'error',
|
|
'react/no-danger-with-children': 'error',
|
|
'react/no-deprecated': 'error',
|
|
'react/no-direct-mutation-state': 'error',
|
|
'react/no-find-dom-node': 'error',
|
|
'react/no-is-mounted': 'error',
|
|
'react/no-render-return-value': 'error',
|
|
'react/no-string-refs': 'error',
|
|
'react/no-unescaped-entities': 'error',
|
|
'react/no-unknown-property': 'error',
|
|
'react/require-render-return': 'error',
|
|
'react/self-closing-comp': 'error',
|
|
|
|
// React Hooks rules
|
|
'react-hooks/rules-of-hooks': 'error',
|
|
'react-hooks/exhaustive-deps': 'warn',
|
|
|
|
// General rules
|
|
'no-console': ['warn', { allow: ['warn', 'error'] }],
|
|
'no-debugger': 'error',
|
|
'no-duplicate-imports': 'error',
|
|
'no-unused-expressions': 'error',
|
|
'prefer-const': 'error',
|
|
'no-var': 'error',
|
|
eqeqeq: ['error', 'always'],
|
|
curly: ['error', 'all'],
|
|
|
|
// Prettier integration
|
|
'prettier/prettier': 'error',
|
|
};
|
|
|
|
function createReactPackageConfig(packageDir, project) {
|
|
return {
|
|
basePath: path.join(__dirname, packageDir),
|
|
files: ['**/*.ts', '**/*.tsx'],
|
|
ignores: ['tests/**/*', '**/*.test.*', '**/*.spec.*'],
|
|
languageOptions: {
|
|
ecmaVersion: 'latest',
|
|
sourceType: 'module',
|
|
parserOptions: {
|
|
project,
|
|
tsconfigRootDir: __dirname,
|
|
ecmaFeatures: {
|
|
jsx: true,
|
|
},
|
|
},
|
|
globals: {
|
|
...globals.browser,
|
|
...globals.es2021,
|
|
...globals.node,
|
|
},
|
|
},
|
|
plugins: {
|
|
react: react,
|
|
'react-hooks': reactHooks,
|
|
prettier: prettierPlugin,
|
|
},
|
|
settings: {
|
|
react: {
|
|
version: 'detect',
|
|
},
|
|
},
|
|
rules: reactPackageRules,
|
|
};
|
|
}
|
|
|
|
export default defineConfig(
|
|
js.configs.recommended,
|
|
...tseslint.configs.recommended,
|
|
prettierConfig,
|
|
// Frontend and shared React packages configuration
|
|
createReactPackageConfig('frontend', './frontend/tsconfig.json'),
|
|
createReactPackageConfig('packages/dashboard', './packages/dashboard/tsconfig.json'),
|
|
createReactPackageConfig('packages/ui', './packages/ui/tsconfig.json'),
|
|
// Backend configuration
|
|
{
|
|
files: ['backend/**/*.ts', 'backend/**/*.tsx'],
|
|
ignores: ['backend/tests/**/*', 'backend/**/*.test.*', 'backend/**/*.spec.*'],
|
|
languageOptions: {
|
|
ecmaVersion: 'latest',
|
|
sourceType: 'module',
|
|
parserOptions: {
|
|
project: './backend/tsconfig.json',
|
|
tsconfigRootDir: __dirname,
|
|
},
|
|
globals: {
|
|
...globals.node,
|
|
...globals.es2021,
|
|
},
|
|
},
|
|
plugins: {
|
|
prettier: prettierPlugin,
|
|
},
|
|
rules: {
|
|
// TypeScript rules
|
|
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
'@typescript-eslint/no-explicit-any': 'warn',
|
|
'@typescript-eslint/no-unused-vars': [
|
|
'error',
|
|
{
|
|
argsIgnorePattern: '^_',
|
|
varsIgnorePattern: '^_',
|
|
},
|
|
],
|
|
'@typescript-eslint/no-non-null-assertion': 'warn',
|
|
'@typescript-eslint/strict-boolean-expressions': 'off',
|
|
'@typescript-eslint/no-floating-promises': 'error',
|
|
'@typescript-eslint/no-misused-promises': [
|
|
'error',
|
|
{
|
|
checksVoidReturn: {
|
|
arguments: false,
|
|
attributes: false,
|
|
},
|
|
},
|
|
],
|
|
'@typescript-eslint/await-thenable': 'error',
|
|
'@typescript-eslint/require-await': 'error',
|
|
|
|
// General rules
|
|
'no-console': ['warn', { allow: ['warn', 'error'] }],
|
|
'no-debugger': 'error',
|
|
'no-duplicate-imports': 'error',
|
|
'no-unused-expressions': 'error',
|
|
'prefer-const': 'error',
|
|
'no-var': 'error',
|
|
eqeqeq: ['error', 'always'],
|
|
curly: ['error', 'all'],
|
|
|
|
// Prettier integration
|
|
'prettier/prettier': 'error',
|
|
},
|
|
},
|
|
{
|
|
basePath: path.join(__dirname, 'packages/dashboard'),
|
|
files: ['**/*.ts', '**/*.tsx'],
|
|
rules: {
|
|
'no-restricted-imports': [
|
|
'error',
|
|
{
|
|
patterns: [
|
|
{
|
|
regex: '^\\.\\.(?:/|$)',
|
|
message:
|
|
'Use relative imports only within the same folder. Use dashboard #... aliases for imports outside the current folder.',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
},
|
|
// Shared schemas configuration - minimal rules for schema definitions
|
|
{
|
|
files: ['packages/shared-schemas/**/*.ts'],
|
|
languageOptions: {
|
|
ecmaVersion: 'latest',
|
|
sourceType: 'module',
|
|
parserOptions: {
|
|
project: './packages/shared-schemas/tsconfig.json',
|
|
tsconfigRootDir: __dirname,
|
|
},
|
|
globals: {
|
|
...globals.node,
|
|
...globals.es2021,
|
|
},
|
|
},
|
|
plugins: {
|
|
prettier: prettierPlugin,
|
|
},
|
|
rules: {
|
|
// Minimal TypeScript rules for schema definitions
|
|
'@typescript-eslint/no-explicit-any': 'error', // Schemas should be strongly typed
|
|
'@typescript-eslint/no-unused-vars': [
|
|
'error',
|
|
{
|
|
argsIgnorePattern: '^_',
|
|
varsIgnorePattern: '^_',
|
|
},
|
|
],
|
|
|
|
// Naming conventions for schemas
|
|
'@typescript-eslint/naming-convention': [
|
|
'error',
|
|
// Exported types - PascalCase
|
|
{
|
|
selector: ['typeLike', 'class'],
|
|
format: ['PascalCase'],
|
|
},
|
|
// Enum members - UPPER_CASE
|
|
{
|
|
selector: 'enumMember',
|
|
format: ['UPPER_CASE'],
|
|
},
|
|
// Shared schemas model external wire contracts. Object literal keys may
|
|
// intentionally use snake_case while local identifiers stay camelCase.
|
|
{
|
|
selector: 'objectLiteralProperty',
|
|
format: ['camelCase', 'snake_case'],
|
|
leadingUnderscore: 'allow',
|
|
},
|
|
// Allow exported constant maps like ERROR_CODES.
|
|
{
|
|
selector: 'variable',
|
|
modifiers: ['const', 'global'],
|
|
format: ['camelCase', 'UPPER_CASE', 'PascalCase'],
|
|
leadingUnderscore: 'allow',
|
|
},
|
|
// Default for everything else - camelCase
|
|
{
|
|
selector: 'default',
|
|
format: ['camelCase'],
|
|
leadingUnderscore: 'allow',
|
|
},
|
|
],
|
|
|
|
// Essential rules
|
|
'no-duplicate-imports': 'error',
|
|
'prefer-const': 'error',
|
|
|
|
// Prettier integration
|
|
'prettier/prettier': 'error',
|
|
},
|
|
},
|
|
// Global ignores
|
|
{
|
|
ignores: [
|
|
'**/node_modules/**',
|
|
'**/dist/**',
|
|
'**/build/**',
|
|
'**/.next/**',
|
|
'**/coverage/**',
|
|
'**/.turbo/**',
|
|
'**/public/**',
|
|
'**/*.config.js',
|
|
'**/*.config.ts',
|
|
'**/vite.config.ts',
|
|
'**/vitest.config.ts',
|
|
'tailwind.config.js',
|
|
'eslint.config.js',
|
|
'**/*.md',
|
|
'**/*.yaml',
|
|
'**/*.yml',
|
|
'**/*.json',
|
|
'docs/**',
|
|
'examples/**',
|
|
'openapi/**',
|
|
'functions/',
|
|
'backend/src/infra/database/migrations/bootstrap/**', // Bootstrap scripts run before build
|
|
],
|
|
}
|
|
);
|