@sun-asterisk/sunlint 1.3.6 → 1.3.8
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/CHANGELOG.md +76 -1
- package/config/defaults/default.json +2 -1
- package/config/rule-analysis-strategies.js +20 -0
- package/config/rules/enhanced-rules-registry.json +230 -43
- package/core/analysis-orchestrator.js +9 -5
- package/core/file-targeting-service.js +83 -7
- package/core/performance-optimizer.js +8 -2
- package/package.json +1 -1
- package/rules/common/C065_one_behavior_per_test/analyzer.js +851 -0
- package/rules/common/C065_one_behavior_per_test/config.json +95 -0
- package/rules/common/C073_validate_required_config_on_startup/README.md +110 -0
- package/rules/common/C073_validate_required_config_on_startup/analyzer.js +770 -0
- package/rules/common/C073_validate_required_config_on_startup/config.json +46 -0
- package/rules/common/C073_validate_required_config_on_startup/symbol-based-analyzer.js +370 -0
- package/rules/security/S037_cache_headers/README.md +128 -0
- package/rules/security/S037_cache_headers/analyzer.js +263 -0
- package/rules/security/S037_cache_headers/config.json +50 -0
- package/rules/security/S037_cache_headers/regex-based-analyzer.js +463 -0
- package/rules/security/S037_cache_headers/symbol-based-analyzer.js +546 -0
- package/rules/security/S038_no_version_headers/README.md +234 -0
- package/rules/security/S038_no_version_headers/analyzer.js +262 -0
- package/rules/security/S038_no_version_headers/config.json +49 -0
- package/rules/security/S038_no_version_headers/regex-based-analyzer.js +339 -0
- package/rules/security/S038_no_version_headers/symbol-based-analyzer.js +375 -0
- package/rules/security/S039_no_session_tokens_in_url/README.md +198 -0
- package/rules/security/S039_no_session_tokens_in_url/analyzer.js +262 -0
- package/rules/security/S039_no_session_tokens_in_url/config.json +92 -0
- package/rules/security/S039_no_session_tokens_in_url/regex-based-analyzer.js +337 -0
- package/rules/security/S039_no_session_tokens_in_url/symbol-based-analyzer.js +436 -0
- package/rules/security/S049_short_validity_tokens/analyzer.js +175 -0
- package/rules/security/S049_short_validity_tokens/config.json +124 -0
- package/rules/security/S049_short_validity_tokens/regex-based-analyzer.js +295 -0
- package/rules/security/S049_short_validity_tokens/symbol-based-analyzer.js +389 -0
- package/rules/security/S051_password_length_policy/analyzer.js +410 -0
- package/rules/security/S051_password_length_policy/config.json +83 -0
- package/rules/security/S052_weak_otp_entropy/analyzer.js +403 -0
- package/rules/security/S052_weak_otp_entropy/config.json +57 -0
- package/rules/security/S054_no_default_accounts/README.md +129 -0
- package/rules/security/S054_no_default_accounts/analyzer.js +792 -0
- package/rules/security/S054_no_default_accounts/config.json +101 -0
- package/rules/security/S056_log_injection_protection/analyzer.js +242 -0
- package/rules/security/S056_log_injection_protection/config.json +148 -0
- package/rules/security/S056_log_injection_protection/regex-based-analyzer.js +120 -0
- package/rules/security/S056_log_injection_protection/symbol-based-analyzer.js +287 -0
- package/rules/security/S057_utc_logging/README.md +152 -0
- package/rules/security/S057_utc_logging/analyzer.js +457 -0
- package/rules/security/S057_utc_logging/config.json +105 -0
- package/rules/security/S058_no_ssrf/README.md +180 -0
- package/rules/security/S058_no_ssrf/analyzer.js +403 -0
- package/rules/security/S058_no_ssrf/config.json +125 -0
|
@@ -16,7 +16,7 @@ class FileTargetingService {
|
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Get target files based on enhanced configuration
|
|
19
|
-
* ENHANCED: Uses metadata for intelligent file targeting
|
|
19
|
+
* ENHANCED: Uses metadata for intelligent file targeting with smart project-level optimization
|
|
20
20
|
*/
|
|
21
21
|
async getTargetFiles(inputPaths, config, cliOptions = {}) {
|
|
22
22
|
try {
|
|
@@ -32,11 +32,14 @@ class FileTargetingService {
|
|
|
32
32
|
|
|
33
33
|
let allFiles = [];
|
|
34
34
|
|
|
35
|
+
// Smart project-level optimization
|
|
36
|
+
const optimizedPaths = this.optimizeProjectPaths(inputPaths, cliOptions);
|
|
37
|
+
|
|
35
38
|
// Use enhanced targeting based on metadata
|
|
36
39
|
if (metadata?.shouldBypassProjectDiscovery) {
|
|
37
|
-
allFiles = await this.collectTargetedFiles(
|
|
40
|
+
allFiles = await this.collectTargetedFiles(optimizedPaths, config, cliOptions);
|
|
38
41
|
} else {
|
|
39
|
-
allFiles = await this.collectProjectFiles(
|
|
42
|
+
allFiles = await this.collectProjectFiles(optimizedPaths, config, cliOptions);
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
// Apply filtering logic
|
|
@@ -150,13 +153,69 @@ class FileTargetingService {
|
|
|
150
153
|
return allFiles;
|
|
151
154
|
}
|
|
152
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Optimize project paths to focus on source and test directories
|
|
158
|
+
* Prevents unnecessary scanning of entire project when smart targeting is possible
|
|
159
|
+
*/
|
|
160
|
+
optimizeProjectPaths(inputPaths, cliOptions = {}) {
|
|
161
|
+
const optimizedPaths = [];
|
|
162
|
+
|
|
163
|
+
for (const inputPath of inputPaths) {
|
|
164
|
+
// If targeting entire project directory, try to find source/test subdirectories
|
|
165
|
+
if (fs.existsSync(inputPath) && fs.statSync(inputPath).isDirectory()) {
|
|
166
|
+
const projectOptimization = this.findProjectSourceDirs(inputPath, cliOptions);
|
|
167
|
+
if (projectOptimization.length > 0) {
|
|
168
|
+
if (cliOptions.verbose) {
|
|
169
|
+
console.log(chalk.blue(`🎯 Smart targeting: Found ${projectOptimization.length} source directories in ${path.basename(inputPath)}`));
|
|
170
|
+
}
|
|
171
|
+
optimizedPaths.push(...projectOptimization);
|
|
172
|
+
} else {
|
|
173
|
+
optimizedPaths.push(inputPath);
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
optimizedPaths.push(inputPath);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return optimizedPaths;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Find source directories in project to avoid scanning entire project
|
|
185
|
+
*/
|
|
186
|
+
findProjectSourceDirs(projectPath, cliOptions = {}) {
|
|
187
|
+
const sourceDirs = [];
|
|
188
|
+
const candidateDirs = ['src', 'lib', 'app', 'packages'];
|
|
189
|
+
const testDirs = ['test', 'tests', '__tests__', 'spec', 'specs'];
|
|
190
|
+
|
|
191
|
+
// Always include test directories if --include-tests flag is used
|
|
192
|
+
const dirsToCheck = cliOptions.includeTests ? [...candidateDirs, ...testDirs] : candidateDirs;
|
|
193
|
+
|
|
194
|
+
for (const dir of dirsToCheck) {
|
|
195
|
+
const dirPath = path.join(projectPath, dir);
|
|
196
|
+
if (fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory()) {
|
|
197
|
+
sourceDirs.push(dirPath);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return sourceDirs;
|
|
202
|
+
}
|
|
203
|
+
|
|
153
204
|
/**
|
|
154
205
|
* Check if directory should be skipped
|
|
206
|
+
* Enhanced with more comprehensive ignore patterns
|
|
207
|
+
* Enhanced with more comprehensive ignore patterns
|
|
155
208
|
*/
|
|
156
209
|
shouldSkipDirectory(dirName) {
|
|
157
210
|
const skipDirs = [
|
|
158
211
|
'node_modules', '.git', 'dist', 'build', 'coverage',
|
|
159
|
-
'.next', '.nuxt', 'vendor', 'target', 'generated'
|
|
212
|
+
'.next', '.nuxt', 'vendor', 'target', 'generated',
|
|
213
|
+
'.vscode', '.id',
|
|
214
|
+
'.vscode', '.idea', '.husky', '.github', '.yarn',
|
|
215
|
+
'out', 'public', 'static', 'assets', 'tmp', 'temp',
|
|
216
|
+
'cache', '.cache', 'logs', 'logea', '.husky', '.github', '.yarn',
|
|
217
|
+
'out', 'public', 'static', 'assets', 'tmp', 'temp',
|
|
218
|
+
'cache', '.cache', 'logs', 'log'
|
|
160
219
|
];
|
|
161
220
|
return skipDirs.includes(dirName);
|
|
162
221
|
}
|
|
@@ -278,10 +337,27 @@ class FileTargetingService {
|
|
|
278
337
|
if (debug) console.log(`🔍 [DEBUG] After include patterns ${langConfig.include}: ${langFiles.length} files`);
|
|
279
338
|
}
|
|
280
339
|
|
|
281
|
-
// Apply language-specific exclude patterns
|
|
340
|
+
// Apply language-specific exclude patterns (but respect --include-tests for test files)
|
|
282
341
|
if (langConfig.exclude && langConfig.exclude.length > 0) {
|
|
283
|
-
|
|
284
|
-
|
|
342
|
+
// Skip test-related exclude patterns if --include-tests is enabled
|
|
343
|
+
let effectiveExcludes = langConfig.exclude;
|
|
344
|
+
if (cliOptions.includeTests === true) {
|
|
345
|
+
// Remove test-related patterns completely
|
|
346
|
+
effectiveExcludes = langConfig.exclude.filter(pattern => {
|
|
347
|
+
const isTestPattern = pattern.includes('.test.') || pattern.includes('.spec.') ||
|
|
348
|
+
pattern.includes('/test/') || pattern.includes('/tests/') ||
|
|
349
|
+
pattern.includes('/__tests__/');
|
|
350
|
+
return !isTestPattern;
|
|
351
|
+
});
|
|
352
|
+
if (debug) console.log(`🔍 [DEBUG] --include-tests enabled, filtered excludes: ${effectiveExcludes}`);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if (effectiveExcludes.length > 0) {
|
|
356
|
+
langFiles = this.applyExcludePatterns(langFiles, effectiveExcludes, debug);
|
|
357
|
+
if (debug) console.log(`🔍 [DEBUG] After exclude patterns ${effectiveExcludes}: ${langFiles.length} files`);
|
|
358
|
+
} else {
|
|
359
|
+
if (debug) console.log(`🔍 [DEBUG] All exclude patterns filtered out by --include-tests`);
|
|
360
|
+
}
|
|
285
361
|
}
|
|
286
362
|
|
|
287
363
|
languageFiles.push(...langFiles);
|
|
@@ -26,6 +26,12 @@ class PerformanceOptimizer {
|
|
|
26
26
|
...DEFAULT_PERFORMANCE,
|
|
27
27
|
...config
|
|
28
28
|
};
|
|
29
|
+
|
|
30
|
+
// Override maxTotalFiles if provided in config
|
|
31
|
+
if (config.maxFiles !== undefined) {
|
|
32
|
+
this.fileSizeLimits.maxTotalFiles = config.maxFiles;
|
|
33
|
+
}
|
|
34
|
+
|
|
29
35
|
this.initialized = true;
|
|
30
36
|
}
|
|
31
37
|
|
|
@@ -106,8 +112,8 @@ class PerformanceOptimizer {
|
|
|
106
112
|
break;
|
|
107
113
|
}
|
|
108
114
|
|
|
109
|
-
// Check file count limit
|
|
110
|
-
if (filtered.length >= this.fileSizeLimits.maxTotalFiles) {
|
|
115
|
+
// Check file count limit (skip if unlimited -1)
|
|
116
|
+
if (this.fileSizeLimits.maxTotalFiles > 0 && filtered.length >= this.fileSizeLimits.maxTotalFiles) {
|
|
111
117
|
if (this.config.verbose) {
|
|
112
118
|
console.log(`⚠️ Reached file count limit: ${this.fileSizeLimits.maxTotalFiles} files`);
|
|
113
119
|
}
|
package/package.json
CHANGED