@getcodesentinel/codesentinel 1.19.0 → 1.19.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/dist/index.js +125 -30
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3702,6 +3702,7 @@ var ANSI2 = {
|
|
|
3702
3702
|
cyan: "\x1B[36m",
|
|
3703
3703
|
green: "\x1B[32m"
|
|
3704
3704
|
};
|
|
3705
|
+
var PROMPT_PADDING = " ";
|
|
3705
3706
|
var renderMenu = (currentVersion, actions, selectedIndex) => {
|
|
3706
3707
|
const optionLabels = actions.map((action, index) => `${index + 1}. ${action.label}`);
|
|
3707
3708
|
const labelWidth = optionLabels.reduce((max, label) => Math.max(max, label.length), 0);
|
|
@@ -3732,6 +3733,46 @@ var hideCursor2 = () => {
|
|
|
3732
3733
|
var showCursor2 = () => {
|
|
3733
3734
|
stderr2.write("\x1B[?25h");
|
|
3734
3735
|
};
|
|
3736
|
+
var pipeWithPadding = (stream, target, padding) => {
|
|
3737
|
+
if (stream === null) {
|
|
3738
|
+
return;
|
|
3739
|
+
}
|
|
3740
|
+
stream.setEncoding("utf8");
|
|
3741
|
+
let buffer = "";
|
|
3742
|
+
let needsPrefix = true;
|
|
3743
|
+
const writeChunk = (chunk) => {
|
|
3744
|
+
let start = 0;
|
|
3745
|
+
while (start < chunk.length) {
|
|
3746
|
+
if (needsPrefix) {
|
|
3747
|
+
target.write(padding);
|
|
3748
|
+
needsPrefix = false;
|
|
3749
|
+
}
|
|
3750
|
+
const newlineIndex = chunk.indexOf("\n", start);
|
|
3751
|
+
if (newlineIndex === -1) {
|
|
3752
|
+
target.write(chunk.slice(start));
|
|
3753
|
+
return;
|
|
3754
|
+
}
|
|
3755
|
+
target.write(chunk.slice(start, newlineIndex + 1));
|
|
3756
|
+
needsPrefix = true;
|
|
3757
|
+
start = newlineIndex + 1;
|
|
3758
|
+
}
|
|
3759
|
+
};
|
|
3760
|
+
stream.on("data", (chunk) => {
|
|
3761
|
+
buffer += chunk;
|
|
3762
|
+
const lastNewlineIndex = buffer.lastIndexOf("\n");
|
|
3763
|
+
if (lastNewlineIndex === -1) {
|
|
3764
|
+
return;
|
|
3765
|
+
}
|
|
3766
|
+
writeChunk(buffer.slice(0, lastNewlineIndex + 1));
|
|
3767
|
+
buffer = buffer.slice(lastNewlineIndex + 1);
|
|
3768
|
+
});
|
|
3769
|
+
stream.on("end", () => {
|
|
3770
|
+
if (buffer.length > 0) {
|
|
3771
|
+
writeChunk(buffer);
|
|
3772
|
+
buffer = "";
|
|
3773
|
+
}
|
|
3774
|
+
});
|
|
3775
|
+
};
|
|
3735
3776
|
var promptSelection = async (currentVersion, actions) => {
|
|
3736
3777
|
if (!stdin2.isTTY || !stderr2.isTTY || typeof stdin2.setRawMode !== "function") {
|
|
3737
3778
|
return "exit";
|
|
@@ -3788,46 +3829,99 @@ var createPrompt = () => createPromisesInterface({
|
|
|
3788
3829
|
output: stderr2
|
|
3789
3830
|
});
|
|
3790
3831
|
var promptText = async (prompt, label, defaultValue) => {
|
|
3791
|
-
const suffix = defaultValue === void 0 ? "" : ` [${defaultValue}]`;
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3832
|
+
const suffix = defaultValue === void 0 || defaultValue.length === 0 ? "" : ` [${defaultValue}]`;
|
|
3833
|
+
let answer;
|
|
3834
|
+
try {
|
|
3835
|
+
answer = await prompt.question(
|
|
3836
|
+
`${PROMPT_PADDING}${label}${suffix}: `
|
|
3837
|
+
);
|
|
3838
|
+
} catch (error) {
|
|
3839
|
+
if (error instanceof Error && "code" in error && error.code === "ABORT_ERR") {
|
|
3840
|
+
stderr2.write("\n");
|
|
3841
|
+
return null;
|
|
3842
|
+
}
|
|
3843
|
+
throw error;
|
|
3844
|
+
}
|
|
3795
3845
|
const trimmed = answer.trim();
|
|
3796
3846
|
return trimmed.length > 0 ? trimmed : defaultValue ?? "";
|
|
3797
3847
|
};
|
|
3848
|
+
var renderDependencyRiskPrompt = (errorMessage) => {
|
|
3849
|
+
clearTerminal();
|
|
3850
|
+
stderr2.write(`${PROMPT_PADDING}${ANSI2.bold}Scan dependency risk${ANSI2.reset}
|
|
3851
|
+
`);
|
|
3852
|
+
if (errorMessage !== void 0) {
|
|
3853
|
+
stderr2.write(`
|
|
3854
|
+
${PROMPT_PADDING}${errorMessage}
|
|
3855
|
+
`);
|
|
3856
|
+
}
|
|
3857
|
+
stderr2.write("\n");
|
|
3858
|
+
};
|
|
3798
3859
|
var buildDependencyRiskArgs = async () => {
|
|
3799
3860
|
const prompt = createPrompt();
|
|
3800
3861
|
try {
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3862
|
+
let errorMessage;
|
|
3863
|
+
while (true) {
|
|
3864
|
+
renderDependencyRiskPrompt(errorMessage);
|
|
3865
|
+
const dependency = await promptText(prompt, "Package name");
|
|
3866
|
+
if (dependency === null) {
|
|
3867
|
+
return { kind: "cancel" };
|
|
3868
|
+
}
|
|
3869
|
+
if (dependency.length === 0) {
|
|
3870
|
+
errorMessage = "A package name is required.";
|
|
3871
|
+
continue;
|
|
3872
|
+
}
|
|
3873
|
+
return {
|
|
3874
|
+
kind: "run",
|
|
3875
|
+
args: ["dependency-risk", dependency]
|
|
3876
|
+
};
|
|
3805
3877
|
}
|
|
3806
|
-
return ["dependency-risk", dependency];
|
|
3807
3878
|
} finally {
|
|
3808
3879
|
prompt.close();
|
|
3809
3880
|
}
|
|
3810
3881
|
};
|
|
3811
3882
|
var waitForReturnToMenu = async () => {
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
output: stderr2
|
|
3815
|
-
});
|
|
3816
|
-
try {
|
|
3817
|
-
await prompt.question("Press enter to return to the menu...");
|
|
3818
|
-
} finally {
|
|
3819
|
-
prompt.close();
|
|
3883
|
+
if (!stdin2.isTTY || !stderr2.isTTY || typeof stdin2.setRawMode !== "function") {
|
|
3884
|
+
return;
|
|
3820
3885
|
}
|
|
3886
|
+
stderr2.write(`
|
|
3887
|
+
${PROMPT_PADDING}Press enter to return to the menu...`);
|
|
3888
|
+
await new Promise((resolve6) => {
|
|
3889
|
+
emitKeypressEvents2(stdin2);
|
|
3890
|
+
const previousRawMode = stdin2.isRaw;
|
|
3891
|
+
const cleanup = () => {
|
|
3892
|
+
stdin2.off("keypress", onKeypress);
|
|
3893
|
+
stdin2.pause();
|
|
3894
|
+
stdin2.setRawMode(previousRawMode);
|
|
3895
|
+
showCursor2();
|
|
3896
|
+
stderr2.write("\n");
|
|
3897
|
+
resolve6();
|
|
3898
|
+
};
|
|
3899
|
+
const onKeypress = (_str, key) => {
|
|
3900
|
+
if (key.ctrl === true && key.name === "c") {
|
|
3901
|
+
cleanup();
|
|
3902
|
+
return;
|
|
3903
|
+
}
|
|
3904
|
+
if (key.name === "return" || key.name === "enter") {
|
|
3905
|
+
cleanup();
|
|
3906
|
+
}
|
|
3907
|
+
};
|
|
3908
|
+
hideCursor2();
|
|
3909
|
+
stdin2.on("keypress", onKeypress);
|
|
3910
|
+
stdin2.setRawMode(true);
|
|
3911
|
+
stdin2.resume();
|
|
3912
|
+
});
|
|
3821
3913
|
};
|
|
3822
3914
|
var runCliCommand = async (scriptPath2, args) => {
|
|
3823
3915
|
return await new Promise((resolve6, reject) => {
|
|
3824
3916
|
const child = spawn2(process.execPath, [...process.execArgv, scriptPath2, ...args], {
|
|
3825
|
-
stdio: "inherit",
|
|
3917
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
3826
3918
|
env: {
|
|
3827
3919
|
...process.env,
|
|
3828
3920
|
CODESENTINEL_NO_UPDATE_NOTIFIER: "1"
|
|
3829
3921
|
}
|
|
3830
3922
|
});
|
|
3923
|
+
pipeWithPadding(child.stdout, stdout, PROMPT_PADDING);
|
|
3924
|
+
pipeWithPadding(child.stderr, stderr2, PROMPT_PADDING);
|
|
3831
3925
|
child.on("error", (error) => {
|
|
3832
3926
|
reject(error);
|
|
3833
3927
|
});
|
|
@@ -3838,34 +3932,35 @@ var runCliCommand = async (scriptPath2, args) => {
|
|
|
3838
3932
|
};
|
|
3839
3933
|
var runInteractiveCliMenu = async (input) => {
|
|
3840
3934
|
if (!stdin2.isTTY || !stderr2.isTTY || !stdout.isTTY) {
|
|
3841
|
-
stderr2.write(
|
|
3935
|
+
stderr2.write(`${PROMPT_PADDING}Interactive menu requires a TTY.
|
|
3936
|
+
`);
|
|
3842
3937
|
return 1;
|
|
3843
3938
|
}
|
|
3844
3939
|
const actions = [
|
|
3845
3940
|
{
|
|
3846
3941
|
label: "Run overview",
|
|
3847
3942
|
description: "combined analyze + explain + report",
|
|
3848
|
-
commandBuilder: () => ["run"]
|
|
3943
|
+
commandBuilder: () => ({ kind: "run", args: ["run"] })
|
|
3849
3944
|
},
|
|
3850
3945
|
{
|
|
3851
3946
|
label: "Analyze repository",
|
|
3852
3947
|
description: "structural and health scoring summary",
|
|
3853
|
-
commandBuilder: () => ["analyze"]
|
|
3948
|
+
commandBuilder: () => ({ kind: "run", args: ["analyze"] })
|
|
3854
3949
|
},
|
|
3855
3950
|
{
|
|
3856
3951
|
label: "Explain hotspots",
|
|
3857
3952
|
description: "top findings in markdown by default",
|
|
3858
|
-
commandBuilder: () => ["explain", "--format", "md"]
|
|
3953
|
+
commandBuilder: () => ({ kind: "run", args: ["explain", "--format", "md"] })
|
|
3859
3954
|
},
|
|
3860
3955
|
{
|
|
3861
3956
|
label: "Generate report",
|
|
3862
3957
|
description: "create a full report for a repository",
|
|
3863
|
-
commandBuilder: () => ["report", "--format", "md"]
|
|
3958
|
+
commandBuilder: () => ({ kind: "run", args: ["report", "--format", "md"] })
|
|
3864
3959
|
},
|
|
3865
3960
|
{
|
|
3866
3961
|
label: "Run policy check",
|
|
3867
3962
|
description: "execute governance gates",
|
|
3868
|
-
commandBuilder: () => ["check"]
|
|
3963
|
+
commandBuilder: () => ({ kind: "run", args: ["check"] })
|
|
3869
3964
|
},
|
|
3870
3965
|
{
|
|
3871
3966
|
label: "Scan dependency risk",
|
|
@@ -3881,18 +3976,18 @@ var runInteractiveCliMenu = async (input) => {
|
|
|
3881
3976
|
}
|
|
3882
3977
|
const selectedAction = actions[selectedIndex];
|
|
3883
3978
|
if (selectedAction === void 0) {
|
|
3884
|
-
stderr2.write(
|
|
3979
|
+
stderr2.write(`
|
|
3980
|
+
${PROMPT_PADDING}`);
|
|
3885
3981
|
return 1;
|
|
3886
3982
|
}
|
|
3887
|
-
const
|
|
3888
|
-
if (
|
|
3889
|
-
await waitForReturnToMenu();
|
|
3983
|
+
const actionResult = await selectedAction.commandBuilder();
|
|
3984
|
+
if (actionResult.kind === "cancel") {
|
|
3890
3985
|
continue;
|
|
3891
3986
|
}
|
|
3892
|
-
const exitCode = await runCliCommand(input.scriptPath, args);
|
|
3987
|
+
const exitCode = await runCliCommand(input.scriptPath, actionResult.args);
|
|
3893
3988
|
if (exitCode !== 0) {
|
|
3894
3989
|
stderr2.write(`
|
|
3895
|
-
Command exited with code ${exitCode}.
|
|
3990
|
+
${PROMPT_PADDING}Command exited with code ${exitCode}.
|
|
3896
3991
|
`);
|
|
3897
3992
|
} else {
|
|
3898
3993
|
stderr2.write("\n");
|