Skip to content

Commit 17e1062

Browse files
committed
fix(cli): show help for a bare devframe invocation
Bare `devframe` (no subcommand) silently exited 0 — cac only shows help automatically for an explicit -h/--help flag, not an unmatched command. Check matchedCommand after parse() and fall back to outputHelp(), guarding against the already-handled --help case so it doesn't print twice.
1 parent 35f3122 commit 17e1062

2 files changed

Lines changed: 46 additions & 0 deletions

File tree

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { afterEach, describe, expect, it, vi } from 'vitest'
2+
import { runDevframeCli } from './main'
3+
4+
describe('runDevframeCli', () => {
5+
afterEach(() => {
6+
vi.restoreAllMocks()
7+
})
8+
9+
it('shows help for a bare invocation (no subcommand)', async () => {
10+
const info = vi.spyOn(console, 'info').mockImplementation(() => {})
11+
await runDevframeCli(['node', 'devframe'])
12+
expect(info).toHaveBeenCalledTimes(1)
13+
expect(info.mock.calls[0]![0]).toContain('connect')
14+
})
15+
16+
it('shows help exactly once for --help (not doubled by the bare-invocation fallback)', async () => {
17+
const info = vi.spyOn(console, 'info').mockImplementation(() => {})
18+
await runDevframeCli(['node', 'devframe', '--help'])
19+
expect(info).toHaveBeenCalledTimes(1)
20+
})
21+
22+
it('shows help for an unrecognized subcommand', async () => {
23+
const info = vi.spyOn(console, 'info').mockImplementation(() => {})
24+
await runDevframeCli(['node', 'devframe', 'bogus'])
25+
expect(info).toHaveBeenCalledTimes(1)
26+
})
27+
28+
it('does not show help when a real subcommand matches', async () => {
29+
const info = vi.spyOn(console, 'info').mockImplementation(() => {})
30+
// `connect --help` matches the `connect` command and prints *its* help
31+
// (cac's built-in per-command path) rather than the bare-invocation
32+
// fallback — still exactly once.
33+
await runDevframeCli(['node', 'devframe', 'connect', '--help'])
34+
expect(info).toHaveBeenCalledTimes(1)
35+
expect(info.mock.calls[0]![0]).toContain('--port')
36+
})
37+
})

packages/devframe/src/cli/main.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,14 @@ export async function runDevframeCli(argv: string[] = process.argv): Promise<voi
2828

2929
cli.help()
3030
cli.parse(argv, { run: false })
31+
// A bare `devframe` (no subcommand) also leaves `matchedCommand` unset —
32+
// same as `-h`/`--help`, which cac already prints help for internally.
33+
// Only step in for the *other* unset case (no help flag, no command) so
34+
// `--help` doesn't print twice.
35+
if (!cli.matchedCommand) {
36+
if (!cli.options.help)
37+
cli.outputHelp()
38+
return
39+
}
3140
await cli.runMatchedCommand()
3241
}

0 commit comments

Comments
 (0)