@sun-asterisk/sunlint 1.0.5
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 +202 -0
- package/LICENSE +21 -0
- package/README.md +490 -0
- package/cli-legacy.js +355 -0
- package/cli.js +35 -0
- package/config/default.json +22 -0
- package/config/presets/beginner.json +36 -0
- package/config/presets/ci.json +46 -0
- package/config/presets/recommended.json +24 -0
- package/config/presets/strict.json +32 -0
- package/config/rules-registry.json +681 -0
- package/config/sunlint-schema.json +166 -0
- package/config/typescript/custom-rules-new.js +0 -0
- package/config/typescript/custom-rules.js +9 -0
- package/config/typescript/eslint.config.js +110 -0
- package/config/typescript/package-lock.json +1585 -0
- package/config/typescript/package.json +13 -0
- package/config/typescript/security-rules/index.js +90 -0
- package/config/typescript/security-rules/s005-no-origin-auth.js +95 -0
- package/config/typescript/security-rules/s006-activation-recovery-secret-not-plaintext.js +69 -0
- package/config/typescript/security-rules/s008-crypto-agility.js +62 -0
- package/config/typescript/security-rules/s009-no-insecure-crypto.js +103 -0
- package/config/typescript/security-rules/s010-no-insecure-random-in-sensitive-context.js +123 -0
- package/config/typescript/security-rules/s011-no-insecure-uuid.js +66 -0
- package/config/typescript/security-rules/s012-hardcode-secret.js +71 -0
- package/config/typescript/security-rules/s014-insecure-tls-version.js +50 -0
- package/config/typescript/security-rules/s015-insecure-tls-certificate.js +43 -0
- package/config/typescript/security-rules/s016-sensitive-query-parameter.js +59 -0
- package/config/typescript/security-rules/s017-no-sql-injection.js +193 -0
- package/config/typescript/security-rules/s018-positive-input-validation.js +56 -0
- package/config/typescript/security-rules/s019-no-raw-user-input-in-email.js +113 -0
- package/config/typescript/security-rules/s020-no-eval-dynamic-execution.js +89 -0
- package/config/typescript/security-rules/s022-output-encoding.js +78 -0
- package/config/typescript/security-rules/s023-no-json-injection.js +300 -0
- package/config/typescript/security-rules/s025-server-side-input-validation.js +217 -0
- package/config/typescript/security-rules/s026-json-schema-validation.js +68 -0
- package/config/typescript/security-rules/s027-no-hardcoded-secrets.js +80 -0
- package/config/typescript/security-rules/s029-require-csrf-protection.js +79 -0
- package/config/typescript/security-rules/s030-no-directory-browsing.js +78 -0
- package/config/typescript/security-rules/s033-require-samesite-cookie.js +80 -0
- package/config/typescript/security-rules/s034-require-host-cookie-prefix.js +77 -0
- package/config/typescript/security-rules/s035-cookie-specific-path.js +74 -0
- package/config/typescript/security-rules/s036-no-unsafe-file-include.js +68 -0
- package/config/typescript/security-rules/s037-require-anti-cache-headers.js +70 -0
- package/config/typescript/security-rules/s038-no-version-disclosure.js +74 -0
- package/config/typescript/security-rules/s039-no-session-token-in-url.js +63 -0
- package/config/typescript/security-rules/s041-require-session-invalidate-on-logout.js +211 -0
- package/config/typescript/security-rules/s042-require-periodic-reauthentication.js +294 -0
- package/config/typescript/security-rules/s043-terminate-sessions-on-password-change.js +254 -0
- package/config/typescript/security-rules/s044-require-full-session-for-sensitive-operations.js +292 -0
- package/config/typescript/security-rules/s045-anti-automation-controls.js +46 -0
- package/config/typescript/security-rules/s046-secure-notification-on-auth-change.js +44 -0
- package/config/typescript/security-rules/s048-password-credential-recovery.js +54 -0
- package/config/typescript/security-rules/s050-session-token-weak-hash.js +94 -0
- package/config/typescript/security-rules/s052-secure-random-authentication-code.js +66 -0
- package/config/typescript/security-rules/s054-verification-default-account.js +109 -0
- package/config/typescript/security-rules/s057-utc-logging.js +54 -0
- package/config/typescript/security-rules/s058-no-ssrf.js +73 -0
- package/config/typescript/test-s005-working.ts +22 -0
- package/config/typescript/tsconfig.json +29 -0
- package/core/ai-analyzer.js +169 -0
- package/core/analysis-orchestrator.js +705 -0
- package/core/cli-action-handler.js +230 -0
- package/core/cli-program.js +106 -0
- package/core/config-manager.js +396 -0
- package/core/config-merger.js +136 -0
- package/core/config-override-processor.js +74 -0
- package/core/config-preset-resolver.js +65 -0
- package/core/config-source-loader.js +152 -0
- package/core/config-validator.js +126 -0
- package/core/dependency-manager.js +105 -0
- package/core/eslint-engine-service.js +312 -0
- package/core/eslint-instance-manager.js +104 -0
- package/core/eslint-integration-service.js +363 -0
- package/core/git-utils.js +170 -0
- package/core/multi-rule-runner.js +239 -0
- package/core/output-service.js +250 -0
- package/core/report-generator.js +320 -0
- package/core/rule-mapping-service.js +309 -0
- package/core/rule-selection-service.js +121 -0
- package/core/sunlint-engine-service.js +23 -0
- package/core/typescript-analyzer.js +262 -0
- package/core/typescript-engine.js +313 -0
- package/docs/AI.md +163 -0
- package/docs/ARCHITECTURE.md +78 -0
- package/docs/CI-CD-GUIDE.md +315 -0
- package/docs/COMMAND-EXAMPLES.md +256 -0
- package/docs/DEBUG.md +86 -0
- package/docs/DISTRIBUTION.md +153 -0
- package/docs/ESLINT-INTEGRATION-STRATEGY.md +392 -0
- package/docs/ESLINT_INTEGRATION.md +238 -0
- package/docs/FOLDER_STRUCTURE.md +59 -0
- package/docs/HEURISTIC_VS_AI.md +113 -0
- package/docs/README.md +32 -0
- package/docs/RELEASE_GUIDE.md +230 -0
- package/docs/RULE-RESPONSIBILITY-MATRIX.md +204 -0
- package/eslint-integration/.eslintrc.js +98 -0
- package/eslint-integration/cli.js +35 -0
- package/eslint-integration/eslint-plugin-custom/c002-no-duplicate-code.js +204 -0
- package/eslint-integration/eslint-plugin-custom/c003-no-vague-abbreviations.js +246 -0
- package/eslint-integration/eslint-plugin-custom/c006-function-name-verb-noun.js +207 -0
- package/eslint-integration/eslint-plugin-custom/c010-limit-block-nesting.js +90 -0
- package/eslint-integration/eslint-plugin-custom/c013-no-dead-code.js +43 -0
- package/eslint-integration/eslint-plugin-custom/c014-abstract-dependency-preferred.js +38 -0
- package/eslint-integration/eslint-plugin-custom/c017-limit-constructor-logic.js +39 -0
- package/eslint-integration/eslint-plugin-custom/c018-no-generic-throw.js +335 -0
- package/eslint-integration/eslint-plugin-custom/c023-no-duplicate-variable-name-in-scope.js +142 -0
- package/eslint-integration/eslint-plugin-custom/c027-limit-function-nesting.js +50 -0
- package/eslint-integration/eslint-plugin-custom/c029-catch-block-logging.js +80 -0
- package/eslint-integration/eslint-plugin-custom/c030-use-custom-error-classes.js +294 -0
- package/eslint-integration/eslint-plugin-custom/c034-no-implicit-return.js +34 -0
- package/eslint-integration/eslint-plugin-custom/c035-no-empty-catch.js +32 -0
- package/eslint-integration/eslint-plugin-custom/c041-no-config-inline.js +64 -0
- package/eslint-integration/eslint-plugin-custom/c042-boolean-name-prefix.js +406 -0
- package/eslint-integration/eslint-plugin-custom/c043-no-console-or-print.js +300 -0
- package/eslint-integration/eslint-plugin-custom/c047-no-duplicate-retry-logic.js +239 -0
- package/eslint-integration/eslint-plugin-custom/c048-no-var-declaration.js +31 -0
- package/eslint-integration/eslint-plugin-custom/c076-one-assert-per-test.js +184 -0
- package/eslint-integration/eslint-plugin-custom/index.js +155 -0
- package/eslint-integration/eslint-plugin-custom/package.json +13 -0
- package/eslint-integration/eslint-plugin-custom/package.json.bak +9 -0
- package/eslint-integration/eslint-plugin-custom/s003-no-unvalidated-redirect.js +86 -0
- package/eslint-integration/eslint-plugin-custom/s005-no-origin-auth.js +95 -0
- package/eslint-integration/eslint-plugin-custom/s006-activation-recovery-secret-not-plaintext.js +69 -0
- package/eslint-integration/eslint-plugin-custom/s008-crypto-agility.js +62 -0
- package/eslint-integration/eslint-plugin-custom/s009-no-insecure-crypto.js +103 -0
- package/eslint-integration/eslint-plugin-custom/s010-no-insecure-random-in-sensitive-context.js +123 -0
- package/eslint-integration/eslint-plugin-custom/s011-no-insecure-uuid.js +66 -0
- package/eslint-integration/eslint-plugin-custom/s012-hardcode-secret.js +71 -0
- package/eslint-integration/eslint-plugin-custom/s014-insecure-tls-version.js +50 -0
- package/eslint-integration/eslint-plugin-custom/s015-insecure-tls-certificate.js +43 -0
- package/eslint-integration/eslint-plugin-custom/s016-sensitive-query-parameter.js +59 -0
- package/eslint-integration/eslint-plugin-custom/s017-no-sql-injection.js +193 -0
- package/eslint-integration/eslint-plugin-custom/s018-positive-input-validation.js +56 -0
- package/eslint-integration/eslint-plugin-custom/s019-no-raw-user-input-in-email.js +113 -0
- package/eslint-integration/eslint-plugin-custom/s020-no-eval-dynamic-execution.js +89 -0
- package/eslint-integration/eslint-plugin-custom/s022-output-encoding.js +78 -0
- package/eslint-integration/eslint-plugin-custom/s023-no-json-injection.js +300 -0
- package/eslint-integration/eslint-plugin-custom/s025-server-side-input-validation.js +217 -0
- package/eslint-integration/eslint-plugin-custom/s026-json-schema-validation.js +68 -0
- package/eslint-integration/eslint-plugin-custom/s027-no-hardcoded-secrets.js +80 -0
- package/eslint-integration/eslint-plugin-custom/s029-require-csrf-protection.js +79 -0
- package/eslint-integration/eslint-plugin-custom/s030-no-directory-browsing.js +78 -0
- package/eslint-integration/eslint-plugin-custom/s033-require-samesite-cookie.js +80 -0
- package/eslint-integration/eslint-plugin-custom/s034-require-host-cookie-prefix.js +77 -0
- package/eslint-integration/eslint-plugin-custom/s035-cookie-specific-path.js +74 -0
- package/eslint-integration/eslint-plugin-custom/s036-no-unsafe-file-include.js +68 -0
- package/eslint-integration/eslint-plugin-custom/s037-require-anti-cache-headers.js +70 -0
- package/eslint-integration/eslint-plugin-custom/s038-no-version-disclosure.js +74 -0
- package/eslint-integration/eslint-plugin-custom/s039-no-session-token-in-url.js +63 -0
- package/eslint-integration/eslint-plugin-custom/s041-require-session-invalidate-on-logout.js +211 -0
- package/eslint-integration/eslint-plugin-custom/s042-require-periodic-reauthentication.js +294 -0
- package/eslint-integration/eslint-plugin-custom/s043-terminate-sessions-on-password-change.js +254 -0
- package/eslint-integration/eslint-plugin-custom/s044-require-full-session-for-sensitive-operations.js +292 -0
- package/eslint-integration/eslint-plugin-custom/s045-anti-automation-controls.js +46 -0
- package/eslint-integration/eslint-plugin-custom/s046-secure-notification-on-auth-change.js +44 -0
- package/eslint-integration/eslint-plugin-custom/s047-secure-random-passwords.js +108 -0
- package/eslint-integration/eslint-plugin-custom/s048-password-credential-recovery.js +54 -0
- package/eslint-integration/eslint-plugin-custom/s050-session-token-weak-hash.js +94 -0
- package/eslint-integration/eslint-plugin-custom/s052-secure-random-authentication-code.js +66 -0
- package/eslint-integration/eslint-plugin-custom/s054-verification-default-account.js +109 -0
- package/eslint-integration/eslint-plugin-custom/s055-verification-rest-check-the-incoming-content-type.js +143 -0
- package/eslint-integration/eslint-plugin-custom/s057-utc-logging.js +54 -0
- package/eslint-integration/eslint-plugin-custom/s058-no-ssrf.js +73 -0
- package/eslint-integration/eslint-plugin-custom/t002-interface-prefix-i.js +42 -0
- package/eslint-integration/eslint-plugin-custom/t003-ts-ignore-reason.js +48 -0
- package/eslint-integration/eslint-plugin-custom/t004-interface-public-only.js +160 -0
- package/eslint-integration/eslint-plugin-custom/t007-no-fn-in-constructor.js +52 -0
- package/eslint-integration/eslint-plugin-custom/t011-no-real-time-dependency.js +175 -0
- package/eslint-integration/eslint-plugin-custom/t019-no-empty-type.js +95 -0
- package/eslint-integration/eslint-plugin-custom/t025-no-nested-union-tuple.js +48 -0
- package/eslint-integration/eslint-plugin-custom/t026-limit-nested-generics.js +377 -0
- package/eslint-integration/eslint.config.js +125 -0
- package/eslint-integration/eslint.config.simple.js +24 -0
- package/eslint-integration/node_modules/eslint-plugin-custom/package.json +0 -0
- package/eslint-integration/package.json +23 -0
- package/eslint-integration/sample.ts +53 -0
- package/eslint-integration/test-s003.js +5 -0
- package/eslint-integration/tsconfig.json +27 -0
- package/examples/.github/workflows/code-quality.yml +111 -0
- package/examples/.sunlint.json +42 -0
- package/examples/README.md +47 -0
- package/examples/package.json +33 -0
- package/package.json +100 -0
- package/rules/C006_function_naming/analyzer.js +338 -0
- package/rules/C006_function_naming/config.json +86 -0
- package/rules/C019_log_level_usage/analyzer.js +359 -0
- package/rules/C019_log_level_usage/config.json +121 -0
- package/rules/C029_catch_block_logging/analyzer.js +339 -0
- package/rules/C029_catch_block_logging/config.json +59 -0
- package/rules/C031_validation_separation/README.md +72 -0
- package/rules/C031_validation_separation/analyzer.js +186 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Handles loading configuration from various sources (files, environment, etc.)
|
|
7
|
+
* Rule C005: Single responsibility - chỉ load config từ sources
|
|
8
|
+
* Rule C015: Domain language - ConfigSourceLoader
|
|
9
|
+
*/
|
|
10
|
+
class ConfigSourceLoader {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.configNames = [
|
|
13
|
+
'.sunlint.json',
|
|
14
|
+
'.sunlint.js',
|
|
15
|
+
'sunlint.config.json',
|
|
16
|
+
'sunlint.config.js'
|
|
17
|
+
];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Rule C006: loadGlobalConfiguration - verb-noun naming
|
|
22
|
+
*/
|
|
23
|
+
loadGlobalConfiguration(homePath, verbose = false) {
|
|
24
|
+
const globalConfigPath = path.join(homePath, '.sunlint.json');
|
|
25
|
+
if (!fs.existsSync(globalConfigPath)) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const globalConfig = JSON.parse(fs.readFileSync(globalConfigPath, 'utf8'));
|
|
31
|
+
if (verbose) {
|
|
32
|
+
console.log(chalk.gray(`🌍 Loaded global config: ${globalConfigPath}`));
|
|
33
|
+
}
|
|
34
|
+
return { config: globalConfig, path: globalConfigPath };
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.warn(chalk.yellow(`⚠️ Failed to load global config: ${error.message}`));
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Rule C006: findProjectConfiguration - verb-noun naming
|
|
43
|
+
*/
|
|
44
|
+
findProjectConfiguration(startDir) {
|
|
45
|
+
let currentDir = path.resolve(startDir);
|
|
46
|
+
const rootDir = path.parse(currentDir).root;
|
|
47
|
+
|
|
48
|
+
while (currentDir !== rootDir) {
|
|
49
|
+
// Check for SunLint config files
|
|
50
|
+
for (const configName of this.configNames) {
|
|
51
|
+
const configPath = path.join(currentDir, configName);
|
|
52
|
+
if (fs.existsSync(configPath)) {
|
|
53
|
+
try {
|
|
54
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
55
|
+
return { path: configPath, config, dir: currentDir };
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.warn(chalk.yellow(`⚠️ Invalid config file ${configPath}: ${error.message}`));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Check package.json for sunlint config
|
|
63
|
+
const packageResult = this.loadPackageJsonConfig(currentDir);
|
|
64
|
+
if (packageResult) {
|
|
65
|
+
return packageResult;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
currentDir = path.dirname(currentDir);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Rule C006: loadPackageJsonConfig - verb-noun naming
|
|
76
|
+
* Rule C005: Extracted method for single responsibility
|
|
77
|
+
*/
|
|
78
|
+
loadPackageJsonConfig(directory) {
|
|
79
|
+
const packageJsonPath = path.join(directory, 'package.json');
|
|
80
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
86
|
+
if (packageJson.sunlint) {
|
|
87
|
+
return { path: packageJsonPath, config: packageJson.sunlint, dir: directory };
|
|
88
|
+
}
|
|
89
|
+
} catch (error) {
|
|
90
|
+
// Ignore package.json parse errors
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Rule C006: loadSpecificConfigFile - verb-noun naming
|
|
98
|
+
*/
|
|
99
|
+
loadSpecificConfigFile(configPath, verbose = false) {
|
|
100
|
+
if (!configPath || !fs.existsSync(configPath)) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
const fileConfig = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
106
|
+
if (verbose) {
|
|
107
|
+
console.log(chalk.gray(`📄 Loaded config from: ${configPath}`));
|
|
108
|
+
}
|
|
109
|
+
return { config: fileConfig, path: configPath };
|
|
110
|
+
} catch (error) {
|
|
111
|
+
console.error(chalk.red(`❌ Failed to load config from ${configPath}:`), error.message);
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Rule C006: loadIgnorePatterns - verb-noun naming
|
|
118
|
+
*/
|
|
119
|
+
loadIgnorePatterns(projectDir, verbose = false) {
|
|
120
|
+
const ignoreFiles = ['.sunlintignore', '.eslintignore', '.gitignore'];
|
|
121
|
+
const ignorePatterns = [];
|
|
122
|
+
|
|
123
|
+
for (const ignoreFile of ignoreFiles) {
|
|
124
|
+
const ignorePath = path.join(projectDir, ignoreFile);
|
|
125
|
+
if (fs.existsSync(ignorePath)) {
|
|
126
|
+
try {
|
|
127
|
+
const ignoreContent = fs.readFileSync(ignorePath, 'utf8');
|
|
128
|
+
const patterns = ignoreContent
|
|
129
|
+
.split('\n')
|
|
130
|
+
.map(line => line.trim())
|
|
131
|
+
.filter(line => line && !line.startsWith('#'))
|
|
132
|
+
.filter(line => !ignorePatterns.includes(line));
|
|
133
|
+
|
|
134
|
+
ignorePatterns.push(...patterns);
|
|
135
|
+
|
|
136
|
+
if (verbose) {
|
|
137
|
+
console.log(chalk.gray(`📋 Loaded ignore patterns from: ${ignorePath} (${patterns.length} patterns)`));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Only use the first ignore file found
|
|
141
|
+
break;
|
|
142
|
+
} catch (error) {
|
|
143
|
+
console.warn(chalk.yellow(`⚠️ Failed to load ignore file ${ignorePath}: ${error.message}`));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return [...new Set(ignorePatterns)]; // Remove duplicates
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
module.exports = ConfigSourceLoader;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handles configuration validation and rule value normalization
|
|
3
|
+
* Rule C005: Single responsibility - chỉ validation và normalization
|
|
4
|
+
* Rule C015: Domain language - ConfigValidator
|
|
5
|
+
* Rule C031: Validation logic tách riêng
|
|
6
|
+
*/
|
|
7
|
+
class ConfigValidator {
|
|
8
|
+
|
|
9
|
+
constructor() {
|
|
10
|
+
this.validFormats = ['eslint', 'json', 'summary', 'table'];
|
|
11
|
+
this.validRuleValues = ['error', 'warning', 'info', 'warn', 'off', true, false, 0, 1, 2];
|
|
12
|
+
this.ruleValueMapping = {
|
|
13
|
+
0: 'off',
|
|
14
|
+
1: 'warning',
|
|
15
|
+
2: 'error',
|
|
16
|
+
'warn': 'warning',
|
|
17
|
+
true: 'warning',
|
|
18
|
+
false: 'off'
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Rule C006: validateConfiguration - verb-noun naming
|
|
24
|
+
* Rule C031: Main validation method
|
|
25
|
+
*/
|
|
26
|
+
validateConfiguration(config) {
|
|
27
|
+
this.validateRulesSection(config.rules);
|
|
28
|
+
this.validateLanguagesSection(config.languages);
|
|
29
|
+
this.validateIncludeExcludePatterns(config.include, config.exclude);
|
|
30
|
+
this.validateOutputFormat(config.output);
|
|
31
|
+
this.validateRuleValues(config.rules);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Rule C006: validateRulesSection - verb-noun naming
|
|
36
|
+
* Rule C031: Specific validation logic
|
|
37
|
+
*/
|
|
38
|
+
validateRulesSection(rules) {
|
|
39
|
+
if (rules && typeof rules !== 'object') {
|
|
40
|
+
throw new Error('Config error: rules must be an object');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Rule C006: validateLanguagesSection - verb-noun naming
|
|
46
|
+
* Rule C031: Specific validation logic
|
|
47
|
+
*/
|
|
48
|
+
validateLanguagesSection(languages) {
|
|
49
|
+
if (languages && !Array.isArray(languages)) {
|
|
50
|
+
throw new Error('Config error: languages must be an array');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Rule C006: validateIncludeExcludePatterns - verb-noun naming
|
|
56
|
+
* Rule C031: Specific validation logic
|
|
57
|
+
*/
|
|
58
|
+
validateIncludeExcludePatterns(include, exclude) {
|
|
59
|
+
if (include && !Array.isArray(include)) {
|
|
60
|
+
throw new Error('Config error: include must be an array');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (exclude && !Array.isArray(exclude)) {
|
|
64
|
+
throw new Error('Config error: exclude must be an array');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Rule C006: validateOutputFormat - verb-noun naming
|
|
70
|
+
* Rule C031: Specific validation logic
|
|
71
|
+
*/
|
|
72
|
+
validateOutputFormat(output) {
|
|
73
|
+
if (output && output.format && !this.validFormats.includes(output.format)) {
|
|
74
|
+
throw new Error(`Config error: invalid output format '${output.format}'. Valid formats: ${this.validFormats.join(', ')}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Rule C006: validateRuleValues - verb-noun naming
|
|
80
|
+
* Rule C031: Specific validation logic
|
|
81
|
+
*/
|
|
82
|
+
validateRuleValues(rules) {
|
|
83
|
+
if (!rules) return;
|
|
84
|
+
|
|
85
|
+
for (const [ruleId, ruleValue] of Object.entries(rules)) {
|
|
86
|
+
if (!this.validRuleValues.includes(ruleValue)) {
|
|
87
|
+
throw new Error(`Config error: invalid value '${ruleValue}' for rule '${ruleId}'. Valid values: ${this.validRuleValues.join(', ')}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Rule C006: normalizeRuleValue - verb-noun naming
|
|
94
|
+
* Rule C012: Pure function - no side effects
|
|
95
|
+
*/
|
|
96
|
+
normalizeRuleValue(value) {
|
|
97
|
+
return this.ruleValueMapping[value] || value;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Rule C006: getEffectiveRuleConfiguration - verb-noun naming
|
|
102
|
+
* Rule C014: Accept rulesRegistry as dependency injection
|
|
103
|
+
*/
|
|
104
|
+
getEffectiveRuleConfiguration(ruleId, config, rulesRegistry) {
|
|
105
|
+
// Check direct rule configuration
|
|
106
|
+
if (config.rules && config.rules[ruleId] !== undefined) {
|
|
107
|
+
return this.normalizeRuleValue(config.rules[ruleId]);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Check category configuration
|
|
111
|
+
const rule = rulesRegistry.rules[ruleId];
|
|
112
|
+
|
|
113
|
+
if (rule && config.categories && config.categories[rule.category] !== undefined) {
|
|
114
|
+
return this.normalizeRuleValue(config.categories[rule.category]);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Use rule default
|
|
118
|
+
if (rule) {
|
|
119
|
+
return this.normalizeRuleValue(rule.severity);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return 'off';
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
module.exports = ConfigValidator;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const { execSync } = require('child_process');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Handles dependency validation and installation
|
|
6
|
+
* Rule C005: Single responsibility - only dependency management
|
|
7
|
+
* Rule C015: Domain language - DependencyManager
|
|
8
|
+
* Rule C032: No external API calls in constructor
|
|
9
|
+
*/
|
|
10
|
+
class DependencyManager {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.requiredDependencies = [
|
|
13
|
+
'@typescript-eslint/parser',
|
|
14
|
+
'@typescript-eslint/eslint-plugin',
|
|
15
|
+
'eslint'
|
|
16
|
+
];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Rule C006: checkDependenciesAvailable - verb-noun naming
|
|
21
|
+
* Rule C012: Query method - checks without side effects
|
|
22
|
+
*/
|
|
23
|
+
async checkDependenciesAvailable() {
|
|
24
|
+
const missingDeps = [];
|
|
25
|
+
|
|
26
|
+
for (const dep of this.requiredDependencies) {
|
|
27
|
+
try {
|
|
28
|
+
require.resolve(dep);
|
|
29
|
+
} catch (error) {
|
|
30
|
+
missingDeps.push(dep);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
allAvailable: missingDeps.length === 0,
|
|
36
|
+
missing: missingDeps
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Rule C006: installMissingDependencies - verb-noun naming
|
|
42
|
+
* Rule C012: Command method - performs installation
|
|
43
|
+
*/
|
|
44
|
+
async installMissingDependencies() {
|
|
45
|
+
const { allAvailable, missing } = await this.checkDependenciesAvailable();
|
|
46
|
+
|
|
47
|
+
if (allAvailable) {
|
|
48
|
+
console.log(chalk.green('✅ All TypeScript dependencies are available'));
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
console.log(chalk.yellow(`⚠️ Missing dependencies: ${missing.join(', ')}`));
|
|
53
|
+
console.log(chalk.blue('📦 Installing missing dependencies...'));
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
const installCommand = `npm install ${missing.join(' ')}`;
|
|
57
|
+
execSync(installCommand, { stdio: 'inherit', cwd: process.cwd() });
|
|
58
|
+
|
|
59
|
+
console.log(chalk.green('✅ Dependencies installed successfully'));
|
|
60
|
+
return true;
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error(chalk.red('❌ Failed to install dependencies:'), error.message);
|
|
63
|
+
console.log(chalk.yellow('💡 Please install manually:'));
|
|
64
|
+
console.log(chalk.gray(` npm install ${missing.join(' ')}`));
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Rule C006: validateDependencyVersions - verb-noun naming
|
|
71
|
+
* Rule C012: Query method
|
|
72
|
+
*/
|
|
73
|
+
validateDependencyVersions() {
|
|
74
|
+
const versions = {};
|
|
75
|
+
|
|
76
|
+
for (const dep of this.requiredDependencies) {
|
|
77
|
+
try {
|
|
78
|
+
const packagePath = require.resolve(`${dep}/package.json`);
|
|
79
|
+
const packageInfo = require(packagePath);
|
|
80
|
+
versions[dep] = packageInfo.version;
|
|
81
|
+
} catch (error) {
|
|
82
|
+
versions[dep] = 'not found';
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return versions;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Rule C006: logDependencyStatus - verb-noun naming
|
|
91
|
+
*/
|
|
92
|
+
logDependencyStatus() {
|
|
93
|
+
const versions = this.validateDependencyVersions();
|
|
94
|
+
|
|
95
|
+
console.log(chalk.blue('📦 TypeScript Dependencies:'));
|
|
96
|
+
for (const [dep, version] of Object.entries(versions)) {
|
|
97
|
+
const status = version === 'not found'
|
|
98
|
+
? chalk.red('❌ Not found')
|
|
99
|
+
: chalk.green(`✅ v${version}`);
|
|
100
|
+
console.log(` ${dep}: ${status}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
module.exports = DependencyManager;
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ESLint Engine Service
|
|
3
|
+
* Handles ESLint integration for TypeScript analysis
|
|
4
|
+
* Following Rule C005: Single responsibility - only handle ESLint execution
|
|
5
|
+
* Following Rule C014: Dependency injection for configuration
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { execSync } = require('child_process');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const chalk = require('chalk');
|
|
12
|
+
|
|
13
|
+
class ESLintEngineService {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.eslintConfigPath = path.join(__dirname, '../config/typescript/eslint.config.js');
|
|
16
|
+
this.eslintPackagePath = path.join(__dirname, '../config/typescript');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Query: Check if ESLint is available
|
|
21
|
+
*/
|
|
22
|
+
isAvailable() {
|
|
23
|
+
try {
|
|
24
|
+
// Check if config exists
|
|
25
|
+
if (!fs.existsSync(this.eslintConfigPath)) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Check if ESLint is available
|
|
30
|
+
execSync('npx eslint --version', {
|
|
31
|
+
stdio: 'ignore',
|
|
32
|
+
cwd: this.eslintPackagePath
|
|
33
|
+
});
|
|
34
|
+
return true;
|
|
35
|
+
} catch (error) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Command: Ensure ESLint dependencies are installed
|
|
42
|
+
*/
|
|
43
|
+
async ensureDependencies() {
|
|
44
|
+
try {
|
|
45
|
+
console.log(chalk.blue('🔧 Ensuring ESLint dependencies...'));
|
|
46
|
+
|
|
47
|
+
const packageJsonPath = path.join(this.eslintPackagePath, 'package.json');
|
|
48
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
49
|
+
execSync('npm install', {
|
|
50
|
+
cwd: this.eslintPackagePath,
|
|
51
|
+
stdio: 'inherit'
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
console.log(chalk.green('✅ ESLint dependencies ready'));
|
|
56
|
+
} catch (error) {
|
|
57
|
+
throw new Error(`Failed to ensure ESLint dependencies: ${error.message}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Command: Run ESLint analysis
|
|
63
|
+
*/
|
|
64
|
+
async runAnalysis(rulesToRun, options) {
|
|
65
|
+
try {
|
|
66
|
+
// Map SunLint rules to ESLint rules
|
|
67
|
+
const eslintRules = this.mapSunLintRulesToESLint(rulesToRun);
|
|
68
|
+
|
|
69
|
+
// Build ESLint command
|
|
70
|
+
const command = this.buildESLintCommand(eslintRules, options);
|
|
71
|
+
|
|
72
|
+
if (options.debug) {
|
|
73
|
+
console.log(chalk.yellow('ESLint command:'), command);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Execute ESLint
|
|
77
|
+
const output = execSync(command, {
|
|
78
|
+
cwd: this.eslintPackagePath,
|
|
79
|
+
encoding: 'utf-8'
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Parse results
|
|
83
|
+
return this.parseESLintOutput(output, options);
|
|
84
|
+
|
|
85
|
+
} catch (error) {
|
|
86
|
+
// ESLint might exit with non-zero code when violations are found
|
|
87
|
+
if (error.stdout) {
|
|
88
|
+
return this.parseESLintOutput(error.stdout, options);
|
|
89
|
+
}
|
|
90
|
+
throw new Error(`ESLint execution failed: ${error.message}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Query: Map SunLint rule IDs to ESLint rule IDs
|
|
96
|
+
*/
|
|
97
|
+
mapSunLintRulesToESLint(rules) {
|
|
98
|
+
const ruleMapping = {
|
|
99
|
+
// Quality rules (C-rules)
|
|
100
|
+
'C002': 'custom/c002',
|
|
101
|
+
'C003': 'custom/c003',
|
|
102
|
+
'C006': 'custom/c006',
|
|
103
|
+
'C010': 'custom/c010',
|
|
104
|
+
'C013': 'custom/c013',
|
|
105
|
+
'C014': 'custom/c014',
|
|
106
|
+
'C017': 'custom/c017',
|
|
107
|
+
'C018': 'custom/c018',
|
|
108
|
+
'C023': 'custom/c023',
|
|
109
|
+
'C027': 'custom/c027',
|
|
110
|
+
'C029': 'custom/c029',
|
|
111
|
+
'C030': 'custom/c030',
|
|
112
|
+
'C034': 'custom/c034',
|
|
113
|
+
'C035': 'custom/c035',
|
|
114
|
+
'C041': 'custom/c041',
|
|
115
|
+
'C042': 'custom/c042',
|
|
116
|
+
'C043': 'custom/c043',
|
|
117
|
+
'C047': 'custom/c047',
|
|
118
|
+
'C048': 'custom/c048',
|
|
119
|
+
|
|
120
|
+
// Security rules (S-rules)
|
|
121
|
+
'S005': 'custom/typescript_s005',
|
|
122
|
+
'S006': 'custom/typescript_s006',
|
|
123
|
+
'S008': 'custom/typescript_s008',
|
|
124
|
+
'S009': 'custom/typescript_s009',
|
|
125
|
+
'S010': 'custom/typescript_s010',
|
|
126
|
+
'S011': 'custom/typescript_s011',
|
|
127
|
+
'S012': 'custom/typescript_s012',
|
|
128
|
+
'S014': 'custom/typescript_s014',
|
|
129
|
+
'S015': 'custom/typescript_s015',
|
|
130
|
+
'S016': 'custom/typescript_s016',
|
|
131
|
+
'S017': 'custom/typescript_s017',
|
|
132
|
+
'S018': 'custom/typescript_s018',
|
|
133
|
+
'S019': 'custom/typescript_s019',
|
|
134
|
+
'S020': 'custom/typescript_s020',
|
|
135
|
+
'S022': 'custom/typescript_s022',
|
|
136
|
+
'S023': 'custom/typescript_s023',
|
|
137
|
+
'S025': 'custom/typescript_s025',
|
|
138
|
+
'S026': 'custom/typescript_s026',
|
|
139
|
+
'S027': 'custom/typescript_s027',
|
|
140
|
+
'S029': 'custom/typescript_s029',
|
|
141
|
+
'S030': 'custom/typescript_s030',
|
|
142
|
+
'S033': 'custom/typescript_s033',
|
|
143
|
+
'S034': 'custom/typescript_s034',
|
|
144
|
+
'S035': 'custom/typescript_s035',
|
|
145
|
+
'S036': 'custom/typescript_s036',
|
|
146
|
+
'S037': 'custom/typescript_s037',
|
|
147
|
+
'S038': 'custom/typescript_s038',
|
|
148
|
+
'S039': 'custom/typescript_s039',
|
|
149
|
+
'S041': 'custom/typescript_s041',
|
|
150
|
+
'S042': 'custom/typescript_s042',
|
|
151
|
+
'S043': 'custom/typescript_s043',
|
|
152
|
+
'S044': 'custom/typescript_s044',
|
|
153
|
+
'S045': 'custom/typescript_s045',
|
|
154
|
+
'S046': 'custom/typescript_s046',
|
|
155
|
+
'S048': 'custom/typescript_s048',
|
|
156
|
+
'S050': 'custom/typescript_s050',
|
|
157
|
+
'S052': 'custom/typescript_s052',
|
|
158
|
+
'S054': 'custom/typescript_s054',
|
|
159
|
+
'S057': 'custom/typescript_s057',
|
|
160
|
+
'S058': 'custom/typescript_s058'
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
return rules
|
|
164
|
+
.filter(rule => ruleMapping[rule.id])
|
|
165
|
+
.map(rule => ruleMapping[rule.id]);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Command: Build ESLint command
|
|
170
|
+
*/
|
|
171
|
+
buildESLintCommand(eslintRules, options) {
|
|
172
|
+
const parts = [
|
|
173
|
+
'npx eslint',
|
|
174
|
+
`--config ${this.eslintConfigPath}`,
|
|
175
|
+
'--format json',
|
|
176
|
+
`"${options.input}"`
|
|
177
|
+
];
|
|
178
|
+
|
|
179
|
+
// Add specific rules if provided
|
|
180
|
+
if (eslintRules.length > 0) {
|
|
181
|
+
const rulesFlag = eslintRules.map(rule => `${rule}:error`).join(' ');
|
|
182
|
+
parts.push(`--rule "${rulesFlag}"`);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Add file extensions
|
|
186
|
+
parts.push('--ext .ts,.tsx,.js,.jsx');
|
|
187
|
+
|
|
188
|
+
return parts.join(' ');
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Query: Parse ESLint JSON output to SunLint format
|
|
193
|
+
*/
|
|
194
|
+
parseESLintOutput(output, options) {
|
|
195
|
+
try {
|
|
196
|
+
const eslintResults = JSON.parse(output);
|
|
197
|
+
|
|
198
|
+
const results = {
|
|
199
|
+
results: [],
|
|
200
|
+
filesAnalyzed: eslintResults.length,
|
|
201
|
+
engine: 'eslint'
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
eslintResults.forEach(file => {
|
|
205
|
+
if (file.messages.length > 0) {
|
|
206
|
+
const violations = file.messages.map(msg => ({
|
|
207
|
+
ruleId: this.mapESLintRuleToSunLint(msg.ruleId),
|
|
208
|
+
severity: this.mapESLintSeverity(msg.severity),
|
|
209
|
+
message: msg.message,
|
|
210
|
+
line: msg.line,
|
|
211
|
+
column: msg.column,
|
|
212
|
+
file: file.filePath
|
|
213
|
+
}));
|
|
214
|
+
|
|
215
|
+
results.results.push({
|
|
216
|
+
file: file.filePath,
|
|
217
|
+
violations: violations
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
return results;
|
|
223
|
+
} catch (error) {
|
|
224
|
+
throw new Error(`Failed to parse ESLint output: ${error.message}`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Query: Map ESLint rule ID back to SunLint rule ID
|
|
230
|
+
*/
|
|
231
|
+
mapESLintRuleToSunLint(eslintRuleId) {
|
|
232
|
+
const reverseMapping = {
|
|
233
|
+
// Quality rules (C-rules)
|
|
234
|
+
'custom/c002': 'C002',
|
|
235
|
+
'custom/c003': 'C003',
|
|
236
|
+
'custom/c006': 'C006',
|
|
237
|
+
'custom/c010': 'C010',
|
|
238
|
+
'custom/c013': 'C013',
|
|
239
|
+
'custom/c014': 'C014',
|
|
240
|
+
'custom/c017': 'C017',
|
|
241
|
+
'custom/c018': 'C018',
|
|
242
|
+
'custom/c023': 'C023',
|
|
243
|
+
'custom/c027': 'C027',
|
|
244
|
+
'custom/c029': 'C029',
|
|
245
|
+
'custom/c030': 'C030',
|
|
246
|
+
'custom/c034': 'C034',
|
|
247
|
+
'custom/c035': 'C035',
|
|
248
|
+
'custom/c041': 'C041',
|
|
249
|
+
'custom/c042': 'C042',
|
|
250
|
+
'custom/c043': 'C043',
|
|
251
|
+
'custom/c047': 'C047',
|
|
252
|
+
'custom/c048': 'C048',
|
|
253
|
+
|
|
254
|
+
// Security rules (S-rules)
|
|
255
|
+
'custom/typescript_s005': 'S005',
|
|
256
|
+
'custom/typescript_s006': 'S006',
|
|
257
|
+
'custom/typescript_s008': 'S008',
|
|
258
|
+
'custom/typescript_s009': 'S009',
|
|
259
|
+
'custom/typescript_s010': 'S010',
|
|
260
|
+
'custom/typescript_s011': 'S011',
|
|
261
|
+
'custom/typescript_s012': 'S012',
|
|
262
|
+
'custom/typescript_s014': 'S014',
|
|
263
|
+
'custom/typescript_s015': 'S015',
|
|
264
|
+
'custom/typescript_s016': 'S016',
|
|
265
|
+
'custom/typescript_s017': 'S017',
|
|
266
|
+
'custom/typescript_s018': 'S018',
|
|
267
|
+
'custom/typescript_s019': 'S019',
|
|
268
|
+
'custom/typescript_s020': 'S020',
|
|
269
|
+
'custom/typescript_s022': 'S022',
|
|
270
|
+
'custom/typescript_s023': 'S023',
|
|
271
|
+
'custom/typescript_s025': 'S025',
|
|
272
|
+
'custom/typescript_s026': 'S026',
|
|
273
|
+
'custom/typescript_s027': 'S027',
|
|
274
|
+
'custom/typescript_s029': 'S029',
|
|
275
|
+
'custom/typescript_s030': 'S030',
|
|
276
|
+
'custom/typescript_s033': 'S033',
|
|
277
|
+
'custom/typescript_s034': 'S034',
|
|
278
|
+
'custom/typescript_s035': 'S035',
|
|
279
|
+
'custom/typescript_s036': 'S036',
|
|
280
|
+
'custom/typescript_s037': 'S037',
|
|
281
|
+
'custom/typescript_s038': 'S038',
|
|
282
|
+
'custom/typescript_s039': 'S039',
|
|
283
|
+
'custom/typescript_s041': 'S041',
|
|
284
|
+
'custom/typescript_s042': 'S042',
|
|
285
|
+
'custom/typescript_s043': 'S043',
|
|
286
|
+
'custom/typescript_s044': 'S044',
|
|
287
|
+
'custom/typescript_s045': 'S045',
|
|
288
|
+
'custom/typescript_s046': 'S046',
|
|
289
|
+
'custom/typescript_s048': 'S048',
|
|
290
|
+
'custom/typescript_s050': 'S050',
|
|
291
|
+
'custom/typescript_s052': 'S052',
|
|
292
|
+
'custom/typescript_s054': 'S054',
|
|
293
|
+
'custom/typescript_s057': 'S057',
|
|
294
|
+
'custom/typescript_s058': 'S058'
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
return reverseMapping[eslintRuleId] || eslintRuleId;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Query: Map ESLint severity to SunLint severity
|
|
302
|
+
*/
|
|
303
|
+
mapESLintSeverity(eslintSeverity) {
|
|
304
|
+
switch (eslintSeverity) {
|
|
305
|
+
case 1: return 'warning';
|
|
306
|
+
case 2: return 'error';
|
|
307
|
+
default: return 'info';
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
module.exports = ESLintEngineService;
|