Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,12 @@ available programmatically via `@waymarks/core` (see `WaymarkCache`), and
| Code | Meaning |
| --- | --- |
| 0 | Success |
| 1 | Waymark error (lint failures, parse errors) |
| 2 | Usage error (invalid arguments) |
| 3 | Configuration error |
| 4 | I/O error (file not found, permission denied) |
| 1 | Validation error (invalid flags, arguments, or waymark syntax) |
| 2 | Not found (file, waymark, or resource missing) |
| 3 | Conflict (concurrent modification) |
| 4 | Permission error |
| 8 | Internal error (unexpected failure) |
| 130 | Cancelled (user interrupted) |

#### Shell Completions

Expand Down
7 changes: 3 additions & 4 deletions packages/cli/src/commands/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

import type { WaymarkConfig } from "@waymarks/core";

import { createUsageError } from "../errors.ts";
import { ExitCode } from "../exit-codes.ts";
import { ValidationError } from "@outfitter/contracts";
import type { CommandContext } from "../types.ts";

export type ConfigCommandOptions = {
Expand Down Expand Up @@ -37,7 +36,7 @@ export function runConfigCommand(
options: ConfigCommandOptions = {}
): ConfigCommandResult {
if (!options.print) {
throw createUsageError("Config command requires --print.");
throw ValidationError.fromMessage("Config command requires --print.");
}

const output = serializeConfig(context.config, {
Expand All @@ -46,6 +45,6 @@ export function runConfigCommand(

return {
output,
exitCode: ExitCode.success,
exitCode: 0,
};
}
10 changes: 4 additions & 6 deletions packages/cli/src/commands/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ import { existsSync } from "node:fs";
import { mkdir, readFile, writeFile } from "node:fs/promises";
import { homedir } from "node:os";
import { join, resolve } from "node:path";
import { InternalError, Result } from "@outfitter/contracts";
import { CliError } from "../errors.ts";
import { ExitCode } from "../exit-codes.ts";
import { CancelledError, InternalError, Result } from "@outfitter/contracts";
import { promptSelect } from "../utils/clack-prompts.ts";
import { logger } from "../utils/logger.ts";
import { assertPromptAllowed } from "../utils/prompts.ts";
Expand Down Expand Up @@ -71,7 +69,7 @@ async function runInitCommandInner(
initialValue: "yaml" as ConfigFormat,
});
if (formatResult.isErr()) {
throw new CliError("Init cancelled", ExitCode.usageError);
throw CancelledError.create("Init cancelled");
}
format = formatResult.value;

Expand All @@ -81,7 +79,7 @@ async function runInitCommandInner(
initialValue: "full" as ConfigPreset,
});
if (presetResult.isErr()) {
throw new CliError("Init cancelled", ExitCode.usageError);
throw CancelledError.create("Init cancelled");
}
preset = presetResult.value;

Expand All @@ -91,7 +89,7 @@ async function runInitCommandInner(
initialValue: "project" as ConfigScope,
});
if (scopeResult.isErr()) {
throw new CliError("Init cancelled", ExitCode.usageError);
throw CancelledError.create("Init cancelled");
}
scope = scopeResult.value;

Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/commands/register.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// tldr ::: commander command registration for waymark CLI

import { Command, InvalidArgumentError } from "commander";
import { createUsageError } from "../errors.ts";
import { ValidationError } from "@outfitter/contracts";
import type { ModifyCliOptions } from "../types.ts";
import { parsePropertyEntry } from "../utils/properties.ts";
import type { CheckCommandOptions } from "./check.ts";
Expand Down Expand Up @@ -135,7 +135,7 @@ export function registerCommands(
if (helpTopicNames.length > 0) {
writeStdout(`Available topics: ${helpTopicNames.join(", ")}`);
}
throw createUsageError(`Unknown command or topic: ${commandName}`);
throw ValidationError.fromMessage(`Unknown command or topic: ${commandName}`);
} catch (error) {
handleCommandError(program, error);
}
Expand Down
17 changes: 8 additions & 9 deletions packages/cli/src/commands/skill.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
// tldr ::: implement the wm skill command outputs [[cli/skill-command]]

import { resolve } from "node:path";
import { createUsageError } from "../errors.ts";
import { ExitCode } from "../exit-codes.ts";
import { ValidationError } from "@outfitter/contracts";
import {
listSkillSections,
loadSkillData,
Expand Down Expand Up @@ -55,15 +54,15 @@ export async function runSkillCommand(
const skillData = await loadSkillData(skillDir);
return {
output: formatJsonOutput(skillData),
exitCode: ExitCode.success,
exitCode: 0,
};
}

const core = await loadSkillSection(skillDir, "core", "core", "SKILL.md");

return {
output: core.content,
exitCode: ExitCode.success,
exitCode: 0,
};
}

Expand Down Expand Up @@ -140,7 +139,7 @@ export async function runSkillShowCommand(
const resolved = resolveSkillSection(manifest, section);

if (!resolved) {
throw createUsageError(`Unknown skill section: ${section}`);
throw ValidationError.fromMessage(`Unknown skill section: ${section}`);
}

const content = await loadSkillSection(
Expand All @@ -153,13 +152,13 @@ export async function runSkillShowCommand(
if (options.json) {
return {
output: formatJsonOutput(content),
exitCode: ExitCode.success,
exitCode: 0,
};
}

return {
output: content.content,
exitCode: ExitCode.success,
exitCode: 0,
};
}

Expand Down Expand Up @@ -207,7 +206,7 @@ export async function runSkillListCommand(

return {
output: lines.join("\n"),
exitCode: ExitCode.success,
exitCode: 0,
};
}

Expand All @@ -222,6 +221,6 @@ export function runSkillPathCommand(
const skillDir = resolveSkillDirectory(overrides);
return {
output: skillDir,
exitCode: ExitCode.success,
exitCode: 0,
};
}
31 changes: 0 additions & 31 deletions packages/cli/src/errors.ts

This file was deleted.

11 changes: 0 additions & 11 deletions packages/cli/src/exit-codes.ts

This file was deleted.

6 changes: 3 additions & 3 deletions packages/cli/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
} from "./commands/unified/index";
import { parseUnifiedArgs } from "./commands/unified/parser";
import type { UnifiedCommandOptions } from "./commands/unified/types";
import { ExitCode } from "./exit-codes";
import { getExitCode } from "@outfitter/contracts";
import { runCli } from "./index";
import type { CommandContext } from "./types";
import { renderRecords } from "./utils/output";
Expand Down Expand Up @@ -1302,7 +1302,7 @@ describe("Commander integration", () => {

test("unknown option returns a usage error exit code", async () => {
const result = await runCliCaptured(["find", "--definitely-not-a-flag"]);
expect(result.exitCode).toBe(ExitCode.usageError);
expect(result.exitCode).toBe(getExitCode("validation"));
});

test("no-input fails when format requires confirmation", async () => {
Expand All @@ -1315,7 +1315,7 @@ describe("Commander integration", () => {
"--write",
"--no-input",
]);
expect(result.exitCode).toBe(ExitCode.usageError);
expect(result.exitCode).toBe(getExitCode("validation"));
} finally {
await cleanup();
}
Expand Down
Loading