Skip to content

Commit 94aabb4

Browse files
ivanvpetrovCopilotkdinevonlyexeption
authored
Improve error handling and error readability for all commands (#1614)
* fix(cli): improve error handling and error readability for all commands * chore: bug fix text moved * fix(cli): consolidate fail() handler message and set exitCode=1 for errors Agent-Logs-Url: https://github.com/IgniteUI/igniteui-cli/sessions/9e5da6c9-348d-43b7-8bc9-e0b558ebbab3 Co-authored-by: ivanvpetrov <110455887+ivanvpetrov@users.noreply.github.com> * fix(cli): replace showHelp with getHelp --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Konstantin Dinev <kdinev@infragistics.com> Co-authored-by: onlyexeption <ibarakov@infragistics.com>
1 parent b9ea116 commit 94aabb4

4 files changed

Lines changed: 45 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ A comprehensive modernization of all Angular templates to align with Angular v21
8484
* **ci:** mark `Util.sanitizeShellArg(x)` as command injection sanitizer for CodeQL ([#1524](https://github.com/IgniteUI/igniteui-cli/pull/1524))
8585
* **deps:** bump minimatch, ajv, immutable, and lodash ([#1549](https://github.com/IgniteUI/igniteui-cli/pull/1549))
8686
* **deps:** bump flatted ([#1559](https://github.com/IgniteUI/igniteui-cli/pull/1559))
87+
* **CLI error handling:** added `.fail()` handler to yargs to gracefully handle command validation errors (e.g., missing required subcommands) instead of showing raw stack traces ([#1614](https://github.com/IgniteUI/igniteui-cli/pull/1614))
88+
* **Unknown command detection:** running `ig <unknown>` now prints an error message and available commands instead of silently falling through to the step-by-step interactive mode ([#1614](https://github.com/IgniteUI/igniteui-cli/pull/1614))
89+
* **Unhandled promise rejection:** added `.catch()` in the CLI entry point to catch and display unexpected errors cleanly ([#1614](https://github.com/IgniteUI/igniteui-cli/pull/1614))
8790

8891
---
8992

packages/cli/bin/execute.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,8 @@ resolve("igniteui-cli", { basedir: process.cwd() }, function (err, res) {
1919
} else {
2020
cli = require("../lib/cli");
2121
}
22-
cli.run(args);
22+
cli.run(args).catch(function (err) {
23+
console.error("Error: " + (err.message || err));
24+
process.exit(1);
25+
});
2326
});

packages/cli/lib/cli.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,14 @@ export async function run(args = null) {
8383
false // setting this to `true` is supposed to exec the middleware after parsing and before arg validation
8484
// but in reality it also does not trigger the command's handler (╯°□°)╯︵ ┻━┻
8585
)
86+
.fail((msg, err, yargs) => {
87+
const message = err?.message ?? msg;
88+
if (message) {
89+
Util.error(message, "red");
90+
yargs.showHelp();
91+
process.exitCode = 1;
92+
}
93+
})
8694
.help().alias("help", "h")
8795
.parseAsync(
8896
args, // the args to parse to argv
@@ -121,10 +129,16 @@ export async function run(args = null) {
121129
App.testMode = !!argv.testMode;
122130

123131
if (!helpRequest && !ALL_COMMANDS.has(command?.toString())) {
124-
Util.log("Starting Step by step mode.", "green");
125-
Util.log("For available commands, stop this execution and use --help.", "green");
126-
const prompts = new PromptSession(templateManager);
127-
prompts.start();
132+
if (command) {
133+
process.exitCode = 1;
134+
Util.error(`Unknown command: "${command}"`, "red");
135+
Util.log(await yargsModule.getHelp());
136+
} else {
137+
Util.log("Starting Step by step mode.", "green");
138+
Util.log("For available commands, stop this execution and use --help.", "green");
139+
const prompts = new PromptSession(templateManager);
140+
prompts.start();
141+
}
128142
}
129143
}
130144
);

spec/unit/cli-spec.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,33 @@ describe("Unit - Cli.ts", () => {
5454
await run.run("list");
5555
expect(list.handler).toHaveBeenCalled();
5656
});
57-
it("Should fire properly - fallback to default", async () => {
57+
it("Should fire properly - fallback to default with no args", async () => {
5858
spyOn(Util , "log");
5959
spyOn(GoogleAnalytics, "post");
6060
spyOn(PromptSession.prototype, "start");
61-
await run.run("Nonexistent command");
61+
await run.run([]);
6262

6363
// expected console output:
6464
expect(Util.log).toHaveBeenCalledWith("Starting Step by step mode.", "green");
6565
expect(Util.log).toHaveBeenCalledWith("For available commands, stop this execution and use --help.", "green");
6666
expect(PromptSession.prototype.start).toHaveBeenCalled();
6767
});
68+
it("Should show error for unknown command", async () => {
69+
spyOn(Util , "log");
70+
spyOn(Util , "error");
71+
spyOn(GoogleAnalytics, "post");
72+
spyOn(PromptSession.prototype, "start");
73+
await run.run("nonexistent");
74+
75+
expect(Util.error).toHaveBeenCalledWith(`Unknown command: "nonexistent"`, "red");
76+
expect(PromptSession.prototype.start).not.toHaveBeenCalled();
77+
});
78+
it("Should gracefully handle subcommand validation errors", async () => {
79+
spyOn(Util , "log");
80+
spyOn(Util , "error");
81+
spyOn(GoogleAnalytics, "post");
82+
await run.run("generate");
83+
84+
expect(Util.error).toHaveBeenCalledWith("Please select command", "red");
85+
});
6886
});

0 commit comments

Comments
 (0)