@vibgrate/cli 1.0.79 → 1.0.81
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/DOCS.md +14 -3
- package/HCS-EXTRACT.md +442 -0
- package/HCS-RUNTIME-SETUP.md +73 -0
- package/LICENSE.md +1 -1
- package/README.md +1 -1
- package/dist/{baseline-NRKROYVK.js → baseline-5AZAIOQ6.js} +2 -2
- package/dist/{chunk-DKSPLRJV.js → chunk-DEPG5EIH.js} +1 -1
- package/dist/{chunk-TKNDQ337.js → chunk-W6TXQI4D.js} +27 -22
- package/dist/cli.js +170 -16
- package/dist/hcs-worker.js +562 -25
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/package.json +4 -2
|
@@ -2,7 +2,6 @@ import {
|
|
|
2
2
|
FileCache,
|
|
3
3
|
Semaphore,
|
|
4
4
|
ensureDir,
|
|
5
|
-
findCsprojFiles,
|
|
6
5
|
findFiles,
|
|
7
6
|
findPackageJsonFiles,
|
|
8
7
|
findSolutionFiles,
|
|
@@ -578,7 +577,7 @@ function formatArchitectureDiagram(arch) {
|
|
|
578
577
|
lines.push("");
|
|
579
578
|
if (arch.layers.length > 0) {
|
|
580
579
|
for (const layer of arch.layers) {
|
|
581
|
-
const risk = layer.riskLevel === "low" ? chalk.green("low") : layer.riskLevel === "moderate" ? chalk.yellow("moderate") : chalk.red("high");
|
|
580
|
+
const risk = layer.riskLevel === "none" ? chalk.dim("none") : layer.riskLevel === "low" ? chalk.green("low") : layer.riskLevel === "moderate" ? chalk.yellow("moderate") : chalk.red("high");
|
|
582
581
|
lines.push(` ${chalk.bold(layer.layer)} ${layer.fileCount} file${layer.fileCount !== 1 ? "s" : ""} drift ${scoreBar(layer.driftScore)} risk ${risk}`);
|
|
583
582
|
}
|
|
584
583
|
lines.push("");
|
|
@@ -2344,11 +2343,17 @@ function parseTfmMajor(tfm) {
|
|
|
2344
2343
|
if (fxMatch) return null;
|
|
2345
2344
|
return null;
|
|
2346
2345
|
}
|
|
2347
|
-
function
|
|
2346
|
+
function isDotnetProjectFile(name) {
|
|
2347
|
+
return name.endsWith(".csproj") || name.endsWith(".vbproj");
|
|
2348
|
+
}
|
|
2349
|
+
function stripDotnetProjectExtension(filePath) {
|
|
2350
|
+
return path5.basename(filePath).replace(/\.(cs|vb)proj$/i, "");
|
|
2351
|
+
}
|
|
2352
|
+
function parseDotnetProjectFile(xml, filePath) {
|
|
2348
2353
|
const parsed = parser.parse(xml);
|
|
2349
2354
|
const project = parsed?.Project;
|
|
2350
2355
|
if (!project) {
|
|
2351
|
-
return { targetFrameworks: [], packageReferences: [], projectReferences: [], projectName:
|
|
2356
|
+
return { targetFrameworks: [], packageReferences: [], projectReferences: [], projectName: stripDotnetProjectExtension(filePath) };
|
|
2352
2357
|
}
|
|
2353
2358
|
const propertyGroups = Array.isArray(project.PropertyGroup) ? project.PropertyGroup : project.PropertyGroup ? [project.PropertyGroup] : [];
|
|
2354
2359
|
const targetFrameworks = [];
|
|
@@ -2385,34 +2390,34 @@ function parseCsproj(xml, filePath) {
|
|
|
2385
2390
|
targetFrameworks: [...new Set(targetFrameworks)],
|
|
2386
2391
|
packageReferences,
|
|
2387
2392
|
projectReferences,
|
|
2388
|
-
projectName:
|
|
2393
|
+
projectName: stripDotnetProjectExtension(filePath)
|
|
2389
2394
|
};
|
|
2390
2395
|
}
|
|
2391
2396
|
async function scanDotnetProjects(rootDir, nugetCache, cache, projectScanTimeout) {
|
|
2392
|
-
const
|
|
2397
|
+
const projectFiles = cache ? await cache.findFiles(rootDir, isDotnetProjectFile) : await findFiles(rootDir, isDotnetProjectFile);
|
|
2393
2398
|
const slnFiles = cache ? await cache.findSolutionFiles(rootDir) : await findSolutionFiles(rootDir);
|
|
2394
|
-
const
|
|
2399
|
+
const slnProjectPaths = /* @__PURE__ */ new Set();
|
|
2395
2400
|
for (const slnPath of slnFiles) {
|
|
2396
2401
|
try {
|
|
2397
2402
|
const slnContent = cache ? await cache.readTextFile(slnPath) : await readTextFile(slnPath);
|
|
2398
2403
|
const slnDir = path5.dirname(slnPath);
|
|
2399
|
-
const projectRegex = /Project\("[^"]*"\)\s*=\s*"[^"]*",\s*"([^"]+\.
|
|
2404
|
+
const projectRegex = /Project\("[^"]*"\)\s*=\s*"[^"]*",\s*"([^"]+\.(?:cs|vb)proj)"/g;
|
|
2400
2405
|
let match;
|
|
2401
2406
|
while ((match = projectRegex.exec(slnContent)) !== null) {
|
|
2402
2407
|
if (match[1]) {
|
|
2403
2408
|
const csprojPath = path5.resolve(slnDir, match[1].replace(/\\/g, "/"));
|
|
2404
|
-
|
|
2409
|
+
slnProjectPaths.add(csprojPath);
|
|
2405
2410
|
}
|
|
2406
2411
|
}
|
|
2407
2412
|
} catch {
|
|
2408
2413
|
}
|
|
2409
2414
|
}
|
|
2410
|
-
const allCsprojFiles = /* @__PURE__ */ new Set([...
|
|
2415
|
+
const allCsprojFiles = /* @__PURE__ */ new Set([...projectFiles, ...slnProjectPaths]);
|
|
2411
2416
|
const results = [];
|
|
2412
2417
|
const STUCK_TIMEOUT_MS = projectScanTimeout ?? cache?.projectScanTimeout ?? 18e4;
|
|
2413
2418
|
for (const csprojPath of allCsprojFiles) {
|
|
2414
2419
|
try {
|
|
2415
|
-
const scanPromise =
|
|
2420
|
+
const scanPromise = scanOneDotnetProjectFile(csprojPath, rootDir, nugetCache, cache);
|
|
2416
2421
|
const result = await withTimeout(scanPromise, STUCK_TIMEOUT_MS);
|
|
2417
2422
|
if (result.ok) {
|
|
2418
2423
|
results.push(result.value);
|
|
@@ -2433,9 +2438,9 @@ async function scanDotnetProjects(rootDir, nugetCache, cache, projectScanTimeout
|
|
|
2433
2438
|
}
|
|
2434
2439
|
return results;
|
|
2435
2440
|
}
|
|
2436
|
-
async function
|
|
2441
|
+
async function scanOneDotnetProjectFile(csprojPath, rootDir, nugetCache, cache) {
|
|
2437
2442
|
const xml = cache ? await cache.readTextFile(csprojPath) : await readTextFile(csprojPath);
|
|
2438
|
-
const data =
|
|
2443
|
+
const data = parseDotnetProjectFile(xml, csprojPath);
|
|
2439
2444
|
const csprojDir = path5.dirname(csprojPath);
|
|
2440
2445
|
const primaryTfm = data.targetFrameworks[0];
|
|
2441
2446
|
let runtimeMajorsBehind;
|
|
@@ -2516,7 +2521,7 @@ async function scanOneCsproj(csprojPath, rootDir, nugetCache, cache) {
|
|
|
2516
2521
|
const projectReferences = data.projectReferences.map((refPath) => {
|
|
2517
2522
|
const absRefPath = path5.resolve(csprojDir, refPath);
|
|
2518
2523
|
const relRefPath = normalizePath(path5.relative(rootDir, path5.dirname(absRefPath)));
|
|
2519
|
-
const refName =
|
|
2524
|
+
const refName = stripDotnetProjectExtension(absRefPath);
|
|
2520
2525
|
return {
|
|
2521
2526
|
path: relRefPath || ".",
|
|
2522
2527
|
name: refName,
|
|
@@ -7425,6 +7430,10 @@ var ScanProgress = class {
|
|
|
7425
7430
|
lines.push(` ${ROBOT[2]}`);
|
|
7426
7431
|
lines.push(` ${ROBOT[3]} ${chalk4.dim(this.rootDir)}`);
|
|
7427
7432
|
lines.push("");
|
|
7433
|
+
for (const step of this.steps) {
|
|
7434
|
+
lines.push(this.renderStep(step));
|
|
7435
|
+
}
|
|
7436
|
+
lines.push("");
|
|
7428
7437
|
const totalWeight = this.steps.reduce((sum, s) => sum + (s.weight ?? 1), 0);
|
|
7429
7438
|
let completedWeight = 0;
|
|
7430
7439
|
for (const step of this.steps) {
|
|
@@ -7452,10 +7461,6 @@ var ScanProgress = class {
|
|
|
7452
7461
|
const treePart = this.stats.treeSummary ? chalk4.dim(` \xB7 ${this.stats.treeSummary.totalFiles.toLocaleString()} files \xB7 ${this.stats.treeSummary.totalDirs.toLocaleString()} dirs`) : "";
|
|
7453
7462
|
lines.push(` ${bar} ${chalk4.bold.white(`${pct}%`)} ${chalk4.dim(elapsedStr)}${etaStr}${treePart}`);
|
|
7454
7463
|
lines.push("");
|
|
7455
|
-
for (const step of this.steps) {
|
|
7456
|
-
lines.push(this.renderStep(step));
|
|
7457
|
-
}
|
|
7458
|
-
lines.push("");
|
|
7459
7464
|
lines.push(this.renderStats());
|
|
7460
7465
|
lines.push("");
|
|
7461
7466
|
const content = lines.join("\n") + "\n";
|
|
@@ -7918,7 +7923,7 @@ async function scanPlatformMatrix(rootDir, cache) {
|
|
|
7918
7923
|
}
|
|
7919
7924
|
result.nativeModules.sort();
|
|
7920
7925
|
result.osAssumptions = [...osAssumptions].sort();
|
|
7921
|
-
const csprojFiles = cache ? await cache.
|
|
7926
|
+
const csprojFiles = cache ? await cache.findFiles(rootDir, (name) => name.endsWith(".csproj") || name.endsWith(".vbproj")) : await findFiles(rootDir, (name) => name.endsWith(".csproj") || name.endsWith(".vbproj"));
|
|
7922
7927
|
const tfms = /* @__PURE__ */ new Set();
|
|
7923
7928
|
for (const csprojPath of csprojFiles) {
|
|
7924
7929
|
try {
|
|
@@ -10018,7 +10023,7 @@ function classifyFile(filePath, archetype) {
|
|
|
10018
10023
|
}
|
|
10019
10024
|
function computeLayerDrift(packages) {
|
|
10020
10025
|
if (packages.length === 0) {
|
|
10021
|
-
return { score:
|
|
10026
|
+
return { score: 0, riskLevel: "none" };
|
|
10022
10027
|
}
|
|
10023
10028
|
let current = 0;
|
|
10024
10029
|
let oneBehind = 0;
|
|
@@ -10036,7 +10041,7 @@ function computeLayerDrift(packages) {
|
|
|
10036
10041
|
}
|
|
10037
10042
|
}
|
|
10038
10043
|
const known = current + oneBehind + twoPlusBehind;
|
|
10039
|
-
if (known === 0) return { score:
|
|
10044
|
+
if (known === 0) return { score: 0, riskLevel: "none" };
|
|
10040
10045
|
const currentPct = current / known;
|
|
10041
10046
|
const onePct = oneBehind / known;
|
|
10042
10047
|
const twoPct = twoPlusBehind / known;
|
|
@@ -11702,7 +11707,7 @@ async function discoverSolutions(rootDir, fileCache) {
|
|
|
11702
11707
|
const rootBasename = path32.basename(rootDir);
|
|
11703
11708
|
const relSolutionPath = [rootBasename, path32.relative(rootDir, solutionFile).replace(/\\/g, "/")].join("/");
|
|
11704
11709
|
const projectPaths = /* @__PURE__ */ new Set();
|
|
11705
|
-
const projectRegex = /Project\("[^"]*"\)\s*=\s*"([^"]*)",\s*"([^"]+\.
|
|
11710
|
+
const projectRegex = /Project\("[^"]*"\)\s*=\s*"([^"]*)",\s*"([^"]+\.(?:cs|vb)proj)"/g;
|
|
11706
11711
|
let match;
|
|
11707
11712
|
while ((match = projectRegex.exec(content)) !== null) {
|
|
11708
11713
|
const projectRelative = match[2];
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
baselineCommand
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-DEPG5EIH.js";
|
|
5
5
|
import {
|
|
6
6
|
VERSION,
|
|
7
7
|
computeHmac,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
pushCommand,
|
|
13
13
|
scanCommand,
|
|
14
14
|
writeDefaultConfig
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-W6TXQI4D.js";
|
|
16
16
|
import {
|
|
17
17
|
Semaphore,
|
|
18
18
|
ensureDir,
|
|
@@ -42,7 +42,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
|
|
|
42
42
|
console.log(chalk.green("\u2714") + ` Created ${chalk.bold("vibgrate.config.ts")}`);
|
|
43
43
|
}
|
|
44
44
|
if (opts.baseline) {
|
|
45
|
-
const { runBaseline } = await import("./baseline-
|
|
45
|
+
const { runBaseline } = await import("./baseline-5AZAIOQ6.js");
|
|
46
46
|
await runBaseline(rootDir);
|
|
47
47
|
}
|
|
48
48
|
console.log("");
|
|
@@ -172,6 +172,32 @@ async function writeCache(data) {
|
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
// src/commands/update.ts
|
|
175
|
+
function detectGlobalInstall() {
|
|
176
|
+
const execPath = process.argv[1] || "";
|
|
177
|
+
if (execPath.includes("/lib/node_modules/") || execPath.includes("\\node_modules\\")) {
|
|
178
|
+
if (!execPath.includes(process.cwd())) {
|
|
179
|
+
if (execPath.includes("pnpm")) return "pnpm";
|
|
180
|
+
if (execPath.includes("yarn")) return "yarn";
|
|
181
|
+
if (execPath.includes("bun")) return "bun";
|
|
182
|
+
return "npm";
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
function getGlobalUpdateCommand(pm, pkg, version) {
|
|
188
|
+
const spec = `${pkg}@${version}`;
|
|
189
|
+
switch (pm) {
|
|
190
|
+
case "pnpm":
|
|
191
|
+
return `pnpm add -g ${spec}`;
|
|
192
|
+
case "yarn":
|
|
193
|
+
return `yarn global add ${spec}`;
|
|
194
|
+
case "bun":
|
|
195
|
+
return `bun add -g ${spec}`;
|
|
196
|
+
case "npm":
|
|
197
|
+
default:
|
|
198
|
+
return `npm install -g ${spec}`;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
175
201
|
async function detectPackageManager(cwd) {
|
|
176
202
|
if (await pathExists(path4.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
177
203
|
if (await pathExists(path4.join(cwd, "bun.lockb"))) return "bun";
|
|
@@ -202,7 +228,7 @@ async function isDevDependency(cwd) {
|
|
|
202
228
|
return true;
|
|
203
229
|
}
|
|
204
230
|
}
|
|
205
|
-
var updateCommand = new Command3("update").description("Update vibgrate to the latest version").option("--check", "Only check for updates, do not install").option("--pm <manager>", "Package manager to use (npm, pnpm, yarn, bun)").action(async (opts) => {
|
|
231
|
+
var updateCommand = new Command3("update").description("Update vibgrate to the latest version").option("--check", "Only check for updates, do not install").option("--pm <manager>", "Package manager to use (npm, pnpm, yarn, bun)").option("--global", "Update global installation").action(async (opts) => {
|
|
206
232
|
console.log(chalk3.dim(`Current version: ${VERSION}`));
|
|
207
233
|
console.log(chalk3.dim("Checking npm registry..."));
|
|
208
234
|
const latest = await fetchLatestVersion();
|
|
@@ -221,10 +247,18 @@ var updateCommand = new Command3("update").description("Update vibgrate to the l
|
|
|
221
247
|
return;
|
|
222
248
|
}
|
|
223
249
|
const cwd = process.cwd();
|
|
224
|
-
const
|
|
225
|
-
const
|
|
226
|
-
const
|
|
227
|
-
|
|
250
|
+
const globalPm = detectGlobalInstall();
|
|
251
|
+
const isGlobal = opts.global || globalPm !== null;
|
|
252
|
+
const pm = opts.pm || (globalPm ?? await detectPackageManager(cwd));
|
|
253
|
+
let cmd;
|
|
254
|
+
if (isGlobal) {
|
|
255
|
+
cmd = getGlobalUpdateCommand(pm, "@vibgrate/cli", latest);
|
|
256
|
+
console.log(chalk3.dim(`Updating global installation with ${pm}: ${cmd}`));
|
|
257
|
+
} else {
|
|
258
|
+
const isDev = await isDevDependency(cwd);
|
|
259
|
+
cmd = getInstallCommand(pm, "@vibgrate/cli", latest, isDev);
|
|
260
|
+
console.log(chalk3.dim(`Using ${pm}: ${cmd}`));
|
|
261
|
+
}
|
|
228
262
|
try {
|
|
229
263
|
execSync(cmd, { cwd, stdio: "inherit" });
|
|
230
264
|
console.log(chalk3.green("\u2714") + ` Updated to @vibgrate/cli@${latest}`);
|
|
@@ -417,7 +451,7 @@ import * as path6 from "path";
|
|
|
417
451
|
import * as os2 from "os";
|
|
418
452
|
import * as fs2 from "fs/promises";
|
|
419
453
|
import { existsSync } from "fs";
|
|
420
|
-
import { spawn } from "child_process";
|
|
454
|
+
import { spawn, spawnSync } from "child_process";
|
|
421
455
|
import { Command as Command5 } from "commander";
|
|
422
456
|
import chalk5 from "chalk";
|
|
423
457
|
var EXIT_SUCCESS = 0;
|
|
@@ -440,7 +474,9 @@ var LANGUAGE_EXTENSIONS = {
|
|
|
440
474
|
go: /* @__PURE__ */ new Set([".go"]),
|
|
441
475
|
python: /* @__PURE__ */ new Set([".py"]),
|
|
442
476
|
java: /* @__PURE__ */ new Set([".java"]),
|
|
443
|
-
csharp: /* @__PURE__ */ new Set([".cs"])
|
|
477
|
+
csharp: /* @__PURE__ */ new Set([".cs"]),
|
|
478
|
+
cplusplus: /* @__PURE__ */ new Set([".cpp", ".cc", ".cxx", ".hpp", ".hh", ".hxx", ".h", ".ixx", ".vcxproj"]),
|
|
479
|
+
vbnet: /* @__PURE__ */ new Set([".vb"])
|
|
444
480
|
};
|
|
445
481
|
var SUPPORTED_LANGUAGES = new Set(Object.keys(LANGUAGE_EXTENSIONS));
|
|
446
482
|
var SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
@@ -489,6 +525,13 @@ var TEST_PATTERNS = [
|
|
|
489
525
|
function isTestPath(relPath) {
|
|
490
526
|
return TEST_PATTERNS.some((p) => p.test(relPath));
|
|
491
527
|
}
|
|
528
|
+
function normalizeLanguageToken(language) {
|
|
529
|
+
const normalized = language.trim().toLowerCase();
|
|
530
|
+
if (normalized === "vb.net" || normalized === "visualbasic" || normalized === "visual-basic") {
|
|
531
|
+
return "vbnet";
|
|
532
|
+
}
|
|
533
|
+
return normalized;
|
|
534
|
+
}
|
|
492
535
|
async function detectLanguages(rootDir, includeTests) {
|
|
493
536
|
const counts = /* @__PURE__ */ new Map();
|
|
494
537
|
async function walk(dir, relBase) {
|
|
@@ -582,14 +625,81 @@ var NODE_WORKER_TEXT_LANGS = /* @__PURE__ */ new Set([
|
|
|
582
625
|
"php",
|
|
583
626
|
"dart",
|
|
584
627
|
"scala",
|
|
585
|
-
"cobol"
|
|
628
|
+
"cobol",
|
|
629
|
+
"cplusplus"
|
|
586
630
|
]);
|
|
587
631
|
var NODE_WORKER_ALL_LANGS = /* @__PURE__ */ new Set([
|
|
588
632
|
...NODE_WORKER_AST_LANGS,
|
|
589
633
|
...NODE_WORKER_TEXT_LANGS
|
|
590
634
|
]);
|
|
591
|
-
var NATIVE_AST_LANGS = /* @__PURE__ */ new Set(["go", "python", "java", "csharp"]);
|
|
635
|
+
var NATIVE_AST_LANGS = /* @__PURE__ */ new Set(["go", "python", "java", "csharp", "vbnet"]);
|
|
592
636
|
var ALL_WORKER_LANGS = /* @__PURE__ */ new Set([...NODE_WORKER_ALL_LANGS, ...NATIVE_AST_LANGS]);
|
|
637
|
+
var NATIVE_RUNTIME_REQUIREMENTS = {
|
|
638
|
+
go: {
|
|
639
|
+
command: "go",
|
|
640
|
+
displayName: "Go toolchain",
|
|
641
|
+
installGuideByPlatform: {
|
|
642
|
+
darwin: "brew install go",
|
|
643
|
+
linux: "Install Go 1.22+ from https://go.dev/dl/ or your distro package manager.",
|
|
644
|
+
win32: "winget install GoLang.Go"
|
|
645
|
+
},
|
|
646
|
+
docsUrl: "https://go.dev/doc/install"
|
|
647
|
+
},
|
|
648
|
+
python: {
|
|
649
|
+
command: "python3",
|
|
650
|
+
displayName: "Python 3 runtime",
|
|
651
|
+
installGuideByPlatform: {
|
|
652
|
+
darwin: "brew install python",
|
|
653
|
+
linux: "Install Python 3.10+ from your distro package manager (apt/dnf/pacman).",
|
|
654
|
+
win32: "winget install Python.Python.3.12"
|
|
655
|
+
},
|
|
656
|
+
docsUrl: "https://www.python.org/downloads/"
|
|
657
|
+
},
|
|
658
|
+
java: {
|
|
659
|
+
command: "java",
|
|
660
|
+
displayName: "Java 17+ runtime",
|
|
661
|
+
installGuideByPlatform: {
|
|
662
|
+
darwin: "brew install --cask temurin",
|
|
663
|
+
linux: "Install OpenJDK 17+ (for example: apt install openjdk-17-jre).",
|
|
664
|
+
win32: "winget install EclipseAdoptium.Temurin.17.JRE"
|
|
665
|
+
},
|
|
666
|
+
docsUrl: "https://adoptium.net/"
|
|
667
|
+
},
|
|
668
|
+
csharp: {
|
|
669
|
+
command: "dotnet",
|
|
670
|
+
displayName: ".NET SDK/runtime",
|
|
671
|
+
installGuideByPlatform: {
|
|
672
|
+
darwin: "brew install --cask dotnet-sdk",
|
|
673
|
+
linux: "Install .NET 8 SDK/runtime from https://dotnet.microsoft.com/download.",
|
|
674
|
+
win32: "winget install Microsoft.DotNet.SDK.8"
|
|
675
|
+
},
|
|
676
|
+
docsUrl: "https://dotnet.microsoft.com/download"
|
|
677
|
+
},
|
|
678
|
+
vbnet: {
|
|
679
|
+
command: "dotnet",
|
|
680
|
+
displayName: ".NET SDK/runtime",
|
|
681
|
+
installGuideByPlatform: {
|
|
682
|
+
darwin: "brew install --cask dotnet-sdk",
|
|
683
|
+
linux: "Install .NET 8 SDK/runtime from https://dotnet.microsoft.com/download.",
|
|
684
|
+
win32: "winget install Microsoft.DotNet.SDK.8"
|
|
685
|
+
},
|
|
686
|
+
docsUrl: "https://dotnet.microsoft.com/download"
|
|
687
|
+
}
|
|
688
|
+
};
|
|
689
|
+
function commandExistsOnPath(command) {
|
|
690
|
+
const probeArgs = process.platform === "win32" ? ["/c", command, "--version"] : ["--version"];
|
|
691
|
+
const probeCmd = process.platform === "win32" ? "cmd" : command;
|
|
692
|
+
const result = spawnSync(probeCmd, probeArgs, { stdio: "ignore" });
|
|
693
|
+
return !result.error && result.status === 0;
|
|
694
|
+
}
|
|
695
|
+
function buildNativeInstallHint(language) {
|
|
696
|
+
const req = NATIVE_RUNTIME_REQUIREMENTS[language];
|
|
697
|
+
if (!req) {
|
|
698
|
+
return "See HCS runtime setup docs for prerequisites: https://vibgrate.com/help";
|
|
699
|
+
}
|
|
700
|
+
const platformHint = req.installGuideByPlatform[process.platform] ?? `Install ${req.displayName} and ensure '${req.command}' is available on PATH.`;
|
|
701
|
+
return `${platformHint} More details: ${req.docsUrl}`;
|
|
702
|
+
}
|
|
593
703
|
async function runNodeWorker(rootDir, language, opts) {
|
|
594
704
|
const workerBin = resolveHcsWorkerBin();
|
|
595
705
|
const args = [];
|
|
@@ -666,6 +776,29 @@ async function runNodeWorker(rootDir, language, opts) {
|
|
|
666
776
|
});
|
|
667
777
|
});
|
|
668
778
|
}
|
|
779
|
+
function resolveDotnetPublishedWorker(workersDir) {
|
|
780
|
+
const candidatesByPlatform = {
|
|
781
|
+
win32: ["hcs-worker-win-x64.exe"],
|
|
782
|
+
linux: ["hcs-worker-linux-x64"],
|
|
783
|
+
darwin: ["hcs-worker-osx-arm64", "hcs-worker-osx-x64"],
|
|
784
|
+
aix: [],
|
|
785
|
+
android: [],
|
|
786
|
+
freebsd: [],
|
|
787
|
+
haiku: [],
|
|
788
|
+
openbsd: [],
|
|
789
|
+
cygwin: [],
|
|
790
|
+
netbsd: [],
|
|
791
|
+
sunos: []
|
|
792
|
+
};
|
|
793
|
+
const candidates = candidatesByPlatform[process.platform] ?? [];
|
|
794
|
+
for (const filename of candidates) {
|
|
795
|
+
const fullPath = path6.join(workersDir, filename);
|
|
796
|
+
if (existsSync(fullPath)) {
|
|
797
|
+
return fullPath;
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
return null;
|
|
801
|
+
}
|
|
669
802
|
function resolveNativeWorker(language, projectDir) {
|
|
670
803
|
const base = import.meta.dirname ?? path6.dirname(new URL(import.meta.url).pathname);
|
|
671
804
|
const hcsFromBundle = path6.resolve(base, "..", "..", "vibgrate-hcs");
|
|
@@ -716,7 +849,12 @@ function resolveNativeWorker(language, projectDir) {
|
|
|
716
849
|
}
|
|
717
850
|
return null;
|
|
718
851
|
}
|
|
719
|
-
case "csharp":
|
|
852
|
+
case "csharp":
|
|
853
|
+
case "vbnet": {
|
|
854
|
+
const publishedWorker = resolveDotnetPublishedWorker(workersDir);
|
|
855
|
+
if (publishedWorker) {
|
|
856
|
+
return { cmd: publishedWorker, args: ["--project", projectDir, "--output", "ndjson"] };
|
|
857
|
+
}
|
|
720
858
|
const dll = path6.join(workersDir, "VibgrateHcsWorker.dll");
|
|
721
859
|
if (existsSync(dll)) {
|
|
722
860
|
return { cmd: "dotnet", args: [dll, "--project", projectDir, "--output", "ndjson"] };
|
|
@@ -741,7 +879,8 @@ async function runNativeWorker(rootDir, language, opts) {
|
|
|
741
879
|
language,
|
|
742
880
|
facts: [],
|
|
743
881
|
errors: [
|
|
744
|
-
`[error] No native worker found for '${language}'.
|
|
882
|
+
`[error] No native worker found for '${language}'. Build/package workers for this platform or use source mode.`,
|
|
883
|
+
`[hint] ${buildNativeInstallHint(language)}`
|
|
745
884
|
],
|
|
746
885
|
exitCode: EXIT_PARSE_FAILURE
|
|
747
886
|
};
|
|
@@ -755,6 +894,21 @@ async function runNativeWorker(rootDir, language, opts) {
|
|
|
755
894
|
process.stderr.write(chalk5.dim(`[${language}] Spawning: ${spec.cmd} ${spec.args.join(" ")}
|
|
756
895
|
`));
|
|
757
896
|
}
|
|
897
|
+
const runtimeReq = NATIVE_RUNTIME_REQUIREMENTS[language];
|
|
898
|
+
const usesPathCommand = runtimeReq && spec.cmd === runtimeReq.command;
|
|
899
|
+
if (usesPathCommand && !commandExistsOnPath(spec.cmd)) {
|
|
900
|
+
resolve6({
|
|
901
|
+
language,
|
|
902
|
+
facts: [],
|
|
903
|
+
errors: [
|
|
904
|
+
`[error] Required runtime command '${spec.cmd}' is not available on PATH.`,
|
|
905
|
+
`[hint] ${buildNativeInstallHint(language)}`,
|
|
906
|
+
"[hint] You can also package native workers into dist/workers to avoid local toolchain requirements."
|
|
907
|
+
],
|
|
908
|
+
exitCode: EXIT_PARSE_FAILURE
|
|
909
|
+
});
|
|
910
|
+
return;
|
|
911
|
+
}
|
|
758
912
|
const child = spawn(spec.cmd, spec.args, {
|
|
759
913
|
cwd: spec.cwd ?? rootDir,
|
|
760
914
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -799,7 +953,7 @@ async function runNativeWorker(rootDir, language, opts) {
|
|
|
799
953
|
clearTimeout(timer);
|
|
800
954
|
const isNotFound = err.code === "ENOENT";
|
|
801
955
|
errors.push(
|
|
802
|
-
isNotFound ? `[error] '${spec.cmd}' not found.
|
|
956
|
+
isNotFound ? `[error] '${spec.cmd}' not found. ${buildNativeInstallHint(language)}` : `[error] Failed to spawn native worker: ${err.message}`
|
|
803
957
|
);
|
|
804
958
|
resolve6({ language, facts, errors, exitCode: EXIT_PARSE_FAILURE });
|
|
805
959
|
});
|
|
@@ -1012,7 +1166,7 @@ var extractCommand = new Command5("extract").description("Analyze source code an
|
|
|
1012
1166
|
}
|
|
1013
1167
|
let targetLanguages;
|
|
1014
1168
|
if (opts.language) {
|
|
1015
|
-
targetLanguages = opts.language.split(",").map((l) => l
|
|
1169
|
+
targetLanguages = opts.language.split(",").map((l) => normalizeLanguageToken(l)).filter(Boolean);
|
|
1016
1170
|
for (const lang of targetLanguages) {
|
|
1017
1171
|
if (!SUPPORTED_LANGUAGES.has(lang)) {
|
|
1018
1172
|
process.stderr.write(chalk5.red(`Unknown language: "${lang}"
|