@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.
Files changed (192) hide show
  1. package/CHANGELOG.md +202 -0
  2. package/LICENSE +21 -0
  3. package/README.md +490 -0
  4. package/cli-legacy.js +355 -0
  5. package/cli.js +35 -0
  6. package/config/default.json +22 -0
  7. package/config/presets/beginner.json +36 -0
  8. package/config/presets/ci.json +46 -0
  9. package/config/presets/recommended.json +24 -0
  10. package/config/presets/strict.json +32 -0
  11. package/config/rules-registry.json +681 -0
  12. package/config/sunlint-schema.json +166 -0
  13. package/config/typescript/custom-rules-new.js +0 -0
  14. package/config/typescript/custom-rules.js +9 -0
  15. package/config/typescript/eslint.config.js +110 -0
  16. package/config/typescript/package-lock.json +1585 -0
  17. package/config/typescript/package.json +13 -0
  18. package/config/typescript/security-rules/index.js +90 -0
  19. package/config/typescript/security-rules/s005-no-origin-auth.js +95 -0
  20. package/config/typescript/security-rules/s006-activation-recovery-secret-not-plaintext.js +69 -0
  21. package/config/typescript/security-rules/s008-crypto-agility.js +62 -0
  22. package/config/typescript/security-rules/s009-no-insecure-crypto.js +103 -0
  23. package/config/typescript/security-rules/s010-no-insecure-random-in-sensitive-context.js +123 -0
  24. package/config/typescript/security-rules/s011-no-insecure-uuid.js +66 -0
  25. package/config/typescript/security-rules/s012-hardcode-secret.js +71 -0
  26. package/config/typescript/security-rules/s014-insecure-tls-version.js +50 -0
  27. package/config/typescript/security-rules/s015-insecure-tls-certificate.js +43 -0
  28. package/config/typescript/security-rules/s016-sensitive-query-parameter.js +59 -0
  29. package/config/typescript/security-rules/s017-no-sql-injection.js +193 -0
  30. package/config/typescript/security-rules/s018-positive-input-validation.js +56 -0
  31. package/config/typescript/security-rules/s019-no-raw-user-input-in-email.js +113 -0
  32. package/config/typescript/security-rules/s020-no-eval-dynamic-execution.js +89 -0
  33. package/config/typescript/security-rules/s022-output-encoding.js +78 -0
  34. package/config/typescript/security-rules/s023-no-json-injection.js +300 -0
  35. package/config/typescript/security-rules/s025-server-side-input-validation.js +217 -0
  36. package/config/typescript/security-rules/s026-json-schema-validation.js +68 -0
  37. package/config/typescript/security-rules/s027-no-hardcoded-secrets.js +80 -0
  38. package/config/typescript/security-rules/s029-require-csrf-protection.js +79 -0
  39. package/config/typescript/security-rules/s030-no-directory-browsing.js +78 -0
  40. package/config/typescript/security-rules/s033-require-samesite-cookie.js +80 -0
  41. package/config/typescript/security-rules/s034-require-host-cookie-prefix.js +77 -0
  42. package/config/typescript/security-rules/s035-cookie-specific-path.js +74 -0
  43. package/config/typescript/security-rules/s036-no-unsafe-file-include.js +68 -0
  44. package/config/typescript/security-rules/s037-require-anti-cache-headers.js +70 -0
  45. package/config/typescript/security-rules/s038-no-version-disclosure.js +74 -0
  46. package/config/typescript/security-rules/s039-no-session-token-in-url.js +63 -0
  47. package/config/typescript/security-rules/s041-require-session-invalidate-on-logout.js +211 -0
  48. package/config/typescript/security-rules/s042-require-periodic-reauthentication.js +294 -0
  49. package/config/typescript/security-rules/s043-terminate-sessions-on-password-change.js +254 -0
  50. package/config/typescript/security-rules/s044-require-full-session-for-sensitive-operations.js +292 -0
  51. package/config/typescript/security-rules/s045-anti-automation-controls.js +46 -0
  52. package/config/typescript/security-rules/s046-secure-notification-on-auth-change.js +44 -0
  53. package/config/typescript/security-rules/s048-password-credential-recovery.js +54 -0
  54. package/config/typescript/security-rules/s050-session-token-weak-hash.js +94 -0
  55. package/config/typescript/security-rules/s052-secure-random-authentication-code.js +66 -0
  56. package/config/typescript/security-rules/s054-verification-default-account.js +109 -0
  57. package/config/typescript/security-rules/s057-utc-logging.js +54 -0
  58. package/config/typescript/security-rules/s058-no-ssrf.js +73 -0
  59. package/config/typescript/test-s005-working.ts +22 -0
  60. package/config/typescript/tsconfig.json +29 -0
  61. package/core/ai-analyzer.js +169 -0
  62. package/core/analysis-orchestrator.js +705 -0
  63. package/core/cli-action-handler.js +230 -0
  64. package/core/cli-program.js +106 -0
  65. package/core/config-manager.js +396 -0
  66. package/core/config-merger.js +136 -0
  67. package/core/config-override-processor.js +74 -0
  68. package/core/config-preset-resolver.js +65 -0
  69. package/core/config-source-loader.js +152 -0
  70. package/core/config-validator.js +126 -0
  71. package/core/dependency-manager.js +105 -0
  72. package/core/eslint-engine-service.js +312 -0
  73. package/core/eslint-instance-manager.js +104 -0
  74. package/core/eslint-integration-service.js +363 -0
  75. package/core/git-utils.js +170 -0
  76. package/core/multi-rule-runner.js +239 -0
  77. package/core/output-service.js +250 -0
  78. package/core/report-generator.js +320 -0
  79. package/core/rule-mapping-service.js +309 -0
  80. package/core/rule-selection-service.js +121 -0
  81. package/core/sunlint-engine-service.js +23 -0
  82. package/core/typescript-analyzer.js +262 -0
  83. package/core/typescript-engine.js +313 -0
  84. package/docs/AI.md +163 -0
  85. package/docs/ARCHITECTURE.md +78 -0
  86. package/docs/CI-CD-GUIDE.md +315 -0
  87. package/docs/COMMAND-EXAMPLES.md +256 -0
  88. package/docs/DEBUG.md +86 -0
  89. package/docs/DISTRIBUTION.md +153 -0
  90. package/docs/ESLINT-INTEGRATION-STRATEGY.md +392 -0
  91. package/docs/ESLINT_INTEGRATION.md +238 -0
  92. package/docs/FOLDER_STRUCTURE.md +59 -0
  93. package/docs/HEURISTIC_VS_AI.md +113 -0
  94. package/docs/README.md +32 -0
  95. package/docs/RELEASE_GUIDE.md +230 -0
  96. package/docs/RULE-RESPONSIBILITY-MATRIX.md +204 -0
  97. package/eslint-integration/.eslintrc.js +98 -0
  98. package/eslint-integration/cli.js +35 -0
  99. package/eslint-integration/eslint-plugin-custom/c002-no-duplicate-code.js +204 -0
  100. package/eslint-integration/eslint-plugin-custom/c003-no-vague-abbreviations.js +246 -0
  101. package/eslint-integration/eslint-plugin-custom/c006-function-name-verb-noun.js +207 -0
  102. package/eslint-integration/eslint-plugin-custom/c010-limit-block-nesting.js +90 -0
  103. package/eslint-integration/eslint-plugin-custom/c013-no-dead-code.js +43 -0
  104. package/eslint-integration/eslint-plugin-custom/c014-abstract-dependency-preferred.js +38 -0
  105. package/eslint-integration/eslint-plugin-custom/c017-limit-constructor-logic.js +39 -0
  106. package/eslint-integration/eslint-plugin-custom/c018-no-generic-throw.js +335 -0
  107. package/eslint-integration/eslint-plugin-custom/c023-no-duplicate-variable-name-in-scope.js +142 -0
  108. package/eslint-integration/eslint-plugin-custom/c027-limit-function-nesting.js +50 -0
  109. package/eslint-integration/eslint-plugin-custom/c029-catch-block-logging.js +80 -0
  110. package/eslint-integration/eslint-plugin-custom/c030-use-custom-error-classes.js +294 -0
  111. package/eslint-integration/eslint-plugin-custom/c034-no-implicit-return.js +34 -0
  112. package/eslint-integration/eslint-plugin-custom/c035-no-empty-catch.js +32 -0
  113. package/eslint-integration/eslint-plugin-custom/c041-no-config-inline.js +64 -0
  114. package/eslint-integration/eslint-plugin-custom/c042-boolean-name-prefix.js +406 -0
  115. package/eslint-integration/eslint-plugin-custom/c043-no-console-or-print.js +300 -0
  116. package/eslint-integration/eslint-plugin-custom/c047-no-duplicate-retry-logic.js +239 -0
  117. package/eslint-integration/eslint-plugin-custom/c048-no-var-declaration.js +31 -0
  118. package/eslint-integration/eslint-plugin-custom/c076-one-assert-per-test.js +184 -0
  119. package/eslint-integration/eslint-plugin-custom/index.js +155 -0
  120. package/eslint-integration/eslint-plugin-custom/package.json +13 -0
  121. package/eslint-integration/eslint-plugin-custom/package.json.bak +9 -0
  122. package/eslint-integration/eslint-plugin-custom/s003-no-unvalidated-redirect.js +86 -0
  123. package/eslint-integration/eslint-plugin-custom/s005-no-origin-auth.js +95 -0
  124. package/eslint-integration/eslint-plugin-custom/s006-activation-recovery-secret-not-plaintext.js +69 -0
  125. package/eslint-integration/eslint-plugin-custom/s008-crypto-agility.js +62 -0
  126. package/eslint-integration/eslint-plugin-custom/s009-no-insecure-crypto.js +103 -0
  127. package/eslint-integration/eslint-plugin-custom/s010-no-insecure-random-in-sensitive-context.js +123 -0
  128. package/eslint-integration/eslint-plugin-custom/s011-no-insecure-uuid.js +66 -0
  129. package/eslint-integration/eslint-plugin-custom/s012-hardcode-secret.js +71 -0
  130. package/eslint-integration/eslint-plugin-custom/s014-insecure-tls-version.js +50 -0
  131. package/eslint-integration/eslint-plugin-custom/s015-insecure-tls-certificate.js +43 -0
  132. package/eslint-integration/eslint-plugin-custom/s016-sensitive-query-parameter.js +59 -0
  133. package/eslint-integration/eslint-plugin-custom/s017-no-sql-injection.js +193 -0
  134. package/eslint-integration/eslint-plugin-custom/s018-positive-input-validation.js +56 -0
  135. package/eslint-integration/eslint-plugin-custom/s019-no-raw-user-input-in-email.js +113 -0
  136. package/eslint-integration/eslint-plugin-custom/s020-no-eval-dynamic-execution.js +89 -0
  137. package/eslint-integration/eslint-plugin-custom/s022-output-encoding.js +78 -0
  138. package/eslint-integration/eslint-plugin-custom/s023-no-json-injection.js +300 -0
  139. package/eslint-integration/eslint-plugin-custom/s025-server-side-input-validation.js +217 -0
  140. package/eslint-integration/eslint-plugin-custom/s026-json-schema-validation.js +68 -0
  141. package/eslint-integration/eslint-plugin-custom/s027-no-hardcoded-secrets.js +80 -0
  142. package/eslint-integration/eslint-plugin-custom/s029-require-csrf-protection.js +79 -0
  143. package/eslint-integration/eslint-plugin-custom/s030-no-directory-browsing.js +78 -0
  144. package/eslint-integration/eslint-plugin-custom/s033-require-samesite-cookie.js +80 -0
  145. package/eslint-integration/eslint-plugin-custom/s034-require-host-cookie-prefix.js +77 -0
  146. package/eslint-integration/eslint-plugin-custom/s035-cookie-specific-path.js +74 -0
  147. package/eslint-integration/eslint-plugin-custom/s036-no-unsafe-file-include.js +68 -0
  148. package/eslint-integration/eslint-plugin-custom/s037-require-anti-cache-headers.js +70 -0
  149. package/eslint-integration/eslint-plugin-custom/s038-no-version-disclosure.js +74 -0
  150. package/eslint-integration/eslint-plugin-custom/s039-no-session-token-in-url.js +63 -0
  151. package/eslint-integration/eslint-plugin-custom/s041-require-session-invalidate-on-logout.js +211 -0
  152. package/eslint-integration/eslint-plugin-custom/s042-require-periodic-reauthentication.js +294 -0
  153. package/eslint-integration/eslint-plugin-custom/s043-terminate-sessions-on-password-change.js +254 -0
  154. package/eslint-integration/eslint-plugin-custom/s044-require-full-session-for-sensitive-operations.js +292 -0
  155. package/eslint-integration/eslint-plugin-custom/s045-anti-automation-controls.js +46 -0
  156. package/eslint-integration/eslint-plugin-custom/s046-secure-notification-on-auth-change.js +44 -0
  157. package/eslint-integration/eslint-plugin-custom/s047-secure-random-passwords.js +108 -0
  158. package/eslint-integration/eslint-plugin-custom/s048-password-credential-recovery.js +54 -0
  159. package/eslint-integration/eslint-plugin-custom/s050-session-token-weak-hash.js +94 -0
  160. package/eslint-integration/eslint-plugin-custom/s052-secure-random-authentication-code.js +66 -0
  161. package/eslint-integration/eslint-plugin-custom/s054-verification-default-account.js +109 -0
  162. package/eslint-integration/eslint-plugin-custom/s055-verification-rest-check-the-incoming-content-type.js +143 -0
  163. package/eslint-integration/eslint-plugin-custom/s057-utc-logging.js +54 -0
  164. package/eslint-integration/eslint-plugin-custom/s058-no-ssrf.js +73 -0
  165. package/eslint-integration/eslint-plugin-custom/t002-interface-prefix-i.js +42 -0
  166. package/eslint-integration/eslint-plugin-custom/t003-ts-ignore-reason.js +48 -0
  167. package/eslint-integration/eslint-plugin-custom/t004-interface-public-only.js +160 -0
  168. package/eslint-integration/eslint-plugin-custom/t007-no-fn-in-constructor.js +52 -0
  169. package/eslint-integration/eslint-plugin-custom/t011-no-real-time-dependency.js +175 -0
  170. package/eslint-integration/eslint-plugin-custom/t019-no-empty-type.js +95 -0
  171. package/eslint-integration/eslint-plugin-custom/t025-no-nested-union-tuple.js +48 -0
  172. package/eslint-integration/eslint-plugin-custom/t026-limit-nested-generics.js +377 -0
  173. package/eslint-integration/eslint.config.js +125 -0
  174. package/eslint-integration/eslint.config.simple.js +24 -0
  175. package/eslint-integration/node_modules/eslint-plugin-custom/package.json +0 -0
  176. package/eslint-integration/package.json +23 -0
  177. package/eslint-integration/sample.ts +53 -0
  178. package/eslint-integration/test-s003.js +5 -0
  179. package/eslint-integration/tsconfig.json +27 -0
  180. package/examples/.github/workflows/code-quality.yml +111 -0
  181. package/examples/.sunlint.json +42 -0
  182. package/examples/README.md +47 -0
  183. package/examples/package.json +33 -0
  184. package/package.json +100 -0
  185. package/rules/C006_function_naming/analyzer.js +338 -0
  186. package/rules/C006_function_naming/config.json +86 -0
  187. package/rules/C019_log_level_usage/analyzer.js +359 -0
  188. package/rules/C019_log_level_usage/config.json +121 -0
  189. package/rules/C029_catch_block_logging/analyzer.js +339 -0
  190. package/rules/C029_catch_block_logging/config.json +59 -0
  191. package/rules/C031_validation_separation/README.md +72 -0
  192. package/rules/C031_validation_separation/analyzer.js +186 -0
