@vibgrate/cli 1.0.78 → 1.0.79

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 (2) hide show
  1. package/dist/cli.js +152 -17
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -588,7 +588,8 @@ var NODE_WORKER_ALL_LANGS = /* @__PURE__ */ new Set([
588
588
  ...NODE_WORKER_AST_LANGS,
589
589
  ...NODE_WORKER_TEXT_LANGS
590
590
  ]);
591
- var EXTERNAL_WORKER_LANGS = /* @__PURE__ */ new Set(["go", "python", "java", "csharp"]);
591
+ var NATIVE_AST_LANGS = /* @__PURE__ */ new Set(["go", "python", "java", "csharp"]);
592
+ var ALL_WORKER_LANGS = /* @__PURE__ */ new Set([...NODE_WORKER_ALL_LANGS, ...NATIVE_AST_LANGS]);
592
593
  async function runNodeWorker(rootDir, language, opts) {
593
594
  const workerBin = resolveHcsWorkerBin();
594
595
  const args = [];
@@ -665,6 +666,145 @@ async function runNodeWorker(rootDir, language, opts) {
665
666
  });
666
667
  });
667
668
  }
669
+ function resolveNativeWorker(language, projectDir) {
670
+ const base = import.meta.dirname ?? path6.dirname(new URL(import.meta.url).pathname);
671
+ const hcsFromBundle = path6.resolve(base, "..", "..", "vibgrate-hcs");
672
+ const hcsFromSrc = path6.resolve(base, "..", "..", "..", "vibgrate-hcs");
673
+ const hcsRoot = existsSync(hcsFromBundle) ? hcsFromBundle : hcsFromSrc;
674
+ const workersDir = path6.resolve(base, "workers");
675
+ switch (language) {
676
+ case "go": {
677
+ const bin = path6.join(workersDir, process.platform === "win32" ? "vibgrate-hcs-go.exe" : "vibgrate-hcs-go");
678
+ if (existsSync(bin)) {
679
+ return { cmd: bin, args: ["--project", projectDir, "--output", "ndjson"] };
680
+ }
681
+ const src = path6.join(hcsRoot, "go");
682
+ if (existsSync(path6.join(src, "main.go"))) {
683
+ return { cmd: "go", args: ["run", ".", "--project", projectDir, "--output", "ndjson"], cwd: src };
684
+ }
685
+ return null;
686
+ }
687
+ case "python": {
688
+ const bin = path6.join(workersDir, "vibgrate-hcs-python");
689
+ if (existsSync(bin)) {
690
+ return { cmd: bin, args: ["--project", projectDir, "--output", "ndjson"] };
691
+ }
692
+ const src = path6.join(hcsRoot, "python");
693
+ if (existsSync(path6.join(src, "pyproject.toml"))) {
694
+ return {
695
+ cmd: "python3",
696
+ args: ["-m", "vibgrate_hcs_python.main", "--project", projectDir, "--output", "ndjson"],
697
+ cwd: src
698
+ };
699
+ }
700
+ return null;
701
+ }
702
+ case "java": {
703
+ const jar = path6.join(workersDir, "vibgrate-hcs-jvm.jar");
704
+ if (existsSync(jar)) {
705
+ return { cmd: "java", args: ["-jar", jar, "--project", projectDir, "--output", "ndjson"] };
706
+ }
707
+ const src = path6.join(hcsRoot, "jvm");
708
+ if (existsSync(path6.join(src, "build.gradle.kts"))) {
709
+ const gradlew = path6.join(src, process.platform === "win32" ? "gradlew.bat" : "gradlew");
710
+ const launcher = existsSync(gradlew) ? gradlew : "gradle";
711
+ return {
712
+ cmd: launcher,
713
+ args: ["-q", "--console=plain", "run", `--args=--project ${projectDir} --output ndjson`],
714
+ cwd: src
715
+ };
716
+ }
717
+ return null;
718
+ }
719
+ case "csharp": {
720
+ const dll = path6.join(workersDir, "VibgrateHcsWorker.dll");
721
+ if (existsSync(dll)) {
722
+ return { cmd: "dotnet", args: [dll, "--project", projectDir, "--output", "ndjson"] };
723
+ }
724
+ const csproj = path6.join(hcsRoot, "dotnet", "src", "VibgrateHcsWorker", "VibgrateHcsWorker.csproj");
725
+ if (existsSync(csproj)) {
726
+ return {
727
+ cmd: "dotnet",
728
+ args: ["run", "--project", csproj, "--", "--project", projectDir, "--output", "ndjson"]
729
+ };
730
+ }
731
+ return null;
732
+ }
733
+ default:
734
+ return null;
735
+ }
736
+ }
737
+ async function runNativeWorker(rootDir, language, opts) {
738
+ const spec = resolveNativeWorker(language, rootDir);
739
+ if (!spec) {
740
+ return {
741
+ language,
742
+ facts: [],
743
+ errors: [
744
+ `[error] No native worker found for '${language}'. Install the toolchain (${language === "go" ? "Go" : language === "python" ? "Python 3" : language === "java" ? "Java 17+" : "dotnet SDK"}) or build the worker binary.`
745
+ ],
746
+ exitCode: EXIT_PARSE_FAILURE
747
+ };
748
+ }
749
+ return new Promise((resolve6) => {
750
+ const facts = [];
751
+ const errors = [];
752
+ let stdoutBuf = "";
753
+ let killed = false;
754
+ if (opts.verbose) {
755
+ process.stderr.write(chalk5.dim(`[${language}] Spawning: ${spec.cmd} ${spec.args.join(" ")}
756
+ `));
757
+ }
758
+ const child = spawn(spec.cmd, spec.args, {
759
+ cwd: spec.cwd ?? rootDir,
760
+ stdio: ["ignore", "pipe", "pipe"]
761
+ });
762
+ const timer = setTimeout(() => {
763
+ killed = true;
764
+ child.kill("SIGKILL");
765
+ }, opts.timeoutMs);
766
+ child.stdout.on("data", (chunk) => {
767
+ stdoutBuf += chunk.toString();
768
+ const lines = stdoutBuf.split("\n");
769
+ stdoutBuf = lines.pop();
770
+ for (const line of lines) {
771
+ const trimmed = line.trim();
772
+ if (trimmed) facts.push(trimmed);
773
+ }
774
+ });
775
+ child.stderr.on("data", (chunk) => {
776
+ const text = chunk.toString();
777
+ for (const line of text.split("\n")) {
778
+ const trimmed = line.trim();
779
+ if (!trimmed) continue;
780
+ if (opts.verbose) {
781
+ process.stderr.write(chalk5.dim(`[${language}] ${trimmed}
782
+ `));
783
+ }
784
+ if (trimmed.startsWith("[error]")) {
785
+ errors.push(trimmed);
786
+ }
787
+ }
788
+ });
789
+ child.on("close", (code) => {
790
+ clearTimeout(timer);
791
+ if (stdoutBuf.trim()) facts.push(stdoutBuf.trim());
792
+ if (killed) {
793
+ resolve6({ language, facts, errors: ["Worker killed: timeout exceeded"], exitCode: EXIT_TIMEOUT });
794
+ } else {
795
+ resolve6({ language, facts, errors, exitCode: code ?? 0 });
796
+ }
797
+ });
798
+ child.on("error", (err) => {
799
+ clearTimeout(timer);
800
+ const isNotFound = err.code === "ENOENT";
801
+ errors.push(
802
+ isNotFound ? `[error] '${spec.cmd}' not found. Is the required toolchain installed and on PATH?` : `[error] Failed to spawn native worker: ${err.message}`
803
+ );
804
+ resolve6({ language, facts, errors, exitCode: EXIT_PARSE_FAILURE });
805
+ });
806
+ });
807
+ }
668
808
  async function pushFacts(facts, dsn, verbose) {
669
809
  const parsed = parseDsn(dsn);
670
810
  if (!parsed) {
@@ -897,25 +1037,16 @@ var extractCommand = new Command5("extract").description("Analyze source code an
897
1037
  }
898
1038
  }
899
1039
  }
