Repository navigation
fix(cli): add top-level error handler for command rejections - #56
Merged
Merged
Conversation
Commander's `.parse()` does not await async action handlers, so a handler rejection (e.g. `add`'s ensureProjexInstalled hitting ENOENT, or the non-ENOENT rethrows in the theme/config existence checks) escaped as an unhandled rejection: Node printed a raw internal stack trace and exited 1. Wrap `program.parseAsync()` in a single top-level try/catch that prints a chalk-formatted `✖` error (matching the existing message style) and sets a non-zero exit code via process.exitCode rather than process.exit, since an immediate exit may prevent piped output from fully flushing. The one catch covers all five commands and future ones; commander usage errors (unknown option) still go through commander's own handler and never reach it. Entry point is now detected via a realpath comparison so `main(argv)` can be imported and driven by the test suite without auto-running parse on import. Closes #52
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Owner
Author
Review: APPROVEIndependent review of Acceptance criteria — verified on the branch (not taken on report)
Standards
Spec
Scope guard: 1 commit, 3 files, all on-purpose. No scope creep. Verdict: APPROVE — ready to merge. |
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #52.
packages/core/src/cli.tscalledprogram.parse()(which does not await async action handlers) with no top-level error handling, so any command rejection surfaced as an unhandled rejection — Node printed a raw internal stack trace and exited 1.This wraps
program.parseAsync()in a single top-leveltry/catchthat prints a chalk-formatted✖error (matching the existing message style) and sets a non-zero exit code viaprocess.exitCode(notprocess.exit, since an immediate exit can cut off piped output). The one catch covers all five commands and any future ones.Why not the alternatives
process.on('unhandledRejection')— it would mask genuine future bugs, and the handler would still have to exit or the process keeps running..catch()chains — a single catch covers every command and stays correct as commands are added.parseAsync, an unknown option printserror: unknown option ...and callsprocess.exit(1)internally, so it never reaches this catch.What now formats instead of stack-tracing
Rejections that escaped as raw stack traces now print the formatted error:
add theme-minimalin a dir withoutpackage.json(ENOENT)add theme-minimalwithstyles/present as a regular file (ENOTDIR)inithitting a non-ENOENT error on the config existence check (e.g. ELOOP)The intentional non-ENOENT rethrows in
add.ts(theme existence check) andinit.ts(config existence check) are unchanged — they still surface; the top-level handler now formats them.Test plan
packages/core/src/__tests__/cli.test.ts) drives the realaddpath to a genuine ENOENT rejection and asserts the formatted✖message, a non-zeroprocess.exitCode, and thatprocess.exitis not used.pnpm install && pnpm build && pnpm typecheck && pnpm lint && pnpm test— all green (1053 tests).Before (raw stack, exit 1)
After (formatted, exit 1)
Unknown option (unchanged — commander default, exit 1, no double-print)
Closes #52