2025-10-03 16:51:44 +02:00
import { dirname , resolve } from 'node:path' ;
import { fileURLToPath } from 'node:url' ;
import pluginVue from 'eslint-plugin-vue' ;
import vueTsEslintConfig from '@vue/eslint-config-typescript' ;
import tsParser from '@typescript-eslint/parser' ;
import stylistic from '@stylistic/eslint-plugin' ;
import prettier from 'eslint-config-prettier' ;
const _ _filename = fileURLToPath ( import . meta . url ) ;
const _ _dirname = dirname ( _ _filename ) ;
export default [
{
name : 'app/files-to-lint' ,
files : [ '**/*.{ts,mts,tsx,vue}' ] ,
languageOptions : {
parser : tsParser ,
parserOptions : {
2026-02-19 20:18:27 +01:00
projectService : {
defaultProject : resolve ( _ _dirname , 'tsconfig.app.json' ) ,
} ,
2025-10-03 16:51:44 +02:00
tsconfigRootDir : _ _dirname ,
sourceType : 'module' ,
ecmaVersion : 'latest' ,
allowDefaultProject : true ,
} ,
} ,
plugins : {
'@stylistic' : stylistic ,
} ,
} ,
{
name : 'app/files-to-ignore' ,
ignores : [ '**/dist/**' , '**/dist-ssr/**' , '**/coverage/**' , '**/node_modules/**' , '**/.ponder/**' , '**/__tests__/**' ] ,
} ,
... pluginVue . configs [ 'flat/essential' ] ,
... vueTsEslintConfig ( ) ,
{
name : 'app/custom-rules' ,
rules : {
// TypeScript rules
'@typescript-eslint/no-explicit-any' : 'error' ,
'@typescript-eslint/no-unused-vars' : [
'error' ,
{
argsIgnorePattern : '^_' ,
varsIgnorePattern : '^_' ,
caughtErrorsIgnorePattern : '^_' ,
} ,
] ,
// General code quality
'no-console' : 'error' ,
'@stylistic/indent' : [ 'error' , 2 , { SwitchCase : 1 } ] ,
'max-len' : [ 'error' , { code : 140 } ] ,
// Vue specific rules
'vue/multi-word-component-names' : 'error' ,
'vue/component-name-in-template-casing' : [ 'error' , 'PascalCase' ] ,
'vue/require-prop-types' : 'error' ,
'vue/require-default-prop' : 'error' ,
'vue/html-indent' : [ 'error' , 2 ] ,
'vue/no-unused-vars' : 'error' ,
// Disable rules that conflict with Prettier
'vue/max-attributes-per-line' : 'off' ,
'vue/singleline-html-element-content-newline' : 'off' ,
'vue/html-self-closing' : 'off' ,
// Naming conventions
camelcase : [ 'error' , { properties : 'never' , ignoreDestructuring : true , allow : [ '^UNSAFE_' ] } ] ,
// Complexity rules (disabled as per requirements)
complexity : 'off' ,
'max-depth' : 'off' ,
'max-lines' : 'off' ,
'max-params' : 'off' ,
} ,
} ,
2026-02-24 20:44:17 +00:00
{
name : 'arch/graphql-no-interpolation' ,
rules : {
'no-restricted-syntax' : [
'error' ,
{
selector :
"Property[key.name='query'] > TemplateLiteral[expressions.length>0], Property[key.name='mutation'] > TemplateLiteral[expressions.length>0]" ,
message :
'String interpolation used in a GraphQL query or mutation string. GraphQL queries must not use string interpolation — it bypasses type-checking and is unsafe. Use the `variables` parameter in the fetch body instead. Example: `variables: { holder: address }`. See PR #191 for the pattern.' ,
} ,
] ,
} ,
} ,
2025-10-03 16:51:44 +02:00
{
name : 'app/tests-override' ,
files : [ 'src/**/__tests__/**/*.ts' , 'src/**/__tests__/**/*.tsx' ] ,
languageOptions : {
parserOptions : {
projectService : false ,
project : undefined ,
} ,
} ,
} ,
prettier ,
] ;