teqo/eslint.config.mjs
Francisco Ignácio Fontoura Solla bcac665cb5 Ship /campanha nuclei MVP with RBAC, invites, and vote estimates.
Adds electoral nuclei, leaderships, updates, and WhatsApp invite flows behind campaign auth, plus the consolidated schema migration that Vercel applies on deploy.
2026-07-18 15:01:56 -03:00

145 lines
4 KiB
JavaScript

import { dirname } from 'path'
import { fileURLToPath } from 'url'
import { FlatCompat } from '@eslint/eslintrc'
import { globalIgnores } from 'eslint/config'
import prettier from 'eslint-config-prettier/flat'
import checkFile from 'eslint-plugin-check-file'
import { localRules } from './eslint-local-rules.mjs'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
// eslint-config-next ships legacy (eslintrc) configs, so wrap them with
// FlatCompat to use them from this flat config with ESLint 9.
const compat = new FlatCompat({ baseDirectory: __dirname })
const frameworkComponentFiles = [
'src/app/**/{page,layout,loading,error,not-found,template,default,global-error}.tsx',
]
// These predate the naming convention. Keep them linted by Next's rules while
// requiring new component files to use PascalCase.
const legacyComponentFilenameIgnores = [
'src/components/campaign/campaign-logo.tsx',
'src/components/socialIcons.tsx',
'src/components/socialLinks.tsx',
'src/components/ui/breadcrumb.tsx',
'src/components/ui/button.tsx',
'src/components/ui/card.tsx',
'src/components/ui/combobox.tsx',
'src/components/ui/dialog.tsx',
'src/components/ui/field.tsx',
'src/components/ui/input-group.tsx',
'src/components/ui/input.tsx',
'src/components/ui/label.tsx',
'src/components/ui/native-select.tsx',
'src/components/ui/select.tsx',
'src/components/ui/separator.tsx',
'src/components/ui/skeleton.tsx',
'src/components/ui/textarea.tsx',
'src/components/ui/tooltip.tsx',
]
const legacyFrameworkExportIgnores = [
'src/app/(payload)/admin/\\[\\[...segments\\]\\]/not-found.tsx',
'src/app/(payload)/admin/\\[\\[...segments\\]\\]/page.tsx',
'src/app/(payload)/layout.tsx',
]
const legacyComponentSyntaxIgnores = [
'src/components/StateSelect.tsx',
'src/components/ThemeProvider.tsx',
]
const legacyCamelCaseFilenameIgnores = [
'src/lib/schemas/campaign-login.ts',
'src/lib/schemas/petition-form.ts',
'src/lib/schemas/whatsapp-form.ts',
'tests/int/petition-page-layout.int.spec.ts',
]
const eslintConfig = [
...compat.extends('next/core-web-vitals', 'next/typescript'),
{
files: ['src/**/*.tsx'],
ignores: [
...frameworkComponentFiles,
...legacyComponentFilenameIgnores,
...legacyFrameworkExportIgnores,
...legacyComponentSyntaxIgnores,
],
plugins: {
'check-file': checkFile,
local: localRules,
},
rules: {
'check-file/filename-naming-convention': [
'error',
{
'**/*.tsx': 'PASCAL_CASE',
},
],
'local/component-arrow-conventions': 'error',
'local/no-component-default-export': 'error',
'react/function-component-definition': [
'error',
{
namedComponents: 'arrow-function',
unnamedComponents: 'arrow-function',
},
],
},
},
{
files: frameworkComponentFiles,
ignores: legacyFrameworkExportIgnores,
plugins: {
'check-file': checkFile,
local: localRules,
},
rules: {
'check-file/filename-naming-convention': [
'error',
{
'**/*.tsx': '@(page|layout|loading|error|not-found|template|default|global-error)',
},
],
'local/framework-default-export': 'error',
'react/function-component-definition': 'off',
},
},
{
files: [
'src/components/**/*.{js,ts}',
'src/lib/**/*.{js,ts}',
'src/utilities/**/*.{js,ts}',
'tests/**/*.{js,jsx,ts,tsx}',
],
ignores: legacyCamelCaseFilenameIgnores,
plugins: {
'check-file': checkFile,
},
rules: {
'check-file/filename-naming-convention': [
'error',
{
'**/*.{js,jsx,ts,tsx}': 'CAMEL_CASE',
},
{
ignoreMiddleExtensions: true,
},
],
},
},
prettier,
// Override default ignores of eslint-config-next.
globalIgnores([
// Default ignores of eslint-config-next:
'.next/**',
'out/**',
'build/**',
'next-env.d.ts',
]),
]
export default eslintConfig