@sun-asterisk/sunlint 1.0.7 → 1.1.4

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 (219) hide show
  1. package/.sunlint.json +35 -0
  2. package/CHANGELOG.md +30 -3
  3. package/CONTRIBUTING.md +235 -0
  4. package/PROJECT_STRUCTURE.md +60 -0
  5. package/README.md +146 -58
  6. package/cli.js +1 -0
  7. package/config/README.md +88 -0
  8. package/config/defaults/ai-rules-context.json +231 -0
  9. package/config/engines/engines.json +49 -0
  10. package/config/engines/eslint-rule-mapping.json +74 -0
  11. package/config/eslint-rule-mapping.json +126 -0
  12. package/config/integrations/eslint/base.config.js +125 -0
  13. package/config/integrations/eslint/simple.config.js +24 -0
  14. package/config/presets/strict.json +0 -1
  15. package/config/rule-analysis-strategies.js +74 -0
  16. package/config/{rules-registry.json → rules/rules-registry.json} +30 -7
  17. package/core/analysis-orchestrator.js +383 -591
  18. package/core/ast-modules/README.md +103 -0
  19. package/core/ast-modules/base-parser.js +90 -0
  20. package/core/ast-modules/index.js +97 -0
  21. package/core/ast-modules/package.json +37 -0
  22. package/core/ast-modules/parsers/eslint-js-parser.js +153 -0
  23. package/core/ast-modules/parsers/eslint-ts-parser.js +98 -0
  24. package/core/ast-modules/parsers/javascript-parser.js +187 -0
  25. package/core/ast-modules/parsers/typescript-parser.js +187 -0
  26. package/core/cli-action-handler.js +271 -255
  27. package/core/cli-program.js +18 -4
  28. package/core/config-manager.js +9 -3
  29. package/core/config-merger.js +40 -1
  30. package/core/config-validator.js +2 -2
  31. package/core/dependency-checker.js +125 -0
  32. package/core/enhanced-rules-registry.js +331 -0
  33. package/core/file-targeting-service.js +92 -23
  34. package/core/interfaces/analysis-engine.interface.js +100 -0
  35. package/core/multi-rule-runner.js +0 -221
  36. package/core/output-service.js +1 -1
  37. package/core/rule-mapping-service.js +1 -1
  38. package/core/rule-selection-service.js +10 -2
  39. package/core/smart-installer.js +164 -0
  40. package/docs/AI.md +163 -0
  41. package/docs/ARCHITECTURE.md +78 -0
  42. package/docs/CI-CD-GUIDE.md +315 -0
  43. package/docs/COMMAND-EXAMPLES.md +256 -0
  44. package/docs/CONFIGURATION.md +414 -0
  45. package/docs/DEBUG.md +86 -0
  46. package/docs/DEPENDENCIES.md +90 -0
  47. package/docs/DEPLOYMENT-STRATEGIES.md +270 -0
  48. package/docs/DISTRIBUTION.md +153 -0
  49. package/docs/ESLINT-INTEGRATION-STRATEGY.md +392 -0
  50. package/docs/ESLINT_INTEGRATION.md +238 -0
  51. package/docs/FOLDER_STRUCTURE.md +59 -0
  52. package/docs/FUTURE_PACKAGES.md +83 -0
  53. package/docs/HEURISTIC_VS_AI.md +113 -0
  54. package/docs/PRODUCTION_DEPLOYMENT_ANALYSIS.md +112 -0
  55. package/docs/PRODUCTION_SIZE_IMPACT.md +183 -0
  56. package/docs/README.md +32 -0
  57. package/docs/RELEASE_GUIDE.md +230 -0
  58. package/engines/eslint-engine.js +610 -0
  59. package/engines/heuristic-engine.js +864 -0
  60. package/engines/openai-engine.js +374 -0
  61. package/engines/tree-sitter-parser.js +0 -0
  62. package/engines/universal-ast-engine.js +0 -0
  63. package/integrations/eslint/README.md +99 -0
  64. package/integrations/eslint/configs/.eslintrc.js +98 -0
  65. package/integrations/eslint/configs/eslint.config.js +133 -0
  66. package/integrations/eslint/configs/eslint.config.simple.js +24 -0
  67. package/integrations/eslint/package.json +23 -0
  68. package/integrations/eslint/plugin/index.js +164 -0
  69. package/integrations/eslint/plugin/package.json +13 -0
  70. package/integrations/eslint/plugin/rules/common/c002-no-duplicate-code.js +204 -0
  71. package/integrations/eslint/plugin/rules/common/c003-no-vague-abbreviations.js +246 -0
  72. package/integrations/eslint/plugin/rules/common/c006-function-name-verb-noun.js +216 -0
  73. package/integrations/eslint/plugin/rules/common/c010-limit-block-nesting.js +90 -0
  74. package/integrations/eslint/plugin/rules/common/c013-no-dead-code.js +78 -0
  75. package/integrations/eslint/plugin/rules/common/c014-abstract-dependency-preferred.js +38 -0
  76. package/integrations/eslint/plugin/rules/common/c017-limit-constructor-logic.js +146 -0
  77. package/integrations/eslint/plugin/rules/common/c018-no-generic-throw.js +335 -0
  78. package/integrations/eslint/plugin/rules/common/c023-no-duplicate-variable-name-in-scope.js +142 -0
  79. package/integrations/eslint/plugin/rules/common/c029-catch-block-logging.js +115 -0
  80. package/integrations/eslint/plugin/rules/common/c030-use-custom-error-classes.js +294 -0
  81. package/integrations/eslint/plugin/rules/common/c035-no-empty-catch.js +162 -0
  82. package/integrations/eslint/plugin/rules/common/c041-no-config-inline.js +122 -0
  83. package/integrations/eslint/plugin/rules/common/c042-boolean-name-prefix.js +406 -0
  84. package/integrations/eslint/plugin/rules/common/c043-no-console-or-print.js +300 -0
  85. package/integrations/eslint/plugin/rules/common/c047-no-duplicate-retry-logic.js +239 -0
  86. package/integrations/eslint/plugin/rules/common/c072-one-assert-per-test.js +184 -0
  87. package/integrations/eslint/plugin/rules/common/c075-explicit-function-return-types.js +168 -0
  88. package/integrations/eslint/plugin/rules/common/c076-single-behavior-per-test.js +254 -0
  89. package/integrations/eslint/plugin/rules/security/s001-fail-securely.js +381 -0
  90. package/integrations/eslint/plugin/rules/security/s002-idor-check.js +945 -0
  91. package/integrations/eslint/plugin/rules/security/s003-no-unvalidated-redirect.js +86 -0
  92. package/integrations/eslint/plugin/rules/security/s007-no-plaintext-otp.js +74 -0
  93. package/integrations/eslint/plugin/rules/security/s013-verify-tls-connection.js +47 -0
  94. package/integrations/eslint/plugin/rules/security/s047-secure-random-passwords.js +108 -0
  95. package/integrations/eslint/plugin/rules/security/s055-verification-rest-check-the-incoming-content-type.js +143 -0
  96. package/integrations/eslint/plugin/rules/typescript/t002-interface-prefix-i.js +42 -0
  97. package/integrations/eslint/plugin/rules/typescript/t003-ts-ignore-reason.js +48 -0
  98. package/integrations/eslint/plugin/rules/typescript/t004-no-empty-type.js +95 -0
  99. package/integrations/eslint/plugin/rules/typescript/t007-no-fn-in-constructor.js +52 -0
  100. package/integrations/eslint/plugin/rules/typescript/t010-no-nested-union-tuple.js +48 -0
  101. package/integrations/eslint/plugin/rules/typescript/t019-no-this-assign.js +81 -0
  102. package/integrations/eslint/plugin/rules/typescript/t020-no-default-multi-export.js +127 -0
  103. package/integrations/eslint/plugin/rules/typescript/t021-limit-nested-generics.js +150 -0
  104. package/integrations/eslint/tsconfig.json +27 -0
  105. package/package.json +61 -21
  106. package/rules/README.md +252 -0
  107. package/rules/common/C002_no_duplicate_code/analyzer.js +65 -0
  108. package/rules/common/C002_no_duplicate_code/config.json +23 -0
  109. package/rules/common/C003_no_vague_abbreviations/analyzer.js +418 -0
  110. package/rules/common/C003_no_vague_abbreviations/config.json +35 -0
  111. package/rules/{C006_function_naming → common/C006_function_naming}/analyzer.js +13 -2
  112. package/rules/common/C010_limit_block_nesting/analyzer.js +389 -0
  113. package/rules/common/C013_no_dead_code/analyzer.js +206 -0
  114. package/rules/common/C014_dependency_injection/analyzer.js +338 -0
  115. package/rules/common/C017_constructor_logic/analyzer.js +314 -0
  116. package/rules/{C019_log_level_usage → common/C019_log_level_usage}/analyzer.js +5 -2
  117. package/rules/{C029_catch_block_logging → common/C029_catch_block_logging}/analyzer.js +49 -15
  118. package/rules/common/C041_no_sensitive_hardcode/analyzer.js +292 -0
  119. package/rules/common/C042_boolean_name_prefix/analyzer.js +300 -0
  120. package/rules/common/C043_no_console_or_print/analyzer.js +304 -0
  121. package/rules/common/C047_no_duplicate_retry_logic/analyzer.js +351 -0
  122. package/rules/common/C075_explicit_return_types/analyzer.js +103 -0
  123. package/rules/common/C076_single_test_behavior/analyzer.js +121 -0
  124. package/rules/docs/C002_no_duplicate_code.md +57 -0
  125. package/rules/index.js +149 -0
  126. package/rules/migration/converter.js +385 -0
  127. package/rules/migration/mapping.json +164 -0
  128. package/rules/security/S026_json_schema_validation/analyzer.js +251 -0
  129. package/rules/security/S026_json_schema_validation/config.json +27 -0
  130. package/rules/security/S027_no_hardcoded_secrets/analyzer.js +263 -0
  131. package/rules/security/S027_no_hardcoded_secrets/config.json +29 -0
  132. package/rules/security/S029_csrf_protection/analyzer.js +264 -0
  133. package/rules/tests/C002_no_duplicate_code.test.js +50 -0
  134. package/rules/universal/C010/generic.js +0 -0
  135. package/rules/universal/C010/tree-sitter-analyzer.js +0 -0
  136. package/rules/utils/ast-utils.js +191 -0
  137. package/rules/utils/base-analyzer.js +98 -0
  138. package/rules/utils/pattern-matchers.js +239 -0
  139. package/rules/utils/rule-helpers.js +264 -0
  140. package/rules/utils/severity-constants.js +93 -0
  141. package/scripts/build-release.sh +117 -0
  142. package/scripts/ci-report.js +179 -0
  143. package/scripts/install.sh +196 -0
  144. package/scripts/manual-release.sh +338 -0
  145. package/scripts/merge-reports.js +424 -0
  146. package/scripts/pre-release-test.sh +175 -0
  147. package/scripts/prepare-release.sh +202 -0
  148. package/scripts/setup-github-registry.sh +42 -0
  149. package/scripts/test-scripts/README.md +22 -0
  150. package/scripts/test-scripts/test-c041-comparison.js +114 -0
  151. package/scripts/test-scripts/test-c041-eslint.js +67 -0
  152. package/scripts/test-scripts/test-eslint-rules.js +146 -0
  153. package/scripts/test-scripts/test-real-world.js +44 -0
  154. package/scripts/test-scripts/test-rules-on-real-projects.js +86 -0
  155. package/scripts/trigger-release.sh +285 -0
  156. package/scripts/validate-rule-structure.js +148 -0
  157. package/scripts/verify-install.sh +82 -0
  158. package/config/sunlint-schema.json +0 -159
  159. package/config/typescript/custom-rules.js +0 -9
  160. package/config/typescript/package-lock.json +0 -1585
  161. package/config/typescript/package.json +0 -13
  162. package/config/typescript/security-rules/index.js +0 -90
  163. package/config/typescript/tsconfig.json +0 -29
  164. package/core/ai-analyzer.js +0 -169
  165. package/core/eslint-engine-service.js +0 -312
  166. package/core/eslint-instance-manager.js +0 -104
  167. package/core/eslint-integration-service.js +0 -363
  168. package/core/sunlint-engine-service.js +0 -23
  169. package/core/typescript-analyzer.js +0 -262
  170. package/core/typescript-engine.js +0 -313
  171. /package/config/{default.json → defaults/default.json} +0 -0
  172. /package/config/{typescript/eslint.config.js → integrations/eslint/typescript.config.js} +0 -0
  173. /package/config/{typescript/custom-rules-new.js → schemas/sunlint-schema.json} +0 -0
  174. /package/config/{typescript → testing}/test-s005-working.ts +0 -0
  175. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s005-no-origin-auth.js +0 -0
  176. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s006-activation-recovery-secret-not-plaintext.js +0 -0
  177. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s008-crypto-agility.js +0 -0
  178. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s009-no-insecure-crypto.js +0 -0
  179. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s010-no-insecure-random-in-sensitive-context.js +0 -0
  180. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s011-no-insecure-uuid.js +0 -0
  181. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s012-hardcode-secret.js +0 -0
  182. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s014-insecure-tls-version.js +0 -0
  183. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s015-insecure-tls-certificate.js +0 -0
  184. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s016-sensitive-query-parameter.js +0 -0
  185. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s017-no-sql-injection.js +0 -0
  186. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s018-positive-input-validation.js +0 -0
  187. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s019-no-raw-user-input-in-email.js +0 -0
  188. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s020-no-eval-dynamic-execution.js +0 -0
  189. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s022-output-encoding.js +0 -0
  190. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s023-no-json-injection.js +0 -0
  191. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s025-server-side-input-validation.js +0 -0
  192. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s026-json-schema-validation.js +0 -0
  193. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s027-no-hardcoded-secrets.js +0 -0
  194. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s029-require-csrf-protection.js +0 -0
  195. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s030-no-directory-browsing.js +0 -0
  196. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s033-require-samesite-cookie.js +0 -0
  197. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s034-require-host-cookie-prefix.js +0 -0
  198. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s035-cookie-specific-path.js +0 -0
  199. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s036-no-unsafe-file-include.js +0 -0
  200. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s037-require-anti-cache-headers.js +0 -0
  201. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s038-no-version-disclosure.js +0 -0
  202. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s039-no-session-token-in-url.js +0 -0
  203. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s041-require-session-invalidate-on-logout.js +0 -0
  204. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s042-require-periodic-reauthentication.js +0 -0
  205. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s043-terminate-sessions-on-password-change.js +0 -0
  206. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s044-require-full-session-for-sensitive-operations.js +0 -0
  207. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s045-anti-automation-controls.js +0 -0
  208. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s046-secure-notification-on-auth-change.js +0 -0
  209. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s048-password-credential-recovery.js +0 -0
  210. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s050-session-token-weak-hash.js +0 -0
  211. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s052-secure-random-authentication-code.js +0 -0
  212. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s054-verification-default-account.js +0 -0
  213. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s057-utc-logging.js +0 -0
  214. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s058-no-ssrf.js +0 -0
  215. /package/rules/{C006_function_naming → common/C006_function_naming}/config.json +0 -0
  216. /package/rules/{C019_log_level_usage → common/C019_log_level_usage}/config.json +0 -0
  217. /package/rules/{C029_catch_block_logging → common/C029_catch_block_logging}/config.json +0 -0
  218. /package/rules/{C031_validation_separation → common/C031_validation_separation}/analyzer.js +0 -0
  219. /package/rules/{C031_validation_separation/README.md → docs/C031_validation_separation.md} +0 -0
