diff --git a/src/move.ts b/src/move.ts index ef9c2ab..39ef3fd 100755 --- a/src/move.ts +++ b/src/move.ts @@ -32,8 +32,13 @@ import { loadConfigFile } from "./configFile.ts"; import { runKeeper } from "./keeper.ts"; /** - * Print a CLI-style error and exit 2. Returns `never` so callers can use - * it without TypeScript flagging "variable might be undefined" downstream. + * Print a user-error message and exit 2. Used for anything that comes from + * invalid input: unknown CLI flags, bad numbers, malformed or missing + * config files, unresolvable default paths. The accompanying "Try 'move + * --help'" pointer is appropriate for these cases. + * + * Returns `never` so callers can invoke it without TypeScript flagging + * "variable might be undefined" downstream. */ function failUser(err: unknown): never { const msg: string = err instanceof Error ? err.message : String(err); @@ -41,6 +46,19 @@ function failUser(err: unknown): never { process.exit(2); } +/** + * Print a runtime-failure message and exit 1. Used for anything the user + * couldn't have prevented from the command line: nut.js errors, missing + * Accessibility permission on macOS, unexpected exceptions from the + * keeper loop. Prefers the stack trace when available since these failures + * usually need a developer to interpret. + */ +function failRuntime(err: unknown): never { + const detail: string = err instanceof Error ? (err.stack ?? err.message) : String(err); + process.stderr.write(`move: runtime error: ${detail}\n`); + process.exit(1); +} + let cliArgs: ParsedCliArgs; try { cliArgs = parseCliArgs(); @@ -80,7 +98,4 @@ const cliOverrides: ConfigOverrides = { const config = resolveConfig(fileOverrides, cliOverrides); -runKeeper(config).catch((err: unknown): void => { - console.error("Error:", err); - process.exit(1); -}); +runKeeper(config).catch(failRuntime);