package/cli-legacy.js ADDED
@@ -0,0 +1,355 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * LEGACY CLI - DO NOT USE
5
+ * This is the old monolithic CLI implementation kept for reference only.
6
+ * Use cli.js instead - it has the new modular architecture with ESLint integration.
7
+ */
8
+
9
+ const { Command } = require('commander');
10
+ const chalk = require('chalk');
11
+ const path = require('path');
12
+ const fs = require('fs');
13
+ const MultiRuleRunner = require('./core/multi-rule-runner');
14
+ const ConfigManager = require('./core/config-manager');
15
+ const ReportGenerator = require('./core/report-generator');
16
+ const { version } = require('./package.json');
17
+
18
+ const program = new Command();
19
+
20
+ program
21
+ .name('sunlint')
22
+ .description('☀️ Sun Lint - Coding Standards Checker | Multi-rule Quality & Security Analysis')
23
+ .version(version);
24
+
25
+ // Rule selection
26
+ program
27
+ .option('-r, --rule <rule>', 'Run single rule (e.g., C019)')
28
+ .option('-R, --rules <rules>', 'Run multiple rules (e.g., C019,C006,C021)')
29
+ .option('-a, --all', 'Run all available rules')
30
+ .option('-c, --category <category>', 'Run rules by category (quality,security,logging,naming)')
31
+ .option('--quality', 'Run all code quality rules')
32
+ .option('--security', 'Run all secure coding rules')
33
+ .option('--preset <preset>', 'Use predefined rule preset (recommended,strict,beginner)')
34
+
35
+ // Input/Output
36
+ .option('-i, --input <path>', 'Input file or directory to analyze', 'src')
37
+ .option('-f, --format <format>', 'Output format (eslint,json,summary,table)', 'eslint')
38
+ .option('-o, --output <file>', 'Output file path')
39
+ .option('--config <file>', 'Configuration file path', '.sunlint.json')
40
+
41
+ // CI/CD and Git integration
42
+ .option('--changed-files', 'Only analyze files changed in current branch (git diff)')
43
+ .option('--staged-files', 'Only analyze staged files (git diff --cached)')
44
+ .option('--diff-base <ref>', 'Compare against specific git reference (e.g., origin/main)')
45
+ .option('--since <commit>', 'Only analyze files changed since specific commit')
46
+ .option('--pr-mode', 'Enable PR mode (changed files + baseline comparison)')
47
+ .option('--baseline <file>', 'Load baseline results to compare against')
48
+ .option('--save-baseline <file>', 'Save current results as baseline')
49
+ .option('--fail-on-new-violations', 'Exit with error only on new violations (not existing)')
50
+
51
+ // Rule control
52
+ .option('--exclude-rules <rules>', 'Exclude specific rules (e.g., C019,C006)')
53
+ .option('--include-rules <rules>', 'Include only specific rules (e.g., C019,C006)')
54
+ .option('--disable-rule <rule>', 'Disable specific rule')
55
+ .option('--enable-rule <rule>', 'Enable specific rule')
56
+ .option('--severity <level>', 'Minimum severity level (error,warning,info)', 'info')
57
+ .option('--languages <langs>', 'Target languages (typescript,dart,kotlin)')
58
+
59
+ // Advanced options
60
+ .option('--ai', 'Enable AI-powered analysis')
61
+ .option('--no-ai', 'Force disable AI analysis (use heuristic only)')
62
+ .option('--no-cache', 'Disable result caching')
63
+ .option('--max-concurrent <n>', 'Maximum concurrent rule execution', '5')
64
+ .option('--timeout <ms>', 'Timeout for rule execution (ms)', '30000')
65
+ .option('--fix', 'Auto-fix issues when possible')
66
+ .option('--dry-run', 'Show what would be analyzed without running')
67
+ .option('--verbose', 'Enable verbose logging')
68
+ .option('--quiet', 'Suppress non-error output')
69
+ .option('--debug', 'Enable debug mode');
70
+
71
+ program.action(async (options) => {
72
+ try {
73
+ // Sun Lint banner
74
+ console.log(chalk.yellow.bold('☀️ Sun Lint - Coding Standards Checker'));
75
+ console.log(chalk.gray(`Version: ${version} | Sun* Engineering`));
76
+
77
+ if (options.debug) {
78
+ console.log(chalk.yellow('Debug mode enabled'));
79
+ console.log('Options:', options);
80
+ }
81
+
82
+ // Handle quality/security shortcuts
83
+ if (options.quality) {
84
+ options.category = 'quality';
85
+ }
86
+ if (options.security) {
87
+ options.category = 'security';
88
+ }
89
+
90
+ // Load configuration
91
+ const configManager = new ConfigManager();
92
+ const config = await configManager.loadConfig(options.config, options);
93
+
94
+ if (options.verbose) {
95
+ console.log(chalk.gray('Configuration loaded:'), config);
96
+ }
97
+
98
+ // Validate input
99
+ if (!fs.existsSync(options.input)) {
100
+ console.error(chalk.red(`❌ Input path not found: ${options.input}`));
101
+ process.exit(1);
102
+ }
103
+
104
+ // Show dry run info
105
+ if (options.dryRun) {
106
+ console.log(chalk.yellow('🔍 Dry run mode - Analysis preview:'));
107
+ await showDryRunPreview(config, options);
108
+ return;
109
+ }
110
+
111
+ // Initialize multi-rule runner
112
+ const runner = new MultiRuleRunner(config, options);
113
+
114
+ // Get rules to run
115
+ const rulesToRun = await getRulesToRun(config, options);
116
+
117
+ if (rulesToRun.length === 0) {
118
+ console.log(chalk.yellow('⚠️ No rules to run'));
119
+ return;
120
+ }
121
+
122
+ if (!options.quiet) {
123
+ const rulesByCategory = categorizeRules(rulesToRun);
124
+ console.log(chalk.green(`🚀 Running ${rulesToRun.length} rules on: ${options.input}`));
125
+
126
+ if (rulesByCategory.quality.length > 0) {
127
+ console.log(chalk.blue(` 📋 Quality rules: ${rulesByCategory.quality.map(r => r.id).join(', ')}`));
128
+ }
129
+ if (rulesByCategory.security.length > 0) {
130
+ console.log(chalk.red(` 🔒 Security rules: ${rulesByCategory.security.map(r => r.id).join(', ')}`));
131
+ }
132
+ if (rulesByCategory.other.length > 0) {
133
+ console.log(chalk.gray(` ⚙️ Other rules: ${rulesByCategory.other.map(r => r.id).join(', ')}`));
134
+ }
135
+ }
136
+
137
+ // Run analysis
138
+ const startTime = Date.now();
139
+ const results = await runner.runRules(rulesToRun, options.input, options);
140
+ const duration = Date.now() - startTime;
141
+
142
+ // Generate report
143
+ const reportGenerator = new ReportGenerator(config, options);
144
+ const report = await reportGenerator.generateReport(results, {
145
+ duration,
146
+ rulesRun: rulesToRun.length,
147
+ filesAnalyzed: results.filesAnalyzed || 0
148
+ });
149
+
150
+ // Output results
151
+ await outputResults(report, options);
152
+
153
+ // Exit with appropriate code
154
+ const allResults = results.results || [];
155
+ const hasErrors = allResults.some(r =>
156
+ r.violations && r.violations.some(v => v.severity === 'error')
157
+ );
158
+ process.exit(hasErrors ? 1 : 0);
159
+
160
+ } catch (error) {
161
+ console.error(chalk.red('❌ Sun Lint Error:'), error.message);
162
+ if (options.debug) {
163
+ console.error(error.stack);
164
+ }
165
+ process.exit(1);
166
+ }
167
+ });
168
+
169
+ async function getRulesToRun(config, options) {
170
+ const allRules = config.rules || {};
171
+ const rulesRegistry = require('./config/rules-registry.json');
172
+
173
+ let selectedRules = [];
174
+
175
+ if (options.rule) {
176
+ // Single rule
177
+ selectedRules = [options.rule];
178
+ } else if (options.rules) {
179
+ // Multiple rules
180
+ selectedRules = options.rules.split(',').map(r => r.trim());
181
+ } else if (options.all) {
182
+ // All rules
183
+ selectedRules = Object.keys(rulesRegistry.rules);
184
+ } else if (options.category) {
185
+ // Rules by category
186
+ const category = rulesRegistry.categories[options.category];
187
+ if (category && category.rules) {
188
+ selectedRules = category.rules;
189
+ }
190
+ } else if (options.preset) {
191
+ // Load preset using ConfigManager
192
+ try {
193
+ const ConfigManager = require('./core/config-manager');
194
+ const configManager = new ConfigManager();
195
+
196
+ const presetName = options.preset.startsWith('@sun/sunlint/')
197
+ ? options.preset
198
+ : `@sun/sunlint/${options.preset}`;
199
+ const presetConfig = await configManager.loadPreset(presetName);
200
+ if (presetConfig && presetConfig.rules) {
201
+ selectedRules = Object.keys(presetConfig.rules).filter(ruleId =>
202
+ presetConfig.rules[ruleId] !== 'off' && presetConfig.rules[ruleId] !== false
203
+ );
204
+ console.log(chalk.blue(`🎯 Using preset: ${presetName}`));
205
+ }
206
+ } catch (error) {
207
+ console.error(chalk.red(`❌ Failed to load preset '${options.preset}':`), error.message);
208
+ process.exit(1);
209
+ }
210
+ } else {
211
+ // Default: use config rules
212
+ selectedRules = Object.keys(allRules).filter(ruleId =>
213
+ allRules[ruleId] !== 'off' && allRules[ruleId] !== false
214
+ );
215
+ }
216
+
217
+ // Filter out excluded rules
218
+ if (options.excludeRules) {
219
+ const excludedRules = options.excludeRules.split(',').map(r => r.trim());
220
+ selectedRules = selectedRules.filter(rule => !excludedRules.includes(rule));
221
+ }
222
+
223
+ // Filter by severity
224
+ if (options.severity) {
225
+ const minSeverity = options.severity;
226
+ const severityLevels = { info: 0, warning: 1, error: 2 };
227
+ const minLevel = severityLevels[minSeverity] || 0;
228
+
229
+ selectedRules = selectedRules.filter(ruleId => {
230
+ const rule = rulesRegistry.rules[ruleId];
231
+ if (!rule) return false;
232
+ const ruleLevel = severityLevels[rule.severity] || 0;
233
+ return ruleLevel >= minLevel;
234
+ });
235
+ }
236
+
237
+ // Filter by languages
238
+ if (options.languages) {
239
+ const targetLanguages = options.languages.split(',').map(l => l.trim());
240
+ selectedRules = selectedRules.filter(ruleId => {
241
+ const rule = rulesRegistry.rules[ruleId];
242
+ if (!rule) return false;
243
+ return rule.languages.some(lang => targetLanguages.includes(lang));
244
+ });
245
+ }
246
+
247
+ // Convert to rule objects
248
+ return selectedRules.map(ruleId => ({
249
+ id: ruleId,
250
+ ...rulesRegistry.rules[ruleId]
251
+ })).filter(rule => rule.name); // Filter out invalid rules
252
+ }
253
+
254
+ function categorizeRules(rules) {
255
+ const categories = {
256
+ quality: [],
257
+ security: [],
258
+ other: []
259
+ };
260
+
261
+ rules.forEach(rule => {
262
+ if (rule.category === 'security' || rule.id.startsWith('S')) {
263
+ categories.security.push(rule);
264
+ } else if (['logging', 'naming', 'validation', 'design'].includes(rule.category)) {
265
+ categories.quality.push(rule);
266
+ } else {
267
+ categories.other.push(rule);
268
+ }
269
+ });
270
+
271
+ return categories;
272
+ }
273
+
274
+ async function showDryRunPreview(config, options) {
275
+ const rulesToRun = await getRulesToRun(config, options);
276
+ const rulesByCategory = categorizeRules(rulesToRun);
277
+
278
+ console.log(chalk.blue('📋 Sun Lint Analysis Preview:'));
279
+ console.log(chalk.gray(`Input: ${options.input}`));
280
+ console.log(chalk.gray(`Format: ${options.format}`));
281
+ console.log(chalk.gray(`Rules to run: ${rulesToRun.length}`));
282
+
283
+ if (rulesByCategory.quality.length > 0) {
284
+ console.log(chalk.blue('📋 Quality Rules:'));
285
+ rulesByCategory.quality.forEach(rule => {
286
+ console.log(` ${chalk.cyan(rule.id)}: ${rule.name} (${rule.severity})`);
287
+ });
288
+ }
289
+
290
+ if (rulesByCategory.security.length > 0) {
291
+ console.log(chalk.red('🔒 Security Rules:'));
292
+ rulesByCategory.security.forEach(rule => {
293
+ console.log(` ${chalk.cyan(rule.id)}: ${rule.name} (${rule.severity})`);
294
+ });
295
+ }
296
+
297
+ if (rulesByCategory.other.length > 0) {
298
+ console.log(chalk.white('⚙️ Other Rules:'));
299
+ rulesByCategory.other.forEach(rule => {
300
+ console.log(` ${chalk.cyan(rule.id)}: ${rule.name} (${rule.severity})`);
301
+ });
302
+ }
303
+ }
304
+
305
+ async function outputResults(report, options) {
306
+ // Console output
307
+ if (!options.quiet) {
308
+ console.log(report.formatted);
309
+ }
310
+
311
+ // File output
312
+ if (options.output) {
313
+ fs.writeFileSync(options.output, JSON.stringify(report.raw, null, 2));
314
+ console.log(chalk.green(`📄 Report saved to: ${options.output}`));
315
+ }
316
+
317
+ // Summary
318
+ if (report.summary && !options.quiet) {
319
+ console.log(chalk.blue('\n📊 Sun Lint Summary:'));
320
+ console.log(report.summary);
321
+ }
322
+ }
323
+
324
+ // Error handling
325
+ process.on('unhandledRejection', (reason, promise) => {
326
+ console.error(chalk.red('Sun Lint - Unhandled Rejection:'), promise, chalk.red('reason:'), reason);
327
+ process.exit(1);
328
+ });
329
+
330
+ process.on('uncaughtException', (error) => {
331
+ console.error(chalk.red('Sun Lint - Uncaught Exception:'), error);
332
+ process.exit(1);
333
+ });
334
+
335
+ // Help examples
336
+ program.addHelpText('after', `
337
+ Examples:
338
+ $ sunlint --rule=C019 --input=src
339
+ $ sunlint --rules=C019,C006 --input=src --format=json
340
+ $ sunlint --all --input=src --format=summary
341
+ $ sunlint --quality --input=src
342
+ $ sunlint --security --input=src
343
+ $ sunlint --category=logging --input=src
344
+ $ sunlint --preset=recommended --input=src
345
+ $ sunlint --config=.sunlint.json --input=src
346
+ $ sunlint --rule=C019 --input=src --output=report.json
347
+ $ sunlint --all --input=src --exclude-rules=C006,C031
348
+ $ sunlint --rule=C019 --input=src --ai
349
+ $ sunlint --rule=C019 --input=src --no-ai
350
+ $ sunlint --all --input=src --severity=error --ai
351
+
352
+ Sun* Engineering - Coding Standards Made Simple ☀️
353
+ `);
354
+
355
+ program.parse();
package/cli.js ADDED
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * SunLint CLI Entry Point
5
+ * Main CLI entry point with modular architecture
6
+ * Following Rule C005: Single responsibility - only handle CLI bootstrapping
7
+ * Following Rule C014: Dependency injection for services
8
+ */
9
+
10
+ const chalk = require('chalk');
11
+ const { createCliProgram } = require('./core/cli-program');
12
+ const CliActionHandler = require('./core/cli-action-handler');
13
+
14
+ // Create CLI program
15
+ const program = createCliProgram();
16
+
17
+ // Set up main action handler
18
+ program.action(async (options) => {
19
+ const actionHandler = new CliActionHandler(options);
20
+ await actionHandler.execute();
21
+ });
22
+
23
+ // Global error handling
24
+ process.on('unhandledRejection', (reason, promise) => {
25
+ console.error(chalk.red('Sun Lint - Unhandled Rejection:'), promise, chalk.red('reason:'), reason);
26
+ process.exit(1);
27
+ });
28
+
29
+ process.on('uncaughtException', (error) => {
30
+ console.error(chalk.red('Sun Lint - Uncaught Exception:'), error);
31
+ process.exit(1);
32
+ });
33
+
34
+ // Parse CLI arguments
35
+ program.parse();
@@ -0,0 +1,22 @@
1
+ {
2
+ "rules": {
3
+ "C006": true,
4
+ "C019": true,
5
+ "C032": true,
6
+ "C045": true
7
+ },
8
+ "categories": ["quality", "security"],
9
+ "integration": {
10
+ "eslint": {
11
+ "enabled": true,
12
+ "legacySupport": false,
13
+ "autoDetect": true,
14
+ "fallbackToStandalone": true
15
+ }
16
+ },
17
+ "compatibility": {
18
+ "eslintV8": false,
19
+ "eslintV9": true,
20
+ "strictConfigValidation": false
21
+ }
22
+ }
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@sun/sunlint/beginner",
3
+ "description": "Beginner-friendly configuration with warnings only",
4
+ "rules": {
5
+ "C019": "warning",
6
+ "C029": "warning",
7
+ "C006": "info"
8
+ },
9
+ "categories": {
10
+ "quality": "warning",
11
+ "security": "warning",
12
+ "logging": "warning",
13
+ "naming": "info",
14
+ "validation": "warning"
15
+ },
16
+ "languages": ["typescript"],
17
+ "ignorePatterns": [
18
+ "**/node_modules/**",
19
+ "**/build/**",
20
+ "**/dist/**",
21
+ "**/*.generated.*",
22
+ "**/*.min.*",
23
+ "**/test/**",
24
+ "**/tests/**"
25
+ ],
26
+ "ai": {
27
+ "enabled": false,
28
+ "fallbackToPattern": true
29
+ },
30
+ "reporting": {
31
+ "exitOnError": false,
32
+ "showProgress": true,
33
+ "includeContext": true,
34
+ "showFixSuggestions": true
35
+ }
36
+ }
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@sun/sunlint/ci",
3
+ "description": "Configuration optimized for CI/CD pipelines",
4
+ "rules": {
5
+ "C019": "error",
6
+ "C029": "error",
7
+ "C006": "off"
8
+ },
9
+ "categories": {
10
+ "quality": "error",
11
+ "security": "error",
12
+ "logging": "error",
13
+ "naming": "off",
14
+ "validation": "error"
15
+ },
16
+ "languages": ["typescript", "dart", "javascript"],
17
+ "ignorePatterns": [
18
+ "**/node_modules/**",
19
+ "**/build/**",
20
+ "**/dist/**",
21
+ "**/*.generated.*",
22
+ "**/*.min.*",
23
+ "coverage/**"
24
+ ],
25
+ "ai": {
26
+ "enabled": false,
27
+ "fallbackToPattern": true
28
+ },
29
+ "output": {
30
+ "format": "github",
31
+ "console": false,
32
+ "summary": true,
33
+ "file": "sunlint-report.json"
34
+ },
35
+ "performance": {
36
+ "maxConcurrentRules": 10,
37
+ "timeoutMs": 60000,
38
+ "cacheEnabled": true
39
+ },
40
+ "reporting": {
41
+ "exitOnError": true,
42
+ "showProgress": false,
43
+ "includeContext": false,
44
+ "showFixSuggestions": false
45
+ }
46
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@sun/sunlint/recommended",
3
+ "description": "Sun* Engineering recommended configuration",
4
+ "rules": {
5
+ "C019": "warning",
6
+ "C029": "error",
7
+ "C006": "off"
8
+ },
9
+ "categories": {
10
+ "quality": "warning",
11
+ "security": "error",
12
+ "logging": "warning",
13
+ "naming": "off",
14
+ "validation": "error"
15
+ },
16
+ "languages": ["typescript", "dart"],
17
+ "ignorePatterns": [
18
+ "**/node_modules/**",
19
+ "**/build/**",
20
+ "**/dist/**",
21
+ "**/*.generated.*",
22
+ "**/*.min.*"
23
+ ]
24
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@sun/sunlint/strict",
3
+ "description": "Strict configuration for production projects",
4
+ "rules": {
5
+ "C019": "error",
6
+ "C029": "error",
7
+ "C006": "warning"
8
+ },
9
+ "categories": {
10
+ "quality": "error",
11
+ "security": "error",
12
+ "logging": "error",
13
+ "naming": "warning",
14
+ "validation": "error"
15
+ },
16
+ "languages": ["typescript", "dart", "javascript"],
17
+ "ignorePatterns": [
18
+ "**/node_modules/**",
19
+ "**/build/**",
20
+ "**/dist/**",
21
+ "**/*.generated.*",
22
+ "**/*.min.*"
23
+ ],
24
+ "ai": {
25
+ "enabled": true,
26
+ "fallbackToPattern": false
27
+ },
28
+ "reporting": {
29
+ "exitOnError": true,
30
+ "showProgress": true
31
+ }
32
+ }