@getcodesentinel/codesentinel 1.18.0 → 1.19.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.
- package/dist/index.js +234 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2809,10 +2809,10 @@ var runGit = async (repositoryPath, args) => {
|
|
|
2809
2809
|
};
|
|
2810
2810
|
var tryRunGit = async (repositoryPath, args) => {
|
|
2811
2811
|
try {
|
|
2812
|
-
const { stdout } = await execFileAsync("git", ["-C", repositoryPath, ...args], {
|
|
2812
|
+
const { stdout: stdout2 } = await execFileAsync("git", ["-C", repositoryPath, ...args], {
|
|
2813
2813
|
encoding: "utf8"
|
|
2814
2814
|
});
|
|
2815
|
-
return { ok: true, stdout:
|
|
2815
|
+
return { ok: true, stdout: stdout2.trim() };
|
|
2816
2816
|
} catch (error) {
|
|
2817
2817
|
const message = error instanceof Error ? error.message : "unknown git error";
|
|
2818
2818
|
return { ok: false, message };
|
|
@@ -3336,6 +3336,12 @@ var ANSI = {
|
|
|
3336
3336
|
green: "\x1B[32m",
|
|
3337
3337
|
yellow: "\x1B[33m"
|
|
3338
3338
|
};
|
|
3339
|
+
var hideCursor = () => {
|
|
3340
|
+
stderr.write("\x1B[?25l");
|
|
3341
|
+
};
|
|
3342
|
+
var showCursor = () => {
|
|
3343
|
+
stderr.write("\x1B[?25h");
|
|
3344
|
+
};
|
|
3339
3345
|
var parsePrereleaseIdentifier = (identifier) => {
|
|
3340
3346
|
if (/^\d+$/.test(identifier)) {
|
|
3341
3347
|
return Number.parseInt(identifier, 10);
|
|
@@ -3539,7 +3545,7 @@ var renderUpdatePrompt = (packageName, latestVersion, currentVersion, selectedIn
|
|
|
3539
3545
|
return `${prefix} ${text}`;
|
|
3540
3546
|
}),
|
|
3541
3547
|
"",
|
|
3542
|
-
` ${ANSI.dim}Use \u2191/\u2193 to choose. Press enter to continue
|
|
3548
|
+
` ${ANSI.dim}Use \u2191/\u2193 to choose. Press enter to continue. Press q or Ctrl+C to exit.${ANSI.reset}`
|
|
3543
3549
|
];
|
|
3544
3550
|
stderr.write(lines.join("\n"));
|
|
3545
3551
|
return lines.length;
|
|
@@ -3571,6 +3577,7 @@ var promptInstall = async (packageName, latestVersion, currentVersion) => {
|
|
|
3571
3577
|
stdin.setRawMode(previousRawMode);
|
|
3572
3578
|
}
|
|
3573
3579
|
clearPromptArea();
|
|
3580
|
+
showCursor();
|
|
3574
3581
|
if (choice === "install") {
|
|
3575
3582
|
stderr.write(`${ANSI.yellow}${renderUpdateInProgressMessage(packageName)}${ANSI.reset}`);
|
|
3576
3583
|
} else {
|
|
@@ -3580,7 +3587,11 @@ var promptInstall = async (packageName, latestVersion, currentVersion) => {
|
|
|
3580
3587
|
};
|
|
3581
3588
|
const onKeypress = (_str, key) => {
|
|
3582
3589
|
if (key.ctrl === true && key.name === "c") {
|
|
3583
|
-
cleanup("
|
|
3590
|
+
cleanup("skip");
|
|
3591
|
+
return;
|
|
3592
|
+
}
|
|
3593
|
+
if (key.name === "q") {
|
|
3594
|
+
cleanup("skip");
|
|
3584
3595
|
return;
|
|
3585
3596
|
}
|
|
3586
3597
|
if (key.name === "up") {
|
|
@@ -3599,6 +3610,7 @@ var promptInstall = async (packageName, latestVersion, currentVersion) => {
|
|
|
3599
3610
|
};
|
|
3600
3611
|
stdin.on("keypress", onKeypress);
|
|
3601
3612
|
if (typeof stdin.setRawMode === "function") {
|
|
3613
|
+
hideCursor();
|
|
3602
3614
|
stdin.setRawMode(true);
|
|
3603
3615
|
}
|
|
3604
3616
|
stdin.resume();
|
|
@@ -3625,9 +3637,6 @@ var runManualCliUpdate = async (input) => {
|
|
|
3625
3637
|
return 0;
|
|
3626
3638
|
}
|
|
3627
3639
|
const choice = await promptInstall(input.packageName, latestVersion, input.currentVersion);
|
|
3628
|
-
if (choice === "interrupt") {
|
|
3629
|
-
return 130;
|
|
3630
|
-
}
|
|
3631
3640
|
if (choice !== "install") {
|
|
3632
3641
|
return 0;
|
|
3633
3642
|
}
|
|
@@ -3665,9 +3674,6 @@ var checkForCliUpdates = async (input) => {
|
|
|
3665
3674
|
return;
|
|
3666
3675
|
}
|
|
3667
3676
|
const choice = await promptInstall(input.packageName, latestVersion, input.currentVersion);
|
|
3668
|
-
if (choice === "interrupt") {
|
|
3669
|
-
process.exit(130);
|
|
3670
|
-
}
|
|
3671
3677
|
if (choice !== "install") {
|
|
3672
3678
|
return;
|
|
3673
3679
|
}
|
|
@@ -3684,6 +3690,217 @@ var checkForCliUpdates = async (input) => {
|
|
|
3684
3690
|
}
|
|
3685
3691
|
};
|
|
3686
3692
|
|
|
3693
|
+
// src/application/interactive-menu.ts
|
|
3694
|
+
import { spawn as spawn2 } from "child_process";
|
|
3695
|
+
import { stderr as stderr2, stdin as stdin2, stdout } from "process";
|
|
3696
|
+
import { clearScreenDown as clearScreenDown2, cursorTo as cursorTo2, emitKeypressEvents as emitKeypressEvents2, moveCursor } from "readline";
|
|
3697
|
+
import { createInterface as createPromisesInterface } from "readline/promises";
|
|
3698
|
+
var ANSI2 = {
|
|
3699
|
+
reset: "\x1B[0m",
|
|
3700
|
+
bold: "\x1B[1m",
|
|
3701
|
+
dim: "\x1B[2m",
|
|
3702
|
+
cyan: "\x1B[36m",
|
|
3703
|
+
green: "\x1B[32m"
|
|
3704
|
+
};
|
|
3705
|
+
var renderMenu = (currentVersion, actions, selectedIndex) => {
|
|
3706
|
+
const optionLabels = actions.map((action, index) => `${index + 1}. ${action.label}`);
|
|
3707
|
+
const labelWidth = optionLabels.reduce((max, label) => Math.max(max, label.length), 0);
|
|
3708
|
+
const lines = [
|
|
3709
|
+
` ${ANSI2.bold}${ANSI2.cyan}CodeSentinel${ANSI2.reset} ${ANSI2.dim}v${currentVersion}${ANSI2.reset}`,
|
|
3710
|
+
"",
|
|
3711
|
+
" Choose an action:",
|
|
3712
|
+
"",
|
|
3713
|
+
...actions.map((action, index) => {
|
|
3714
|
+
const selected = index === selectedIndex;
|
|
3715
|
+
const prefix = selected ? `${ANSI2.green}>${ANSI2.reset}` : " ";
|
|
3716
|
+
const label = optionLabels[index]?.padEnd(labelWidth, " ") ?? "";
|
|
3717
|
+
const renderedLabel = selected ? `${ANSI2.bold}${label}${ANSI2.reset}` : label;
|
|
3718
|
+
return `${prefix} ${renderedLabel} ${ANSI2.dim}${action.description}${ANSI2.reset}`;
|
|
3719
|
+
}),
|
|
3720
|
+
"",
|
|
3721
|
+
` ${ANSI2.dim}Use \u2191/\u2193 to choose. Press enter to continue. Press q or Ctrl+C to exit.${ANSI2.reset}`
|
|
3722
|
+
];
|
|
3723
|
+
stderr2.write(lines.join("\n"));
|
|
3724
|
+
};
|
|
3725
|
+
var clearTerminal = () => {
|
|
3726
|
+
cursorTo2(stderr2, 0, 0);
|
|
3727
|
+
clearScreenDown2(stderr2);
|
|
3728
|
+
};
|
|
3729
|
+
var hideCursor2 = () => {
|
|
3730
|
+
stderr2.write("\x1B[?25l");
|
|
3731
|
+
};
|
|
3732
|
+
var showCursor2 = () => {
|
|
3733
|
+
stderr2.write("\x1B[?25h");
|
|
3734
|
+
};
|
|
3735
|
+
var promptSelection = async (currentVersion, actions) => {
|
|
3736
|
+
if (!stdin2.isTTY || !stderr2.isTTY || typeof stdin2.setRawMode !== "function") {
|
|
3737
|
+
return "exit";
|
|
3738
|
+
}
|
|
3739
|
+
return await new Promise((resolve6) => {
|
|
3740
|
+
emitKeypressEvents2(stdin2);
|
|
3741
|
+
let selectedIndex = 0;
|
|
3742
|
+
const previousRawMode = stdin2.isRaw;
|
|
3743
|
+
const redraw = () => {
|
|
3744
|
+
clearTerminal();
|
|
3745
|
+
renderMenu(currentVersion, actions, selectedIndex);
|
|
3746
|
+
moveCursor(stderr2, -1, 0);
|
|
3747
|
+
};
|
|
3748
|
+
const cleanup = (selection) => {
|
|
3749
|
+
stdin2.off("keypress", onKeypress);
|
|
3750
|
+
stdin2.pause();
|
|
3751
|
+
stdin2.setRawMode(previousRawMode);
|
|
3752
|
+
clearTerminal();
|
|
3753
|
+
showCursor2();
|
|
3754
|
+
resolve6(selection);
|
|
3755
|
+
};
|
|
3756
|
+
const onKeypress = (_str, key) => {
|
|
3757
|
+
if (key.ctrl === true && key.name === "c") {
|
|
3758
|
+
cleanup("exit");
|
|
3759
|
+
return;
|
|
3760
|
+
}
|
|
3761
|
+
if (key.name === "q") {
|
|
3762
|
+
cleanup("exit");
|
|
3763
|
+
return;
|
|
3764
|
+
}
|
|
3765
|
+
if (key.name === "up") {
|
|
3766
|
+
selectedIndex = selectedIndex > 0 ? selectedIndex - 1 : actions.length - 1;
|
|
3767
|
+
redraw();
|
|
3768
|
+
return;
|
|
3769
|
+
}
|
|
3770
|
+
if (key.name === "down") {
|
|
3771
|
+
selectedIndex = selectedIndex < actions.length - 1 ? selectedIndex + 1 : 0;
|
|
3772
|
+
redraw();
|
|
3773
|
+
return;
|
|
3774
|
+
}
|
|
3775
|
+
if (key.name === "return" || key.name === "enter") {
|
|
3776
|
+
cleanup(selectedIndex);
|
|
3777
|
+
}
|
|
3778
|
+
};
|
|
3779
|
+
stdin2.on("keypress", onKeypress);
|
|
3780
|
+
hideCursor2();
|
|
3781
|
+
stdin2.setRawMode(true);
|
|
3782
|
+
stdin2.resume();
|
|
3783
|
+
redraw();
|
|
3784
|
+
});
|
|
3785
|
+
};
|
|
3786
|
+
var createPrompt = () => createPromisesInterface({
|
|
3787
|
+
input: stdin2,
|
|
3788
|
+
output: stderr2
|
|
3789
|
+
});
|
|
3790
|
+
var promptText = async (prompt, label, defaultValue) => {
|
|
3791
|
+
const suffix = defaultValue === void 0 ? "" : ` [${defaultValue}]`;
|
|
3792
|
+
const answer = await prompt.question(
|
|
3793
|
+
`${label}${suffix}: `
|
|
3794
|
+
);
|
|
3795
|
+
const trimmed = answer.trim();
|
|
3796
|
+
return trimmed.length > 0 ? trimmed : defaultValue ?? "";
|
|
3797
|
+
};
|
|
3798
|
+
var buildDependencyRiskArgs = async () => {
|
|
3799
|
+
const prompt = createPrompt();
|
|
3800
|
+
try {
|
|
3801
|
+
const dependency = await promptText(prompt, "Dependency spec", "");
|
|
3802
|
+
if (dependency.length === 0) {
|
|
3803
|
+
stderr2.write("A dependency spec is required.\n");
|
|
3804
|
+
return null;
|
|
3805
|
+
}
|
|
3806
|
+
return ["dependency-risk", dependency];
|
|
3807
|
+
} finally {
|
|
3808
|
+
prompt.close();
|
|
3809
|
+
}
|
|
3810
|
+
};
|
|
3811
|
+
var waitForReturnToMenu = async () => {
|
|
3812
|
+
const prompt = createPromisesInterface({
|
|
3813
|
+
input: stdin2,
|
|
3814
|
+
output: stderr2
|
|
3815
|
+
});
|
|
3816
|
+
try {
|
|
3817
|
+
await prompt.question("Press enter to return to the menu...");
|
|
3818
|
+
} finally {
|
|
3819
|
+
prompt.close();
|
|
3820
|
+
}
|
|
3821
|
+
};
|
|
3822
|
+
var runCliCommand = async (scriptPath2, args) => {
|
|
3823
|
+
return await new Promise((resolve6, reject) => {
|
|
3824
|
+
const child = spawn2(process.execPath, [...process.execArgv, scriptPath2, ...args], {
|
|
3825
|
+
stdio: "inherit",
|
|
3826
|
+
env: {
|
|
3827
|
+
...process.env,
|
|
3828
|
+
CODESENTINEL_NO_UPDATE_NOTIFIER: "1"
|
|
3829
|
+
}
|
|
3830
|
+
});
|
|
3831
|
+
child.on("error", (error) => {
|
|
3832
|
+
reject(error);
|
|
3833
|
+
});
|
|
3834
|
+
child.on("close", (code) => {
|
|
3835
|
+
resolve6(code ?? 1);
|
|
3836
|
+
});
|
|
3837
|
+
});
|
|
3838
|
+
};
|
|
3839
|
+
var runInteractiveCliMenu = async (input) => {
|
|
3840
|
+
if (!stdin2.isTTY || !stderr2.isTTY || !stdout.isTTY) {
|
|
3841
|
+
stderr2.write("Interactive menu requires a TTY.\n");
|
|
3842
|
+
return 1;
|
|
3843
|
+
}
|
|
3844
|
+
const actions = [
|
|
3845
|
+
{
|
|
3846
|
+
label: "Run overview",
|
|
3847
|
+
description: "combined analyze + explain + report",
|
|
3848
|
+
commandBuilder: () => ["run"]
|
|
3849
|
+
},
|
|
3850
|
+
{
|
|
3851
|
+
label: "Analyze repository",
|
|
3852
|
+
description: "structural and health scoring summary",
|
|
3853
|
+
commandBuilder: () => ["analyze"]
|
|
3854
|
+
},
|
|
3855
|
+
{
|
|
3856
|
+
label: "Explain hotspots",
|
|
3857
|
+
description: "top findings in markdown by default",
|
|
3858
|
+
commandBuilder: () => ["explain", "--format", "md"]
|
|
3859
|
+
},
|
|
3860
|
+
{
|
|
3861
|
+
label: "Generate report",
|
|
3862
|
+
description: "create a full report for a repository",
|
|
3863
|
+
commandBuilder: () => ["report", "--format", "md"]
|
|
3864
|
+
},
|
|
3865
|
+
{
|
|
3866
|
+
label: "Run policy check",
|
|
3867
|
+
description: "execute governance gates",
|
|
3868
|
+
commandBuilder: () => ["check"]
|
|
3869
|
+
},
|
|
3870
|
+
{
|
|
3871
|
+
label: "Scan dependency risk",
|
|
3872
|
+
description: "inspect a package from the registry",
|
|
3873
|
+
commandBuilder: buildDependencyRiskArgs
|
|
3874
|
+
}
|
|
3875
|
+
];
|
|
3876
|
+
while (true) {
|
|
3877
|
+
const selectedIndex = await promptSelection(input.currentVersion, actions);
|
|
3878
|
+
if (selectedIndex === "exit") {
|
|
3879
|
+
stderr2.write("\n");
|
|
3880
|
+
return 0;
|
|
3881
|
+
}
|
|
3882
|
+
const selectedAction = actions[selectedIndex];
|
|
3883
|
+
if (selectedAction === void 0) {
|
|
3884
|
+
stderr2.write("\n");
|
|
3885
|
+
return 1;
|
|
3886
|
+
}
|
|
3887
|
+
const args = await selectedAction.commandBuilder();
|
|
3888
|
+
if (args === null) {
|
|
3889
|
+
await waitForReturnToMenu();
|
|
3890
|
+
continue;
|
|
3891
|
+
}
|
|
3892
|
+
const exitCode = await runCliCommand(input.scriptPath, args);
|
|
3893
|
+
if (exitCode !== 0) {
|
|
3894
|
+
stderr2.write(`
|
|
3895
|
+
Command exited with code ${exitCode}.
|
|
3896
|
+
`);
|
|
3897
|
+
} else {
|
|
3898
|
+
stderr2.write("\n");
|
|
3899
|
+
}
|
|
3900
|
+
await waitForReturnToMenu();
|
|
3901
|
+
}
|
|
3902
|
+
};
|
|
3903
|
+
|
|
3687
3904
|
// src/application/run-analyze-command.ts
|
|
3688
3905
|
import { resolve as resolve3 } from "path";
|
|
3689
3906
|
|
|
@@ -8052,14 +8269,17 @@ program.command("ci").argument("[path]", "path to the project to analyze").addOp
|
|
|
8052
8269
|
}
|
|
8053
8270
|
}
|
|
8054
8271
|
);
|
|
8055
|
-
if (process.argv.length <= 2) {
|
|
8056
|
-
program.outputHelp();
|
|
8057
|
-
process.exit(0);
|
|
8058
|
-
}
|
|
8059
8272
|
var executablePath = process.argv[0] ?? "";
|
|
8060
8273
|
var scriptPath = process.argv[1] ?? "";
|
|
8061
8274
|
var argv = process.argv[2] === "--" ? [executablePath, scriptPath, ...process.argv.slice(3)] : process.argv;
|
|
8062
8275
|
if (argv.length <= 2) {
|
|
8276
|
+
if (process.stdin.isTTY && process.stdout.isTTY && process.stderr.isTTY) {
|
|
8277
|
+
process.exitCode = await runInteractiveCliMenu({
|
|
8278
|
+
currentVersion: version,
|
|
8279
|
+
scriptPath
|
|
8280
|
+
});
|
|
8281
|
+
process.exit(process.exitCode ?? 0);
|
|
8282
|
+
}
|
|
8063
8283
|
program.outputHelp();
|
|
8064
8284
|
process.exit(0);
|
|
8065
8285
|
}
|