@sun-asterisk/sunlint 1.0.6 → 1.1.3

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 (314) hide show
  1. package/.sunlint.json +35 -0
  2. package/CHANGELOG.md +135 -169
  3. package/CONTRIBUTING.md +235 -0
  4. package/PROJECT_STRUCTURE.md +60 -0
  5. package/README.md +77 -50
  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/{typescript/eslint.config.js → integrations/eslint/typescript.config.js} +4 -0
  13. package/config/presets/beginner.json +1 -1
  14. package/config/presets/ci.json +3 -2
  15. package/config/presets/recommended.json +1 -1
  16. package/config/presets/strict.json +2 -2
  17. package/config/rule-analysis-strategies.js +74 -0
  18. package/config/{rules-registry.json → rules/rules-registry.json} +82 -0
  19. package/core/analysis-orchestrator.js +383 -591
  20. package/core/ast-modules/README.md +103 -0
  21. package/core/ast-modules/base-parser.js +90 -0
  22. package/core/ast-modules/index.js +97 -0
  23. package/core/ast-modules/package.json +37 -0
  24. package/core/ast-modules/parsers/eslint-js-parser.js +147 -0
  25. package/core/ast-modules/parsers/eslint-ts-parser.js +106 -0
  26. package/core/ast-modules/parsers/javascript-parser.js +187 -0
  27. package/core/ast-modules/parsers/typescript-parser.js +187 -0
  28. package/core/cli-action-handler.js +271 -255
  29. package/core/cli-program.js +18 -4
  30. package/core/config-manager.js +18 -11
  31. package/core/config-merger.js +52 -1
  32. package/core/config-validator.js +2 -2
  33. package/core/enhanced-rules-registry.js +331 -0
  34. package/core/file-targeting-service.js +93 -29
  35. package/core/interfaces/analysis-engine.interface.js +100 -0
  36. package/core/multi-rule-runner.js +0 -221
  37. package/core/output-service.js +1 -1
  38. package/core/rule-mapping-service.js +9 -1
  39. package/core/rule-selection-service.js +10 -2
  40. package/docs/CONFIGURATION.md +414 -0
  41. package/docs/DEPLOYMENT-STRATEGIES.md +270 -0
  42. package/engines/eslint-engine.js +601 -0
  43. package/engines/heuristic-engine.js +860 -0
  44. package/engines/openai-engine.js +374 -0
  45. package/integrations/eslint/README.md +99 -0
  46. package/{eslint-integration → integrations/eslint/configs}/.eslintrc.js +1 -1
  47. package/integrations/eslint/configs/eslint.config.js +133 -0
  48. package/integrations/eslint/configs/eslint.config.simple.js +24 -0
  49. package/integrations/eslint/plugin/index.js +164 -0
  50. package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/common}/c006-function-name-verb-noun.js +11 -2
  51. package/integrations/eslint/plugin/rules/common/c013-no-dead-code.js +78 -0
  52. package/integrations/eslint/plugin/rules/common/c017-limit-constructor-logic.js +146 -0
  53. package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/common}/c029-catch-block-logging.js +35 -0
  54. package/integrations/eslint/plugin/rules/common/c035-no-empty-catch.js +162 -0
  55. package/integrations/eslint/plugin/rules/common/c041-no-config-inline.js +122 -0
  56. package/integrations/eslint/plugin/rules/common/c072-one-assert-per-test.js +184 -0
  57. package/integrations/eslint/plugin/rules/common/c075-explicit-function-return-types.js +168 -0
  58. package/integrations/eslint/plugin/rules/common/c076-single-behavior-per-test.js +254 -0
  59. package/integrations/eslint/plugin/rules/security/s001-fail-securely.js +381 -0
  60. package/integrations/eslint/plugin/rules/security/s002-idor-check.js +945 -0
  61. package/integrations/eslint/plugin/rules/security/s007-no-plaintext-otp.js +74 -0
  62. package/integrations/eslint/plugin/rules/security/s013-verify-tls-connection.js +47 -0
  63. package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/typescript}/t003-ts-ignore-reason.js +3 -3
  64. package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/typescript}/t007-no-fn-in-constructor.js +1 -1
  65. package/integrations/eslint/plugin/rules/typescript/t019-no-this-assign.js +81 -0
  66. package/integrations/eslint/plugin/rules/typescript/t020-no-default-multi-export.js +127 -0
  67. package/integrations/eslint/plugin/rules/typescript/t021-limit-nested-generics.js +150 -0
  68. package/integrations/eslint/test-c041-rule.js +87 -0
  69. package/package.json +29 -19
  70. package/rules/README.md +252 -0
  71. package/rules/common/C002_no_duplicate_code/analyzer.js +65 -0
  72. package/rules/common/C002_no_duplicate_code/config.json +23 -0
  73. package/rules/common/C003_no_vague_abbreviations/analyzer.js +418 -0
  74. package/rules/common/C003_no_vague_abbreviations/config.json +35 -0
  75. package/rules/{C006_function_naming → common/C006_function_naming}/analyzer.js +13 -2
  76. package/rules/common/C010_limit_block_nesting/analyzer.js +389 -0
  77. package/rules/common/C013_no_dead_code/analyzer.js +206 -0
  78. package/rules/common/C014_dependency_injection/analyzer.js +338 -0
  79. package/rules/common/C017_constructor_logic/analyzer.js +314 -0
  80. package/rules/{C019_log_level_usage → common/C019_log_level_usage}/analyzer.js +5 -2
  81. package/rules/{C029_catch_block_logging → common/C029_catch_block_logging}/analyzer.js +49 -15
  82. package/rules/common/C041_no_sensitive_hardcode/analyzer.js +292 -0
  83. package/rules/common/C042_boolean_name_prefix/analyzer.js +300 -0
  84. package/rules/common/C043_no_console_or_print/analyzer.js +304 -0
  85. package/rules/common/C047_no_duplicate_retry_logic/analyzer.js +351 -0
  86. package/rules/common/C075_explicit_return_types/analyzer.js +103 -0
  87. package/rules/common/C076_single_test_behavior/analyzer.js +121 -0
  88. package/rules/docs/C002_no_duplicate_code.md +57 -0
  89. package/rules/index.js +149 -0
  90. package/rules/migration/converter.js +385 -0
  91. package/rules/migration/mapping.json +164 -0
  92. package/rules/security/S026_json_schema_validation/analyzer.js +251 -0
  93. package/rules/security/S026_json_schema_validation/config.json +27 -0
  94. package/rules/security/S027_no_hardcoded_secrets/analyzer.js +263 -0
  95. package/rules/security/S027_no_hardcoded_secrets/config.json +29 -0
  96. package/rules/security/S029_csrf_protection/analyzer.js +264 -0
  97. package/rules/tests/C002_no_duplicate_code.test.js +50 -0
  98. package/rules/utils/ast-utils.js +191 -0
  99. package/rules/utils/base-analyzer.js +98 -0
  100. package/rules/utils/pattern-matchers.js +239 -0
  101. package/rules/utils/rule-helpers.js +264 -0
  102. package/rules/utils/severity-constants.js +93 -0
  103. package/scripts/build-release.sh +117 -0
  104. package/scripts/ci-report.js +179 -0
  105. package/scripts/install.sh +196 -0
  106. package/scripts/manual-release.sh +338 -0
  107. package/scripts/merge-reports.js +424 -0
  108. package/scripts/pre-release-test.sh +175 -0
  109. package/scripts/prepare-release.sh +202 -0
  110. package/scripts/setup-github-registry.sh +42 -0
  111. package/scripts/test-scripts/README.md +22 -0
  112. package/scripts/test-scripts/test-c041-comparison.js +114 -0
  113. package/scripts/test-scripts/test-c041-eslint.js +67 -0
  114. package/scripts/test-scripts/test-eslint-rules.js +146 -0
  115. package/scripts/test-scripts/test-real-world.js +44 -0
  116. package/scripts/test-scripts/test-rules-on-real-projects.js +86 -0
  117. package/scripts/trigger-release.sh +285 -0
  118. package/scripts/validate-rule-structure.js +148 -0
  119. package/scripts/verify-install.sh +82 -0
  120. package/cli-legacy.js +0 -355
  121. package/config/sunlint-schema.json +0 -166
  122. package/config/typescript/custom-rules-new.js +0 -0
  123. package/config/typescript/custom-rules.js +0 -9
  124. package/config/typescript/package-lock.json +0 -1585
  125. package/config/typescript/package.json +0 -13
  126. package/config/typescript/security-rules/index.js +0 -90
  127. package/config/typescript/security-rules/s005-no-origin-auth.js +0 -95
  128. package/config/typescript/security-rules/s006-activation-recovery-secret-not-plaintext.js +0 -69
  129. package/config/typescript/security-rules/s008-crypto-agility.js +0 -62
  130. package/config/typescript/security-rules/s009-no-insecure-crypto.js +0 -103
  131. package/config/typescript/security-rules/s010-no-insecure-random-in-sensitive-context.js +0 -123
  132. package/config/typescript/security-rules/s011-no-insecure-uuid.js +0 -66
  133. package/config/typescript/security-rules/s012-hardcode-secret.js +0 -71
  134. package/config/typescript/security-rules/s014-insecure-tls-version.js +0 -50
  135. package/config/typescript/security-rules/s015-insecure-tls-certificate.js +0 -43
  136. package/config/typescript/security-rules/s016-sensitive-query-parameter.js +0 -59
  137. package/config/typescript/security-rules/s017-no-sql-injection.js +0 -193
  138. package/config/typescript/security-rules/s018-positive-input-validation.js +0 -56
  139. package/config/typescript/security-rules/s019-no-raw-user-input-in-email.js +0 -113
  140. package/config/typescript/security-rules/s020-no-eval-dynamic-execution.js +0 -89
  141. package/config/typescript/security-rules/s022-output-encoding.js +0 -78
  142. package/config/typescript/security-rules/s023-no-json-injection.js +0 -300
  143. package/config/typescript/security-rules/s025-server-side-input-validation.js +0 -217
  144. package/config/typescript/security-rules/s026-json-schema-validation.js +0 -68
  145. package/config/typescript/security-rules/s027-no-hardcoded-secrets.js +0 -80
  146. package/config/typescript/security-rules/s029-require-csrf-protection.js +0 -79
  147. package/config/typescript/security-rules/s030-no-directory-browsing.js +0 -78
  148. package/config/typescript/security-rules/s033-require-samesite-cookie.js +0 -80
  149. package/config/typescript/security-rules/s034-require-host-cookie-prefix.js +0 -77
  150. package/config/typescript/security-rules/s035-cookie-specific-path.js +0 -74
  151. package/config/typescript/security-rules/s036-no-unsafe-file-include.js +0 -68
  152. package/config/typescript/security-rules/s037-require-anti-cache-headers.js +0 -70
  153. package/config/typescript/security-rules/s038-no-version-disclosure.js +0 -74
  154. package/config/typescript/security-rules/s039-no-session-token-in-url.js +0 -63
  155. package/config/typescript/security-rules/s041-require-session-invalidate-on-logout.js +0 -211
  156. package/config/typescript/security-rules/s042-require-periodic-reauthentication.js +0 -294
  157. package/config/typescript/security-rules/s043-terminate-sessions-on-password-change.js +0 -254
  158. package/config/typescript/security-rules/s044-require-full-session-for-sensitive-operations.js +0 -292
  159. package/config/typescript/security-rules/s045-anti-automation-controls.js +0 -46
  160. package/config/typescript/security-rules/s046-secure-notification-on-auth-change.js +0 -44
  161. package/config/typescript/security-rules/s048-password-credential-recovery.js +0 -54
  162. package/config/typescript/security-rules/s050-session-token-weak-hash.js +0 -94
  163. package/config/typescript/security-rules/s052-secure-random-authentication-code.js +0 -66
  164. package/config/typescript/security-rules/s054-verification-default-account.js +0 -109
  165. package/config/typescript/security-rules/s057-utc-logging.js +0 -54
  166. package/config/typescript/security-rules/s058-no-ssrf.js +0 -73
  167. package/config/typescript/tsconfig.json +0 -29
  168. package/core/ai-analyzer.js +0 -169
  169. package/core/eslint-engine-service.js +0 -312
  170. package/core/eslint-instance-manager.js +0 -104
  171. package/core/eslint-integration-service.js +0 -363
  172. package/core/sunlint-engine-service.js +0 -23
  173. package/core/typescript-analyzer.js +0 -262
  174. package/core/typescript-engine.js +0 -313
  175. package/docs/ENHANCED_FILE_TARGETING.md +0 -0
  176. package/docs/FILE_TARGETING_COMPARISON.md +0 -0
  177. package/docs/RULE-RESPONSIBILITY-MATRIX.md +0 -204
  178. package/eslint-integration/cli.js +0 -35
  179. package/eslint-integration/eslint-plugin-custom/c013-no-dead-code.js +0 -43
  180. package/eslint-integration/eslint-plugin-custom/c017-limit-constructor-logic.js +0 -39
  181. package/eslint-integration/eslint-plugin-custom/c027-limit-function-nesting.js +0 -50
  182. package/eslint-integration/eslint-plugin-custom/c034-no-implicit-return.js +0 -34
  183. package/eslint-integration/eslint-plugin-custom/c035-no-empty-catch.js +0 -32
  184. package/eslint-integration/eslint-plugin-custom/c041-no-config-inline.js +0 -64
  185. package/eslint-integration/eslint-plugin-custom/c048-no-var-declaration.js +0 -31
  186. package/eslint-integration/eslint-plugin-custom/index.js +0 -155
  187. package/eslint-integration/eslint-plugin-custom/package.json.bak +0 -9
  188. package/eslint-integration/eslint-plugin-custom/t004-interface-public-only.js +0 -160
  189. package/eslint-integration/eslint-plugin-custom/t011-no-real-time-dependency.js +0 -175
  190. package/eslint-integration/eslint-plugin-custom/t026-limit-nested-generics.js +0 -377
  191. package/eslint-integration/sample.ts +0 -53
  192. package/eslint-integration/test-s003.js +0 -5
  193. package/examples/.github/workflows/code-quality.yml +0 -111
  194. package/examples/README.md +0 -69
  195. package/examples/basic-typescript-demo/.eslintrc.json +0 -18
  196. package/examples/basic-typescript-demo/.next/cache/eslint/.cache_1othrmo +0 -1
  197. package/examples/basic-typescript-demo/.sunlint.json +0 -29
  198. package/examples/basic-typescript-demo/eslint.config.mjs +0 -37
  199. package/examples/basic-typescript-demo/next-env.d.ts +0 -5
  200. package/examples/basic-typescript-demo/next.config.mjs +0 -4
  201. package/examples/basic-typescript-demo/package-lock.json +0 -5656
  202. package/examples/basic-typescript-demo/package.json +0 -34
  203. package/examples/basic-typescript-demo/src/app/layout.tsx +0 -18
  204. package/examples/basic-typescript-demo/src/app/page.tsx +0 -48
  205. package/examples/basic-typescript-demo/src/config.ts +0 -14
  206. package/examples/basic-typescript-demo/src/good-practices.ts +0 -58
  207. package/examples/basic-typescript-demo/src/types.generated.ts +0 -13
  208. package/examples/basic-typescript-demo/src/user.test.ts +0 -19
  209. package/examples/basic-typescript-demo/src/violations.ts +0 -61
  210. package/examples/basic-typescript-demo/tsconfig.json +0 -27
  211. package/examples/eslint-integration-demo/.eslintrc.js +0 -38
  212. package/examples/eslint-integration-demo/.sunlint.json +0 -42
  213. package/examples/eslint-integration-demo/next-env.d.ts +0 -5
  214. package/examples/eslint-integration-demo/next.config.js +0 -8
  215. package/examples/eslint-integration-demo/package-lock.json +0 -5740
  216. package/examples/eslint-integration-demo/package.json +0 -37
  217. package/examples/eslint-integration-demo/src/api.test.ts +0 -20
  218. package/examples/eslint-integration-demo/src/conflict-test.tsx +0 -44
  219. package/examples/eslint-integration-demo/src/naming-conflicts.ts +0 -50
  220. package/examples/eslint-integration-demo/tsconfig.json +0 -26
  221. package/examples/file-targeting-demo/global.d.ts +0 -11
  222. package/examples/file-targeting-demo/jest.config.js +0 -8
  223. package/examples/file-targeting-demo/sample.ts +0 -53
  224. package/examples/file-targeting-demo/src/server.js +0 -11
  225. package/examples/file-targeting-demo/src/server.test.js +0 -11
  226. package/examples/file-targeting-demo/src/types.d.ts +0 -4
  227. package/examples/file-targeting-demo/src/types.generated.ts +0 -10
  228. package/examples/file-targeting-demo/user-service.test.ts +0 -15
  229. package/examples/file-targeting-demo/user-service.ts +0 -13
  230. package/examples/file-targeting-demo/utils.js +0 -15
  231. package/examples/multi-language-project/.eslintrc.json +0 -38
  232. package/examples/multi-language-project/package.json +0 -37
  233. package/examples/multi-language-project/src/sample.ts +0 -39
  234. package/examples/rule-test-fixtures/README.md +0 -67
  235. package/examples/rule-test-fixtures/rules/C006_function_naming/clean/typescript-clean.ts +0 -64
  236. package/examples/rule-test-fixtures/rules/C006_function_naming/violations/dart-violations.dart +0 -56
  237. package/examples/rule-test-fixtures/rules/C006_function_naming/violations/typescript-violations.ts +0 -47
  238. package/examples/rule-test-fixtures/rules/C019_log_level_usage/clean/typescript-clean.ts +0 -93
  239. package/examples/rule-test-fixtures/rules/C019_log_level_usage/violations/dart-violations.dart +0 -75
  240. package/examples/rule-test-fixtures/rules/C019_log_level_usage/violations/typescript-violations.ts +0 -84
  241. package/examples/rule-test-fixtures/rules/C029_catch_block_logging/violations/typescript-violations.ts +0 -37
  242. /package/config/{default.json → defaults/default.json} +0 -0
  243. /package/{eslint-integration/eslint.config.js → config/integrations/eslint/base.config.js} +0 -0
  244. /package/{eslint-integration/eslint.config.simple.js → config/integrations/eslint/simple.config.js} +0 -0
  245. /package/{examples/rule-test-fixtures/rules/C029_catch_block_logging/clean/typescript-clean.ts → config/schemas/sunlint-schema.json} +0 -0
  246. /package/config/{typescript → testing}/test-s005-working.ts +0 -0
  247. /package/{examples/eslint-integration-demo/test-file-targeting.sh → engines/tree-sitter-parser.js} +0 -0
  248. /package/{examples/enhanced-config.json → engines/universal-ast-engine.js} +0 -0
  249. /package/{eslint-integration → integrations/eslint}/package.json +0 -0
  250. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin}/package.json +0 -0
  251. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/common}/c002-no-duplicate-code.js +0 -0
  252. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/common}/c003-no-vague-abbreviations.js +0 -0
  253. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/common}/c010-limit-block-nesting.js +0 -0
  254. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/common}/c014-abstract-dependency-preferred.js +0 -0
  255. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/common}/c018-no-generic-throw.js +0 -0
  256. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/common}/c023-no-duplicate-variable-name-in-scope.js +0 -0
  257. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/common}/c030-use-custom-error-classes.js +0 -0
  258. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/common}/c042-boolean-name-prefix.js +0 -0
  259. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/common}/c043-no-console-or-print.js +0 -0
  260. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/common}/c047-no-duplicate-retry-logic.js +0 -0
  261. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s003-no-unvalidated-redirect.js +0 -0
  262. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s005-no-origin-auth.js +0 -0
  263. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s006-activation-recovery-secret-not-plaintext.js +0 -0
  264. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s008-crypto-agility.js +0 -0
  265. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s009-no-insecure-crypto.js +0 -0
  266. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s010-no-insecure-random-in-sensitive-context.js +0 -0
  267. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s011-no-insecure-uuid.js +0 -0
  268. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s012-hardcode-secret.js +0 -0
  269. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s014-insecure-tls-version.js +0 -0
  270. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s015-insecure-tls-certificate.js +0 -0
  271. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s016-sensitive-query-parameter.js +0 -0
  272. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s017-no-sql-injection.js +0 -0
  273. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s018-positive-input-validation.js +0 -0
  274. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s019-no-raw-user-input-in-email.js +0 -0
  275. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s020-no-eval-dynamic-execution.js +0 -0
  276. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s022-output-encoding.js +0 -0
  277. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s023-no-json-injection.js +0 -0
  278. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s025-server-side-input-validation.js +0 -0
  279. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s026-json-schema-validation.js +0 -0
  280. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s027-no-hardcoded-secrets.js +0 -0
  281. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s029-require-csrf-protection.js +0 -0
  282. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s030-no-directory-browsing.js +0 -0
  283. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s033-require-samesite-cookie.js +0 -0
  284. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s034-require-host-cookie-prefix.js +0 -0
  285. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s035-cookie-specific-path.js +0 -0
  286. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s036-no-unsafe-file-include.js +0 -0
  287. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s037-require-anti-cache-headers.js +0 -0
  288. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s038-no-version-disclosure.js +0 -0
  289. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s039-no-session-token-in-url.js +0 -0
  290. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s041-require-session-invalidate-on-logout.js +0 -0
  291. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s042-require-periodic-reauthentication.js +0 -0
  292. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s043-terminate-sessions-on-password-change.js +0 -0
  293. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s044-require-full-session-for-sensitive-operations.js +0 -0
  294. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s045-anti-automation-controls.js +0 -0
  295. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s046-secure-notification-on-auth-change.js +0 -0
  296. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s047-secure-random-passwords.js +0 -0
  297. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s048-password-credential-recovery.js +0 -0
  298. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s050-session-token-weak-hash.js +0 -0
  299. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s052-secure-random-authentication-code.js +0 -0
  300. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s054-verification-default-account.js +0 -0
  301. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s055-verification-rest-check-the-incoming-content-type.js +0 -0
  302. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s057-utc-logging.js +0 -0
  303. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/security}/s058-no-ssrf.js +0 -0
  304. /package/{eslint-integration/eslint-plugin-custom → integrations/eslint/plugin/rules/typescript}/t002-interface-prefix-i.js +0 -0
  305. /package/{eslint-integration/eslint-plugin-custom/t019-no-empty-type.js → integrations/eslint/plugin/rules/typescript/t004-no-empty-type.js} +0 -0
  306. /package/{eslint-integration/eslint-plugin-custom/t025-no-nested-union-tuple.js → integrations/eslint/plugin/rules/typescript/t010-no-nested-union-tuple.js} +0 -0
  307. /package/{eslint-integration → integrations/eslint}/tsconfig.json +0 -0
  308. /package/rules/{C006_function_naming → common/C006_function_naming}/config.json +0 -0
  309. /package/rules/{C019_log_level_usage → common/C019_log_level_usage}/config.json +0 -0
  310. /package/rules/{C029_catch_block_logging → common/C029_catch_block_logging}/config.json +0 -0
  311. /package/rules/{C031_validation_separation → common/C031_validation_separation}/analyzer.js +0 -0
  312. /package/rules/{C031_validation_separation/README.md → docs/C031_validation_separation.md} +0 -0
  313. /package/{examples/basic-typescript-demo/test-file-targeting.sh → rules/universal/C010/generic.js} +0 -0
  314. /package/{examples/basic-typescript-demo/test-config-priority.sh → rules/universal/C010/tree-sitter-analyzer.js} +0 -0