@@ -0,0 +1,374 @@
1
+ /**
2
+ * OpenAI Analysis Engine Plugin
3
+ * Following Rule C005: Single responsibility - AI-powered analysis
4
+ * Following Rule C014: Dependency injection - implements interface
5
+ * Following Rule C015: Use domain language - clear AI analysis terms
6
+ */
7
+
8
+ const AnalysisEngineInterface = require('../core/interfaces/analysis-engine.interface');
9
+ const fs = require('fs');
10
+
11
+ class OpenAIEngine extends AnalysisEngineInterface {
12
+ constructor() {
13
+ super('openai', '1.0', ['typescript', 'javascript', 'dart', 'swift', 'kotlin', 'all']);
14
+
15
+ this.apiKey = null;
16
+ this.model = 'gpt-4o-mini';
17
+ this.provider = 'openai';
18
+ this.aiRulesContext = {};
19
+ this.supportedRulesList = [];
20
+ }
21
+
22
+ /**
23
+ * Initialize OpenAI engine with configuration
24
+ * Following Rule C006: Verb-noun naming
25
+ * @param {Object} config - Engine configuration
26
+ */
27
+ async initialize(config) {
28
+ try {
29
+ // Set up API configuration
30
+ this.apiKey = process.env.OPENAI_API_KEY || config.apiKey;
31
+ this.model = config.model || 'gpt-4o-mini';
32
+ this.provider = config.provider || 'openai';
33
+
34
+ if (!this.apiKey) {
35
+ throw new Error('OpenAI API key not configured. Set OPENAI_API_KEY environment variable.');
36
+ }
37
+
38
+ // Load AI rules context
39
+ this.loadAIRulesContext();
40
+
41
+ // Test connection
42
+ await this.testConnection();
43
+
44
+ this.initialized = true;
45
+ console.log(`🤖 OpenAI engine initialized with model ${this.model}`);
46
+
47
+ } catch (error) {
48
+ console.error('Failed to initialize OpenAI engine:', error.message);
49
+ throw error;
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Load AI rules context configuration
55
+ * Following Rule C006: Verb-noun naming
56
+ */
57
+ loadAIRulesContext() {
58
+ try {
59
+ const contextPath = require('path').resolve(__dirname, '../config/defaults/ai-rules-context.json');
60
+ if (fs.existsSync(contextPath)) {
61
+ const contextData = require(contextPath);
62
+ this.aiRulesContext = contextData.rules || {};
63
+ this.supportedRulesList = Object.keys(this.aiRulesContext);
64
+ console.log(`📋 Loaded AI context for ${this.supportedRulesList.length} rules`);
65
+ } else {
66
+ console.warn('⚠️ AI rules context not found, using basic support');
67
+ // Fallback to basic rules that we know work
68
+ this.supportedRulesList = ['C006', 'C019', 'C029', 'C031'];
69
+ this.aiRulesContext = this.createBasicRulesContext();
70
+ }
71
+ } catch (error) {
72
+ console.warn('⚠️ Failed to load AI rules context:', error.message);
73
+ this.supportedRulesList = ['C019']; // Minimum fallback
74
+ this.aiRulesContext = this.createFallbackContext();
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Create basic rules context for common rules
80
+ * Following Rule C006: Verb-noun naming
81
+ * @returns {Object} Basic rules context
82
+ */
83
+ createBasicRulesContext() {
84
+ return {
85
+ 'C006': {
86
+ name: 'Function Naming Convention',
87
+ context: 'Analyze function naming patterns for verb-noun convention',
88
+ focus_areas: ['function declarations', 'method names', 'arrow functions'],
89
+ severity: 'warning'
90
+ },
91
+ 'C019': {
92
+ name: 'Log Level Usage',
93
+ context: 'Analyze logging patterns for appropriate error levels',
94
+ focus_areas: ['console.error', 'logger.error', 'log levels'],
95
+ severity: 'warning'
96
+ },
97
+ 'C029': {
98
+ name: 'Catch Block Error Logging',
99
+ context: 'Analyze error handling in catch blocks',
100
+ focus_areas: ['try-catch blocks', 'error logging', 'exception handling'],
101
+ severity: 'error'
102
+ },
103
+ 'C031': {
104
+ name: 'Validation Logic Separation',
105
+ context: 'Analyze separation of validation logic from business logic',
106
+ focus_areas: ['validation functions', 'business logic', 'separation of concerns'],
107
+ severity: 'error'
108
+ }
109
+ };
110
+ }
111
+
112
+ /**
113
+ * Create fallback context for minimal support
114
+ * Following Rule C006: Verb-noun naming
115
+ * @returns {Object} Fallback context
116
+ */
117
+ createFallbackContext() {
118
+ return {
119
+ 'C019': {
120
+ name: 'Log Level Usage',
121
+ context: 'Analyze logging patterns for appropriate error levels',
122
+ focus_areas: ['console.error', 'logger.error', 'log levels'],
123
+ severity: 'warning'
124
+ }
125
+ };
126
+ }
127
+
128
+ /**
129
+ * Analyze files using OpenAI
130
+ * Following Rule C006: Verb-noun naming
131
+ * @param {string[]} files - Files to analyze
132
+ * @param {Object[]} rules - Rules to apply
133
+ * @param {Object} options - Analysis options
134
+ * @returns {Promise<Object>} Analysis results
135
+ */
136
+ async analyze(files, rules, options) {
137
+ if (!this.initialized) {
138
+ throw new Error('OpenAI engine not initialized');
139
+ }
140
+
141
+ const results = {
142
+ results: [],
143
+ filesAnalyzed: files.length,
144
+ engine: 'openai',
145
+ metadata: {
146
+ model: this.model,
147
+ rulesAnalyzed: rules.map(r => r.id)
148
+ }
149
+ };
150
+
151
+ for (const filePath of files) {
152
+ try {
153
+ const fileContent = fs.readFileSync(filePath, 'utf8');
154
+ const fileViolations = [];
155
+
156
+ // Analyze each rule for this file
157
+ for (const rule of rules) {
158
+ if (!this.isRuleSupported(rule.id)) {
159
+ console.warn(`⚠️ Rule ${rule.id} not supported by OpenAI engine, skipping...`);
160
+ continue;
161
+ }
162
+
163
+ const ruleViolations = await this.analyzeRuleForFile(filePath, fileContent, rule);
164
+ fileViolations.push(...ruleViolations);
165
+ }
166
+
167
+ if (fileViolations.length > 0) {
168
+ results.results.push({
169
+ file: filePath,
170
+ violations: fileViolations
171
+ });
172
+ }
173
+
174
+ } catch (error) {
175
+ console.error(`❌ Failed to analyze ${filePath}:`, error.message);
176
+ // Continue with other files
177
+ }
178
+ }
179
+
180
+ return results;
181
+ }
182
+
183
+ /**
184
+ * Analyze a specific rule for a file using AI
185
+ * Following Rule C006: Verb-noun naming
186
+ * @param {string} filePath - File path
187
+ * @param {string} content - File content
188
+ * @param {Object} rule - Rule to analyze
189
+ * @returns {Promise<Object[]>} Rule violations
190
+ */
191
+ async analyzeRuleForFile(filePath, content, rule) {
192
+ const ruleContext = this.aiRulesContext[rule.id];
193
+ if (!ruleContext) {
194
+ return [];
195
+ }
196
+
197
+ try {
198
+ const prompt = this.buildDynamicPrompt(content, rule, ruleContext);
199
+ const aiResponse = await this.callOpenAI(prompt);
200
+ return this.parseAIResponse(aiResponse, filePath, rule.id);
201
+ } catch (error) {
202
+ console.error(`❌ AI analysis failed for rule ${rule.id}:`, error.message);
203
+ return [];
204
+ }
205
+ }
206
+
207
+ /**
208
+ * Build dynamic prompt based on rule context
209
+ * Following Rule C006: Verb-noun naming
210
+ * @param {string} content - File content
211
+ * @param {Object} rule - Rule object
212
+ * @param {Object} ruleContext - Rule-specific context
213
+ * @returns {string} Generated prompt
214
+ */
215
+ buildDynamicPrompt(content, rule, ruleContext) {
216
+ return `You are a code quality expert analyzing code for ${ruleContext.name}.
217
+
218
+ RULE: ${rule.id} - ${rule.name || ruleContext.name}
219
+ CONTEXT: ${ruleContext.context}
220
+ DESCRIPTION: ${rule.description || ruleContext.name}
221
+
222
+ FOCUS AREAS: ${ruleContext.focus_areas.join(', ')}
223
+
224
+ ANALYZE THIS CODE:
225
+ \`\`\`
226
+ ${content}
227
+ \`\`\`
228
+
229
+ SPECIFIC INSTRUCTIONS:
230
+ - Only analyze for the specified rule and focus areas
231
+ - Be precise about line numbers and column positions
232
+ - Provide actionable suggestions for fixes
233
+ - Do not analyze other code quality issues outside the focus areas
234
+
235
+ RESPOND WITH JSON FORMAT:
236
+ {
237
+ "violations": [
238
+ {
239
+ "line": <line_number>,
240
+ "column": <column_number>,
241
+ "message": "<specific_violation_description>",
242
+ "severity": "${ruleContext.severity}",
243
+ "code": "<code_snippet>",
244
+ "suggestion": "<how_to_fix>"
245
+ }
246
+ ],
247
+ "summary": "<overall_assessment>"
248
+ }
249
+
250
+ Be precise and focused only on the rule: ${rule.id}`;
251
+ }
252
+
253
+ /**
254
+ * Call OpenAI API
255
+ * Following Rule C006: Verb-noun naming
256
+ * @param {string} prompt - Prompt to send
257
+ * @returns {Promise<string>} AI response
258
+ */
259
+ async callOpenAI(prompt) {
260
+ const fetch = (await import('node-fetch')).default;
261
+
262
+ const response = await fetch('https://api.openai.com/v1/chat/completions', {
263
+ method: 'POST',
264
+ headers: {
265
+ 'Content-Type': 'application/json',
266
+ 'Authorization': `Bearer ${this.apiKey}`
267
+ },
268
+ body: JSON.stringify({
269
+ model: this.model,
270
+ messages: [
271
+ {
272
+ role: 'system',
273
+ content: 'You are an expert code analyzer. Provide precise, actionable feedback focused only on the specified rule.'
274
+ },
275
+ {
276
+ role: 'user',
277
+ content: prompt
278
+ }
279
+ ],
280
+ temperature: 0.1,
281
+ max_tokens: 2000
282
+ })
283
+ });
284
+
285
+ if (!response.ok) {
286
+ throw new Error(`OpenAI API error: ${response.status} ${response.statusText}`);
287
+ }
288
+
289
+ const data = await response.json();
290
+ return data.choices[0].message.content;
291
+ }
292
+
293
+ /**
294
+ * Parse AI response into violation format
295
+ * Following Rule C006: Verb-noun naming
296
+ * @param {string} aiResponse - AI response text
297
+ * @param {string} filePath - File path
298
+ * @param {string} ruleId - Rule ID
299
+ * @returns {Object[]} Parsed violations
300
+ */
301
+ parseAIResponse(aiResponse, filePath, ruleId) {
302
+ try {
303
+ // Extract JSON from AI response
304
+ const jsonMatch = aiResponse.match(/\{[\s\S]*\}/);
305
+ if (!jsonMatch) {
306
+ console.warn('⚠️ No JSON found in AI response');
307
+ return [];
308
+ }
309
+
310
+ const parsed = JSON.parse(jsonMatch[0]);
311
+
312
+ if (!parsed.violations || !Array.isArray(parsed.violations)) {
313
+ console.warn('⚠️ Invalid violations format in AI response');
314
+ return [];
315
+ }
316
+
317
+ return parsed.violations.map(violation => ({
318
+ line: violation.line || 1,
319
+ column: violation.column || 1,
320
+ message: violation.message || 'AI detected violation',
321
+ severity: violation.severity || 'warning',
322
+ ruleId: ruleId, // ✅ Dynamic rule ID instead of hardcoded
323
+ code: violation.code || '',
324
+ suggestion: violation.suggestion || '',
325
+ file: filePath,
326
+ source: 'ai'
327
+ }));
328
+
329
+ } catch (error) {
330
+ console.error('Failed to parse AI response:', error.message);
331
+ return [];
332
+ }
333
+ }
334
+
335
+ /**
336
+ * Get supported rules
337
+ * Following Rule C006: Verb-noun naming
338
+ * @returns {string[]} Supported rule IDs
339
+ */
340
+ getSupportedRules() {
341
+ return this.supportedRulesList;
342
+ }
343
+
344
+ /**
345
+ * Test connection to OpenAI API
346
+ * Following Rule C006: Verb-noun naming
347
+ * @returns {Promise<Object>} Connection test result
348
+ */
349
+ async testConnection() {
350
+ if (!this.apiKey) {
351
+ throw new Error('API key not configured');
352
+ }
353
+
354
+ try {
355
+ const testPrompt = 'Respond with: {"status": "ok"}';
356
+ await this.callOpenAI(testPrompt);
357
+ return { success: true, provider: this.provider, model: this.model };
358
+ } catch (error) {
359
+ throw new Error(`Connection test failed: ${error.message}`);
360
+ }
361
+ }
362
+
363
+ /**
364
+ * Cleanup OpenAI engine resources
365
+ * Following Rule C006: Verb-noun naming
366
+ */
367
+ async cleanup() {
368
+ // OpenAI doesn't require specific cleanup
369
+ await super.cleanup();
370
+ console.log('🤖 OpenAI engine cleanup completed');
371
+ }
372
+ }
373
+
374
+ module.exports = OpenAIEngine;
File without changes
File without changes
@@ -0,0 +1,99 @@
1
+ # ESLint Integration
2
+
3
+ This folder contains SunLint's ESLint plugin integration, organized by rule categories.
4
+
5
+ ## 📁 Structure
6
+
7
+ ```
8
+ integrations/eslint/
9
+ ├── package.json # ESLint integration dependencies
10
+ ├── tsconfig.json # TypeScript configuration
11
+ ├── plugin/ # ESLint Plugin
12
+ │ ├── index.js # Plugin entry point
13
+ │ ├── package.json # Plugin package configuration
14
+ │ └── rules/ # Organized rules by category
15
+ │ ├── coding/ # C-series: 22 coding standard rules
16
+ │ ├── security/ # S-series: 49 security rules
17
+ │ └── typescript/ # T-series: 10 TypeScript rules
18
+ ├── configs/ # ESLint Configuration Presets
19
+ │ ├── .eslintrc.js # Legacy ESLint config
20
+ │ ├── eslint.config.js # Modern ESLint config
21
+ │ └── eslint.config.simple.js # Simple config variant
22
+ └── tools/ # ESLint Integration Tools
23
+ └── cli.js # ESLint integration CLI
24
+ ```
25
+
26
+ ## 🚀 Usage
27
+
28
+ ### ESLint Plugin Installation
29
+
30
+ ```bash
31
+ # Install the plugin
32
+ npm install --save-dev ./integrations/eslint/plugin
33
+
34
+ # Use in your ESLint config
35
+ {
36
+ "plugins": ["@sun-asterisk/sunlint"],
37
+ "rules": {
38
+ "@sun-asterisk/sunlint/c006-function-name-verb-noun": "error",
39
+ "@sun-asterisk/sunlint/s001-fail-securely": "error"
40
+ }
41
+ }
42
+ ```
43
+
44
+ ### Direct CLI Usage
45
+
46
+ ```bash
47
+ # Use ESLint integration CLI
48
+ node ../../cli.js --input=src
49
+ ```
50
+
51
+ ## 📊 Rule Categories
52
+
53
+ ### 🔹 Coding Rules (22 rules)
54
+ Quality and best practices rules with `c-` prefix:
55
+ - `c002-no-duplicate-code.js` - Detect code duplication
56
+ - `c006-function-name-verb-noun.js` - Function naming conventions
57
+ - `c010-limit-block-nesting.js` - Control nesting depth
58
+ - *...19 more coding rules*
59
+
60
+ ### 🔒 Security Rules (49 rules)
61
+ Security and vulnerability rules with `s-` prefix:
62
+ - `s001-fail-securely.js` - Secure failure handling
63
+ - `s003-no-unvalidated-redirect.js` - Prevent open redirects
64
+ - `s012-hardcode-secret.js` - Detect hardcoded secrets
65
+ - *...46 more security rules*
66
+
67
+ ### 📘 TypeScript Rules (10 rules)
68
+ TypeScript-specific rules with `t-` prefix:
69
+ - `t002-interface-prefix-i.js` - Interface naming conventions
70
+ - `t003-ts-ignore-reason.js` - Require reasons for @ts-ignore
71
+ - `t004-interface-public-only.js` - Interface member visibility
72
+ - *...7 more TypeScript rules*
73
+
74
+ ## 🔄 Integration with Main SunLint
75
+
76
+ This ESLint integration works alongside the main SunLint heuristic engine:
77
+
78
+ ```bash
79
+ # Combined analysis: SunLint heuristic + ESLint rules
80
+ sunlint --all --eslint-integration --input=src
81
+ ```
82
+
83
+ The ESLint engine is loaded automatically when `--eslint-integration` flag is used or when ESLint config is detected in the project.
84
+
85
+ ## 📦 Distribution
86
+
87
+ The plugin can be packaged and distributed independently:
88
+
89
+ ```bash
90
+ cd integrations/eslint/plugin
91
+ npm pack
92
+ # Creates: sun-asterisk-sunlint-eslint-plugin-x.x.x.tgz
93
+ ```
94
+
95
+ ---
96
+
97
+ **🏗️ Architecture**: Modular, organized by rule categories
98
+ **🎯 Purpose**: Clean ESLint integration with 81 total rules
99
+ **🚀 Status**: Production ready, well-organized structure
@@ -0,0 +1,98 @@
1
+ // ESLint Legacy Configuration for SunLint (ESLint v8.x compatibility)
2
+ // Following Rule C005: Single responsibility - ESLint configuration
3
+ module.exports = {
4
+ env: {
5
+ es2022: true,
6
+ node: true,
7
+ browser: true
8
+ },
9
+
10
+ parser: '@typescript-eslint/parser',
11
+
12
+ parserOptions: {
13
+ ecmaVersion: 2022,
14
+ sourceType: 'module',
15
+ project: '../tsconfig.json'
16
+ },
17
+
18
+ plugins: [
19
+ 'custom',
20
+ '@typescript-eslint'
21
+ ],
22
+
23
+ globals: {
24
+ console: 'readonly',
25
+ process: 'readonly',
26
+ eval: 'readonly'
27
+ },
28
+
29
+ rules: {
30
+ // Rule C019: No console.error for non-critical errors
31
+ 'no-console': ['warn', { allow: ['warn', 'log'] }],
32
+
33
+ // Code quality rules
34
+ 'no-unused-vars': 'warn',
35
+ 'prefer-const': 'warn',
36
+ 'no-var': 'error',
37
+ 'no-undef': 'warn',
38
+
39
+ // Rule C005: Single responsibility principle
40
+ 'max-lines-per-function': ['warn', { max: 50 }],
41
+ 'complexity': ['warn', { max: 10 }],
42
+
43
+ // Rule C014: Avoid direct new instantiation patterns
44
+ 'no-new': 'warn',
45
+
46
+ // Security and best practices
47
+ 'no-eval': 'error',
48
+ 'no-implied-eval': 'error',
49
+ 'no-new-func': 'error',
50
+ 'eqeqeq': 'error',
51
+ 'curly': 'error',
52
+
53
+ // Security rules from custom plugin (dynamic loading based on category)
54
+ 'custom/typescript_s003': 'off', // Will be enabled dynamically
55
+ 'custom/typescript_s005': 'off', // Will be enabled dynamically
56
+ 'custom/typescript_s006': 'off',
57
+ 'custom/typescript_s008': 'off',
58
+ 'custom/typescript_s009': 'off',
59
+ 'custom/typescript_s010': 'off',
60
+ 'custom/typescript_s011': 'off',
61
+ 'custom/typescript_s012': 'off',
62
+ 'custom/typescript_s014': 'off',
63
+ 'custom/typescript_s015': 'off',
64
+ 'custom/typescript_s016': 'off',
65
+ 'custom/typescript_s017': 'off',
66
+ 'custom/typescript_s018': 'off',
67
+ 'custom/typescript_s019': 'off',
68
+ 'custom/typescript_s020': 'off',
69
+ 'custom/typescript_s022': 'off',
70
+ 'custom/typescript_s023': 'off',
71
+ 'custom/typescript_s025': 'off',
72
+ 'custom/typescript_s026': 'off',
73
+ 'custom/typescript_s027': 'off',
74
+ 'custom/typescript_s029': 'off',
75
+ 'custom/typescript_s030': 'off',
76
+ 'custom/typescript_s033': 'off',
77
+ 'custom/typescript_s034': 'off',
78
+ 'custom/typescript_s035': 'off',
79
+ 'custom/typescript_s036': 'off',
80
+ 'custom/typescript_s037': 'off',
81
+ 'custom/typescript_s038': 'off',
82
+ 'custom/typescript_s039': 'off',
83
+ 'custom/typescript_s041': 'off',
84
+ 'custom/typescript_s042': 'off',
85
+ 'custom/typescript_s043': 'off',
86
+ 'custom/typescript_s044': 'off',
87
+ 'custom/typescript_s045': 'off',
88
+ 'custom/typescript_s046': 'off',
89
+ 'custom/typescript_s047': 'off',
90
+ 'custom/typescript_s048': 'off',
91
+ 'custom/typescript_s050': 'off',
92
+ 'custom/typescript_s052': 'off',
93
+ 'custom/typescript_s054': 'off',
94
+ 'custom/typescript_s055': 'off',
95
+ 'custom/typescript_s057': 'off',
96
+ 'custom/typescript_s058': 'off'
97
+ }
98
+ };