From 8eac51cd45048cf2c4acdf9d26f82505668c3122 Mon Sep 17 00:00:00 2001 From: nokeo08 Date: Wed, 17 Jun 2026 16:22:33 -0500 Subject: [PATCH] Extract CliError into src/errors.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CliError used to live in cli.ts and was imported by configFile.ts purely to grab a one-line class — the dependency arrow said 'config-file loader depends on the CLI parser' when really it just needed a shared error type. Moving CliError to its own errors.ts module flattens the graph: errors.ts (no internal deps) | +-- cli.ts +-- configFile.ts +-- config.ts (will use it in the next commit) cli.ts re-exports CliError for any consumer that prefers to keep importing it from there; the canonical home is now errors.ts. --- src/cli.ts | 9 +-------- src/config.ts | 14 +++++++++++++- src/configFile.ts | 2 +- src/errors.ts | 16 ++++++++++++++++ src/move.ts | 8 +++++++- 5 files changed, 38 insertions(+), 11 deletions(-) create mode 100644 src/errors.ts diff --git a/src/cli.ts b/src/cli.ts index bf95382..fb992d2 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -27,14 +27,7 @@ import { fileURLToPath } from "node:url"; import { parseArgs } from "node:util"; import { DEFAULT_CONFIG, defaultConfigPath } from "./config.ts"; - -/** - * Thrown when CLI input is invalid (unknown option, missing value, bad - * number, malformed config file). Distinct from runtime errors so the - * entry point can exit with code 2 (user error) instead of code 1 - * (runtime failure). - */ -export class CliError extends Error {} +import { CliError } from "./errors.ts"; /** * Result of `parseCliArgs`. Numeric fields are `undefined` when the user diff --git a/src/config.ts b/src/config.ts index f6a0f70..616dab7 100644 --- a/src/config.ts +++ b/src/config.ts @@ -21,6 +21,8 @@ import { join } from "node:path"; +import { CliError } from "./errors.ts"; + // Single source of truth for default values. The same file ships in the // install tree and is copied to $XDG_CONFIG_HOME/move/config.json on a // fresh install (only if no config exists there yet). Values use the CLI @@ -141,7 +143,17 @@ export function defaultConfigPath(): string { if (xdg && xdg.length > 0) { return join(xdg, "move", "config.json"); } - const home = process.env.HOME ?? ""; + const home = process.env.HOME; + if (!home || home.length === 0) { + // Neither var is set; we don't have a sensible fallback. Throwing + // CliError lets the entry-point's normal handler surface this as + // 'move: cannot resolve default config path: ...' + exit 2 instead + // of silently producing '/.config/move/config.json' and bewildering + // the user with a downstream 'file not found' message. + throw new CliError( + "cannot resolve default config path: neither $XDG_CONFIG_HOME nor $HOME is set", + ); + } return join(home, ".config", "move", "config.json"); } diff --git a/src/configFile.ts b/src/configFile.ts index cf06be4..3a47c66 100644 --- a/src/configFile.ts +++ b/src/configFile.ts @@ -27,8 +27,8 @@ import { existsSync, readFileSync, statSync } from "node:fs"; -import { CliError } from "./cli.ts"; import { defaultConfigPath, type ConfigOverrides } from "./config.ts"; +import { CliError } from "./errors.ts"; const ALLOWED_KEYS: ReadonlySet = new Set([ "moveInterval", diff --git a/src/errors.ts b/src/errors.ts new file mode 100644 index 0000000..28ab339 --- /dev/null +++ b/src/errors.ts @@ -0,0 +1,16 @@ +/** + * errors.ts + * --------- + * Cross-cutting error types used by parsers, loaders, and config resolution. + * Kept in its own module so feature modules can import error types without + * pulling in unrelated implementation code (e.g., the JSON loader doesn't + * need to depend on the CLI parser just to throw a typed error). + */ + +/** + * Thrown when user-supplied input is invalid: unknown CLI option, missing + * value, non-positive number, malformed config file, unresolvable default + * path, etc. Distinct from runtime errors so the top-level entry can exit + * with code 2 (user error) instead of code 1 (runtime failure). + */ +export class CliError extends Error {} diff --git a/src/move.ts b/src/move.ts index e62b1ff..ef9c2ab 100755 --- a/src/move.ts +++ b/src/move.ts @@ -49,7 +49,13 @@ try { } if (cliArgs.help) { - printHelp(); + // printHelp() resolves defaultConfigPath(), which can throw CliError + // when neither $XDG_CONFIG_HOME nor $HOME is set. + try { + printHelp(); + } catch (err: unknown) { + failUser(err); + } process.exit(0); } if (cliArgs.version) {