cto-ai-cli 4.0.0 → 5.0.0

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.
@@ -483,10 +483,7 @@ function deduplicateFindings(findings) {
483
483
  import { createHash as createHash2 } from "crypto";
484
484
 
485
485
  // src/engine/pruner.ts
486
- import { Project, SyntaxKind } from "ts-morph";
487
486
  import { readFile as readFile3 } from "fs/promises";
488
- import { existsSync as existsSync2 } from "fs";
489
- import { join as join2 } from "path";
490
487
 
491
488
  // src/engine/tokenizer.ts
492
489
  import { encodingForModel } from "js-tiktoken";
@@ -541,23 +538,7 @@ async function pruneTypeScript(file, level) {
541
538
  } catch {
542
539
  return emptyResult(file, level);
543
540
  }
544
- let project;
545
- try {
546
- const tsConfigPath = findTsConfig(file.path);
547
- project = new Project({
548
- tsConfigFilePath: tsConfigPath,
549
- skipAddingFilesFromTsConfig: true,
550
- compilerOptions: tsConfigPath ? void 0 : { allowJs: true, esModuleInterop: true }
551
- });
552
- project.createSourceFile(file.path, content, { overwrite: true });
553
- } catch {
554
- return pruneGenericFromContent(file, content, level);
555
- }
556
- const sourceFile = project.getSourceFiles()[0];
557
- if (!sourceFile) {
558
- return pruneGenericFromContent(file, content, level);
559
- }
560
- const prunedContent = level === "signatures" ? extractSignaturesAST(sourceFile) : extractSkeletonAST(sourceFile);
541
+ const prunedContent = level === "signatures" ? extractSignaturesRegex(content) : extractSkeletonRegex(content);
561
542
  const prunedTokens = countTokensChars4(Buffer.byteLength(prunedContent, "utf-8"));
562
543
  const savingsPercent = file.tokens > 0 ? (file.tokens - prunedTokens) / file.tokens * 100 : 0;
563
544
  return {
@@ -569,131 +550,281 @@ async function pruneTypeScript(file, level) {
569
550
  savingsPercent: Math.max(0, savingsPercent)
570
551
  };
571
552
  }
572
- function extractSignaturesAST(sf) {
553
+ function extractSignaturesRegex(content) {
554
+ const lines = content.split("\n");
573
555
  const parts = [];
574
- for (const imp of sf.getImportDeclarations()) {
575
- parts.push(imp.getText());
576
- }
577
- if (parts.length > 0) parts.push("");
578
- for (const ta of sf.getTypeAliases()) {
579
- addJSDoc(ta, parts);
580
- parts.push(ta.getText());
581
- }
582
- for (const iface of sf.getInterfaces()) {
583
- addJSDoc(iface, parts);
584
- parts.push(iface.getText());
585
- }
586
- for (const en of sf.getEnums()) {
587
- addJSDoc(en, parts);
588
- parts.push(en.getText());
589
- }
590
- for (const fn of sf.getFunctions()) {
591
- addJSDoc(fn, parts);
592
- const isExported = fn.isExported();
593
- const isAsync = fn.isAsync();
594
- const name = fn.getName() ?? "<anonymous>";
595
- const params = fn.getParameters().map((p) => p.getText()).join(", ");
596
- const returnType = fn.getReturnTypeNode()?.getText();
597
- const returnStr = returnType ? `: ${returnType}` : "";
598
- const prefix = isExported ? "export " : "";
599
- const asyncStr = isAsync ? "async " : "";
600
- parts.push(`${prefix}${asyncStr}function ${name}(${params})${returnStr} { /* ... */ }`);
601
- }
602
- for (const stmt of sf.getVariableStatements()) {
603
- for (const decl of stmt.getDeclarations()) {
604
- const init = decl.getInitializer();
605
- if (init && (init.getKind() === SyntaxKind.ArrowFunction || init.getKind() === SyntaxKind.FunctionExpression)) {
606
- addJSDoc(stmt, parts);
607
- const isExported = stmt.isExported();
608
- const prefix = isExported ? "export " : "";
609
- const kind = stmt.getDeclarationKind();
610
- const name = decl.getName();
611
- const typeNode = decl.getTypeNode()?.getText();
612
- const typeStr = typeNode ? `: ${typeNode}` : "";
613
- parts.push(`${prefix}${kind} ${name}${typeStr} = /* ... */;`);
614
- } else {
615
- addJSDoc(stmt, parts);
616
- parts.push(stmt.getText());
556
+ let i = 0;
557
+ while (i < lines.length) {
558
+ const line = lines[i];
559
+ const trimmed = line.trim();
560
+ if (trimmed === "") {
561
+ i++;
562
+ continue;
563
+ }
564
+ if (trimmed.startsWith("/**")) {
565
+ const docLines = [];
566
+ while (i < lines.length) {
567
+ docLines.push(lines[i]);
568
+ if (lines[i].includes("*/")) {
569
+ i++;
570
+ break;
571
+ }
572
+ i++;
573
+ }
574
+ parts.push(docLines.join("\n"));
575
+ continue;
576
+ }
577
+ if (trimmed.startsWith("//")) {
578
+ parts.push(line);
579
+ i++;
580
+ continue;
581
+ }
582
+ if (/^\s*(import|export)\s/.test(line) && (trimmed.includes(" from ") || trimmed.startsWith("import "))) {
583
+ const block = collectBracedLine(lines, i);
584
+ parts.push(block.text);
585
+ i = block.nextIndex;
586
+ continue;
587
+ }
588
+ if (/^\s*export\s*(\{|\*)/.test(trimmed)) {
589
+ const block = collectBracedLine(lines, i);
590
+ parts.push(block.text);
591
+ i = block.nextIndex;
592
+ continue;
593
+ }
594
+ if (/^\s*(export\s+)?type\s+\w/.test(trimmed) && !trimmed.startsWith("typeof")) {
595
+ const block = collectBalanced(lines, i);
596
+ parts.push(block.text);
597
+ i = block.nextIndex;
598
+ continue;
599
+ }
600
+ if (/^\s*(export\s+)?interface\s+\w/.test(trimmed)) {
601
+ const block = collectBalanced(lines, i);
602
+ parts.push(block.text);
603
+ i = block.nextIndex;
604
+ continue;
605
+ }
606
+ if (/^\s*(export\s+)?(const\s+)?enum\s+\w/.test(trimmed)) {
607
+ const block = collectBalanced(lines, i);
608
+ parts.push(block.text);
609
+ i = block.nextIndex;
610
+ continue;
611
+ }
612
+ const fnMatch = trimmed.match(/^(export\s+)?(async\s+)?function\s+(\w+)/);
613
+ if (fnMatch) {
614
+ const sig = extractFnSignature(lines, i);
615
+ parts.push(`${sig} { /* ... */ }`);
616
+ i = skipBlock(lines, i);
617
+ continue;
618
+ }
619
+ const arrowMatch = trimmed.match(/^(export\s+)?(const|let|var)\s+(\w+)/);
620
+ if (arrowMatch && looksLikeFunctionDecl(lines, i)) {
621
+ const prefix = trimmed.match(/^((?:export\s+)?(?:const|let|var)\s+\w+[^=]*=)/)?.[1];
622
+ if (prefix) {
623
+ parts.push(`${prefix} /* ... */;`);
617
624
  }
625
+ i = skipBlock(lines, i);
626
+ continue;
618
627
  }
619
- }
620
- for (const cls of sf.getClasses()) {
621
- addJSDoc(cls, parts);
622
- const isExported = cls.isExported();
623
- const prefix = isExported ? "export " : "";
624
- const name = cls.getName() ?? "<anonymous>";
625
- const ext = cls.getExtends()?.getText();
626
- const impl = cls.getImplements().map((i) => i.getText()).join(", ");
627
- let header = `${prefix}class ${name}`;
628
- if (ext) header += ` extends ${ext}`;
629
- if (impl) header += ` implements ${impl}`;
630
- header += " {";
631
- parts.push(header);
632
- for (const prop of cls.getProperties()) {
633
- parts.push(` ${prop.getText()}`);
634
- }
635
- const ctor = cls.getConstructors()[0];
636
- if (ctor) {
637
- const ctorParams = ctor.getParameters().map((p) => p.getText()).join(", ");
638
- parts.push(` constructor(${ctorParams}) { /* ... */ }`);
639
- }
640
- for (const method of cls.getMethods()) {
641
- const isStatic = method.isStatic();
642
- const isAsync = method.isAsync();
643
- const methodName = method.getName();
644
- const methodParams = method.getParameters().map((p) => p.getText()).join(", ");
645
- const returnType = method.getReturnTypeNode()?.getText();
646
- const returnStr = returnType ? `: ${returnType}` : "";
647
- const staticStr = isStatic ? "static " : "";
648
- const asyncStr = isAsync ? "async " : "";
649
- parts.push(` ${staticStr}${asyncStr}${methodName}(${methodParams})${returnStr} { /* ... */ }`);
650
- }
651
- parts.push("}");
652
- }
653
- for (const exp of sf.getExportDeclarations()) {
654
- parts.push(exp.getText());
655
- }
656
- for (const exp of sf.getExportAssignments()) {
657
- parts.push(exp.getText());
628
+ if (arrowMatch) {
629
+ const block = collectStatement(lines, i);
630
+ parts.push(block.text);
631
+ i = block.nextIndex;
632
+ continue;
633
+ }
634
+ if (/^\s*(export\s+)?(abstract\s+)?class\s+\w/.test(trimmed)) {
635
+ const classOutline = extractClassOutline(lines, i);
636
+ parts.push(classOutline.text);
637
+ i = classOutline.nextIndex;
638
+ continue;
639
+ }
640
+ i++;
658
641
  }
659
642
  return parts.join("\n");
660
643
  }
661
- function extractSkeletonAST(sf) {
644
+ function extractSkeletonRegex(content) {
645
+ const lines = content.split("\n");
662
646
  const parts = [];
663
- for (const imp of sf.getImportDeclarations()) {
664
- parts.push(imp.getText());
665
- }
666
- if (parts.length > 0) parts.push("");
667
- for (const ta of sf.getTypeAliases()) {
668
- if (ta.isExported()) parts.push(ta.getText());
669
- }
670
- for (const iface of sf.getInterfaces()) {
671
- if (!iface.isExported()) continue;
672
- const ext = iface.getExtends().map((e) => e.getText());
673
- const extStr = ext.length > 0 ? ` extends ${ext.join(", ")}` : "";
674
- parts.push(`export interface ${iface.getName()}${extStr} { /* ${iface.getProperties().length} props */ }`);
675
- }
676
- for (const en of sf.getEnums()) {
677
- if (!en.isExported()) continue;
678
- const members = en.getMembers().map((m) => m.getName());
679
- parts.push(`export enum ${en.getName()} { ${members.join(", ")} }`);
680
- }
681
- for (const fn of sf.getFunctions()) {
682
- if (!fn.isExported()) continue;
683
- const name = fn.getName() ?? "<anonymous>";
684
- const params = fn.getParameters().map((p) => p.getText()).join(", ");
685
- parts.push(`export function ${name}(${params});`);
686
- }
687
- for (const cls of sf.getClasses()) {
688
- if (!cls.isExported()) continue;
689
- const methods = cls.getMethods().map((m) => m.getName());
690
- parts.push(`export class ${cls.getName()} { /* methods: ${methods.join(", ")} */ }`);
691
- }
692
- for (const exp of sf.getExportDeclarations()) {
693
- parts.push(exp.getText());
647
+ let i = 0;
648
+ while (i < lines.length) {
649
+ const trimmed = lines[i].trim();
650
+ if (/^import\s/.test(trimmed)) {
651
+ const block = collectBracedLine(lines, i);
652
+ parts.push(block.text);
653
+ i = block.nextIndex;
654
+ continue;
655
+ }
656
+ if (/^export\s+(type|interface)\s+\w/.test(trimmed)) {
657
+ const block = collectBalanced(lines, i);
658
+ parts.push(block.text);
659
+ i = block.nextIndex;
660
+ continue;
661
+ }
662
+ if (/^export\s+(const\s+)?enum\s+\w/.test(trimmed)) {
663
+ const block = collectBalanced(lines, i);
664
+ parts.push(block.text);
665
+ i = block.nextIndex;
666
+ continue;
667
+ }
668
+ if (/^export\s+(async\s+)?function\s+\w/.test(trimmed)) {
669
+ const sig = extractFnSignature(lines, i);
670
+ parts.push(`${sig};`);
671
+ i = skipBlock(lines, i);
672
+ continue;
673
+ }
674
+ if (/^export\s+(abstract\s+)?class\s+/.test(trimmed)) {
675
+ const nameMatch = trimmed.match(/class\s+(\w+)/);
676
+ const name = nameMatch?.[1] ?? "Unknown";
677
+ const end = skipBlock(lines, i);
678
+ const methods = [];
679
+ for (let j = i + 1; j < end; j++) {
680
+ const mt = lines[j].trim();
681
+ const mm = mt.match(/^(?:static\s+)?(?:async\s+)?(\w+)\s*\(/);
682
+ if (mm && mm[1] !== "constructor") methods.push(mm[1]);
683
+ }
684
+ parts.push(`export class ${name} { /* methods: ${methods.join(", ")} */ }`);
685
+ i = end;
686
+ continue;
687
+ }
688
+ if (/^export\s*(\{|\*)/.test(trimmed)) {
689
+ const block = collectBracedLine(lines, i);
690
+ parts.push(block.text);
691
+ i = block.nextIndex;
692
+ continue;
693
+ }
694
+ i++;
694
695
  }
695
696
  return parts.join("\n");
696
697
  }
698
+ function collectBracedLine(lines, start) {
699
+ let text = lines[start];
700
+ let i = start + 1;
701
+ while (i < lines.length && !text.includes(";") && !text.trimEnd().endsWith("'") && !text.trimEnd().endsWith('"')) {
702
+ text += "\n" + lines[i];
703
+ i++;
704
+ }
705
+ return { text, nextIndex: i };
706
+ }
707
+ function collectBalanced(lines, start) {
708
+ let depth = 0;
709
+ let text = "";
710
+ let i = start;
711
+ let started = false;
712
+ while (i < lines.length) {
713
+ const line = lines[i];
714
+ text += (text ? "\n" : "") + line;
715
+ for (const ch of line) {
716
+ if (ch === "{" || ch === "(") {
717
+ depth++;
718
+ started = true;
719
+ }
720
+ if (ch === "}" || ch === ")") depth--;
721
+ }
722
+ i++;
723
+ if (started && depth <= 0) break;
724
+ if (!started && line.includes(";")) break;
725
+ }
726
+ return { text, nextIndex: i };
727
+ }
728
+ function collectStatement(lines, start) {
729
+ let text = lines[start];
730
+ let i = start + 1;
731
+ if (text.includes(";")) return { text, nextIndex: i };
732
+ let depth = 0;
733
+ for (const ch of text) {
734
+ if (ch === "{" || ch === "(" || ch === "[") depth++;
735
+ if (ch === "}" || ch === ")" || ch === "]") depth--;
736
+ }
737
+ while (i < lines.length && depth > 0) {
738
+ text += "\n" + lines[i];
739
+ for (const ch of lines[i]) {
740
+ if (ch === "{" || ch === "(" || ch === "[") depth++;
741
+ if (ch === "}" || ch === ")" || ch === "]") depth--;
742
+ }
743
+ i++;
744
+ }
745
+ return { text, nextIndex: i };
746
+ }
747
+ function extractFnSignature(lines, start) {
748
+ let sig = "";
749
+ let i = start;
750
+ while (i < lines.length) {
751
+ const line = lines[i].trim();
752
+ sig += (sig ? " " : "") + line;
753
+ if (line.includes("{")) {
754
+ sig = sig.replace(/\s*\{[^]*$/, "").trim();
755
+ break;
756
+ }
757
+ i++;
758
+ }
759
+ return sig;
760
+ }
761
+ function skipBlock(lines, start) {
762
+ let depth = 0;
763
+ let i = start;
764
+ let foundBrace = false;
765
+ while (i < lines.length) {
766
+ for (const ch of lines[i]) {
767
+ if (ch === "{") {
768
+ depth++;
769
+ foundBrace = true;
770
+ }
771
+ if (ch === "}") depth--;
772
+ }
773
+ i++;
774
+ if (foundBrace && depth <= 0) break;
775
+ if (!foundBrace && lines[i - 1].includes(";")) break;
776
+ }
777
+ return i;
778
+ }
779
+ function looksLikeFunctionDecl(lines, start) {
780
+ const chunk = lines.slice(start, Math.min(start + 5, lines.length)).join(" ");
781
+ return /=>/.test(chunk) || /=\s*function/.test(chunk);
782
+ }
783
+ function extractClassOutline(lines, start) {
784
+ const header = lines[start].trim();
785
+ let headerText = header;
786
+ let i = start + 1;
787
+ if (!header.includes("{")) {
788
+ while (i < lines.length) {
789
+ headerText += " " + lines[i].trim();
790
+ if (lines[i].includes("{")) {
791
+ i++;
792
+ break;
793
+ }
794
+ i++;
795
+ }
796
+ } else {
797
+ i = start + 1;
798
+ }
799
+ const bodyParts = [headerText.replace(/\{[^]*$/, "{").trim()];
800
+ let depth = 1;
801
+ while (i < lines.length && depth > 0) {
802
+ const line = lines[i];
803
+ const trimmed = line.trim();
804
+ for (const ch of line) {
805
+ if (ch === "{") depth++;
806
+ if (ch === "}") depth--;
807
+ }
808
+ if (depth <= 0) {
809
+ i++;
810
+ break;
811
+ }
812
+ if (depth === 1) {
813
+ if (/^(private|protected|public|readonly|static|#)/.test(trimmed) && !trimmed.includes("(")) {
814
+ bodyParts.push(` ${trimmed}`);
815
+ } else if (/^constructor\s*\(/.test(trimmed)) {
816
+ const sig = extractFnSignature(lines, i);
817
+ bodyParts.push(` ${sig} { /* ... */ }`);
818
+ } else if (/^(?:static\s+)?(?:async\s+)?(?:get\s+|set\s+)?\w+\s*[(<]/.test(trimmed) && !trimmed.startsWith("//")) {
819
+ const sig = extractFnSignature(lines, i);
820
+ bodyParts.push(` ${sig} { /* ... */ }`);
821
+ }
822
+ }
823
+ i++;
824
+ }
825
+ bodyParts.push("}");
826
+ return { text: bodyParts.join("\n"), nextIndex: i };
827
+ }
697
828
  async function pruneGeneric(file, level) {
698
829
  let content;
699
830
  try {
@@ -754,22 +885,6 @@ function emptyResult(file, level) {
754
885
  savingsPercent: 100
755
886
  };
756
887
  }
757
- function addJSDoc(node, parts) {
758
- if (!node.getJsDocs) return;
759
- const docs = node.getJsDocs();
760
- if (docs.length > 0) {
761
- parts.push(docs[0].getText());
762
- }
763
- }
764
- function findTsConfig(filePath) {
765
- let dir = filePath;
766
- for (let i = 0; i < 10; i++) {
767
- dir = join2(dir, "..");
768
- const candidate = join2(dir, "tsconfig.json");
769
- if (existsSync2(candidate)) return candidate;
770
- }
771
- return void 0;
772
- }
773
888
 
774
889
  // src/engine/graph-utils.ts
775
890
  function buildAdjacencyList(edges) {
@@ -1292,8 +1407,8 @@ async function optimizeContext(messages, analysis, config) {
1292
1407
  }
1293
1408
 
1294
1409
  // src/gateway/tracker.ts
1295
- import { mkdirSync as mkdirSync2, appendFileSync, readFileSync as readFileSync3, readdirSync, existsSync as existsSync3 } from "fs";
1296
- import { join as join3 } from "path";
1410
+ import { mkdirSync as mkdirSync2, appendFileSync, readFileSync as readFileSync3, readdirSync, existsSync as existsSync2 } from "fs";
1411
+ import { join as join2 } from "path";
1297
1412
  import { randomUUID } from "crypto";
1298
1413
  var UsageTracker = class {
1299
1414
  logDir;
@@ -1305,7 +1420,7 @@ var UsageTracker = class {
1305
1420
  memRecords = [];
1306
1421
  constructor(config) {
1307
1422
  this.config = config;
1308
- this.logDir = join3(config.logDir, "usage");
1423
+ this.logDir = join2(config.logDir, "usage");
1309
1424
  mkdirSync2(this.logDir, { recursive: true });
1310
1425
  }
1311
1426
  // ===== EVENT SYSTEM =====
@@ -1328,7 +1443,7 @@ var UsageTracker = class {
1328
1443
  ...params
1329
1444
  };
1330
1445
  const monthKey = this.getMonthKey(record.timestamp);
1331
- const logFile = join3(this.logDir, `${monthKey}.jsonl`);
1446
+ const logFile = join2(this.logDir, `${monthKey}.jsonl`);
1332
1447
  const line = JSON.stringify({
1333
1448
  ...record,
1334
1449
  timestamp: record.timestamp.toISOString()
@@ -1462,8 +1577,8 @@ var UsageTracker = class {
1462
1577
  return date.toISOString().slice(0, 7);
1463
1578
  }
1464
1579
  getMonthRecordsByKey(monthKey) {
1465
- const filePath = join3(this.logDir, `${monthKey}.jsonl`);
1466
- if (!existsSync3(filePath)) return [];
1580
+ const filePath = join2(this.logDir, `${monthKey}.jsonl`);
1581
+ if (!existsSync2(filePath)) return [];
1467
1582
  return readFileSync3(filePath, "utf-8").split("\n").filter((line) => line.trim()).map((line) => {
1468
1583
  try {
1469
1584
  const parsed = JSON.parse(line);
@@ -1477,8 +1592,8 @@ var UsageTracker = class {
1477
1592
  getMonthRecords(date) {
1478
1593
  const monthKey = this.getMonthKey(date);
1479
1594
  if (this.cache && this.cacheMonth === monthKey) return this.cache;
1480
- const filePath = join3(this.logDir, `${monthKey}.jsonl`);
1481
- if (!existsSync3(filePath)) return [];
1595
+ const filePath = join2(this.logDir, `${monthKey}.jsonl`);
1596
+ if (!existsSync2(filePath)) return [];
1482
1597
  const records = readFileSync3(filePath, "utf-8").split("\n").filter((line) => line.trim()).map((line) => {
1483
1598
  try {
1484
1599
  const parsed = JSON.parse(line);
@@ -1493,11 +1608,11 @@ var UsageTracker = class {
1493
1608
  return records;
1494
1609
  }
1495
1610
  getAllRecords() {
1496
- if (!existsSync3(this.logDir)) return [];
1611
+ if (!existsSync2(this.logDir)) return [];
1497
1612
  const files = readdirSync(this.logDir).filter((f) => f.endsWith(".jsonl")).sort();
1498
1613
  const allRecords = [];
1499
1614
  for (const file of files) {
1500
- const content = readFileSync3(join3(this.logDir, file), "utf-8");
1615
+ const content = readFileSync3(join2(this.logDir, file), "utf-8");
1501
1616
  const records = content.split("\n").filter((line) => line.trim()).map((line) => {
1502
1617
  try {
1503
1618
  const parsed = JSON.parse(line);
@@ -1515,7 +1630,7 @@ var UsageTracker = class {
1515
1630
 
1516
1631
  // src/engine/analyzer.ts
1517
1632
  import { readFile as readFile4, readdir, stat as stat2 } from "fs/promises";
1518
- import { join as join5, extname, relative as relative3, resolve as resolve4, basename as basename2 } from "path";
1633
+ import { join as join4, extname, relative as relative3, resolve as resolve4, basename as basename2 } from "path";
1519
1634
  import { createHash as createHash3 } from "crypto";
1520
1635
 
1521
1636
  // src/types/engine.ts
@@ -1568,14 +1683,14 @@ var DEFAULT_CONFIG = {
1568
1683
  };
1569
1684
 
1570
1685
  // src/engine/graph.ts
1571
- import { Project as Project2, SyntaxKind as SyntaxKind2 } from "ts-morph";
1572
- import { resolve as resolve3, relative as relative2, dirname as dirname2, join as join4 } from "path";
1573
- import { existsSync as existsSync4 } from "fs";
1686
+ import { Project, SyntaxKind } from "ts-morph";
1687
+ import { resolve as resolve3, relative as relative2, dirname as dirname2, join as join3 } from "path";
1688
+ import { existsSync as existsSync3 } from "fs";
1574
1689
  var TS_EXTENSIONS2 = /* @__PURE__ */ new Set(["ts", "tsx", "js", "jsx", "mts", "mjs", "cts", "cjs"]);
1575
1690
  function createProject(projectPath, filePaths) {
1576
- const tsConfigPath = join4(projectPath, "tsconfig.json");
1577
- const hasTsConfig = existsSync4(tsConfigPath);
1578
- const project = new Project2({
1691
+ const tsConfigPath = join3(projectPath, "tsconfig.json");
1692
+ const hasTsConfig = existsSync3(tsConfigPath);
1693
+ const project = new Project({
1579
1694
  tsConfigFilePath: hasTsConfig ? tsConfigPath : void 0,
1580
1695
  skipAddingFilesFromTsConfig: true,
1581
1696
  compilerOptions: hasTsConfig ? void 0 : {
@@ -1775,7 +1890,7 @@ function enrichComplexity(project, absPath, files) {
1775
1890
  }
1776
1891
  for (const varDecl of sourceFile.getVariableDeclarations()) {
1777
1892
  const init = varDecl.getInitializer();
1778
- if (init && (init.getKind() === SyntaxKind2.ArrowFunction || init.getKind() === SyntaxKind2.FunctionExpression)) {
1893
+ if (init && (init.getKind() === SyntaxKind.ArrowFunction || init.getKind() === SyntaxKind.FunctionExpression)) {
1779
1894
  totalComplexity += calculateCyclomaticComplexity(init);
1780
1895
  }
1781
1896
  }
@@ -1786,22 +1901,22 @@ function calculateCyclomaticComplexity(node) {
1786
1901
  let complexity = 1;
1787
1902
  node.forEachDescendant((descendant) => {
1788
1903
  switch (descendant.getKind()) {
1789
- case SyntaxKind2.IfStatement:
1790
- case SyntaxKind2.ConditionalExpression:
1791
- case SyntaxKind2.ForStatement:
1792
- case SyntaxKind2.ForInStatement:
1793
- case SyntaxKind2.ForOfStatement:
1794
- case SyntaxKind2.WhileStatement:
1795
- case SyntaxKind2.DoStatement:
1796
- case SyntaxKind2.CaseClause:
1797
- case SyntaxKind2.CatchClause:
1904
+ case SyntaxKind.IfStatement:
1905
+ case SyntaxKind.ConditionalExpression:
1906
+ case SyntaxKind.ForStatement:
1907
+ case SyntaxKind.ForInStatement:
1908
+ case SyntaxKind.ForOfStatement:
1909
+ case SyntaxKind.WhileStatement:
1910
+ case SyntaxKind.DoStatement:
1911
+ case SyntaxKind.CaseClause:
1912
+ case SyntaxKind.CatchClause:
1798
1913
  complexity++;
1799
1914
  break;
1800
- case SyntaxKind2.BinaryExpression: {
1915
+ case SyntaxKind.BinaryExpression: {
1801
1916
  const opToken = descendant.getOperatorToken?.();
1802
1917
  if (opToken) {
1803
1918
  const kind = opToken.getKind();
1804
- if (kind === SyntaxKind2.AmpersandAmpersandToken || kind === SyntaxKind2.BarBarToken || kind === SyntaxKind2.QuestionQuestionToken) {
1919
+ if (kind === SyntaxKind.AmpersandAmpersandToken || kind === SyntaxKind.BarBarToken || kind === SyntaxKind.QuestionQuestionToken) {
1805
1920
  complexity++;
1806
1921
  }
1807
1922
  }
@@ -1818,14 +1933,14 @@ function resolveImport(sourceFile, moduleSpecifier, projectRoot) {
1818
1933
  const extensions = [".ts", ".tsx", ".js", ".jsx", "/index.ts", "/index.tsx", "/index.js", "/index.jsx"];
1819
1934
  for (const ext of extensions) {
1820
1935
  const candidate = basePath.endsWith(ext) ? basePath : basePath + ext;
1821
- if (existsSync4(candidate)) {
1936
+ if (existsSync3(candidate)) {
1822
1937
  const rel = relative2(projectRoot, candidate);
1823
1938
  if (!rel.startsWith("..")) return rel;
1824
1939
  }
1825
1940
  }
1826
1941
  if (moduleSpecifier.endsWith(".js")) {
1827
1942
  const tsPath = basePath.replace(/\.js$/, ".ts");
1828
- if (existsSync4(tsPath)) {
1943
+ if (existsSync3(tsPath)) {
1829
1944
  const rel = relative2(projectRoot, tsPath);
1830
1945
  if (!rel.startsWith("..")) return rel;
1831
1946
  }
@@ -1986,7 +2101,7 @@ async function walkProject(rootPath, options) {
1986
2101
  }
1987
2102
  const promises = [];
1988
2103
  for (const entry of entries) {
1989
- const fullPath = join5(dir, entry.name);
2104
+ const fullPath = join4(dir, entry.name);
1990
2105
  if (entry.isDirectory()) {
1991
2106
  if (!ignoreDirSet.has(entry.name) && !entry.name.startsWith(".")) {
1992
2107
  promises.push(walk(fullPath, depth + 1));