-
Notifications
You must be signed in to change notification settings - Fork 167
Expand file tree
/
Copy patheslint.config.mjs
More file actions
266 lines (237 loc) · 8 KB
/
eslint.config.mjs
File metadata and controls
266 lines (237 loc) · 8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
/**
* Root ESLint configuration for The Graph projects
* This configuration is automatically picked up by ESLint
*/
import { existsSync, readFileSync } from 'node:fs'
import path from 'node:path'
import eslint from '@eslint/js'
import typescriptPlugin from '@typescript-eslint/eslint-plugin'
import prettier from 'eslint-config-prettier'
import importPlugin from 'eslint-plugin-import'
import noOnlyTests from 'eslint-plugin-no-only-tests'
import simpleImportSort from 'eslint-plugin-simple-import-sort'
import unusedImportsPlugin from 'eslint-plugin-unused-imports'
import globals from 'globals'
// Function to find the Git repository root by looking for .git directory
function findRepoRoot(startDir) {
let currentDir = startDir
// Traverse up the directory tree until we find .git or reach the filesystem root
while (currentDir !== path.parse(currentDir).root) {
if (existsSync(path.join(currentDir, '.git'))) {
return currentDir
}
currentDir = path.dirname(currentDir)
}
// If we couldn't find .git, return the starting directory
return startDir
}
// Function to translate .gitignore patterns to ESLint glob patterns
function translateGitignorePatterns(gitignorePath, repoRoot) {
try {
const content = readFileSync(gitignorePath, 'utf8')
const originalPatterns = content.split('\n').filter((line) => line.trim() && !line.startsWith('#'))
// Filter out negation patterns for now as ESLint doesn't handle them correctly
const nonNegationPatterns = originalPatterns.filter((line) => !line.startsWith('!'))
const translatedPatterns = nonNegationPatterns.map((line) => {
// Convert .gitignore patterns to ESLint glob patterns
// Preserve the distinction between patterns:
// - dirname/ (matches at any level) -> **/dirname/
// - /dirname/ (matches only at root) -> /absolute/path/to/repo/dirname/
if (line.startsWith('/')) {
// Root-level pattern - convert to absolute path relative to repo root
// This ensures it works correctly regardless of where ESLint is invoked from
return path.join(repoRoot, line.substring(1))
} else {
// Any-level pattern, add **/ prefix if not already there
return line.startsWith('**/') ? line : `**/${line}`
}
})
// Create a mapping of original to translated patterns for debugging
const patternMap = {}
originalPatterns.forEach((pattern) => {
if (pattern.startsWith('!')) {
patternMap[pattern] = `[NEGATION PATTERN - NOT SUPPORTED BY ESLINT]`
} else {
const index = nonNegationPatterns.indexOf(pattern)
if (index !== -1) {
patternMap[pattern] = translatedPatterns[index]
}
}
})
return {
originalPatterns,
translatedPatterns,
patternMap,
}
} catch (error) {
console.warn(`Could not read .gitignore file: ${error.message}`)
return {
originalPatterns: [],
translatedPatterns: [],
patternMap: {},
}
}
}
// Function to include .gitignore patterns in ESLint config
function includeGitignore() {
// Get the repository root directory (where .git is located)
// This ensures patterns are resolved correctly regardless of where ESLint is invoked from
const repoRoot = findRepoRoot(path.resolve('.'))
const gitignorePath = path.join(repoRoot, '.gitignore')
// Translate the patterns
const { originalPatterns, translatedPatterns, patternMap } = translateGitignorePatterns(gitignorePath, repoRoot)
// Debug output if DEBUG_GITIGNORE environment variable is set
if (process.env.DEBUG_GITIGNORE) {
console.log('\n=== .gitignore Pattern Translations ===')
console.log('Repository root:', repoRoot)
console.log('Pattern mappings:')
// Count negation patterns
const negationPatterns = originalPatterns.filter((p) => p.startsWith('!')).length
if (negationPatterns > 0) {
console.log(`\n WARNING: Found ${negationPatterns} negation patterns in .gitignore.`)
console.log(' Negation patterns (starting with !) are not supported by ESLint and will be ignored.')
console.log(' Files matching these patterns will still be ignored.\n')
}
Object.entries(patternMap).forEach(([original, translated]) => {
console.log(` ${original} -> ${translated}`)
})
console.log('=======================================\n')
}
return {
ignores: translatedPatterns,
}
}
// Export the translation function for use in other contexts
export function getGitignorePatterns(customGitignorePath = null) {
const repoRoot = findRepoRoot(path.resolve('.'))
const gitignorePath = customGitignorePath || path.join(repoRoot, '.gitignore')
return translateGitignorePatterns(gitignorePath, repoRoot)
}
/** @type {import('eslint').Linter.Config[]} */
const eslintConfig = [
// Include .gitignore patterns
includeGitignore(),
eslint.configs.recommended,
// Import plugin configuration
{
plugins: {
import: importPlugin,
'simple-import-sort': simpleImportSort,
},
rules: {
// Turn off the original import/order rule
'import/order': 'off',
// Configure simple-import-sort and set to 'error' to enforce sorting
'simple-import-sort/imports': 'error',
'simple-import-sort/exports': 'error',
},
},
// Unused imports plugin configuration
{
plugins: {
'unused-imports': unusedImportsPlugin,
},
rules: {
'unused-imports/no-unused-imports': 'warn',
},
},
// Custom config for TypeScript files
{
files: ['**/*.ts', '**/*.tsx'],
languageOptions: {
parser: (await import('@typescript-eslint/parser')).default,
parserOptions: {
ecmaVersion: 2022,
sourceType: 'module',
},
globals: {
...globals.node,
},
},
plugins: {
'@typescript-eslint': typescriptPlugin,
'no-only-tests': noOnlyTests,
},
rules: {
'prefer-const': 'warn',
'no-only-tests/no-only-tests': 'error',
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/ban-ts-comment': 'warn',
'no-unused-vars': 'off', // Turn off base rule
'@typescript-eslint/no-unused-vars': [
'error',
{
varsIgnorePattern: '^_|Null|Active|Closed|graph|_i',
argsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
},
],
},
},
// Custom config for JavaScript files
{
files: ['**/*.js', '**/*.cjs', '**/*.mjs', '**/*.jsx'],
languageOptions: {
ecmaVersion: 2022,
sourceType: 'module',
globals: {
...globals.node,
},
},
plugins: {
'no-only-tests': noOnlyTests,
},
rules: {
'prefer-const': 'warn',
'no-only-tests/no-only-tests': 'error',
'no-unused-vars': [
'error',
{
varsIgnorePattern: '^_|Null|Active|Closed|graph|_i',
argsIgnorePattern: '^_',
},
],
},
},
// Add Mocha globals for test files
{
files: ['**/*.test.ts', '**/*.test.js', '**/test*/**/*.ts', '**/test*/**/*.js'],
languageOptions: {
globals: {
...globals.mocha,
},
},
rules: {
// Allow 'any' types in test files where they're often necessary for testing edge cases
'@typescript-eslint/no-explicit-any': 'off',
},
},
// Add Hardhat globals for hardhat config files
{
files: ['**/hardhat.config.ts', '**/hardhat.config.js', '**/tasks/**/*.ts', '**/tasks/**/*.js'],
languageOptions: {
globals: {
...globals.node,
task: 'readonly',
HardhatUserConfig: 'readonly',
},
},
},
// Prettier configuration (to avoid conflicts)
prettier,
// Additional global ignores and unignores
{
ignores: [
// Autogenerated GraphClient files (committed but should not be linted)
'**/.graphclient-extracted/**',
'**/.graphclient/**',
// Third-party dependencies (Forge libraries, etc.)
'**/lib/**',
],
},
// Explicitly include packages that should be linted
{
files: ['packages/**/*.{js,ts,cjs,mjs,jsx,tsx}'],
},
]
export default eslintConfig