@mutmutco/cli 3.19.2 → 3.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/main.cjs +35 -7
  2. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -3602,6 +3602,10 @@ async function failGraceful(msg) {
3602
3602
  var ERROR_CODES = {
3603
3603
  /** A required flag was not supplied (e.g. `issue create` without `--priority`). */
3604
3604
  ERR_MISSING_FLAG: "ERR_MISSING_FLAG",
3605
+ /** Two mutually-exclusive flags were both supplied (e.g. `--title` with `--title-file`). */
3606
+ ERR_CONFLICTING_FLAGS: "ERR_CONFLICTING_FLAGS",
3607
+ /** A flag was supplied but its resolved value is empty (e.g. an empty `--title-file` or empty stdin). */
3608
+ ERR_EMPTY_INPUT: "ERR_EMPTY_INPUT",
3605
3609
  /** A flag's value is outside its allowed set (e.g. `--priority nope`). */
3606
3610
  ERR_BAD_ENUM: "ERR_BAD_ENUM",
3607
3611
  /** An unknown flag or subcommand — usually a typo; carries a `did_you_mean`. */
@@ -3619,6 +3623,16 @@ var ERROR_CODE_REFERENCE = [
3619
3623
  meaning: "A required flag was not supplied.",
3620
3624
  typical_fix: "Run `mmi-cli explain <command>` and retry with the required flag."
3621
3625
  },
3626
+ {
3627
+ code: ERROR_CODES.ERR_CONFLICTING_FLAGS,
3628
+ meaning: "Two mutually-exclusive flags were supplied together.",
3629
+ typical_fix: "Pass only one of the conflicting flags (see `offending_flag`) and retry."
3630
+ },
3631
+ {
3632
+ code: ERROR_CODES.ERR_EMPTY_INPUT,
3633
+ meaning: "A flag was supplied but resolved to an empty value (e.g. an empty file or empty stdin).",
3634
+ typical_fix: "Provide non-empty content for the flag in `offending_flag` (a file with text, or a real pipe/heredoc for stdin)."
3635
+ },
3622
3636
  {
3623
3637
  code: ERROR_CODES.ERR_BAD_ENUM,
3624
3638
  meaning: "A flag value is outside the allowed enum.",
@@ -3680,6 +3694,7 @@ function didYouMean(input, candidates) {
3680
3694
  for (const candidate of candidates) {
3681
3695
  const cand = strip(candidate);
3682
3696
  if (!cand) continue;
3697
+ if (cand === target) continue;
3683
3698
  const distance = levenshtein(target, cand);
3684
3699
  const prefix = cand.startsWith(target) || target.startsWith(cand);
3685
3700
  const threshold = Math.max(2, Math.ceil(cand.length * 0.4));
@@ -10135,6 +10150,16 @@ function buildPrArgs({ title, body, base, head, repo, draft }) {
10135
10150
 
10136
10151
  // src/issue-body.ts
10137
10152
  var import_node_os4 = require("node:os");
10153
+ var TextArgError = class extends Error {
10154
+ constructor(message, code, offendingFlag) {
10155
+ super(message);
10156
+ this.code = code;
10157
+ this.offendingFlag = offendingFlag;
10158
+ this.name = "TextArgError";
10159
+ }
10160
+ code;
10161
+ offendingFlag;
10162
+ };
10138
10163
  function emptyStdinMessage(fileFlag) {
10139
10164
  if ((0, import_node_os4.platform)() === "win32") {
10140
10165
  return `${fileFlag} - read empty stdin (on Windows, ${fileFlag} - is unreliable through the npm .cmd shim \u2014 use ${fileFlag} <path>, or pipe to \`node cli/dist/index.cjs\` directly)`;
@@ -10145,17 +10170,20 @@ async function resolveTextArg(input, deps, labels) {
10145
10170
  const hasValue = input.value !== void 0;
10146
10171
  const hasFile = input.file !== void 0;
10147
10172
  if (hasValue && hasFile) {
10148
- throw new Error(`pass only one of ${labels.value} or ${labels.file}`);
10173
+ throw new TextArgError(`pass only one of ${labels.value} or ${labels.file}`, ERROR_CODES.ERR_CONFLICTING_FLAGS, labels.value);
10149
10174
  }
10150
10175
  if (!hasValue && !hasFile) {
10151
- throw new Error(`pass ${labels.value} or ${labels.file}`);
10176
+ throw new TextArgError(`pass ${labels.value} or ${labels.file}`, ERROR_CODES.ERR_MISSING_FLAG, labels.value);
10152
10177
  }
10153
10178
  if (hasValue) return input.value ?? "";
10154
10179
  const source = input.file ?? "";
10155
10180
  const text = source === "-" ? await deps.readStdin() : await deps.readFile(source, "utf8");
10156
10181
  if (text.trim().length === 0) {
10157
- throw new Error(
10158
- source === "-" ? emptyStdinMessage(labels.file) : `${labels.file} produced an empty ${labels.noun}`
10182
+ throw new TextArgError(
10183
+ source === "-" ? emptyStdinMessage(labels.file) : `${labels.file} produced an empty ${labels.noun}`,
10184
+ // The flag WAS supplied — it just resolved empty — so this is ERR_EMPTY_INPUT, not ERR_MISSING_FLAG.
10185
+ ERROR_CODES.ERR_EMPTY_INPUT,
10186
+ labels.file
10159
10187
  );
10160
10188
  }
10161
10189
  return text;
@@ -21036,7 +21064,7 @@ withExamples(mutating(
21036
21064
  });
21037
21065
  if (o.parent !== void 0) parseIssueRef(o.parent);
21038
21066
  } catch (e) {
21039
- return fail(`issue create: ${e.message}`);
21067
+ return fail(`issue create: ${e.message}`, e instanceof TextArgError ? { code: e.code, offending_flag: e.offendingFlag } : void 0);
21040
21068
  }
21041
21069
  for (const label of extraLabels) {
21042
21070
  const la = ["label", "create", label, "--color", "ededed"];
@@ -21311,14 +21339,14 @@ program2.command("skill-lesson").description("file a skill-lesson on the Hub boa
21311
21339
  console.log(JSON.stringify({ ...created, deduped: false, label: SKILL_LESSON_LABEL, skill, priority, projectItemId, onBoard }));
21312
21340
  });
21313
21341
  var pr = program2.command("pr").description("pull requests \u2014 reliable create with structured output");
21314
- withExamples(pr.command("create").description("create a PR and print {number,url} JSON").option("--title <title>", "PR title").option("--title-file <path|->", "read the PR title from a UTF-8 file, or from stdin with -").option("--body <body>", "PR body (markdown)").option("--body-file <path|->", "read PR body from a UTF-8 file, or from stdin with -").option("--base <branch>", "base branch (defaults to the repo default)").option("--head <branch>", "head branch (defaults to the current branch)").option("--repo <owner/repo>", "target repo (defaults to the current repo)").option("--draft", "open the PR in draft state (#2667)").action(async (o) => {
21342
+ withExamples(pr.command("create").description("create a PR and print {number,url} JSON").option("--title <title>", "PR title").option("--title-file <path|->", "read the PR title from a UTF-8 file, or from stdin with -").option("--body <body>", "PR body (markdown)").option("--body-file <path|->", "read PR body from a UTF-8 file, or from stdin with -").option("--base <branch>", "base branch (defaults to the repo default)").option("--head <branch>", "head branch (defaults to the current branch)").option("--repo <owner/repo>", "target repo (defaults to the current repo)").option("--draft", "open the PR in draft state (#2667)").option("--json", "machine-readable output (default; accepted for parity)").action(async (o) => {
21315
21343
  let body;
21316
21344
  let title;
21317
21345
  try {
21318
21346
  title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises5.readFile, readStdin });
21319
21347
  body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises5.readFile, readStdin });
21320
21348
  } catch (e) {
21321
- return fail(`pr create: ${e.message}`);
21349
+ return fail(`pr create: ${e.message}`, e instanceof TextArgError ? { code: e.code, offending_flag: e.offendingFlag } : void 0);
21322
21350
  }
21323
21351
  const created = await ghCreate(buildPrArgs({ title, body, base: o.base, head: o.head, repo: o.repo, draft: o.draft }));
21324
21352
  console.log(JSON.stringify(created));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "3.19.2",
3
+ "version": "3.20.0",
4
4
  "description": "MMI Future CLI — the org dev toolbox (board, registry, keyless secrets, release train, bootstrap, doctor) and the cross-IDE engine the plugin's session-start hook drives.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",