900
- const runnableLanguages = targetLanguages.filter((l) => NODE_WORKER_ALL_LANGS.has(l));
901
- const skippedLanguages = targetLanguages.filter((l) => EXTERNAL_WORKER_LANGS.has(l));
902
- const unknownWorkerLangs = targetLanguages.filter(
903
- (l) => !NODE_WORKER_ALL_LANGS.has(l) && !EXTERNAL_WORKER_LANGS.has(l)
904
- );
905
- if (skippedLanguages.length > 0 && opts.verbose) {
906
- process.stderr.write(chalk5.yellow(
907
- `Skipping languages without built-in HCS worker: ${skippedLanguages.join(", ")}
908
- ` + chalk5.dim("These require dedicated external workers.\n")
1040
+ const runnableLanguages = targetLanguages.filter((l) => ALL_WORKER_LANGS.has(l));
1041
+ const unknownWorkerLangs = targetLanguages.filter((l) => !ALL_WORKER_LANGS.has(l));
1042
+ if (unknownWorkerLangs.length > 0 && opts.verbose) {
1043
+ process.stderr.write(chalk5.dim(
1044
+ `No worker registered for: ${unknownWorkerLangs.join(", ")} \u2014 skipping.
1045
+ `
909
1046
  ));
910
1047
  }
911
1048
  if (runnableLanguages.length === 0) {
912
1049
  process.stderr.write(chalk5.yellow("No languages with available HCS workers found.\n"));
913
- if (skippedLanguages.length > 0) {
914
- process.stderr.write(chalk5.dim(
915
- `Detected: ${skippedLanguages.join(", ")} \u2014 these require external workers not yet integrated.
916
- `
917
- ));
918
- }
919
1050
  process.exit(EXIT_SUCCESS);
920
1051
  }
921
1052
  const startTime = Date.now();
@@ -939,11 +1070,15 @@ var extractCommand = new Command5("extract").description("Analyze source code an
939
1070
  hasTimeout = true;
940
1071
  return;
941
1072
  }
942
- const result = await runNodeWorker(rootDir, language, {
1073
+ const result = NODE_WORKER_ALL_LANGS.has(language) ? await runNodeWorker(rootDir, language, {
943
1074
  includeTests: opts.includeTests ?? false,
944
1075
  verbose: opts.verbose ?? false,
945
1076
  timeoutMs: remaining,
946
1077
  onProgress: (event) => progress.onProgress(language, event)
1078
+ }) : await runNativeWorker(rootDir, language, {
1079
+ verbose: opts.verbose ?? false,
1080
+ timeoutMs: remaining,
1081
+ onProgress: (event) => progress.onProgress(language, event)
947
1082
  });
948
1083
  if (result.exitCode === EXIT_TIMEOUT) {
949
1084
  hasTimeout = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibgrate/cli",
3
- "version": "1.0.78",
3
+ "version": "1.0.79",
4
4
  "description": "CLI for measuring upgrade drift across Node, .NET, Python & Java projects",
5
5
  "type": "module",
6
6
  "bin": {