@defai.digital/ax-cli 3.4.6 → 3.5.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 (223) hide show
  1. package/LICENSE +2 -6
  2. package/README.md +109 -2
  3. package/dist/analyzers/ast/index.d.ts +9 -0
  4. package/dist/analyzers/ast/index.js +10 -0
  5. package/dist/analyzers/ast/index.js.map +1 -0
  6. package/dist/analyzers/ast/node-helpers.d.ts +81 -0
  7. package/dist/analyzers/ast/node-helpers.js +128 -0
  8. package/dist/analyzers/ast/node-helpers.js.map +1 -0
  9. package/dist/analyzers/ast/parser.d.ts +59 -0
  10. package/dist/analyzers/ast/parser.js +293 -0
  11. package/dist/analyzers/ast/parser.js.map +1 -0
  12. package/dist/analyzers/ast/traverser.d.ts +67 -0
  13. package/dist/analyzers/ast/traverser.js +156 -0
  14. package/dist/analyzers/ast/traverser.js.map +1 -0
  15. package/dist/analyzers/ast/types.d.ts +107 -0
  16. package/dist/analyzers/ast/types.js +7 -0
  17. package/dist/analyzers/ast/types.js.map +1 -0
  18. package/dist/analyzers/best-practices/index.d.ts +10 -0
  19. package/dist/analyzers/best-practices/index.js +11 -0
  20. package/dist/analyzers/best-practices/index.js.map +1 -0
  21. package/dist/analyzers/code-smells/base-smell-detector.d.ts +30 -0
  22. package/dist/analyzers/code-smells/base-smell-detector.js +44 -0
  23. package/dist/analyzers/code-smells/base-smell-detector.js.map +1 -0
  24. package/dist/analyzers/code-smells/code-smell-analyzer.d.ts +30 -0
  25. package/dist/analyzers/code-smells/code-smell-analyzer.js +167 -0
  26. package/dist/analyzers/code-smells/code-smell-analyzer.js.map +1 -0
  27. package/dist/analyzers/code-smells/detectors/data-clumps-detector.d.ts +11 -0
  28. package/dist/analyzers/code-smells/detectors/data-clumps-detector.js +66 -0
  29. package/dist/analyzers/code-smells/detectors/data-clumps-detector.js.map +1 -0
  30. package/dist/analyzers/code-smells/detectors/dead-code-detector.d.ts +11 -0
  31. package/dist/analyzers/code-smells/detectors/dead-code-detector.js +53 -0
  32. package/dist/analyzers/code-smells/detectors/dead-code-detector.js.map +1 -0
  33. package/dist/analyzers/code-smells/detectors/duplicate-code-detector.d.ts +11 -0
  34. package/dist/analyzers/code-smells/detectors/duplicate-code-detector.js +51 -0
  35. package/dist/analyzers/code-smells/detectors/duplicate-code-detector.js.map +1 -0
  36. package/dist/analyzers/code-smells/detectors/feature-envy-detector.d.ts +11 -0
  37. package/dist/analyzers/code-smells/detectors/feature-envy-detector.js +64 -0
  38. package/dist/analyzers/code-smells/detectors/feature-envy-detector.js.map +1 -0
  39. package/dist/analyzers/code-smells/detectors/inappropriate-intimacy-detector.d.ts +11 -0
  40. package/dist/analyzers/code-smells/detectors/inappropriate-intimacy-detector.js +56 -0
  41. package/dist/analyzers/code-smells/detectors/inappropriate-intimacy-detector.js.map +1 -0
  42. package/dist/analyzers/code-smells/detectors/large-class-detector.d.ts +13 -0
  43. package/dist/analyzers/code-smells/detectors/large-class-detector.js +58 -0
  44. package/dist/analyzers/code-smells/detectors/large-class-detector.js.map +1 -0
  45. package/dist/analyzers/code-smells/detectors/long-method-detector.d.ts +12 -0
  46. package/dist/analyzers/code-smells/detectors/long-method-detector.js +52 -0
  47. package/dist/analyzers/code-smells/detectors/long-method-detector.js.map +1 -0
  48. package/dist/analyzers/code-smells/detectors/long-parameter-list-detector.d.ts +12 -0
  49. package/dist/analyzers/code-smells/detectors/long-parameter-list-detector.js +50 -0
  50. package/dist/analyzers/code-smells/detectors/long-parameter-list-detector.js.map +1 -0
  51. package/dist/analyzers/code-smells/detectors/magic-numbers-detector.d.ts +12 -0
  52. package/dist/analyzers/code-smells/detectors/magic-numbers-detector.js +54 -0
  53. package/dist/analyzers/code-smells/detectors/magic-numbers-detector.js.map +1 -0
  54. package/dist/analyzers/code-smells/detectors/nested-conditionals-detector.d.ts +13 -0
  55. package/dist/analyzers/code-smells/detectors/nested-conditionals-detector.js +71 -0
  56. package/dist/analyzers/code-smells/detectors/nested-conditionals-detector.js.map +1 -0
  57. package/dist/analyzers/code-smells/index.d.ts +16 -0
  58. package/dist/analyzers/code-smells/index.js +19 -0
  59. package/dist/analyzers/code-smells/index.js.map +1 -0
  60. package/dist/analyzers/code-smells/types.d.ts +82 -0
  61. package/dist/analyzers/code-smells/types.js +30 -0
  62. package/dist/analyzers/code-smells/types.js.map +1 -0
  63. package/dist/analyzers/dependency/circular-detector.d.ts +17 -0
  64. package/dist/analyzers/dependency/circular-detector.js +71 -0
  65. package/dist/analyzers/dependency/circular-detector.js.map +1 -0
  66. package/dist/analyzers/dependency/coupling-calculator.d.ts +24 -0
  67. package/dist/analyzers/dependency/coupling-calculator.js +86 -0
  68. package/dist/analyzers/dependency/coupling-calculator.js.map +1 -0
  69. package/dist/analyzers/dependency/dependency-analyzer.d.ts +40 -0
  70. package/dist/analyzers/dependency/dependency-analyzer.js +214 -0
  71. package/dist/analyzers/dependency/dependency-analyzer.js.map +1 -0
  72. package/dist/analyzers/dependency/dependency-graph.d.ts +57 -0
  73. package/dist/analyzers/dependency/dependency-graph.js +186 -0
  74. package/dist/analyzers/dependency/dependency-graph.js.map +1 -0
  75. package/dist/analyzers/dependency/index.d.ts +8 -0
  76. package/dist/analyzers/dependency/index.js +8 -0
  77. package/dist/analyzers/dependency/index.js.map +1 -0
  78. package/dist/analyzers/dependency/types.d.ts +105 -0
  79. package/dist/analyzers/dependency/types.js +5 -0
  80. package/dist/analyzers/dependency/types.js.map +1 -0
  81. package/dist/analyzers/git/churn-calculator.d.ts +34 -0
  82. package/dist/analyzers/git/churn-calculator.js +214 -0
  83. package/dist/analyzers/git/churn-calculator.js.map +1 -0
  84. package/dist/analyzers/git/git-analyzer.d.ts +19 -0
  85. package/dist/analyzers/git/git-analyzer.js +71 -0
  86. package/dist/analyzers/git/git-analyzer.js.map +1 -0
  87. package/dist/analyzers/git/hotspot-detector.d.ts +34 -0
  88. package/dist/analyzers/git/hotspot-detector.js +170 -0
  89. package/dist/analyzers/git/hotspot-detector.js.map +1 -0
  90. package/dist/analyzers/git/index.d.ts +7 -0
  91. package/dist/analyzers/git/index.js +7 -0
  92. package/dist/analyzers/git/index.js.map +1 -0
  93. package/dist/analyzers/git/types.d.ts +88 -0
  94. package/dist/analyzers/git/types.js +5 -0
  95. package/dist/analyzers/git/types.js.map +1 -0
  96. package/dist/analyzers/metrics/halstead-calculator.d.ts +30 -0
  97. package/dist/analyzers/metrics/halstead-calculator.js +150 -0
  98. package/dist/analyzers/metrics/halstead-calculator.js.map +1 -0
  99. package/dist/analyzers/metrics/index.d.ts +9 -0
  100. package/dist/analyzers/metrics/index.js +9 -0
  101. package/dist/analyzers/metrics/index.js.map +1 -0
  102. package/dist/analyzers/metrics/maintainability-calculator.d.ts +17 -0
  103. package/dist/analyzers/metrics/maintainability-calculator.js +46 -0
  104. package/dist/analyzers/metrics/maintainability-calculator.js.map +1 -0
  105. package/dist/analyzers/metrics/metrics-analyzer.d.ts +32 -0
  106. package/dist/analyzers/metrics/metrics-analyzer.js +140 -0
  107. package/dist/analyzers/metrics/metrics-analyzer.js.map +1 -0
  108. package/dist/analyzers/metrics/types.d.ts +67 -0
  109. package/dist/analyzers/metrics/types.js +5 -0
  110. package/dist/analyzers/metrics/types.js.map +1 -0
  111. package/dist/analyzers/security/base-detector.d.ts +58 -0
  112. package/dist/analyzers/security/base-detector.js +104 -0
  113. package/dist/analyzers/security/base-detector.js.map +1 -0
  114. package/dist/analyzers/security/detectors/command-injection-detector.d.ts +12 -0
  115. package/dist/analyzers/security/detectors/command-injection-detector.js +84 -0
  116. package/dist/analyzers/security/detectors/command-injection-detector.js.map +1 -0
  117. package/dist/analyzers/security/detectors/hardcoded-secrets-detector.d.ts +16 -0
  118. package/dist/analyzers/security/detectors/hardcoded-secrets-detector.js +140 -0
  119. package/dist/analyzers/security/detectors/hardcoded-secrets-detector.js.map +1 -0
  120. package/dist/analyzers/security/detectors/insecure-deserialization-detector.d.ts +12 -0
  121. package/dist/analyzers/security/detectors/insecure-deserialization-detector.js +109 -0
  122. package/dist/analyzers/security/detectors/insecure-deserialization-detector.js.map +1 -0
  123. package/dist/analyzers/security/detectors/insecure-random-detector.d.ts +12 -0
  124. package/dist/analyzers/security/detectors/insecure-random-detector.js +61 -0
  125. package/dist/analyzers/security/detectors/insecure-random-detector.js.map +1 -0
  126. package/dist/analyzers/security/detectors/path-traversal-detector.d.ts +12 -0
  127. package/dist/analyzers/security/detectors/path-traversal-detector.js +82 -0
  128. package/dist/analyzers/security/detectors/path-traversal-detector.js.map +1 -0
  129. package/dist/analyzers/security/detectors/sql-injection-detector.d.ts +12 -0
  130. package/dist/analyzers/security/detectors/sql-injection-detector.js +88 -0
  131. package/dist/analyzers/security/detectors/sql-injection-detector.js.map +1 -0
  132. package/dist/analyzers/security/detectors/weak-crypto-detector.d.ts +12 -0
  133. package/dist/analyzers/security/detectors/weak-crypto-detector.js +104 -0
  134. package/dist/analyzers/security/detectors/weak-crypto-detector.js.map +1 -0
  135. package/dist/analyzers/security/detectors/xss-detector.d.ts +12 -0
  136. package/dist/analyzers/security/detectors/xss-detector.js +90 -0
  137. package/dist/analyzers/security/detectors/xss-detector.js.map +1 -0
  138. package/dist/analyzers/security/index.d.ts +16 -0
  139. package/dist/analyzers/security/index.js +18 -0
  140. package/dist/analyzers/security/index.js.map +1 -0
  141. package/dist/analyzers/security/security-analyzer.d.ts +38 -0
  142. package/dist/analyzers/security/security-analyzer.js +215 -0
  143. package/dist/analyzers/security/security-analyzer.js.map +1 -0
  144. package/dist/analyzers/security/types.d.ts +95 -0
  145. package/dist/analyzers/security/types.js +7 -0
  146. package/dist/analyzers/security/types.js.map +1 -0
  147. package/dist/hooks/use-enhanced-input.d.ts +0 -1
  148. package/dist/hooks/use-enhanced-input.js.map +1 -1
  149. package/dist/index.js +0 -0
  150. package/dist/mcp/validation.js +12 -6
  151. package/dist/mcp/validation.js.map +1 -1
  152. package/dist/tools/analysis-tools.d.ts +73 -0
  153. package/dist/tools/analysis-tools.js +422 -0
  154. package/dist/tools/analysis-tools.js.map +1 -0
  155. package/dist/tools/bash.js +2 -1
  156. package/dist/tools/bash.js.map +1 -1
  157. package/dist/ui/components/toast-notification.js +0 -1
  158. package/dist/ui/components/toast-notification.js.map +1 -1
  159. package/dist/ui/components/welcome-panel.js +1 -1
  160. package/dist/ui/components/welcome-panel.js.map +1 -1
  161. package/dist/ui/hooks/use-input-history.d.ts +9 -0
  162. package/dist/ui/hooks/use-input-history.js +117 -0
  163. package/dist/ui/hooks/use-input-history.js.map +1 -0
  164. package/dist/utils/parallel-analyzer.js +30 -17
  165. package/dist/utils/parallel-analyzer.js.map +1 -1
  166. package/eslint.config.js +3 -0
  167. package/package.json +5 -5
  168. package/vitest.config.ts +1 -0
  169. package/.ax-cli/checkpoints/2025-11-20/checkpoint-11e9e0ba-c39d-4fd2-aa77-bc818811c921.json +0 -69
  170. package/.ax-cli/checkpoints/2025-11-20/checkpoint-2b260b98-b418-4c7c-9694-e2b94967e662.json +0 -24
  171. package/.ax-cli/checkpoints/2025-11-20/checkpoint-7e03601e-e8ab-4cd7-9841-a74b66adf78f.json +0 -69
  172. package/.ax-cli/checkpoints/2025-11-20/checkpoint-7f9c6562-771f-4fd0-adcf-9e7e9ac34ae8.json +0 -44
  173. package/.ax-cli/checkpoints/2025-11-20/checkpoint-e1ebe666-4c3a-4367-ba5c-27fe512a9c70.json +0 -24
  174. package/.ax-cli/checkpoints/2025-11-21/checkpoint-15743e7d-430c-4d76-b6fc-955d7a5c250c.json +0 -44
  175. package/.ax-cli/checkpoints/2025-11-21/checkpoint-25cf7679-0b3f-4988-83d7-704548fbba91.json +0 -69
  176. package/.ax-cli/checkpoints/2025-11-21/checkpoint-54aedbac-6db0-464e-8ebb-dbb3979e6dca.json +0 -24
  177. package/.ax-cli/checkpoints/2025-11-21/checkpoint-7658aed8-fe5d-4222-903f-1a7c63717ea7.json +0 -24
  178. package/.ax-cli/checkpoints/2025-11-21/checkpoint-c9c13497-40dc-4294-a327-6a5fc854eaa1.json +0 -69
  179. package/automatosx.config.json +0 -333
  180. package/config/messages.yaml +0 -75
  181. package/config/models.yaml +0 -66
  182. package/config/prompts.yaml +0 -156
  183. package/config/settings.yaml +0 -86
  184. package/dist/commands/weather.d.ts +0 -8
  185. package/dist/commands/weather.js +0 -160
  186. package/dist/commands/weather.js.map +0 -1
  187. package/dist/grok/client.d.ts +0 -144
  188. package/dist/grok/client.js +0 -237
  189. package/dist/grok/client.js.map +0 -1
  190. package/dist/grok/tools.d.ts +0 -8
  191. package/dist/grok/tools.js +0 -318
  192. package/dist/grok/tools.js.map +0 -1
  193. package/dist/grok/types.d.ts +0 -291
  194. package/dist/grok/types.js +0 -127
  195. package/dist/grok/types.js.map +0 -1
  196. package/dist/tools/morph-editor.d.ts +0 -36
  197. package/dist/tools/morph-editor.js +0 -308
  198. package/dist/tools/morph-editor.js.map +0 -1
  199. package/dist/ui/components/session-recovery.d.ts +0 -12
  200. package/dist/ui/components/session-recovery.js +0 -93
  201. package/dist/ui/components/session-recovery.js.map +0 -1
  202. package/dist/utils/model-config.d.ts +0 -28
  203. package/dist/utils/model-config.js +0 -43
  204. package/dist/utils/model-config.js.map +0 -1
  205. package/dist/utils/tool-helpers.d.ts +0 -25
  206. package/dist/utils/tool-helpers.js +0 -79
  207. package/dist/utils/tool-helpers.js.map +0 -1
  208. package/packages/schemas/dist/index.d.ts +0 -14
  209. package/packages/schemas/dist/index.d.ts.map +0 -1
  210. package/packages/schemas/dist/index.js +0 -19
  211. package/packages/schemas/dist/index.js.map +0 -1
  212. package/packages/schemas/dist/public/core/brand-types.d.ts +0 -308
  213. package/packages/schemas/dist/public/core/brand-types.d.ts.map +0 -1
  214. package/packages/schemas/dist/public/core/brand-types.js +0 -243
  215. package/packages/schemas/dist/public/core/brand-types.js.map +0 -1
  216. package/packages/schemas/dist/public/core/enums.d.ts +0 -227
  217. package/packages/schemas/dist/public/core/enums.d.ts.map +0 -1
  218. package/packages/schemas/dist/public/core/enums.js +0 -222
  219. package/packages/schemas/dist/public/core/enums.js.map +0 -1
  220. package/packages/schemas/dist/public/core/id-types.d.ts +0 -286
  221. package/packages/schemas/dist/public/core/id-types.d.ts.map +0 -1
  222. package/packages/schemas/dist/public/core/id-types.js +0 -136
  223. package/packages/schemas/dist/public/core/id-types.js.map +0 -1
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Maintainability Index Calculator
3
+ *
4
+ * Calculates MI = 171 - 5.2*ln(V) - 0.23*CC - 16.2*ln(LOC)
5
+ * Normalized to 0-100 scale
6
+ */
7
+ export class MaintainabilityCalculator {
8
+ /**
9
+ * Calculate Maintainability Index
10
+ */
11
+ calculateIndex(halsteadVolume, cyclomaticComplexity, linesOfCode) {
12
+ // Original formula: MI = 171 - 5.2*ln(V) - 0.23*CC - 16.2*ln(LOC)
13
+ // Clamp values to avoid invalid log
14
+ const V = Math.max(1, halsteadVolume);
15
+ const CC = Math.max(1, cyclomaticComplexity);
16
+ const LOC = Math.max(1, linesOfCode);
17
+ const rawMI = 171 - 5.2 * Math.log(V) - 0.23 * CC - 16.2 * Math.log(LOC);
18
+ // Normalize to 0-100 scale
19
+ // Original MI can range from negative to ~171
20
+ // We'll use: MI_normalized = max(0, (rawMI / 171) * 100)
21
+ const score = Math.max(0, Math.min(100, (rawMI / 171) * 100));
22
+ const rating = this.getRating(score);
23
+ return Object.freeze({
24
+ score: Math.round(score * 100) / 100,
25
+ rating,
26
+ halsteadVolume: V,
27
+ cyclomaticComplexity: CC,
28
+ linesOfCode: LOC,
29
+ });
30
+ }
31
+ /**
32
+ * Get letter rating from MI score
33
+ */
34
+ getRating(score) {
35
+ if (score >= 80)
36
+ return 'A'; // Highly maintainable
37
+ if (score >= 65)
38
+ return 'B'; // Moderately maintainable
39
+ if (score >= 50)
40
+ return 'C'; // Somewhat maintainable
41
+ if (score >= 35)
42
+ return 'D'; // Difficult to maintain
43
+ return 'F'; // Very difficult to maintain
44
+ }
45
+ }
46
+ //# sourceMappingURL=maintainability-calculator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maintainability-calculator.js","sourceRoot":"","sources":["../../../src/analyzers/metrics/maintainability-calculator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,OAAO,yBAAyB;IACpC;;OAEG;IACH,cAAc,CACZ,cAAsB,EACtB,oBAA4B,EAC5B,WAAmB;QAEnB,kEAAkE;QAClE,oCAAoC;QACpC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;QACtC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,oBAAoB,CAAC,CAAC;QAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;QAErC,MAAM,KAAK,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEzE,2BAA2B;QAC3B,8CAA8C;QAC9C,yDAAyD;QACzD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;QAE9D,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAErC,OAAO,MAAM,CAAC,MAAM,CAAC;YACnB,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,GAAG;YACpC,MAAM;YACN,cAAc,EAAE,CAAC;YACjB,oBAAoB,EAAE,EAAE;YACxB,WAAW,EAAE,GAAG;SACjB,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,SAAS,CAAC,KAAa;QAC7B,IAAI,KAAK,IAAI,EAAE;YAAE,OAAO,GAAG,CAAC,CAAC,sBAAsB;QACnD,IAAI,KAAK,IAAI,EAAE;YAAE,OAAO,GAAG,CAAC,CAAC,0BAA0B;QACvD,IAAI,KAAK,IAAI,EAAE;YAAE,OAAO,GAAG,CAAC,CAAC,wBAAwB;QACrD,IAAI,KAAK,IAAI,EAAE;YAAE,OAAO,GAAG,CAAC,CAAC,wBAAwB;QACrD,OAAO,GAAG,CAAC,CAAC,6BAA6B;IAC3C,CAAC;CACF"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Metrics Analyzer
3
+ *
4
+ * Main orchestrator for advanced code metrics analysis
5
+ */
6
+ import type { MetricsAnalysisResult, MetricsAnalysisOptions } from './types.js';
7
+ export declare class MetricsAnalyzer {
8
+ private halsteadCalculator;
9
+ private maintainabilityCalculator;
10
+ private astParser;
11
+ constructor();
12
+ /**
13
+ * Analyze metrics for files matching patterns
14
+ */
15
+ analyze(directory: string, options?: MetricsAnalysisOptions): Promise<MetricsAnalysisResult>;
16
+ /**
17
+ * Analyze a single file
18
+ */
19
+ private analyzeFile;
20
+ /**
21
+ * Calculate lines of code (excluding blank lines)
22
+ */
23
+ private calculateLinesOfCode;
24
+ /**
25
+ * Get files to analyze based on patterns
26
+ */
27
+ private getFilesToAnalyze;
28
+ /**
29
+ * Calculate summary statistics
30
+ */
31
+ private calculateSummary;
32
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Metrics Analyzer
3
+ *
4
+ * Main orchestrator for advanced code metrics analysis
5
+ */
6
+ import { HalsteadCalculator } from './halstead-calculator.js';
7
+ import { MaintainabilityCalculator } from './maintainability-calculator.js';
8
+ import { ASTParser } from '../ast/parser.js';
9
+ import { glob } from 'glob';
10
+ export class MetricsAnalyzer {
11
+ halsteadCalculator;
12
+ maintainabilityCalculator;
13
+ astParser;
14
+ constructor() {
15
+ this.halsteadCalculator = new HalsteadCalculator();
16
+ this.maintainabilityCalculator = new MaintainabilityCalculator();
17
+ this.astParser = new ASTParser();
18
+ }
19
+ /**
20
+ * Analyze metrics for files matching patterns
21
+ */
22
+ async analyze(directory, options = {}) {
23
+ const files = await this.getFilesToAnalyze(directory, options);
24
+ const fileMetrics = [];
25
+ for (const filePath of files) {
26
+ try {
27
+ const metrics = await this.analyzeFile(filePath);
28
+ fileMetrics.push(metrics);
29
+ }
30
+ catch (error) {
31
+ // Skip files that fail to parse
32
+ continue;
33
+ }
34
+ }
35
+ const summary = this.calculateSummary(fileMetrics);
36
+ return Object.freeze({
37
+ fileMetrics: Object.freeze(fileMetrics),
38
+ summary,
39
+ timestamp: new Date(),
40
+ });
41
+ }
42
+ /**
43
+ * Analyze a single file
44
+ */
45
+ async analyzeFile(filePath) {
46
+ // Calculate Halstead metrics
47
+ const halstead = this.halsteadCalculator.calculateMetrics(filePath);
48
+ // Get AST info for complexity and LOC
49
+ const ast = this.astParser.parseFile(filePath);
50
+ // Calculate average and max complexity
51
+ const complexities = ast.functions.map((f) => f.complexity);
52
+ const averageComplexity = complexities.length > 0
53
+ ? complexities.reduce((a, b) => a + b, 0) / complexities.length
54
+ : 0;
55
+ const maxComplexity = complexities.length > 0 ? Math.max(...complexities) : 0;
56
+ // Calculate total lines of code (excluding blank lines and comments)
57
+ const linesOfCode = this.calculateLinesOfCode(filePath);
58
+ // Calculate Maintainability Index
59
+ const maintainability = this.maintainabilityCalculator.calculateIndex(halstead.volume, averageComplexity, linesOfCode);
60
+ return Object.freeze({
61
+ filePath,
62
+ halstead,
63
+ maintainability,
64
+ averageComplexity: Math.round(averageComplexity * 100) / 100,
65
+ maxComplexity,
66
+ totalFunctions: ast.functions.length,
67
+ });
68
+ }
69
+ /**
70
+ * Calculate lines of code (excluding blank lines)
71
+ */
72
+ calculateLinesOfCode(filePath) {
73
+ const sourceFile = this.astParser.getSourceFile(filePath);
74
+ const text = sourceFile.getFullText();
75
+ const lines = text.split('\n');
76
+ // Count non-blank lines
77
+ let loc = 0;
78
+ for (const line of lines) {
79
+ const trimmed = line.trim();
80
+ if (trimmed.length > 0) {
81
+ loc++;
82
+ }
83
+ }
84
+ return loc;
85
+ }
86
+ /**
87
+ * Get files to analyze based on patterns
88
+ */
89
+ async getFilesToAnalyze(directory, options) {
90
+ const includePatterns = options.includePatterns || ['**/*.ts', '**/*.tsx'];
91
+ const excludePatterns = options.excludePatterns || [
92
+ '**/node_modules/**',
93
+ '**/*.test.ts',
94
+ '**/*.spec.ts',
95
+ '**/dist/**',
96
+ '**/build/**',
97
+ ];
98
+ const allFiles = new Set();
99
+ for (const pattern of includePatterns) {
100
+ const matches = await glob(pattern, {
101
+ cwd: directory,
102
+ absolute: true,
103
+ ignore: excludePatterns ? [...excludePatterns] : [],
104
+ });
105
+ for (const match of matches) {
106
+ allFiles.add(match);
107
+ }
108
+ }
109
+ return Array.from(allFiles).sort();
110
+ }
111
+ /**
112
+ * Calculate summary statistics
113
+ */
114
+ calculateSummary(fileMetrics) {
115
+ if (fileMetrics.length === 0) {
116
+ return Object.freeze({
117
+ filesAnalyzed: 0,
118
+ averageMaintainability: 0,
119
+ averageHalsteadVolume: 0,
120
+ averageComplexity: 0,
121
+ lowMaintainabilityCount: 0,
122
+ highComplexityCount: 0,
123
+ });
124
+ }
125
+ const totalMaintainability = fileMetrics.reduce((sum, m) => sum + m.maintainability.score, 0);
126
+ const totalHalsteadVolume = fileMetrics.reduce((sum, m) => sum + m.halstead.volume, 0);
127
+ const totalComplexity = fileMetrics.reduce((sum, m) => sum + m.averageComplexity, 0);
128
+ const lowMaintainabilityCount = fileMetrics.filter((m) => m.maintainability.score < 65).length;
129
+ const highComplexityCount = fileMetrics.filter((m) => m.maxComplexity > 10).length;
130
+ return Object.freeze({
131
+ filesAnalyzed: fileMetrics.length,
132
+ averageMaintainability: Math.round((totalMaintainability / fileMetrics.length) * 100) / 100,
133
+ averageHalsteadVolume: Math.round((totalHalsteadVolume / fileMetrics.length) * 100) / 100,
134
+ averageComplexity: Math.round((totalComplexity / fileMetrics.length) * 100) / 100,
135
+ lowMaintainabilityCount,
136
+ highComplexityCount,
137
+ });
138
+ }
139
+ }
140
+ //# sourceMappingURL=metrics-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics-analyzer.js","sourceRoot":"","sources":["../../../src/analyzers/metrics/metrics-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Advanced Metrics Types
3
+ */
4
+ /**
5
+ * Halstead complexity metrics
6
+ */
7
+ export interface HalsteadMetrics {
8
+ readonly n1: number;
9
+ readonly n2: number;
10
+ readonly N1: number;
11
+ readonly N2: number;
12
+ readonly vocabulary: number;
13
+ readonly length: number;
14
+ readonly calculatedLength: number;
15
+ readonly volume: number;
16
+ readonly difficulty: number;
17
+ readonly effort: number;
18
+ readonly time: number;
19
+ readonly bugs: number;
20
+ }
21
+ /**
22
+ * Maintainability Index
23
+ */
24
+ export interface MaintainabilityIndex {
25
+ readonly score: number;
26
+ readonly rating: 'A' | 'B' | 'C' | 'D' | 'F';
27
+ readonly halsteadVolume: number;
28
+ readonly cyclomaticComplexity: number;
29
+ readonly linesOfCode: number;
30
+ }
31
+ /**
32
+ * File metrics
33
+ */
34
+ export interface FileMetrics {
35
+ readonly filePath: string;
36
+ readonly halstead: HalsteadMetrics;
37
+ readonly maintainability: MaintainabilityIndex;
38
+ readonly averageComplexity: number;
39
+ readonly maxComplexity: number;
40
+ readonly totalFunctions: number;
41
+ }
42
+ /**
43
+ * Metrics analysis result
44
+ */
45
+ export interface MetricsAnalysisResult {
46
+ readonly fileMetrics: ReadonlyArray<FileMetrics>;
47
+ readonly summary: MetricsSummary;
48
+ readonly timestamp: Date;
49
+ }
50
+ /**
51
+ * Summary statistics
52
+ */
53
+ export interface MetricsSummary {
54
+ readonly filesAnalyzed: number;
55
+ readonly averageMaintainability: number;
56
+ readonly averageHalsteadVolume: number;
57
+ readonly averageComplexity: number;
58
+ readonly lowMaintainabilityCount: number;
59
+ readonly highComplexityCount: number;
60
+ }
61
+ /**
62
+ * Analysis options
63
+ */
64
+ export interface MetricsAnalysisOptions {
65
+ readonly includePatterns?: readonly string[];
66
+ readonly excludePatterns?: readonly string[];
67
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Advanced Metrics Types
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/analyzers/metrics/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Base Security Detector
3
+ *
4
+ * Abstract base class for security vulnerability detectors
5
+ */
6
+ import type { SecurityDetector, SecurityVulnerability, SecuritySeverity, OWASPCategory } from './types.js';
7
+ export declare abstract class BaseSecurityDetector implements SecurityDetector {
8
+ readonly id: string;
9
+ readonly name: string;
10
+ readonly description: string;
11
+ readonly severity: SecuritySeverity;
12
+ readonly owaspCategory?: OWASPCategory;
13
+ readonly cweId?: string;
14
+ readonly enabled: boolean;
15
+ protected readonly fileExtensions: readonly string[];
16
+ constructor(config: {
17
+ id: string;
18
+ name: string;
19
+ description: string;
20
+ severity: SecuritySeverity;
21
+ owaspCategory?: OWASPCategory;
22
+ cweId?: string;
23
+ fileExtensions?: readonly string[];
24
+ enabled?: boolean;
25
+ });
26
+ /**
27
+ * Check if detector applies to this file type
28
+ */
29
+ appliesTo(filePath: string): boolean;
30
+ /**
31
+ * Scan file content for vulnerabilities
32
+ */
33
+ abstract scan(content: string, filePath: string): Promise<SecurityVulnerability[]>;
34
+ /**
35
+ * Create a vulnerability finding
36
+ */
37
+ protected createVulnerability(file: string, line: number, code: string, description: string, recommendation: string, references?: string[]): SecurityVulnerability;
38
+ /**
39
+ * Find line number for a match in content
40
+ */
41
+ protected findLineNumber(content: string, matchIndex: number): number;
42
+ /**
43
+ * Extract code snippet around a match
44
+ */
45
+ protected extractCodeSnippet(content: string, matchIndex: number, contextLines?: number): string;
46
+ /**
47
+ * Check if line is in a comment
48
+ */
49
+ protected isInComment(content: string, matchIndex: number): boolean;
50
+ /**
51
+ * Check if match is in a string literal
52
+ */
53
+ protected isInString(content: string, matchIndex: number): boolean;
54
+ /**
55
+ * Check if match should be ignored
56
+ */
57
+ protected shouldIgnore(content: string, matchIndex: number): boolean;
58
+ }
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Base Security Detector
3
+ *
4
+ * Abstract base class for security vulnerability detectors
5
+ */
6
+ import path from 'path';
7
+ export class BaseSecurityDetector {
8
+ id;
9
+ name;
10
+ description;
11
+ severity;
12
+ owaspCategory;
13
+ cweId;
14
+ enabled;
15
+ fileExtensions;
16
+ constructor(config) {
17
+ this.id = config.id;
18
+ this.name = config.name;
19
+ this.description = config.description;
20
+ this.severity = config.severity;
21
+ this.owaspCategory = config.owaspCategory;
22
+ this.cweId = config.cweId;
23
+ this.fileExtensions = config.fileExtensions || ['.ts', '.tsx', '.js', '.jsx'];
24
+ this.enabled = config.enabled !== false;
25
+ }
26
+ /**
27
+ * Check if detector applies to this file type
28
+ */
29
+ appliesTo(filePath) {
30
+ const ext = path.extname(filePath).toLowerCase();
31
+ return this.fileExtensions.includes(ext);
32
+ }
33
+ /**
34
+ * Create a vulnerability finding
35
+ */
36
+ createVulnerability(file, line, code, description, recommendation, references = []) {
37
+ return Object.freeze({
38
+ id: this.id,
39
+ name: this.name,
40
+ description,
41
+ severity: this.severity,
42
+ owaspCategory: this.owaspCategory,
43
+ cweId: this.cweId,
44
+ file,
45
+ line,
46
+ code: code.trim(),
47
+ recommendation,
48
+ references: Object.freeze(references),
49
+ });
50
+ }
51
+ /**
52
+ * Find line number for a match in content
53
+ */
54
+ findLineNumber(content, matchIndex) {
55
+ const beforeMatch = content.substring(0, matchIndex);
56
+ return beforeMatch.split('\n').length;
57
+ }
58
+ /**
59
+ * Extract code snippet around a match
60
+ */
61
+ extractCodeSnippet(content, matchIndex, contextLines = 0) {
62
+ const lines = content.split('\n');
63
+ const lineNumber = this.findLineNumber(content, matchIndex);
64
+ const startLine = Math.max(0, lineNumber - contextLines - 1);
65
+ const endLine = Math.min(lines.length, lineNumber + contextLines);
66
+ return lines.slice(startLine, endLine).join('\n');
67
+ }
68
+ /**
69
+ * Check if line is in a comment
70
+ */
71
+ isInComment(content, matchIndex) {
72
+ const beforeMatch = content.substring(0, matchIndex);
73
+ const lastLineBreak = beforeMatch.lastIndexOf('\n');
74
+ const currentLine = content.substring(lastLineBreak + 1, matchIndex + 50);
75
+ // Check for single-line comment
76
+ if (currentLine.includes('//')) {
77
+ return true;
78
+ }
79
+ // Check for multi-line comment
80
+ const openComments = (beforeMatch.match(/\/\*/g) || []).length;
81
+ const closeComments = (beforeMatch.match(/\*\//g) || []).length;
82
+ return openComments > closeComments;
83
+ }
84
+ /**
85
+ * Check if match is in a string literal
86
+ */
87
+ isInString(content, matchIndex) {
88
+ const beforeMatch = content.substring(0, matchIndex);
89
+ const lastLineBreak = beforeMatch.lastIndexOf('\n');
90
+ const lineContent = beforeMatch.substring(lastLineBreak + 1);
91
+ // Count unescaped quotes
92
+ const singleQuotes = (lineContent.match(/(?<!\\)'/g) || []).length;
93
+ const doubleQuotes = (lineContent.match(/(?<!\\)"/g) || []).length;
94
+ const backticks = (lineContent.match(/(?<!\\)`/g) || []).length;
95
+ return (singleQuotes % 2 === 1) || (doubleQuotes % 2 === 1) || (backticks % 2 === 1);
96
+ }
97
+ /**
98
+ * Check if match should be ignored
99
+ */
100
+ shouldIgnore(content, matchIndex) {
101
+ return this.isInComment(content, matchIndex) || this.isInString(content, matchIndex);
102
+ }
103
+ }
104
+ //# sourceMappingURL=base-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-detector.js","sourceRoot":"","sources":["../../../src/analyzers/security/base-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Command Injection Detector
3
+ *
4
+ * Detects potential command injection vulnerabilities
5
+ * OWASP A03:2021 - Injection
6
+ */
7
+ import { BaseSecurityDetector } from '../base-detector.js';
8
+ import type { SecurityVulnerability } from '../types.js';
9
+ export declare class CommandInjectionDetector extends BaseSecurityDetector {
10
+ constructor();
11
+ scan(content: string, filePath: string): Promise<SecurityVulnerability[]>;
12
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Command Injection Detector
3
+ *
4
+ * Detects potential command injection vulnerabilities
5
+ * OWASP A03:2021 - Injection
6
+ */
7
+ import { BaseSecurityDetector } from '../base-detector.js';
8
+ export class CommandInjectionDetector extends BaseSecurityDetector {
9
+ constructor() {
10
+ super({
11
+ id: 'command-injection',
12
+ name: 'Command Injection',
13
+ description: 'Detects potential command injection vulnerabilities',
14
+ severity: 'critical',
15
+ owaspCategory: 'A03:2021 - Injection',
16
+ cweId: 'CWE-78',
17
+ });
18
+ }
19
+ async scan(content, filePath) {
20
+ if (!this.appliesTo(filePath)) {
21
+ return [];
22
+ }
23
+ const vulnerabilities = [];
24
+ // Pattern 1: exec/execSync with user input
25
+ const execPatterns = [
26
+ {
27
+ pattern: /(?:exec|execSync|spawn|spawnSync)\([^)]*(?:req\.|params\.|query\.|input|user)/gi,
28
+ method: 'child_process method',
29
+ },
30
+ {
31
+ pattern: /(?:exec|execSync|spawn|spawnSync)\([`'][^`']*\$\{(?:req\.|params\.|query\.|input|user)/gi,
32
+ method: 'child_process method with template literal',
33
+ },
34
+ ];
35
+ for (const { pattern, method } of execPatterns) {
36
+ let match;
37
+ const regex = new RegExp(pattern);
38
+ while ((match = regex.exec(content)) !== null) {
39
+ if (this.shouldIgnore(content, match.index)) {
40
+ continue;
41
+ }
42
+ const line = this.findLineNumber(content, match.index);
43
+ const code = this.extractCodeSnippet(content, match.index, 1);
44
+ vulnerabilities.push(this.createVulnerability(filePath, line, code, `${method} uses user input which may lead to command injection`, 'Never pass user input directly to shell commands. Use execFile with array arguments or validate/sanitize input strictly', [
45
+ 'https://owasp.org/www-community/attacks/Command_Injection',
46
+ 'https://cheatsheetseries.owasp.org/cheatsheets/OS_Command_Injection_Defense_Cheat_Sheet.html',
47
+ ]));
48
+ }
49
+ }
50
+ // Pattern 2: Shell: true option with user input
51
+ const shellTruePattern = /(?:exec|spawn)\([^,)]*,\s*\{[^}]*shell:\s*true[^}]*\}/gi;
52
+ let match;
53
+ while ((match = shellTruePattern.exec(content)) !== null) {
54
+ if (this.shouldIgnore(content, match.index)) {
55
+ continue;
56
+ }
57
+ // Check if user input is nearby
58
+ const contextStart = Math.max(0, match.index - 100);
59
+ const contextEnd = Math.min(content.length, match.index + 200);
60
+ const context = content.substring(contextStart, contextEnd);
61
+ if (/(?:req\.|params\.|query\.|input|user)/.test(context)) {
62
+ const line = this.findLineNumber(content, match.index);
63
+ const code = this.extractCodeSnippet(content, match.index, 1);
64
+ vulnerabilities.push(this.createVulnerability(filePath, line, code, 'Using shell: true with user input is extremely dangerous', 'Avoid shell: true. Use execFile or spawn with array arguments', [
65
+ 'https://owasp.org/www-community/attacks/Command_Injection',
66
+ ]));
67
+ }
68
+ }
69
+ // Pattern 3: String concatenation in commands
70
+ const commandConcatPattern = /(?:exec|execSync)\(['"`][^'"`]*\+\s*(?:req\.|params\.|query\.|input|user)/gi;
71
+ while ((match = commandConcatPattern.exec(content)) !== null) {
72
+ if (this.shouldIgnore(content, match.index)) {
73
+ continue;
74
+ }
75
+ const line = this.findLineNumber(content, match.index);
76
+ const code = this.extractCodeSnippet(content, match.index, 1);
77
+ vulnerabilities.push(this.createVulnerability(filePath, line, code, 'Command constructed using string concatenation with user input', 'Use execFile with array arguments to avoid command injection', [
78
+ 'https://owasp.org/www-community/attacks/Command_Injection',
79
+ ]));
80
+ }
81
+ return vulnerabilities;
82
+ }
83
+ }
84
+ //# sourceMappingURL=command-injection-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-injection-detector.js","sourceRoot":"","sources":["../../../../src/analyzers/security/detectors/command-injection-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Hardcoded Secrets Detector
3
+ *
4
+ * Detects hardcoded passwords, API keys, tokens, and other secrets
5
+ * OWASP A02:2021 - Cryptographic Failures
6
+ */
7
+ import { BaseSecurityDetector } from '../base-detector.js';
8
+ import type { SecurityVulnerability } from '../types.js';
9
+ export declare class HardcodedSecretsDetector extends BaseSecurityDetector {
10
+ constructor();
11
+ scan(content: string, filePath: string): Promise<SecurityVulnerability[]>;
12
+ /**
13
+ * Check if value looks like a placeholder
14
+ */
15
+ private isPlaceholder;
16
+ }