sudeshi-code-review 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -52,6 +52,26 @@ sudeshi-code-review --version
52
52
 
53
53
  Provide a repository directory when running a scan. Review the report and validate findings before acting on them.
54
54
 
55
+ ### Terminal output
56
+
57
+ Interactive terminals display a formatted summary with severity-colored findings and confidence details. Color output is automatically disabled when stdout is not an interactive terminal or when the `NO_COLOR` environment variable is set. JSON output remains machine-readable and contains no terminal styling.
58
+
59
+ Disable terminal colors explicitly:
60
+
61
+ **Git Bash**
62
+
63
+ ```bash
64
+ export NO_COLOR=1
65
+ sudeshi-code-review /path/to/repository
66
+ ```
67
+
68
+ **PowerShell**
69
+
70
+ ```powershell
71
+ $env:NO_COLOR = "1"
72
+ sudeshi-code-review "C:\path\to\repository"
73
+ ```
74
+
55
75
  ## Optional AI-assisted review
56
76
 
57
77
  AI review is optional. Without `SARVAM_API_KEY`, the CLI uses its deterministic rules.
@@ -1 +1 @@
1
- {"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/analyzer/analyze.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,wBAAgB,OAAO,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CASrE"}
1
+ {"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/analyzer/analyze.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAKlD,wBAAgB,OAAO,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAmCrE"}
@@ -1,3 +1,5 @@
1
+ const MAX_EVIDENCE_LENGTH = 240;
2
+ const EVIDENCE_TRUNCATION_MARKER = '… [truncated]';
1
3
  export function analyze(files, rules) {
2
4
  const findings = [];
3
5
  for (const file of files) {
@@ -5,6 +7,24 @@ export function analyze(files, rules) {
5
7
  findings.push(...rule(file));
6
8
  }
7
9
  }
8
- return findings;
10
+ const uniqueFindings = new Map();
11
+ for (const finding of findings) {
12
+ const normalizedPath = finding.file.replaceAll('\\', '/');
13
+ const key = `${finding.rule}\\0${normalizedPath}\\0${finding.line}`;
14
+ if (uniqueFindings.has(key)) {
15
+ continue;
16
+ }
17
+ let normalizedFinding = finding;
18
+ if (finding.evidence && finding.evidence.length > MAX_EVIDENCE_LENGTH) {
19
+ normalizedFinding = {
20
+ ...finding,
21
+ evidence: finding.evidence
22
+ .slice(0, MAX_EVIDENCE_LENGTH - EVIDENCE_TRUNCATION_MARKER.length)
23
+ .trimEnd() + EVIDENCE_TRUNCATION_MARKER,
24
+ };
25
+ }
26
+ uniqueFindings.set(key, normalizedFinding);
27
+ }
28
+ return [...uniqueFindings.values()];
9
29
  }
10
30
  //# sourceMappingURL=analyze.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/analyzer/analyze.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,OAAO,CAAC,KAAmB,EAAE,KAAa;IACxD,MAAM,QAAQ,GAAc,EAAE,CAAC;IAE/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/analyzer/analyze.ts"],"names":[],"mappings":"AAIA,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAChC,MAAM,0BAA0B,GAAG,eAAe,CAAC;AAEnD,MAAM,UAAU,OAAO,CAAC,KAAmB,EAAE,KAAa;IACxD,MAAM,QAAQ,GAAc,EAAE,CAAC;IAE/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,MAAM,cAAc,GAAG,IAAI,GAAG,EAAmB,CAAC;IAElD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC1D,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,IAAI,MAAM,cAAc,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;QAEpE,IAAI,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5B,SAAS;QACX,CAAC;QAED,IAAI,iBAAiB,GAAG,OAAO,CAAC;QAEhC,IAAI,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,GAAG,mBAAmB,EAAE,CAAC;YACtE,iBAAiB,GAAG;gBAClB,GAAG,OAAO;gBACV,QAAQ,EACN,OAAO,CAAC,QAAQ;qBACb,KAAK,CAAC,CAAC,EAAE,mBAAmB,GAAG,0BAA0B,CAAC,MAAM,CAAC;qBACjE,OAAO,EAAE,GAAG,0BAA0B;aAC5C,CAAC;QACJ,CAAC;QAED,cAAc,CAAC,GAAG,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC;AACtC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"hardcodedSecret.d.ts","sourceRoot":"","sources":["../../../src/analyzer/rules/hardcodedSecret.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAWvC,eAAO,MAAM,mBAAmB,EAAE,IAoFjC,CAAC"}