@@ -0,0 +1,601 @@
1
+ /**
2
+ * ESLint Analysis Engine Plugin
3
+ * Following Rule C005: Single responsibility - ESLint integration
4
+ * Following Rule C014: Dependency injection - implements interface
5
+ * Following Rule C015: Use domain language - clear ESLint terms
6
+ */
7
+
8
+ const AnalysisEngineInterface = require('../core/interfaces/analysis-engine.interface');
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+
12
+ class ESLintEngine extends AnalysisEngineInterface {
13
+ constructor() {
14
+ super('eslint', '8.x', ['typescript', 'javascript']);
15
+
16
+ this.eslint = null;
17
+ this.configFiles = new Map();
18
+ this.ruleMapping = new Map();
19
+
20
+ // Load rule mapping immediately (synchronous)
21
+ try {
22
+ this.loadRuleMappingSync();
23
+ } catch (error) {
24
+ console.error('🚨 Constructor failed to load mapping:', error.message);
25
+ this.createDefaultRuleMapping();
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Load SunLint to ESLint rule mapping (synchronous)
31
+ */
32
+ loadRuleMappingSync() {
33
+ try {
34
+ const mappingPath = path.resolve(__dirname, '../config/eslint-rule-mapping.json');
35
+
36
+ if (fs.existsSync(mappingPath)) {
37
+ const mappingData = JSON.parse(fs.readFileSync(mappingPath, 'utf8'));
38
+ const mapping = mappingData.mappings || mappingData;
39
+
40
+ for (const [sunlintRule, eslintRules] of Object.entries(mapping)) {
41
+ this.ruleMapping.set(sunlintRule, eslintRules);
42
+ }
43
+ } else {
44
+ // Create default mapping for common rules
45
+ this.createDefaultRuleMapping();
46
+ console.warn('⚠️ Using default ESLint rule mapping');
47
+ }
48
+
49
+ } catch (error) {
50
+ console.warn('⚠️ [ESLintEngine] Failed to load ESLint rule mapping:', error.message);
51
+ this.createDefaultRuleMapping();
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Initialize ESLint engine with configuration
57
+ * Following Rule C006: Verb-noun naming
58
+ * @param {Object} config - Engine configuration
59
+ */
60
+ async initialize(config) {
61
+ try {
62
+ // Store verbosity setting for use in other methods
63
+ this.verbose = config?.verbose || false;
64
+
65
+ // Dynamically import ESLint
66
+ const { ESLint } = await this.loadESLint();
67
+
68
+ // Initialize ESLint with base configuration (v9+ compatible)
69
+ this.eslint = new ESLint({
70
+ overrideConfigFile: true, // Replaces useEslintrc: false
71
+ overrideConfig: this.createBaseConfig(),
72
+ fix: config?.fix || false,
73
+ cache: config?.cache || false,
74
+ cwd: process.cwd()
75
+ });
76
+
77
+ // Rule mapping already loaded in constructor
78
+ if (this.verbose) {
79
+ console.log(`🔧 [ESLintEngine] Initialize: Rule mapping size = ${this.ruleMapping.size}`);
80
+ console.log(`🔧 ESLint engine initialized`);
81
+ }
82
+
83
+ this.initialized = true;
84
+
85
+ } catch (error) {
86
+ console.error('Failed to initialize ESLint engine:', error.message);
87
+ throw error;
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Load ESLint dynamically
93
+ * Following Rule C006: Verb-noun naming
94
+ * @returns {Promise<Object>} ESLint module
95
+ */
96
+ async loadESLint() {
97
+ try {
98
+ // Try to load ESLint from node_modules
99
+ return await import('eslint');
100
+ } catch (error) {
101
+ // Fallback to require for older versions
102
+ try {
103
+ return require('eslint');
104
+ } catch (requireError) {
105
+ throw new Error('ESLint not found. Please install ESLint: npm install eslint');
106
+ }
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Create base ESLint configuration
112
+ * Following Rule C006: Verb-noun naming
113
+ * @returns {Object} ESLint configuration
114
+ */
115
+ createBaseConfig() {
116
+ // ESLint v9+ flat config format
117
+ return {
118
+ languageOptions: {
119
+ ecmaVersion: 'latest',
120
+ sourceType: 'module',
121
+ parserOptions: {
122
+ ecmaFeatures: {
123
+ jsx: true
124
+ }
125
+ },
126
+ globals: {
127
+ console: 'readonly',
128
+ process: 'readonly',
129
+ Buffer: 'readonly',
130
+ __dirname: 'readonly',
131
+ __filename: 'readonly',
132
+ module: 'readonly',
133
+ require: 'readonly',
134
+ exports: 'readonly',
135
+ global: 'readonly'
136
+ }
137
+ },
138
+ plugins: {},
139
+ rules: {}
140
+ };
141
+ }
142
+
143
+ /**
144
+ * Load SunLint to ESLint rule mapping
145
+ * Following Rule C006: Verb-noun naming
146
+ */
147
+ async loadRuleMapping() {
148
+ // Rule mapping already loaded in constructor - skip async load
149
+ console.log(`� [ESLintEngine] Skipping async loadRuleMapping, using constructor mapping (size: ${this.ruleMapping.size})`);
150
+ return;
151
+ }
152
+
153
+ /**
154
+ * Create default rule mapping
155
+ * Following Rule C006: Verb-noun naming
156
+ */
157
+ createDefaultRuleMapping() {
158
+ console.log(`🚨 [ESLintEngine] createDefaultRuleMapping() called - MAPPING WILL BE OVERWRITTEN!`);
159
+
160
+ // Map common SunLint rules to ESLint equivalents
161
+ const defaultMappings = {
162
+ 'C005': ['max-statements-per-line', 'complexity'],
163
+ 'C006': ['func-names', 'func-name-matching'],
164
+ 'C007': ['spaced-comment', 'no-inline-comments'],
165
+ 'C014': ['no-new'],
166
+ 'C019': ['no-console'],
167
+ 'C031': ['no-implicit-coercion'],
168
+ 'C033': ['prefer-const', 'no-var'],
169
+ 'C037': ['consistent-return'],
170
+ 'C040': ['no-duplicate-imports']
171
+ };
172
+
173
+ // CLEAR existing mapping first
174
+ console.log(`🚨 [ESLintEngine] Clearing existing ${this.ruleMapping.size} rules`);
175
+ this.ruleMapping.clear();
176
+
177
+ for (const [sunlintRule, eslintRules] of Object.entries(defaultMappings)) {
178
+ this.ruleMapping.set(sunlintRule, eslintRules);
179
+ }
180
+
181
+ console.log(`🚨 [ESLintEngine] Set ${this.ruleMapping.size} default rules`);
182
+ console.warn('⚠️ Using default ESLint rule mapping');
183
+ }
184
+
185
+ /**
186
+ * Load React ESLint plugin
187
+ * Following Rule C006: Verb-noun naming
188
+ */
189
+ loadReactPlugin() {
190
+ try {
191
+ // Try current working directory first
192
+ return require(require.resolve('eslint-plugin-react', { paths: [process.cwd()] }));
193
+ } catch (error) {
194
+ try {
195
+ // Fallback to main package
196
+ return require('eslint-plugin-react');
197
+ } catch (fallbackError) {
198
+ console.warn('⚠️ React ESLint plugin not available:', error.message);
199
+ return null;
200
+ }
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Load React Hooks ESLint plugin
206
+ * Following Rule C006: Verb-noun naming
207
+ */
208
+ loadReactHooksPlugin() {
209
+ try {
210
+ // Try current working directory first
211
+ return require(require.resolve('eslint-plugin-react-hooks', { paths: [process.cwd()] }));
212
+ } catch (error) {
213
+ try {
214
+ // Fallback to main package
215
+ return require('eslint-plugin-react-hooks');
216
+ } catch (fallbackError) {
217
+ console.warn('⚠️ React Hooks ESLint plugin not available:', error.message);
218
+ return null;
219
+ }
220
+ }
221
+ }
222
+
223
+ /**
224
+ * Load TypeScript parser
225
+ * Following Rule C006: Verb-noun naming
226
+ */
227
+ loadTypeScriptParser() {
228
+ try {
229
+ return require('@typescript-eslint/parser');
230
+ } catch (error) {
231
+ console.warn('⚠️ TypeScript parser not available:', error.message);
232
+ return null;
233
+ }
234
+ }
235
+
236
+ /**
237
+ * Load TypeScript ESLint plugin
238
+ * Following Rule C006: Verb-noun naming
239
+ */
240
+ loadTypeScriptPlugin() {
241
+ try {
242
+ return require('@typescript-eslint/eslint-plugin');
243
+ } catch (error) {
244
+ console.warn('⚠️ TypeScript ESLint plugin not available:', error.message);
245
+ return null;
246
+ }
247
+ }
248
+
249
+ /**
250
+ * Load custom ESLint plugin with SunLint rules
251
+ * Following Rule C006: Verb-noun naming
252
+ */
253
+ loadCustomPlugin() {
254
+ try {
255
+ const customRulesPath = path.resolve(__dirname, '../integrations/eslint/plugin/rules');
256
+ const plugin = {
257
+ rules: {}
258
+ };
259
+
260
+ // Load all custom rules dynamically
261
+ const ruleDirs = ['common', 'typescript', 'security'];
262
+ for (const dir of ruleDirs) {
263
+ const dirPath = path.join(customRulesPath, dir);
264
+ if (fs.existsSync(dirPath)) {
265
+ const ruleFiles = fs.readdirSync(dirPath).filter(file => file.endsWith('.js'));
266
+ for (const file of ruleFiles) {
267
+ const rulePath = path.join(dirPath, file);
268
+ try {
269
+ const rule = require(rulePath);
270
+ // Keep full filename as rule name for Security rules, remove prefix for others
271
+ const ruleName = dir === 'security' ?
272
+ file.replace('.js', '') :
273
+ file.replace('.js', '').replace(/^[ct]\d+-/, ''); // Remove prefix like c010-, t020-
274
+ plugin.rules[ruleName] = rule;
275
+ } catch (error) {
276
+ console.warn(`⚠️ Failed to load custom rule ${file}:`, error.message);
277
+ }
278
+ }
279
+ }
280
+ }
281
+
282
+ console.log(`✅ [ESLintEngine] Loaded ${Object.keys(plugin.rules).length} custom rules`);
283
+ return plugin;
284
+ } catch (error) {
285
+ console.warn('⚠️ Failed to load custom plugin:', error.message);
286
+ return { rules: {} };
287
+ }
288
+ }
289
+
290
+ /**
291
+ * Analyze files using ESLint
292
+ * Following Rule C006: Verb-noun naming
293
+ * @param {string[]} files - Files to analyze
294
+ * @param {Object[]} rules - Rules to apply
295
+ * @param {Object} options - Analysis options
296
+ * @returns {Promise<Object>} Analysis results
297
+ */
298
+ async analyze(files, rules, options) {
299
+ if (!this.initialized) {
300
+ throw new Error('ESLint engine not initialized');
301
+ }
302
+
303
+ const results = {
304
+ results: [],
305
+ filesAnalyzed: 0,
306
+ engine: 'eslint',
307
+ metadata: {
308
+ rulesAnalyzed: [],
309
+ eslintRulesUsed: []
310
+ }
311
+ };
312
+
313
+ try {
314
+ // Filter files for JS/TS only
315
+ const jstsFiles = files.filter(file => this.isJavaScriptTypeScriptFile(file));
316
+
317
+ if (jstsFiles.length === 0) {
318
+ console.warn('⚠️ No JavaScript/TypeScript files found for ESLint analysis');
319
+ return results;
320
+ }
321
+
322
+ // Convert SunLint rules to ESLint rules
323
+ const eslintConfig = await this.createAnalysisConfig(rules);
324
+
325
+ if (Object.keys(eslintConfig.rules).length === 0) {
326
+ console.warn('⚠️ No ESLint rules mapped from SunLint rules');
327
+ return results;
328
+ }
329
+
330
+ // Reconfigure ESLint with analysis-specific rules (v9+ compatible)
331
+ const { ESLint } = await this.loadESLint();
332
+ const eslintInstance = new ESLint({
333
+ overrideConfigFile: true,
334
+ overrideConfig: {
335
+ ...this.createBaseConfig(),
336
+ ...eslintConfig
337
+ },
338
+ cwd: process.cwd()
339
+ });
340
+
341
+ // Run ESLint analysis
342
+ const eslintResults = await eslintInstance.lintFiles(jstsFiles);
343
+
344
+ // Convert ESLint results to SunLint format
345
+ results.results = this.convertESLintResults(eslintResults, rules);
346
+ results.filesAnalyzed = jstsFiles.length;
347
+ results.metadata.rulesAnalyzed = rules.map(r => r.id);
348
+ results.metadata.eslintRulesUsed = Object.keys(eslintConfig.rules);
349
+
350
+ } catch (error) {
351
+ console.error('❌ ESLint analysis failed:', error.message);
352
+ throw error;
353
+ }
354
+
355
+ return results;
356
+ }
357
+
358
+ /**
359
+ * Check if file is JavaScript or TypeScript
360
+ * Following Rule C006: Verb-noun naming
361
+ * @param {string} filePath - File path to check
362
+ * @returns {boolean} True if JS/TS file
363
+ */
364
+ isJavaScriptTypeScriptFile(filePath) {
365
+ const ext = path.extname(filePath).toLowerCase();
366
+ return ['.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs'].includes(ext);
367
+ }
368
+
369
+ /**
370
+ * Check if rules need React plugins
371
+ */
372
+ needsReactPlugins(rules) {
373
+ return rules.some(rule => {
374
+ const ruleId = typeof rule === 'string' ? rule : rule.id || rule.name;
375
+ return ruleId && ruleId.startsWith('R');
376
+ });
377
+ }
378
+
379
+ /**
380
+ * Check if rules need TypeScript plugins
381
+ */
382
+ needsTypeScriptPlugins(rules) {
383
+ return rules.some(rule => {
384
+ const ruleId = typeof rule === 'string' ? rule : rule.id || rule.name;
385
+ return ruleId && ruleId.startsWith('T');
386
+ });
387
+ }
388
+
389
+ /**
390
+ * Build dynamic plugins based on rules being analyzed
391
+ * @param {Array} rules - Rules to analyze
392
+ * @returns {Object} Plugin configuration
393
+ */
394
+ buildPluginConfig(rules) {
395
+ const plugins = {
396
+ 'custom': this.loadCustomPlugin()
397
+ };
398
+
399
+ // Only load TypeScript plugin if needed
400
+ if (this.needsTypeScriptPlugins(rules)) {
401
+ plugins['@typescript-eslint'] = this.loadTypeScriptPlugin();
402
+ }
403
+
404
+ // Only load React plugins if needed
405
+ if (this.needsReactPlugins(rules)) {
406
+ plugins['react'] = this.loadReactPlugin();
407
+ plugins['react-hooks'] = this.loadReactHooksPlugin();
408
+ }
409
+
410
+ return plugins;
411
+ }
412
+
413
+ /**
414
+ * Create ESLint configuration for analysis
415
+ * Following Rule C006: Verb-noun naming
416
+ * @param {Object[]} rules - SunLint rules
417
+ * @returns {Promise<Object>} ESLint configuration
418
+ */
419
+ async createAnalysisConfig(rules) {
420
+ // ESLint v9+ flat config format
421
+ const config = {
422
+ files: ['**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx'], // Add file patterns
423
+ languageOptions: {
424
+ ecmaVersion: 'latest',
425
+ sourceType: 'module',
426
+ parser: this.loadTypeScriptParser(),
427
+ parserOptions: {
428
+ ecmaFeatures: {
429
+ jsx: true
430
+ }
431
+ },
432
+ globals: {
433
+ console: 'readonly',
434
+ process: 'readonly',
435
+ Buffer: 'readonly',
436
+ __dirname: 'readonly',
437
+ __filename: 'readonly',
438
+ module: 'readonly',
439
+ require: 'readonly',
440
+ exports: 'readonly',
441
+ global: 'readonly'
442
+ }
443
+ },
444
+ plugins: this.buildPluginConfig(rules),
445
+ settings: this.needsReactPlugins(rules) ? {
446
+ react: {
447
+ version: 'detect'
448
+ }
449
+ } : {},
450
+ rules: {}
451
+ };
452
+
453
+ // Map SunLint rules to ESLint rules
454
+ for (const rule of rules) {
455
+ const eslintRules = this.ruleMapping.get(rule.id);
456
+
457
+ if (eslintRules && Array.isArray(eslintRules)) {
458
+ for (const eslintRule of eslintRules) {
459
+ // Set rule severity based on SunLint rule
460
+ const severity = this.mapSeverity(rule.severity || 'warning');
461
+ config.rules[eslintRule] = severity;
462
+ }
463
+ } else {
464
+ // Check if it's a custom rule (C010, etc.)
465
+ const customRuleName = `custom/${rule.id.toLowerCase()}`;
466
+ const ruleConfig = this.mapSeverity(rule.severity || 'warning');
467
+
468
+ // Add rule configuration for specific rules
469
+ if (rule.id === 'C010') {
470
+ config.rules[customRuleName] = [ruleConfig, { maxDepth: 3 }];
471
+ } else {
472
+ config.rules[customRuleName] = ruleConfig;
473
+ }
474
+ }
475
+ }
476
+
477
+ return config;
478
+ }
479
+
480
+ /**
481
+ * Map SunLint severity to ESLint severity
482
+ * Following Rule C006: Verb-noun naming
483
+ * @param {string} sunlintSeverity - SunLint severity level
484
+ * @returns {number|string} ESLint severity
485
+ */
486
+ mapSeverity(sunlintSeverity) {
487
+ switch (sunlintSeverity.toLowerCase()) {
488
+ case 'error': return 'error';
489
+ case 'warning': return 'warn';
490
+ case 'info': return 'warn';
491
+ default: return 'warn';
492
+ }
493
+ }
494
+
495
+ /**
496
+ * Convert ESLint results to SunLint format
497
+ * Following Rule C006: Verb-noun naming
498
+ * @param {Object[]} eslintResults - ESLint results
499
+ * @param {Object[]} originalRules - Original SunLint rules
500
+ * @returns {Object[]} SunLint formatted results
501
+ */
502
+ convertESLintResults(eslintResults, originalRules) {
503
+ const sunlintResults = [];
504
+
505
+ for (const eslintResult of eslintResults) {
506
+ if (eslintResult.messages.length === 0) continue;
507
+
508
+ const fileResult = {
509
+ file: eslintResult.filePath,
510
+ violations: []
511
+ };
512
+
513
+ for (const message of eslintResult.messages) {
514
+ const violation = {
515
+ ruleId: this.mapESLintRuleToSunLint(message.ruleId, originalRules),
516
+ message: message.message,
517
+ severity: message.severity === 2 ? 'error' : 'warning',
518
+ line: message.line,
519
+ column: message.column,
520
+ endLine: message.endLine,
521
+ endColumn: message.endColumn,
522
+ engine: 'eslint',
523
+ eslintRule: message.ruleId,
524
+ fix: message.fix ? {
525
+ range: message.fix.range,
526
+ text: message.fix.text
527
+ } : null
528
+ };
529
+
530
+ fileResult.violations.push(violation);
531
+ }
532
+
533
+ if (fileResult.violations.length > 0) {
534
+ sunlintResults.push(fileResult);
535
+ }
536
+ }
537
+
538
+ return sunlintResults;
539
+ }
540
+
541
+ /**
542
+ * Map ESLint rule back to SunLint rule
543
+ * Following Rule C006: Verb-noun naming
544
+ * @param {string} eslintRuleId - ESLint rule ID
545
+ * @param {Object[]} originalRules - Original SunLint rules
546
+ * @returns {string} SunLint rule ID
547
+ */
548
+ mapESLintRuleToSunLint(eslintRuleId, originalRules) {
549
+ // Find which SunLint rule maps to this ESLint rule
550
+ for (const [sunlintRule, eslintRules] of this.ruleMapping.entries()) {
551
+ if (eslintRules.includes(eslintRuleId)) {
552
+ // Verify this rule was actually requested
553
+ const requestedRule = originalRules.find(r => r.id === sunlintRule);
554
+ if (requestedRule) {
555
+ return sunlintRule;
556
+ }
557
+ }
558
+ }
559
+
560
+ // Fallback to ESLint rule ID if no mapping found
561
+ return eslintRuleId;
562
+ }
563
+
564
+ /**
565
+ * Get supported rules
566
+ * Following Rule C006: Verb-noun naming
567
+ * @returns {string[]} Supported rule IDs
568
+ */
569
+ getSupportedRules() {
570
+ return Array.from(this.ruleMapping.keys());
571
+ }
572
+
573
+ /**
574
+ * Check if rule is supported
575
+ * Following Rule C006: Verb-noun naming
576
+ * @param {string} ruleId - Rule ID to check
577
+ * @returns {boolean} True if supported
578
+ */
579
+ isRuleSupported(ruleId) {
580
+ const supported = this.ruleMapping.has(ruleId);
581
+ if (this.verbose) {
582
+ console.log(`🔍 [ESLintEngine] isRuleSupported(${ruleId}): ${supported} (mapping size: ${this.ruleMapping.size})`);
583
+ }
584
+ return supported;
585
+ }
586
+
587
+ /**
588
+ * Cleanup ESLint engine resources
589
+ * Following Rule C006: Verb-noun naming
590
+ */
591
+ async cleanup() {
592
+ this.eslint = null;
593
+ this.configFiles.clear();
594
+ this.ruleMapping.clear();
595
+
596
+ await super.cleanup();
597
+ console.log('🔧 ESLint engine cleanup completed');
598
+ }
599
+ }
600
+
601
+ module.exports = ESLintEngine;