@sun-asterisk/sunlint 1.0.5 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +119 -384
- package/core/cli-action-handler.js +169 -4
- package/core/cli-program.js +20 -4
- package/core/config-manager.js +84 -5
- package/core/file-targeting-service.js +386 -0
- package/core/multi-rule-runner.js +9 -27
- package/core/output-service.js +5 -6
- package/docs/FILE_TARGETING_COMPARISON.md +0 -0
- package/examples/README.md +56 -34
- package/examples/basic-typescript-demo/.eslintrc.json +18 -0
- package/examples/basic-typescript-demo/.next/cache/eslint/.cache_1othrmo +1 -0
- package/examples/basic-typescript-demo/.sunlint.json +29 -0
- package/examples/basic-typescript-demo/eslint.config.mjs +37 -0
- package/examples/basic-typescript-demo/next-env.d.ts +5 -0
- package/examples/basic-typescript-demo/next.config.mjs +4 -0
- package/examples/basic-typescript-demo/package-lock.json +5656 -0
- package/examples/basic-typescript-demo/package.json +34 -0
- package/examples/basic-typescript-demo/src/app/layout.tsx +18 -0
- package/examples/basic-typescript-demo/src/app/page.tsx +48 -0
- package/examples/basic-typescript-demo/src/config.ts +14 -0
- package/examples/basic-typescript-demo/src/good-practices.ts +58 -0
- package/examples/basic-typescript-demo/src/types.generated.ts +13 -0
- package/examples/basic-typescript-demo/src/user.test.ts +19 -0
- package/examples/basic-typescript-demo/src/violations.ts +61 -0
- package/examples/basic-typescript-demo/test-config-priority.sh +0 -0
- package/examples/basic-typescript-demo/test-file-targeting.sh +0 -0
- package/examples/basic-typescript-demo/tsconfig.json +27 -0
- package/examples/enhanced-config.json +0 -0
- package/examples/eslint-integration-demo/.eslintrc.js +38 -0
- package/examples/eslint-integration-demo/.sunlint.json +42 -0
- package/examples/eslint-integration-demo/next-env.d.ts +5 -0
- package/examples/eslint-integration-demo/next.config.js +8 -0
- package/examples/eslint-integration-demo/package-lock.json +5740 -0
- package/examples/eslint-integration-demo/package.json +37 -0
- package/examples/eslint-integration-demo/src/api.test.ts +20 -0
- package/examples/eslint-integration-demo/src/conflict-test.tsx +44 -0
- package/examples/eslint-integration-demo/src/naming-conflicts.ts +50 -0
- package/examples/eslint-integration-demo/test-file-targeting.sh +0 -0
- package/examples/eslint-integration-demo/tsconfig.json +26 -0
- package/examples/file-targeting-demo/global.d.ts +11 -0
- package/examples/file-targeting-demo/jest.config.js +8 -0
- package/examples/file-targeting-demo/sample.ts +53 -0
- package/examples/file-targeting-demo/src/server.js +11 -0
- package/examples/file-targeting-demo/src/server.test.js +11 -0
- package/examples/file-targeting-demo/src/types.d.ts +4 -0
- package/examples/file-targeting-demo/src/types.generated.ts +10 -0
- package/examples/file-targeting-demo/user-service.test.ts +15 -0
- package/examples/file-targeting-demo/user-service.ts +13 -0
- package/examples/file-targeting-demo/utils.js +15 -0
- package/examples/multi-language-project/.eslintrc.json +38 -0
- package/examples/multi-language-project/package.json +37 -0
- package/examples/multi-language-project/src/sample.ts +39 -0
- package/examples/rule-test-fixtures/README.md +67 -0
- package/examples/rule-test-fixtures/rules/C006_function_naming/clean/typescript-clean.ts +64 -0
- package/examples/rule-test-fixtures/rules/C006_function_naming/violations/dart-violations.dart +56 -0
- package/examples/rule-test-fixtures/rules/C006_function_naming/violations/typescript-violations.ts +47 -0
- package/examples/rule-test-fixtures/rules/C019_log_level_usage/clean/typescript-clean.ts +93 -0
- package/examples/rule-test-fixtures/rules/C019_log_level_usage/violations/dart-violations.dart +75 -0
- package/examples/rule-test-fixtures/rules/C019_log_level_usage/violations/typescript-violations.ts +84 -0
- package/examples/rule-test-fixtures/rules/C029_catch_block_logging/clean/typescript-clean.ts +0 -0
- package/examples/rule-test-fixtures/rules/C029_catch_block_logging/violations/typescript-violations.ts +37 -0
- package/package.json +2 -1
- package/eslint-integration/eslint-plugin-custom/c076-one-assert-per-test.js +0 -184
- package/examples/.sunlint.json +0 -42
- package/examples/package.json +0 -33
- /package/{eslint-integration/node_modules/eslint-plugin-custom/package.json → docs/ENHANCED_FILE_TARGETING.md} +0 -0
|
@@ -10,6 +10,7 @@ const RuleSelectionService = require('./rule-selection-service');
|
|
|
10
10
|
const AnalysisOrchestrator = require('./analysis-orchestrator');
|
|
11
11
|
const OutputService = require('./output-service');
|
|
12
12
|
const GitUtils = require('./git-utils');
|
|
13
|
+
const FileTargetingService = require('./file-targeting-service');
|
|
13
14
|
|
|
14
15
|
class CliActionHandler {
|
|
15
16
|
constructor(options = {}) {
|
|
@@ -18,6 +19,7 @@ class CliActionHandler {
|
|
|
18
19
|
this.ruleSelectionService = new RuleSelectionService();
|
|
19
20
|
this.analysisOrchestrator = new AnalysisOrchestrator();
|
|
20
21
|
this.outputService = new OutputService(options);
|
|
22
|
+
this.fileTargetingService = new FileTargetingService();
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
async execute() {
|
|
@@ -45,8 +47,19 @@ class CliActionHandler {
|
|
|
45
47
|
return;
|
|
46
48
|
}
|
|
47
49
|
|
|
50
|
+
// Apply enhanced file targeting
|
|
51
|
+
const targetingResult = await this.applyFileTargeting(config);
|
|
52
|
+
if (targetingResult.files.length === 0) {
|
|
53
|
+
console.log(chalk.yellow('⚠️ No files to analyze after applying filters'));
|
|
54
|
+
this.displayTargetingStats(targetingResult.stats);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Update options with filtered files
|
|
59
|
+
this.options.targetFiles = targetingResult.files;
|
|
60
|
+
|
|
48
61
|
// Display analysis info
|
|
49
|
-
this.displayAnalysisInfo(rulesToRun);
|
|
62
|
+
this.displayAnalysisInfo(rulesToRun, targetingResult);
|
|
50
63
|
|
|
51
64
|
// Run analysis
|
|
52
65
|
const startTime = Date.now();
|
|
@@ -121,7 +134,11 @@ class CliActionHandler {
|
|
|
121
134
|
return await this.configManager.loadConfig(this.options.config, this.options);
|
|
122
135
|
} catch (error) {
|
|
123
136
|
console.log(chalk.yellow('⚠️ Using default configuration'));
|
|
124
|
-
|
|
137
|
+
// Return default config instead of empty object
|
|
138
|
+
if (!this.configManager) {
|
|
139
|
+
this.configManager = new ConfigManager();
|
|
140
|
+
}
|
|
141
|
+
return this.configManager.defaultConfig;
|
|
125
142
|
}
|
|
126
143
|
}
|
|
127
144
|
|
|
@@ -192,30 +209,178 @@ class CliActionHandler {
|
|
|
192
209
|
}
|
|
193
210
|
}
|
|
194
211
|
|
|
212
|
+
/**
|
|
213
|
+
* Apply enhanced file targeting logic
|
|
214
|
+
* Rule C006: applyFileTargeting - verb-noun naming
|
|
215
|
+
*/
|
|
216
|
+
async applyFileTargeting(config) {
|
|
217
|
+
// Debug config
|
|
218
|
+
if (this.options.debug) {
|
|
219
|
+
console.log('🐛 Debug applyFileTargeting config:', JSON.stringify(config.testPatterns, null, 2));
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Prepare CLI options for file targeting
|
|
223
|
+
const targetingOptions = {
|
|
224
|
+
include: this.options.include ? this.options.include.split(',') : null,
|
|
225
|
+
exclude: this.options.exclude ? this.options.exclude.split(',') : null,
|
|
226
|
+
languages: this.options.languages,
|
|
227
|
+
excludeTests: this.options.excludeTests,
|
|
228
|
+
includeTests: this.options.includeTests,
|
|
229
|
+
onlySource: this.options.onlySource
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
if (this.options.debug) {
|
|
233
|
+
console.log('🐛 Debug targetingOptions:', targetingOptions);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Determine input paths
|
|
237
|
+
let inputPaths = [this.options.input];
|
|
238
|
+
|
|
239
|
+
// Handle git-based file filtering
|
|
240
|
+
if (this.options.changedFiles || this.options.stagedFiles || this.options.since || this.options.prMode) {
|
|
241
|
+
inputPaths = this.getGitFilteredFiles();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Apply file targeting
|
|
245
|
+
if (this.options.debug) {
|
|
246
|
+
console.log('🐛 Calling fileTargetingService.getTargetFiles with inputPaths:', inputPaths);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return await this.fileTargetingService.getTargetFiles(inputPaths, config, targetingOptions);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Get files based on git filtering
|
|
254
|
+
* Rule C006: getGitFilteredFiles - verb-noun naming
|
|
255
|
+
*/
|
|
256
|
+
getGitFilteredFiles() {
|
|
257
|
+
try {
|
|
258
|
+
let files = [];
|
|
259
|
+
|
|
260
|
+
if (this.options.changedFiles) {
|
|
261
|
+
const diffBase = this.options.diffBase || GitUtils.getPRDiffBase('main');
|
|
262
|
+
files = GitUtils.getChangedFiles(diffBase);
|
|
263
|
+
} else if (this.options.stagedFiles) {
|
|
264
|
+
files = GitUtils.getStagedFiles();
|
|
265
|
+
} else if (this.options.since) {
|
|
266
|
+
files = GitUtils.getChangedFilesSince(this.options.since);
|
|
267
|
+
} else if (this.options.prMode) {
|
|
268
|
+
const diffBase = this.options.diffBase || GitUtils.getPRDiffBase('main');
|
|
269
|
+
files = GitUtils.getChangedFiles(diffBase);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (files.length === 0) {
|
|
273
|
+
console.log(chalk.yellow('⚠️ No changed files found'));
|
|
274
|
+
return [];
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (this.options.verbose) {
|
|
278
|
+
console.log(chalk.gray(`🔍 Found ${files.length} changed files`));
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return files.map(file => require('path').resolve(file));
|
|
282
|
+
} catch (error) {
|
|
283
|
+
console.error(chalk.red('❌ Git operation failed:'), error.message);
|
|
284
|
+
if (this.options.debug) {
|
|
285
|
+
console.error(error.stack);
|
|
286
|
+
}
|
|
287
|
+
return [this.options.input]; // Fallback to regular input
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Display file targeting statistics
|
|
293
|
+
* Rule C006: displayTargetingStats - verb-noun naming
|
|
294
|
+
*/
|
|
295
|
+
displayTargetingStats(stats) {
|
|
296
|
+
if (this.options.quiet || this.options.format === 'json') {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
console.log(chalk.blue('\n📊 File Targeting Results:'));
|
|
301
|
+
console.log(chalk.gray(` Total files: ${stats.totalFiles}`));
|
|
302
|
+
|
|
303
|
+
if (Object.keys(stats.byLanguage).length > 0) {
|
|
304
|
+
console.log(chalk.gray(' By language:'));
|
|
305
|
+
for (const [language, count] of Object.entries(stats.byLanguage)) {
|
|
306
|
+
if (count > 0) {
|
|
307
|
+
console.log(chalk.gray(` ${language}: ${count} files`));
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
console.log(chalk.gray(' By category:'));
|
|
313
|
+
console.log(chalk.gray(` Source: ${stats.byCategory.source} files`));
|
|
314
|
+
console.log(chalk.gray(` Test: ${stats.byCategory.test} files`));
|
|
315
|
+
console.log(chalk.gray(` Config: ${stats.byCategory.config} files`));
|
|
316
|
+
console.log(chalk.gray(` Other: ${stats.byCategory.other} files`));
|
|
317
|
+
}
|
|
318
|
+
|
|
195
319
|
async showDryRunPreview(config) {
|
|
196
320
|
console.log(chalk.yellow('🔍 Dry run mode - Analysis preview:'));
|
|
321
|
+
|
|
322
|
+
// Apply file targeting to show which files would be analyzed
|
|
323
|
+
const targetingResult = await this.applyFileTargeting(config);
|
|
197
324
|
const rulesToRun = await this.ruleSelectionService.selectRules(config, this.options);
|
|
198
325
|
|
|
199
326
|
console.log(chalk.blue('📋 Sun Lint Analysis Preview:'));
|
|
200
327
|
console.log(chalk.gray(`Input: ${this.options.input}`));
|
|
201
328
|
console.log(chalk.gray(`Format: ${this.options.format}`));
|
|
202
329
|
console.log(chalk.gray(`Rules to run: ${rulesToRun.length}`));
|
|
330
|
+
console.log(chalk.gray(`Files to analyze: ${targetingResult.files.length}`));
|
|
331
|
+
|
|
332
|
+
// Show file targeting details
|
|
333
|
+
if (this.options.verbose || targetingResult.files.length <= 10) {
|
|
334
|
+
console.log(chalk.blue('\n📁 Target Files:'));
|
|
335
|
+
targetingResult.files.forEach(file => {
|
|
336
|
+
const relativePath = require('path').relative(process.cwd(), file);
|
|
337
|
+
console.log(` ${chalk.gray(relativePath)}`);
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Show targeting stats
|
|
342
|
+
this.displayTargetingStats(targetingResult.stats);
|
|
203
343
|
|
|
204
344
|
if (rulesToRun.length > 0) {
|
|
205
|
-
console.log(chalk.blue('📋 Selected Rules:'));
|
|
345
|
+
console.log(chalk.blue('\n📋 Selected Rules:'));
|
|
206
346
|
rulesToRun.forEach(rule => {
|
|
207
347
|
console.log(` ${chalk.cyan(rule.id)}: ${rule.name} (${rule.severity})`);
|
|
208
348
|
});
|
|
209
349
|
}
|
|
350
|
+
|
|
351
|
+
// Show CLI file targeting options if provided
|
|
352
|
+
if (this.options.include || this.options.exclude || this.options.languages) {
|
|
353
|
+
console.log(chalk.blue('\n🎯 File Targeting Options:'));
|
|
354
|
+
if (this.options.include) {
|
|
355
|
+
console.log(` Include: ${chalk.green(this.options.include)}`);
|
|
356
|
+
}
|
|
357
|
+
if (this.options.exclude) {
|
|
358
|
+
console.log(` Exclude: ${chalk.red(this.options.exclude)}`);
|
|
359
|
+
}
|
|
360
|
+
if (this.options.languages) {
|
|
361
|
+
console.log(` Languages: ${chalk.cyan(this.options.languages)}`);
|
|
362
|
+
}
|
|
363
|
+
if (this.options.excludeTests) {
|
|
364
|
+
console.log(` Exclude tests: ${chalk.yellow('true')}`);
|
|
365
|
+
}
|
|
366
|
+
if (this.options.onlySource) {
|
|
367
|
+
console.log(` Only source: ${chalk.yellow('true')}`);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
210
370
|
}
|
|
211
371
|
|
|
212
|
-
displayAnalysisInfo(rulesToRun) {
|
|
372
|
+
displayAnalysisInfo(rulesToRun, targetingResult) {
|
|
213
373
|
if (this.options.quiet || this.options.format === 'json') return;
|
|
214
374
|
|
|
215
375
|
console.log(chalk.green(`🚀 Running ${rulesToRun.length} rules on: ${this.options.input}`));
|
|
216
376
|
|
|
217
377
|
const ruleIds = rulesToRun.map(r => r.id).join(', ');
|
|
218
378
|
console.log(chalk.blue(` 📋 Rules: ${ruleIds}`));
|
|
379
|
+
|
|
380
|
+
// Display file targeting stats if available
|
|
381
|
+
if (targetingResult && targetingResult.stats) {
|
|
382
|
+
this.displayTargetingStats(targetingResult.stats);
|
|
383
|
+
}
|
|
219
384
|
}
|
|
220
385
|
|
|
221
386
|
handleExit(results) {
|
package/core/cli-program.js
CHANGED
|
@@ -36,6 +36,15 @@ function createCliProgram() {
|
|
|
36
36
|
.option('-o, --output <file>', 'Output file path')
|
|
37
37
|
.option('--config <file>', 'Configuration file path', '.sunlint.json');
|
|
38
38
|
|
|
39
|
+
// File targeting options
|
|
40
|
+
program
|
|
41
|
+
.option('--include <patterns>', 'Include file patterns (comma-separated globs)')
|
|
42
|
+
.option('--exclude <patterns>', 'Exclude file patterns (comma-separated globs)')
|
|
43
|
+
.option('--languages <languages>', 'Target specific languages (comma-separated: typescript,dart,kotlin)')
|
|
44
|
+
.option('--include-tests', 'Include test files in analysis (default: true)')
|
|
45
|
+
.option('--exclude-tests', 'Exclude test files from analysis')
|
|
46
|
+
.option('--only-source', 'Only analyze source files (exclude tests, configs, etc.)');
|
|
47
|
+
|
|
39
48
|
// CI/CD and Git integration options
|
|
40
49
|
program
|
|
41
50
|
.option('--changed-files', 'Only analyze files changed in current branch (git diff)')
|
|
@@ -74,6 +83,12 @@ Examples:
|
|
|
74
83
|
$ sunlint --security --input=src
|
|
75
84
|
$ sunlint --category=logging --input=src
|
|
76
85
|
|
|
86
|
+
File Targeting:
|
|
87
|
+
$ sunlint --all --include="src/**/*.ts" --exclude="**/*.test.*" --input=.
|
|
88
|
+
$ sunlint --all --languages=typescript,dart --input=src
|
|
89
|
+
$ sunlint --typescript --exclude-tests --input=src
|
|
90
|
+
$ sunlint --all --only-source --include="src/**,lib/**" --input=.
|
|
91
|
+
|
|
77
92
|
TypeScript Analysis (Phase 1):
|
|
78
93
|
$ sunlint --typescript --input=src
|
|
79
94
|
$ sunlint --rule=C006 --typescript --input=src
|
|
@@ -92,10 +107,11 @@ ESLint Integration:
|
|
|
92
107
|
$ sunlint --all --eslint-integration --eslint-run-after --input=src
|
|
93
108
|
$ sunlint --typescript --eslint-integration --changed-files
|
|
94
109
|
|
|
95
|
-
|
|
96
|
-
$ sunlint --
|
|
97
|
-
$ sunlint --
|
|
98
|
-
$ sunlint --
|
|
110
|
+
Advanced File Targeting:
|
|
111
|
+
$ sunlint --all --include="src/**/*.ts,lib/**/*.dart" --exclude="**/*.generated.*" --input=.
|
|
112
|
+
$ sunlint --typescript --exclude="**/*.d.ts,**/*.test.*" --input=src
|
|
113
|
+
$ sunlint --languages=typescript,dart --include="src/**,packages/**" --input=.
|
|
114
|
+
$ sunlint --all --only-source --exclude-tests --languages=typescript --input=.
|
|
99
115
|
|
|
100
116
|
Sun* Engineering - Coding Standards Made Simple ☀️
|
|
101
117
|
`);
|
package/core/config-manager.js
CHANGED
|
@@ -28,11 +28,90 @@ class ConfigManager {
|
|
|
28
28
|
this.defaultConfig = {
|
|
29
29
|
rules: {},
|
|
30
30
|
categories: {},
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
|
|
32
|
+
// Enhanced language-specific configuration
|
|
33
|
+
languages: {
|
|
34
|
+
typescript: {
|
|
35
|
+
include: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'],
|
|
36
|
+
exclude: ['**/*.d.ts', '**/*.test.ts', '**/*.spec.ts'],
|
|
37
|
+
parser: 'typescript'
|
|
38
|
+
},
|
|
39
|
+
javascript: {
|
|
40
|
+
include: ['**/*.js', '**/*.jsx', '**/*.mjs', '**/*.cjs'],
|
|
41
|
+
exclude: ['**/*.min.js', '**/*.bundle.js'],
|
|
42
|
+
parser: 'espree'
|
|
43
|
+
},
|
|
44
|
+
dart: {
|
|
45
|
+
include: ['**/*.dart'],
|
|
46
|
+
exclude: ['**/*.g.dart', '**/*.freezed.dart', '**/*.mocks.dart'],
|
|
47
|
+
parser: 'dart'
|
|
48
|
+
},
|
|
49
|
+
kotlin: {
|
|
50
|
+
include: ['**/*.kt', '**/*.kts'],
|
|
51
|
+
exclude: ['**/build/**', '**/generated/**'],
|
|
52
|
+
parser: 'kotlin'
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
// Global file patterns (cross-language)
|
|
57
|
+
include: [
|
|
58
|
+
'src/**',
|
|
59
|
+
'lib/**',
|
|
60
|
+
'app/**',
|
|
61
|
+
'packages/**'
|
|
62
|
+
],
|
|
63
|
+
|
|
64
|
+
exclude: [
|
|
65
|
+
'node_modules/**',
|
|
66
|
+
'dist/**',
|
|
67
|
+
'build/**',
|
|
68
|
+
'coverage/**',
|
|
69
|
+
'.git/**',
|
|
70
|
+
'**/*.min.*',
|
|
71
|
+
'**/*.bundle.*',
|
|
72
|
+
'**/generated/**',
|
|
73
|
+
'**/*.generated.*',
|
|
74
|
+
'.next/**',
|
|
75
|
+
'.nuxt/**',
|
|
76
|
+
'vendor/**'
|
|
77
|
+
],
|
|
78
|
+
|
|
79
|
+
// Test file patterns with specific rules
|
|
80
|
+
testPatterns: {
|
|
81
|
+
include: ['**/*.test.*', '**/*.spec.*', '**/test/**', '**/tests/**', '**/__tests__/**'],
|
|
82
|
+
rules: {
|
|
83
|
+
'C006': 'off', // Function naming less strict in tests
|
|
84
|
+
'C019': 'warn' // Log level still important in tests
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
// Legacy support (backward compatibility)
|
|
34
89
|
ignorePatterns: [],
|
|
35
|
-
|
|
90
|
+
|
|
91
|
+
// Rule-specific overrides for different contexts
|
|
92
|
+
overrides: [
|
|
93
|
+
{
|
|
94
|
+
files: ['**/*.d.ts'],
|
|
95
|
+
rules: {
|
|
96
|
+
'C006': 'off',
|
|
97
|
+
'C007': 'off'
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
files: ['**/migrations/**', '**/seeds/**'],
|
|
102
|
+
rules: {
|
|
103
|
+
'C031': 'off' // Validation separation not needed in migrations
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
files: ['**/config/**', '**/*.config.*'],
|
|
108
|
+
rules: {
|
|
109
|
+
'C006': 'warn', // Config files may have different naming
|
|
110
|
+
'C015': 'off' // Domain language not strict in config
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
],
|
|
114
|
+
|
|
36
115
|
env: {},
|
|
37
116
|
parserOptions: {},
|
|
38
117
|
// ESLint Integration Configuration
|
|
@@ -115,7 +194,7 @@ class ConfigManager {
|
|
|
115
194
|
}
|
|
116
195
|
} else {
|
|
117
196
|
// Load from dedicated config file
|
|
118
|
-
projectConfig = this.sourceLoader.
|
|
197
|
+
projectConfig = this.sourceLoader.loadSpecificConfigFile(resolvedConfigPath, cliOptions.verbose);
|
|
119
198
|
}
|
|
120
199
|
|
|
121
200
|
if (projectConfig) {
|