1
+ {"version":3,"file":"hardcodedSecret.d.ts","sourceRoot":"","sources":["../../../src/analyzer/rules/hardcodedSecret.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AA8BvC,eAAO,MAAM,mBAAmB,EAAE,IA4FjC,CAAC"}
@@ -3,6 +3,15 @@ const SECRET_NAME_PATTERN = /^(apiKey|api_key|paymentApiKey|accessToken|access_t
3
3
  function isStaticSecretString(node) {
4
4
  return ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node);
5
5
  }
6
+ function redactSecretEvidence(line, value, literalText) {
7
+ if (!value) {
8
+ return line;
9
+ }
10
+ if (literalText) {
11
+ return line.replace(literalText, literalText[0] + '[REDACTED]' + literalText[0]);
12
+ }
13
+ return line.replace(value, '[REDACTED]');
14
+ }
6
15
  export const hardcodedSecretRule = (file) => {
7
16
  const findings = [];
8
17
  const sourceFile = ts.createSourceFile(file.path, file.content, ts.ScriptTarget.Latest, true, file.path.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS);
@@ -24,7 +33,7 @@ export const hardcodedSecretRule = (file) => {
24
33
  line: line + 1,
25
34
  rule: 'hardcoded-secret',
26
35
  message: 'A hardcoded secret may be present',
27
- evidence: file.content.split('\n')[line]?.trim() ?? '',
36
+ evidence: redactSecretEvidence(file.content.split('\n')[line]?.trim() ?? '', value, node.initializer.getText(sourceFile)),
28
37
  requiresAIReview: true,
29
38
  });
30
39
  }
@@ -54,7 +63,7 @@ export const hardcodedSecretRule = (file) => {
54
63
  line: line + 1,
55
64
  rule: 'hardcoded-secret',
56
65
  message: 'A hardcoded secret may be present',
57
- evidence: file.content.split('\n')[line]?.trim() ?? '',
66
+ evidence: redactSecretEvidence(file.content.split('\n')[line]?.trim() ?? '', value, node.initializer.getText(sourceFile)),
58
67
  requiresAIReview: true,
59
68
  });
60
69
  }
@@ -1 +1 @@
1
- {"version":3,"file":"hardcodedSecret.js","sourceRoot":"","sources":["../../../src/analyzer/rules/hardcodedSecret.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAI5B,MAAM,mBAAmB,GACvB,mKAAmK,CAAC;AAEtK,SAAS,oBAAoB,CAC3B,IAAmB;IAEnB,OAAO,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,+BAA+B,CAAC,IAAI,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAS,CAAC,IAAI,EAAE,EAAE;IAChD,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAG,EAAE,CAAC,gBAAgB,CACpC,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,OAAO,EACZ,EAAE,CAAC,YAAY,CAAC,MAAM,EACtB,IAAI,EACJ,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,CAClE,CAAC;IAEF,SAAS,KAAK,CAAC,IAAa;QAC1B,IACE,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC;YAC9B,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;YAC1B,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;YACxC,IAAI,CAAC,WAAW;YAChB,oBAAoB,CAAC,IAAI,CAAC,WAAW,CAAC,EACtC,CAAC;YACD,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC,6BAA6B,CACvD,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAC1B,CAAC;YACF,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;YAEpC,IAAI,KAAK,EAAE,CAAC;gBACV,QAAQ,CAAC,IAAI,CAAC;oBACZ,EAAE,EAAE,kBAAkB;oBACtB,QAAQ,EAAE,UAAU;oBACpB,QAAQ,EAAE,MAAM;oBAChB,UAAU,EAAE,CAAC;oBACb,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,IAAI,EAAE,IAAI,GAAG,CAAC;oBACd,IAAI,EAAE,kBAAkB;oBACxB,OAAO,EAAE,mCAAmC;oBAC5C,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE;oBACtD,gBAAgB,EAAE,IAAI;iBACvB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,IACE,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC;YAC7B,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;YAC1B,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;YACxC,oBAAoB,CAAC,IAAI,CAAC,WAAW,CAAC,EACtC,CAAC;YACD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;YACpC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;YAEpC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBAC7B,OAAO;YACT,CAAC;YAED,IACE,+BAA+B,CAAC,IAAI,CAAC,YAAY,CAAC;gBAClD,CAAC,yCAAyC,CAAC,IAAI,CAAC,KAAK,CAAC,EACtD,CAAC;gBACD,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBAC7B,OAAO;YACT,CAAC;YAED,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC,6BAA6B,CACvD,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAC1B,CAAC;YAEF,QAAQ,CAAC,IAAI,CAAC;gBACZ,EAAE,EAAE,kBAAkB;gBACtB,QAAQ,EAAE,UAAU;gBACpB,QAAQ,EAAE,MAAM;gBAChB,UAAU,EAAE,CAAC;gBACb,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,IAAI,EAAE,IAAI,GAAG,CAAC;gBACd,IAAI,EAAE,kBAAkB;gBACxB,OAAO,EAAE,mCAAmC;gBAC5C,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE;gBACtD,gBAAgB,EAAE,IAAI;aACvB,CAAC,CAAC;QACL,CAAC;QAED,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,CAAC;IAClB,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC"}
1
+ {"version":3,"file":"hardcodedSecret.js","sourceRoot":"","sources":["../../../src/analyzer/rules/hardcodedSecret.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAI5B,MAAM,mBAAmB,GACvB,mKAAmK,CAAC;AAEtK,SAAS,oBAAoB,CAC3B,IAAmB;IAEnB,OAAO,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,+BAA+B,CAAC,IAAI,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,oBAAoB,CAC3B,IAAY,EACZ,KAAa,EACb,WAAoB;IAEpB,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC,OAAO,CACjB,WAAW,EACX,WAAW,CAAC,CAAC,CAAC,GAAG,YAAY,GAAG,WAAW,CAAC,CAAC,CAAC,CAC/C,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAS,CAAC,IAAI,EAAE,EAAE;IAChD,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAG,EAAE,CAAC,gBAAgB,CACpC,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,OAAO,EACZ,EAAE,CAAC,YAAY,CAAC,MAAM,EACtB,IAAI,EACJ,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,CAClE,CAAC;IAEF,SAAS,KAAK,CAAC,IAAa;QAC1B,IACE,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC;YAC9B,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;YAC1B,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;YACxC,IAAI,CAAC,WAAW;YAChB,oBAAoB,CAAC,IAAI,CAAC,WAAW,CAAC,EACtC,CAAC;YACD,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC,6BAA6B,CACvD,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAC1B,CAAC;YACF,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;YAEpC,IAAI,KAAK,EAAE,CAAC;gBACV,QAAQ,CAAC,IAAI,CAAC;oBACZ,EAAE,EAAE,kBAAkB;oBACtB,QAAQ,EAAE,UAAU;oBACpB,QAAQ,EAAE,MAAM;oBAChB,UAAU,EAAE,CAAC;oBACb,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,IAAI,EAAE,IAAI,GAAG,CAAC;oBACd,IAAI,EAAE,kBAAkB;oBACxB,OAAO,EAAE,mCAAmC;oBAC5C,QAAQ,EAAE,oBAAoB,CAC5B,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAC5C,KAAK,EACL,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,CACrC;oBACD,gBAAgB,EAAE,IAAI;iBACvB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,IACE,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC;YAC7B,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;YAC1B,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;YACxC,oBAAoB,CAAC,IAAI,CAAC,WAAW,CAAC,EACtC,CAAC;YACD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;YACpC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;YAEpC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBAC7B,OAAO;YACT,CAAC;YAED,IACE,+BAA+B,CAAC,IAAI,CAAC,YAAY,CAAC;gBAClD,CAAC,yCAAyC,CAAC,IAAI,CAAC,KAAK,CAAC,EACtD,CAAC;gBACD,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBAC7B,OAAO;YACT,CAAC;YAED,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC,6BAA6B,CACvD,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAC1B,CAAC;YAEF,QAAQ,CAAC,IAAI,CAAC;gBACZ,EAAE,EAAE,kBAAkB;gBACtB,QAAQ,EAAE,UAAU;gBACpB,QAAQ,EAAE,MAAM;gBAChB,UAAU,EAAE,CAAC;gBACb,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,IAAI,EAAE,IAAI,GAAG,CAAC;gBACd,IAAI,EAAE,kBAAkB;gBACxB,OAAO,EAAE,mCAAmC;gBAC5C,QAAQ,EAAE,oBAAoB,CAC5B,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAC5C,KAAK,EACL,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,CACrC;gBACD,gBAAgB,EAAE,IAAI;aACvB,CAAC,CAAC;QACL,CAAC;QAED,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,CAAC;IAClB,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"unsafeLink.d.ts","sourceRoot":"","sources":["../../../src/analyzer/rules/unsafeLink.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,eAAO,MAAM,cAAc,EAAE,IA4E5B,CAAC"}
1
+ {"version":3,"file":"unsafeLink.d.ts","sourceRoot":"","sources":["../../../src/analyzer/rules/unsafeLink.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,eAAO,MAAM,cAAc,EAAE,IA+F5B,CAAC"}
@@ -2,35 +2,49 @@ import ts from 'typescript';
2
2
  export const unsafeLinkRule = (file) => {
3
3
  const findings = [];
4
4
  const sourceFile = ts.createSourceFile(file.path, file.content, ts.ScriptTarget.Latest, true, file.path.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS);
5
- const dangerousVariables = new Set();
6
- function collectDangerousVariables(node) {
7
- if (ts.isVariableDeclaration(node) &&
8
- ts.isIdentifier(node.name) &&
9
- node.initializer &&
10
- ts.isStringLiteral(node.initializer) &&
11
- /^\s*javascript\s*:/i.test(node.initializer.text)) {
12
- dangerousVariables.add(node.name.text);
5
+ function isDangerousString(node) {
6
+ return ((ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) &&
7
+ /^\s*javascript\s*:/i.test(node.text));
8
+ }
9
+ function findVisibleDeclaration(reference) {
10
+ let current = reference.parent;
11
+ while (current) {
12
+ if (ts.isBlock(current) || ts.isSourceFile(current)) {
13
+ for (const statement of current.statements) {
14
+ if (!ts.isVariableStatement(statement))
15
+ continue;
16
+ for (const declaration of statement.declarationList.declarations) {
17
+ if (ts.isIdentifier(declaration.name) &&
18
+ declaration.name.text === reference.text &&
19
+ declaration.initializer &&
20
+ declaration.getStart(sourceFile) < reference.getStart(sourceFile)) {
21
+ return declaration;
22
+ }
23
+ }
24
+ }
25
+ }
26
+ current = current.parent;
13
27
  }
14
- ts.forEachChild(node, collectDangerousVariables);
28
+ return undefined;
15
29
  }
16
- collectDangerousVariables(sourceFile);
17
30
  function visit(node) {
18
31
  if (ts.isJsxAttribute(node) &&
19
- node.name.getText(sourceFile) === 'href' &&
32
+ ts.isIdentifier(node.name) &&
33
+ node.name.text === 'href' &&
20
34
  node.initializer) {
21
- let isDangerous = false;
35
+ let dangerous = false;
22
36
  if (ts.isStringLiteral(node.initializer)) {
23
- isDangerous = /^\s*javascript\s*:/i.test(node.initializer.text);
37
+ dangerous = /^\s*javascript\s*:/i.test(node.initializer.text);
24
38
  }
25
39
  else if (ts.isJsxExpression(node.initializer)) {
26
40
  const expression = node.initializer.expression;
27
- if (expression &&
28
- ts.isIdentifier(expression) &&
29
- dangerousVariables.has(expression.text)) {
30
- isDangerous = true;
41
+ if (expression && ts.isIdentifier(expression)) {
42
+ const declaration = findVisibleDeclaration(expression);
43
+ dangerous = Boolean(declaration?.initializer &&
44
+ isDangerousString(declaration.initializer));
31
45
  }
32
46
  }
33
- if (isDangerous) {
47
+ if (dangerous) {
34
48
  const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
35
49
  findings.push({
36
50
  id: 'unsafe-link',
@@ -1 +1 @@
1
- {"version":3,"file":"unsafeLink.js","sourceRoot":"","sources":["../../../src/analyzer/rules/unsafeLink.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"unsafeLink.js","sourceRoot":"","sources":["../../../src/analyzer/rules/unsafeLink.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,IAAI,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACtF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAK3D,OAAO,KAAK,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAKjF,KAAK,eAAe,GAAG;IACrB,cAAc,EAAE,OAAO,qBAAqB,CAAC;IAC7C,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,OAAO,EAAE,CAAC;IAC5C,YAAY,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;CACjD,CAAC;AAEF,wBAAsB,MAAM,CAC1B,IAAI,EAAE,MAAM,EAAE,EACd,YAAY,GAAE,eAQb,GACA,OAAO,CAAC,IAAI,CAAC,CAmFf"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,IAAI,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACtF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAK3D,OAAO,KAAK,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAQjF,KAAK,eAAe,GAAG;IACrB,cAAc,EAAE,OAAO,qBAAqB,CAAC;IAC7C,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,OAAO,EAAE,CAAC;IAC5C,YAAY,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;CACjD,CAAC;AAQF,wBAAsB,MAAM,CAC1B,IAAI,EAAE,MAAM,EAAE,EACd,YAAY,GAAE,eAQb,GACA,OAAO,CAAC,IAAI,CAAC,CAyIf"}
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { existsSync, statSync } from 'node:fs';
2
- import { readFile } from 'node:fs/promises';
2
+ import { readFile, writeFile } from 'node:fs/promises';
3
3
  import { resolve } from 'node:path';
4
4
  import { scanRepository as defaultScanRepository } from './scanner/scanRepository.js';
5
5
  import { analyze as defaultAnalyze } from './analyzer/analyze.js';
@@ -9,6 +9,13 @@ import { unsafeLinkRule } from './analyzer/rules/unsafeLink.js';
9
9
  import { generateMarkdownReport } from './reporting/markdownReporter.js';
10
10
  import { SarvamProvider } from './ai/sarvamProvider.js';
11
11
  import { ReviewEngine } from './review/reviewEngine.js';
12
+ import { generateJsonReport } from './reporting/jsonReporter.js';
13
+ import { generateTerminalReport } from './reporting/terminalReporter.js';
14
+ function writeProgress(message) {
15
+ if (process.stderr.isTTY) {
16
+ process.stderr.write(`${message}\n`);
17
+ }
18
+ }
12
19
  export async function runCLI(args, dependencies = {
13
20
  scanRepository: defaultScanRepository,
14
21
  analyze: (files) => defaultAnalyze(files, [
@@ -27,9 +34,12 @@ export async function runCLI(args, dependencies = {
27
34
  'Options:',
28
35
  ' -h, --help Show this help message',
29
36
  ' -v, --version Show the installed version',
37
+ ' --format <format> Report format: markdown or json (default: markdown)',
38
+ ' --output <path> Save the report to a file instead of stdout',
30
39
  '',
31
40
  'Environment:',
32
41
  ' SARVAM_API_KEY Optional API key for AI-assisted review',
42
+ ' NO_COLOR Disable terminal colors when set',
33
43
  '',
34
44
  ].join('\n'));
35
45
  return;
@@ -39,6 +49,25 @@ export async function runCLI(args, dependencies = {
39
49
  process.stdout.write(`${packageJson.version}\n`);
40
50
  return;
41
51
  }
52
+ const formatIndex = args.indexOf('--format');
53
+ const format = formatIndex === -1 ? 'markdown' : args[formatIndex + 1];
54
+ if (formatIndex !== -1 && (!format || format.startsWith('--'))) {
55
+ process.stderr.write('Error: --format requires a value.\n');
56
+ process.exit(1);
57
+ return;
58
+ }
59
+ if (format !== 'markdown' && format !== 'json') {
60
+ process.stderr.write('Error: --format must be either markdown or json.\n');
61
+ process.exit(1);
62
+ return;
63
+ }
64
+ const outputIndex = args.indexOf('--output');
65
+ const outputPath = outputIndex === -1 ? undefined : args[outputIndex + 1];
66
+ if (outputIndex !== -1 && (!outputPath || outputPath.startsWith('--'))) {
67
+ process.stderr.write('Error: --output requires a file path.\n');
68
+ process.exit(1);
69
+ return;
70
+ }
42
71
  const repositoryPath = args[0];
43
72
  if (!repositoryPath) {
44
73
  process.stderr.write('Error: repository path is required.\n');
@@ -56,27 +85,51 @@ export async function runCLI(args, dependencies = {
56
85
  process.exit(1);
57
86
  return;
58
87
  }
88
+ writeProgress('Scanning repository...');
59
89
  const filePaths = await dependencies.scanRepository(absolutePath);
60
90
  const files = await Promise.all(filePaths.map(async (filePath) => ({
61
91
  path: filePath,
62
92
  content: await readFile(resolve(absolutePath, filePath), 'utf8'),
63
93
  })));
94
+ writeProgress('Analyzing files...');
64
95
  const findings = dependencies.analyze(files);
65
96
  const apiKey = process.env.SARVAM_API_KEY;
66
- const reviewEngine = dependencies.reviewEngine ??
67
- (apiKey
68
- ? new ReviewEngine({
69
- provider: new SarvamProvider({ apiKey }),
70
- })
71
- : undefined);
72
- const result = reviewEngine
73
- ? await reviewEngine.review({ files, findings })
74
- : {
97
+ let reviewEngine = dependencies.reviewEngine;
98
+ if (!reviewEngine && apiKey) {
99
+ writeProgress('Initializing AI review...');
100
+ reviewEngine = new ReviewEngine({
101
+ provider: new SarvamProvider({ apiKey }),
102
+ });
103
+ }
104
+ let result;
105
+ if (reviewEngine) {
106
+ writeProgress('Running AI review...');
107
+ result = await reviewEngine.review({ files, findings });
108
+ }
109
+ else {
110
+ result = {
75
111
  findings,
76
112
  filesScanned: files.length,
77
113
  durationMs: 0,
78
114
  };
79
- const report = generateMarkdownReport(result);
80
- process.stdout.write(`${report}\n`);
115
+ }
116
+ writeProgress('Generating report...');
117
+ if (outputPath) {
118
+ const report = format === 'json'
119
+ ? generateJsonReport(result)
120
+ : generateMarkdownReport(result);
121
+ await writeFile(resolve(outputPath), `${report}\n`, 'utf8');
122
+ return;
123
+ }
124
+ if (format === 'json') {
125
+ process.stdout.write(`${generateJsonReport(result)}\n`);
126
+ return;
127
+ }
128
+ if (process.stdout.isTTY) {
129
+ process.stdout.write(`${generateTerminalReport(result)}\n`);
130
+ }
131
+ else {
132
+ process.stdout.write(`${generateMarkdownReport(result)}\n`);
133
+ }
81
134
  }
82
135
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ReviewResult } from '../review/reviewEngine.js';
2
+ export declare function generateJsonReport(result: ReviewResult): string;
3
+ //# sourceMappingURL=jsonReporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonReporter.d.ts","sourceRoot":"","sources":["../../src/reporting/jsonReporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9D,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAE/D"}
@@ -0,0 +1,4 @@
1
+ export function generateJsonReport(result) {
2
+ return JSON.stringify(result, null, 2);
3
+ }
4
+ //# sourceMappingURL=jsonReporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonReporter.js","sourceRoot":"","sources":["../../src/reporting/jsonReporter.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,kBAAkB,CAAC,MAAoB;IACrD,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { ReviewResult } from '../review/reviewEngine.js';
2
+ type TerminalReportOptions = {
3
+ /** Override automatic terminal color detection, primarily for tests. */
4
+ color?: boolean;
5
+ /** Override the output width, primarily for tests. */
6
+ width?: number;
7
+ };
8
+ export declare function generateTerminalReport(result: ReviewResult, options?: TerminalReportOptions): string;
9
+ export {};
10
+ //# sourceMappingURL=terminalReporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminalReporter.d.ts","sourceRoot":"","sources":["../../src/reporting/terminalReporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAY9D,KAAK,qBAAqB,GAAG;IAC3B,wEAAwE;IACxE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAgFF,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE,qBAA0B,GAClC,MAAM,CAyFR"}
@@ -0,0 +1,111 @@
1
+ const ANSI = {
2
+ reset: '\u001b[0m',
3
+ bold: '\u001b[1m',
4
+ dim: '\u001b[2m',
5
+ cyan: '\u001b[36m',
6
+ green: '\u001b[32m',
7
+ yellow: '\u001b[33m',
8
+ red: '\u001b[31m',
9
+ };
10
+ function shouldUseColor() {
11
+ return (Boolean(process.stdout.isTTY) &&
12
+ !('NO_COLOR' in process.env) &&
13
+ process.env.FORCE_COLOR !== '0');
14
+ }
15
+ function paint(text, color, enabled) {
16
+ return enabled ? `${color}${text}${ANSI.reset}` : text;
17
+ }
18
+ function paintSeverity(severity, enabled) {
19
+ const color = severity === 'high'
20
+ ? ANSI.red
21
+ : severity === 'medium'
22
+ ? ANSI.yellow
23
+ : ANSI.cyan;
24
+ return paint(severity.toUpperCase(), `${ANSI.bold}${color}`, enabled);
25
+ }
26
+ /**
27
+ * Wrap plain text to a maximum line width. Long words such as file paths
28
+ * are split when necessary so they cannot overflow a narrow terminal.
29
+ */
30
+ function wrapText(text, width) {
31
+ const safeWidth = Math.max(1, width);
32
+ const words = text.split(/\s+/).filter(Boolean);
33
+ const lines = [];
34
+ let line = '';
35
+ for (const word of words) {
36
+ if (word.length > safeWidth) {
37
+ if (line) {
38
+ lines.push(line);
39
+ line = '';
40
+ }
41
+ // Split long tokens without adding spaces between their chunks.
42
+ for (let offset = 0; offset < word.length; offset += safeWidth) {
43
+ lines.push(word.slice(offset, offset + safeWidth));
44
+ }
45
+ continue;
46
+ }
47
+ if (!line) {
48
+ line = word;
49
+ }
50
+ else if (line.length + 1 + word.length <= safeWidth) {
51
+ line += ` ${word}`;
52
+ }
53
+ else {
54
+ lines.push(line);
55
+ line = word;
56
+ }
57
+ }
58
+ if (line) {
59
+ lines.push(line);
60
+ }
61
+ return lines.length ? lines : [''];
62
+ }
63
+ function appendWrapped(lines, text, width, indent = ' ') {
64
+ const contentWidth = Math.max(1, width - indent.length);
65
+ for (const line of wrapText(text, contentWidth)) {
66
+ lines.push(`${indent}${line}`);
67
+ }
68
+ }
69
+ export function generateTerminalReport(result, options = {}) {
70
+ const color = options.color ?? shouldUseColor();
71
+ const width = Math.max(1, Math.floor(options.width ?? process.stdout.columns ?? 80));
72
+ const divider = '─'.repeat(Math.min(width, 80));
73
+ const counts = {
74
+ high: result.findings.filter((finding) => finding.severity === 'high')
75
+ .length,
76
+ medium: result.findings.filter((finding) => finding.severity === 'medium')
77
+ .length,
78
+ low: result.findings.filter((finding) => finding.severity === 'low').length,
79
+ };
80
+ const lines = [
81
+ paint('SUDESHI CODE REVIEW', `${ANSI.bold}${ANSI.cyan}`, color),
82
+ paint(divider, ANSI.dim, color),
83
+ '',
84
+ `${paint('✓', ANSI.green, color)} Review complete in ${(result.durationMs / 1000).toFixed(2)}s`,
85
+ `${paint(String(result.filesScanned), ANSI.cyan, color)} files scanned · ${paint(String(result.findings.length), result.findings.length ? ANSI.yellow : ANSI.green, color)} findings`,
86
+ '',
87
+ `Severity ${paint(`${counts.high} high`, ANSI.red, color)} · ${paint(`${counts.medium} medium`, ANSI.yellow, color)} · ${paint(`${counts.low} low`, ANSI.cyan, color)}`,
88
+ ];
89
+ if (result.findings.length === 0) {
90
+ lines.push('', paint(divider, ANSI.dim, color), '', paint('✓ No findings detected.', `${ANSI.bold}${ANSI.green}`, color));
91
+ return lines.join('\n');
92
+ }
93
+ lines.push('', paint('FINDINGS', `${ANSI.bold}${ANSI.cyan}`, color), paint(divider, ANSI.dim, color));
94
+ for (const finding of result.findings) {
95
+ lines.push('', `${paintSeverity(finding.severity, color)} ${paint(finding.rule, ANSI.bold, color)}`);
96
+ appendWrapped(lines, `${finding.file}:${finding.line}`, width);
97
+ appendWrapped(lines, finding.message, width);
98
+ appendWrapped(lines, `Confidence: ${Math.round(finding.confidence * 100)}%`, width);
99
+ if (finding.aiReview) {
100
+ const assessment = finding.aiReview.valid
101
+ ? 'Valid finding'
102
+ : 'Possible false positive';
103
+ appendWrapped(lines, `AI assessment: ${assessment}`, width);
104
+ appendWrapped(lines, `AI confidence: ${Math.round(finding.aiReview.confidence * 100)}%`, width);
105
+ appendWrapped(lines, `Recommendation: ${finding.aiReview.recommendation}`, width);
106
+ }
107
+ }
108
+ lines.push('', paint(divider, ANSI.dim, color));
109
+ return lines.join('\n');
110
+ }
111
+ //# sourceMappingURL=terminalReporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminalReporter.js","sourceRoot":"","sources":["../../src/reporting/terminalReporter.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"scanRepository.d.ts","sourceRoot":"","sources":["../../src/scanner/scanRepository.ts"],"names":[],"mappings":"AAaA,wBAAsB,cAAc,CAClC,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,MAAM,EAAE,CAAC,CAkCnB"}
1
+ {"version":3,"file":"scanRepository.d.ts","sourceRoot":"","sources":["../../src/scanner/scanRepository.ts"],"names":[],"mappings":"AAwBA,wBAAsB,cAAc,CAClC,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,MAAM,EAAE,CAAC,CAkCnB"}
@@ -3,11 +3,22 @@ import path from 'node:path';
3
3
  const SOURCE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx']);
4
4
  const IGNORED_DIRECTORIES = new Set([
5
5
  '.git',
6
+ '.venv',
7
+ 'venv',
8
+ 'env',
9
+ '.tox',
10
+ '__pycache__',
11
+ '.pytest_cache',
12
+ '.mypy_cache',
13
+ '.ruff_cache',
6
14
  'node_modules',
7
15
  'dist',
8
16
  'build',
9
17
  '.next',
10
18
  'coverage',
19
+ '.turbo',
20
+ '.output',
21
+ 'vendor',
11
22
  ]);
12
23
  export async function scanRepository(repositoryPath) {
13
24
  const files = [];
@@ -1 +1 @@
1
- {"version":3,"file":"scanRepository.js","sourceRoot":"","sources":["../../src/scanner/scanRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;AAClE,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IAClC,MAAM;IACN,cAAc;IACd,MAAM;IACN,OAAO;IACP,OAAO;IACP,UAAU;CACX,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,cAAsB;IAEtB,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,SAAS,cAAc,CAAC,cAAsB,EAAE,QAAgB;QAC9D,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;QAC7D,OAAO,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAChD,CAAC;IACD,KAAK,UAAU,aAAa,CAAC,aAAqB;QAChD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,aAAa,EAAE;YAC3C,aAAa,EAAE,IAAI;SACpB,CAAC,CAAC;QAEH,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAEvD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,IAAI,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;oBACxC,SAAS;gBACX,CAAC;gBACD,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC;gBAC/B,SAAS;YACX,CAAC;YACD,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;gBACnB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC3C,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC;oBAAE,SAAS;gBAChD,IAAI,iCAAiC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;oBAAE,SAAS;gBACjE,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,aAAa,CAAC,cAAc,CAAC,CAAC;IAEpC,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;AACtB,CAAC"}
1
+ {"version":3,"file":"scanRepository.js","sourceRoot":"","sources":["../../src/scanner/scanRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;AAClE,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IAClC,MAAM;IACN,OAAO;IACP,MAAM;IACN,KAAK;IACL,MAAM;IACN,aAAa;IACb,eAAe;IACf,aAAa;IACb,aAAa;IACb,cAAc;IACd,MAAM;IACN,OAAO;IACP,OAAO;IACP,UAAU;IACV,QAAQ;IACR,SAAS;IACT,QAAQ;CACT,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,cAAsB;IAEtB,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,SAAS,cAAc,CAAC,cAAsB,EAAE,QAAgB;QAC9D,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;QAC7D,OAAO,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAChD,CAAC;IACD,KAAK,UAAU,aAAa,CAAC,aAAqB;QAChD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,aAAa,EAAE;YAC3C,aAAa,EAAE,IAAI;SACpB,CAAC,CAAC;QAEH,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAEvD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,IAAI,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;oBACxC,SAAS;gBACX,CAAC;gBACD,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC;gBAC/B,SAAS;YACX,CAAC;YACD,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;gBACnB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC3C,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC;oBAAE,SAAS;gBAChD,IAAI,iCAAiC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;oBAAE,SAAS;gBACjE,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,aAAa,CAAC,cAAc,CAAC,CAAC;IAEpC,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;AACtB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sudeshi-code-review",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "A TypeScript and React code review CLI with security rules and optional Sarvam AI analysis.",
5
5
  "homepage": "https://github.com/sriram23/sudeshi-code-review#readme",
6
6
  "bugs": {