@jacobsandersen/glab-axi 0.1.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 (82) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +139 -0
  3. package/dist/bin/glab-axi.d.ts +2 -0
  4. package/dist/bin/glab-axi.js +4 -0
  5. package/dist/bin/glab-axi.js.map +1 -0
  6. package/dist/src/args.d.ts +8 -0
  7. package/dist/src/args.js +84 -0
  8. package/dist/src/args.js.map +1 -0
  9. package/dist/src/body.d.ts +15 -0
  10. package/dist/src/body.js +132 -0
  11. package/dist/src/body.js.map +1 -0
  12. package/dist/src/cli.d.ts +9 -0
  13. package/dist/src/cli.js +124 -0
  14. package/dist/src/cli.js.map +1 -0
  15. package/dist/src/commands/api.d.ts +3 -0
  16. package/dist/src/commands/api.js +155 -0
  17. package/dist/src/commands/api.js.map +1 -0
  18. package/dist/src/commands/home.d.ts +3 -0
  19. package/dist/src/commands/home.js +57 -0
  20. package/dist/src/commands/home.js.map +1 -0
  21. package/dist/src/commands/issue.d.ts +3 -0
  22. package/dist/src/commands/issue.js +364 -0
  23. package/dist/src/commands/issue.js.map +1 -0
  24. package/dist/src/commands/job.d.ts +3 -0
  25. package/dist/src/commands/job.js +119 -0
  26. package/dist/src/commands/job.js.map +1 -0
  27. package/dist/src/commands/label.d.ts +3 -0
  28. package/dist/src/commands/label.js +117 -0
  29. package/dist/src/commands/label.js.map +1 -0
  30. package/dist/src/commands/mr.d.ts +3 -0
  31. package/dist/src/commands/mr.js +365 -0
  32. package/dist/src/commands/mr.js.map +1 -0
  33. package/dist/src/commands/pipeline.d.ts +3 -0
  34. package/dist/src/commands/pipeline.js +168 -0
  35. package/dist/src/commands/pipeline.js.map +1 -0
  36. package/dist/src/commands/project.d.ts +3 -0
  37. package/dist/src/commands/project.js +138 -0
  38. package/dist/src/commands/project.js.map +1 -0
  39. package/dist/src/commands/release.d.ts +3 -0
  40. package/dist/src/commands/release.js +179 -0
  41. package/dist/src/commands/release.js.map +1 -0
  42. package/dist/src/commands/search.d.ts +3 -0
  43. package/dist/src/commands/search.js +266 -0
  44. package/dist/src/commands/search.js.map +1 -0
  45. package/dist/src/commands/setup.d.ts +2 -0
  46. package/dist/src/commands/setup.js +23 -0
  47. package/dist/src/commands/setup.js.map +1 -0
  48. package/dist/src/commands/variable.d.ts +3 -0
  49. package/dist/src/commands/variable.js +92 -0
  50. package/dist/src/commands/variable.js.map +1 -0
  51. package/dist/src/context.d.ts +7 -0
  52. package/dist/src/context.js +42 -0
  53. package/dist/src/context.js.map +1 -0
  54. package/dist/src/errors.d.ts +5 -0
  55. package/dist/src/errors.js +81 -0
  56. package/dist/src/errors.js.map +1 -0
  57. package/dist/src/fields.d.ts +10 -0
  58. package/dist/src/fields.js +26 -0
  59. package/dist/src/fields.js.map +1 -0
  60. package/dist/src/format.d.ts +8 -0
  61. package/dist/src/format.js +17 -0
  62. package/dist/src/format.js.map +1 -0
  63. package/dist/src/glab.d.ts +10 -0
  64. package/dist/src/glab.js +73 -0
  65. package/dist/src/glab.js.map +1 -0
  66. package/dist/src/secretValue.d.ts +1 -0
  67. package/dist/src/secretValue.js +33 -0
  68. package/dist/src/secretValue.js.map +1 -0
  69. package/dist/src/skill.d.ts +6 -0
  70. package/dist/src/skill.js +79 -0
  71. package/dist/src/skill.js.map +1 -0
  72. package/dist/src/stdin.d.ts +2 -0
  73. package/dist/src/stdin.js +15 -0
  74. package/dist/src/stdin.js.map +1 -0
  75. package/dist/src/suggestions.d.ts +11 -0
  76. package/dist/src/suggestions.js +262 -0
  77. package/dist/src/suggestions.js.map +1 -0
  78. package/dist/src/toon.d.ts +57 -0
  79. package/dist/src/toon.js +150 -0
  80. package/dist/src/toon.js.map +1 -0
  81. package/package.json +59 -0
  82. package/skills/glab-axi/SKILL.md +51 -0
@@ -0,0 +1,119 @@
1
+ import { encode } from "@toon-format/toon";
2
+ import { glabJson, glabExec } from "../glab.js";
3
+ import { AxiError } from "../errors.js";
4
+ import { getFlag } from "../args.js";
5
+ import { field, lower, relativeTime, renderList, renderDetail, renderHelp, renderOutput, renderError, } from "../toon.js";
6
+ import { formatCountLine } from "../format.js";
7
+ import { getSuggestions } from "../suggestions.js";
8
+ export const JOB_HELP = `usage: glab-axi job <subcommand> [flags]
9
+ subcommands[4]:
10
+ list, view <id>, log <id>, retry <id>
11
+ flags{list}:
12
+ --pipeline <id>, --per-page <n> (default 20)
13
+ examples:
14
+ glab-axi job list --pipeline 12345
15
+ glab-axi job view 67890
16
+ glab-axi job log 67890
17
+ glab-axi job retry 67890`;
18
+ const listSchema = [
19
+ field("id"),
20
+ field("name"),
21
+ lower("status"),
22
+ relativeTime("created_at", "created"),
23
+ field("stage"),
24
+ ];
25
+ const viewSchema = [
26
+ field("id"),
27
+ field("name"),
28
+ lower("status"),
29
+ field("stage"),
30
+ field("ref"),
31
+ relativeTime("created_at", "created"),
32
+ relativeTime("started_at", "started"),
33
+ field("web_url", "url"),
34
+ ];
35
+ async function listJobs(args, ctx) {
36
+ const pipeline = getFlag(args, "--pipeline");
37
+ const perPage = getFlag(args, "--per-page") ?? "20";
38
+ const ghArgs = [
39
+ "job",
40
+ "list",
41
+ "--json",
42
+ "id,name,status,created_at,stage",
43
+ "--per-page",
44
+ perPage,
45
+ ];
46
+ if (pipeline)
47
+ ghArgs.push("--pipeline", pipeline);
48
+ const jobs = await glabJson(ghArgs, ctx);
49
+ const isEmpty = jobs.length === 0;
50
+ const limitNum = Number(perPage);
51
+ const countLine = formatCountLine({ count: jobs.length, limit: limitNum });
52
+ const suggestions = getSuggestions({
53
+ domain: "job",
54
+ action: "list",
55
+ isEmpty,
56
+ repo: ctx,
57
+ });
58
+ return renderOutput([
59
+ countLine,
60
+ renderList("jobs", jobs, listSchema),
61
+ renderHelp(suggestions),
62
+ ]);
63
+ }
64
+ async function viewJob(args, ctx) {
65
+ const positionals = args.filter((a) => !a.startsWith("--"));
66
+ const id = positionals[1];
67
+ if (!id)
68
+ throw new AxiError("Job ID is required: glab-axi job view <id>", "VALIDATION_ERROR");
69
+ const job = await glabJson([
70
+ "job",
71
+ "view",
72
+ id,
73
+ "--json",
74
+ "id,name,status,stage,ref,created_at,started_at,web_url",
75
+ ], ctx);
76
+ return renderOutput([
77
+ renderDetail("job", job, viewSchema),
78
+ renderHelp(getSuggestions({ domain: "job", action: "view", id, repo: ctx })),
79
+ ]);
80
+ }
81
+ async function jobLog(args, ctx) {
82
+ const positionals = args.filter((a) => !a.startsWith("--"));
83
+ const id = positionals[1];
84
+ if (!id)
85
+ throw new AxiError("Job ID is required: glab-axi job log <id>", "VALIDATION_ERROR");
86
+ const log = await glabExec(["job", "log", id], ctx);
87
+ return encode({ job_log: { id, output: log } });
88
+ }
89
+ async function retryJob(args, ctx) {
90
+ const positionals = args.filter((a) => !a.startsWith("--"));
91
+ const id = positionals[1];
92
+ if (!id)
93
+ throw new AxiError("Job ID is required: glab-axi job retry <id>", "VALIDATION_ERROR");
94
+ await glabExec(["job", "retry", id], ctx);
95
+ return renderOutput([
96
+ encode({ retry: "ok", job: id }),
97
+ renderHelp([`Run \`glab-axi job log ${id}\` to monitor progress`]),
98
+ ]);
99
+ }
100
+ export async function jobCommand(args, ctx) {
101
+ const sub = args[0];
102
+ if (sub === "--help" || sub === undefined)
103
+ return JOB_HELP;
104
+ switch (sub) {
105
+ case "list":
106
+ return listJobs(args, ctx);
107
+ case "view":
108
+ return viewJob(args, ctx);
109
+ case "log":
110
+ return jobLog(args, ctx);
111
+ case "retry":
112
+ return retryJob(args, ctx);
113
+ default:
114
+ return renderError(`Unknown subcommand: ${sub}`, "VALIDATION_ERROR", [
115
+ "Available subcommands: list, view, log, retry",
116
+ ]);
117
+ }
118
+ }
119
+ //# sourceMappingURL=job.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job.js","sourceRoot":"","sources":["../../../src/commands/job.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { RepoContext } from "../context.js";
2
+ export declare const LABEL_HELP = "usage: glab-axi label <subcommand> [flags]\nsubcommands[4]:\n list, create, edit <name>, delete <name>\nflags{list}:\n --per-page <n> (default 50)\nflags{create}:\n --name <text> (required), --color <hex> (required, without #), --description <text>\nflags{edit}:\n --name, --color, --description\nexamples:\n glab-axi label list\n glab-axi label create --name \"priority:high\" --color ff0000 --description \"High priority\"\n glab-axi label delete \"priority:low\"";
3
+ export declare function labelCommand(args: string[], ctx?: RepoContext): Promise<string>;
@@ -0,0 +1,117 @@
1
+ import { encode } from "@toon-format/toon";
2
+ import { glabJson, glabExec } from "../glab.js";
3
+ import { AxiError } from "../errors.js";
4
+ import { getFlag } from "../args.js";
5
+ import { field, renderList, renderHelp, renderOutput, renderError, } from "../toon.js";
6
+ import { formatCountLine } from "../format.js";
7
+ import { getSuggestions } from "../suggestions.js";
8
+ export const LABEL_HELP = `usage: glab-axi label <subcommand> [flags]
9
+ subcommands[4]:
10
+ list, create, edit <name>, delete <name>
11
+ flags{list}:
12
+ --per-page <n> (default 50)
13
+ flags{create}:
14
+ --name <text> (required), --color <hex> (required, without #), --description <text>
15
+ flags{edit}:
16
+ --name, --color, --description
17
+ examples:
18
+ glab-axi label list
19
+ glab-axi label create --name "priority:high" --color ff0000 --description "High priority"
20
+ glab-axi label delete "priority:low"`;
21
+ const listSchema = [field("name")];
22
+ async function listLabels(args, ctx) {
23
+ const perPage = getFlag(args, "--per-page") ?? "50";
24
+ const ghArgs = ["label", "list", "--json", "name", "--per-page", perPage];
25
+ const labels = await glabJson(ghArgs, ctx);
26
+ const isEmpty = labels.length === 0;
27
+ const limitNum = Number(perPage);
28
+ const countLine = formatCountLine({ count: labels.length, limit: limitNum });
29
+ const suggestions = getSuggestions({
30
+ domain: "label",
31
+ action: "list",
32
+ isEmpty,
33
+ repo: ctx,
34
+ });
35
+ return renderOutput([
36
+ countLine,
37
+ renderList("labels", labels, listSchema),
38
+ renderHelp(suggestions),
39
+ ]);
40
+ }
41
+ async function createLabel(args, ctx) {
42
+ const name = getFlag(args, "--name");
43
+ if (!name)
44
+ throw new AxiError('--name is required: glab-axi label create --name "..." --color "..."', "VALIDATION_ERROR");
45
+ const color = getFlag(args, "--color");
46
+ if (!color)
47
+ throw new AxiError('--color is required: glab-axi label create --name "..." --color "..."', "VALIDATION_ERROR");
48
+ const existing = await glabJson(["label", "list", "--json", "name"], ctx);
49
+ const found = existing.find((l) => typeof l.name === "string" && l.name.toLowerCase() === name.toLowerCase());
50
+ if (found) {
51
+ return renderOutput([
52
+ encode({ create: "already_exists", label: found.name }),
53
+ renderHelp(getSuggestions({ domain: "label", action: "create", repo: ctx })),
54
+ ]);
55
+ }
56
+ const ghArgs = ["label", "create", name, "--color", color];
57
+ const description = getFlag(args, "--description");
58
+ if (description)
59
+ ghArgs.push("--description", description);
60
+ await glabExec(ghArgs, ctx);
61
+ return renderOutput([
62
+ encode({ created: "ok", label: name }),
63
+ renderHelp(getSuggestions({ domain: "label", action: "create", repo: ctx })),
64
+ ]);
65
+ }
66
+ async function editLabel(args, ctx) {
67
+ const positionals = args.filter((a) => !a.startsWith("--"));
68
+ const labelName = positionals[1];
69
+ if (!labelName)
70
+ throw new AxiError("Label name is required: glab-axi label edit <name>", "VALIDATION_ERROR");
71
+ const ghArgs = ["label", "edit", labelName];
72
+ const newName = getFlag(args, "--name");
73
+ if (newName)
74
+ ghArgs.push("--name", newName);
75
+ const color = getFlag(args, "--color");
76
+ if (color)
77
+ ghArgs.push("--color", color);
78
+ const description = getFlag(args, "--description");
79
+ if (description)
80
+ ghArgs.push("--description", description);
81
+ await glabExec(ghArgs, ctx);
82
+ return renderOutput([
83
+ encode({ edit: "ok", label: newName ?? labelName }),
84
+ renderHelp(getSuggestions({ domain: "label", action: "edit", repo: ctx })),
85
+ ]);
86
+ }
87
+ async function deleteLabel(args, ctx) {
88
+ const positionals = args.filter((a) => !a.startsWith("--"));
89
+ const name = positionals[1];
90
+ if (!name)
91
+ throw new AxiError("Label name is required: glab-axi label delete <name>", "VALIDATION_ERROR");
92
+ await glabExec(["label", "delete", name, "--yes"], ctx);
93
+ return renderOutput([
94
+ encode({ delete: "ok", label: name }),
95
+ renderHelp(getSuggestions({ domain: "label", action: "delete", repo: ctx })),
96
+ ]);
97
+ }
98
+ export async function labelCommand(args, ctx) {
99
+ const sub = args[0];
100
+ if (sub === "--help" || sub === undefined)
101
+ return LABEL_HELP;
102
+ switch (sub) {
103
+ case "list":
104
+ return listLabels(args, ctx);
105
+ case "create":
106
+ return createLabel(args, ctx);
107
+ case "edit":
108
+ return editLabel(args, ctx);
109
+ case "delete":
110
+ return deleteLabel(args, ctx);
111
+ default:
112
+ return renderError(`Unknown subcommand: ${sub}`, "VALIDATION_ERROR", [
113
+ "Available subcommands: list, create, edit, delete",
114
+ ]);
115
+ }
116
+ }
117
+ //# sourceMappingURL=label.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"label.js","sourceRoot":"","sources":["../../../src/commands/label.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { RepoContext } from "../context.js";
2
+ export declare const MR_HELP = "usage: glab-axi mr <subcommand> [flags]\nsubcommands[11]:\n list, view <number>, create, edit <number>, close <number>, reopen <number>, merge <number>, approve <number>, note <number>, diff <number>, checkout <number>\nflags{list}:\n --state <opened|closed|merged|all>, --label, --assignee, --author, --source-branch, --target-branch, --per-page <n> (default 20), --fields <a,b,c>\nflags{view}:\n --comments, --full (show complete description without truncation)\nflags{create}:\n --title <text> (required), --description <text> or --body-file <path>, --source-branch, --target-branch, --draft, --label <name> (repeatable), --assignee <username>, --milestone\nflags{edit}:\n --title <text>, --description <text> or --body-file <path>, --add-label, --remove-label, --add-assignee, --remove-assignee, --milestone\nflags{merge}:\n --squash\nflags{note}:\n --body <text> or --body-file <path> (required)\nexamples:\n glab-axi mr list --state opened --label bug\n glab-axi mr view 42 --comments\n glab-axi mr create --title \"Fix login\" --source-branch fix --target-branch main\n glab-axi mr note 42 --body-file comment.md\n glab-axi mr merge 42 --squash";
3
+ export declare function mrCommand(args: string[], ctx?: RepoContext): Promise<string>;
@@ -0,0 +1,365 @@
1
+ import { encode } from "@toon-format/toon";
2
+ import { glabJson, glabExec } from "../glab.js";
3
+ import { AxiError } from "../errors.js";
4
+ import { takeBody, truncateBody } from "../body.js";
5
+ import { formatCountLine } from "../format.js";
6
+ import { getSuggestions } from "../suggestions.js";
7
+ import { takeFlag, takeBoolFlag, takeNumber, getAllFlags } from "../args.js";
8
+ import { parseFields } from "../fields.js";
9
+ import { field, pluck, lower, mapEnum, relativeTime, joinArray, custom, renderList, renderDetail, renderHelp, renderError, renderOutput, } from "../toon.js";
10
+ const MERGE_STATUS_MAP = {
11
+ can_be_merged: "can_merge",
12
+ cannot_be_merged: "conflict",
13
+ cannot_be_merged_recheck: "conflict",
14
+ unchecked: "unchecked",
15
+ checking: "checking",
16
+ };
17
+ const listSchema = [
18
+ field("iid", "number"),
19
+ field("title"),
20
+ lower("state"),
21
+ pluck("author", "username", "author"),
22
+ mapEnum("merge_status", MERGE_STATUS_MAP, "unknown", "merge_status"),
23
+ ];
24
+ const LIST_JSON_FIELDS = "iid,title,state,author,merge_status";
25
+ const MR_LIST_EXTRA_FIELDS = {
26
+ description: { jsonKey: "description", def: field("description") },
27
+ created_at: {
28
+ jsonKey: "created_at",
29
+ def: relativeTime("created_at", "created"),
30
+ },
31
+ labels: { jsonKey: "labels", def: joinArray("labels", "name", "labels") },
32
+ milestone: {
33
+ jsonKey: "milestone",
34
+ def: pluck("milestone", "title", "milestone"),
35
+ },
36
+ merged_at: {
37
+ jsonKey: "merged_at",
38
+ def: relativeTime("merged_at", "merged_at"),
39
+ },
40
+ url: { jsonKey: "web_url", def: field("web_url", "url") },
41
+ };
42
+ const viewSchema = [
43
+ field("iid", "number"),
44
+ field("title"),
45
+ lower("state"),
46
+ pluck("author", "username", "author"),
47
+ mapEnum("merge_status", MERGE_STATUS_MAP, "unknown", "merge_status"),
48
+ custom("description", (item) => truncateBody(item.description, 500)),
49
+ custom("pipelines", (item) => {
50
+ if (!Array.isArray(item.pipelines) || item.pipelines.length === 0)
51
+ return "none";
52
+ const pipes = item.pipelines;
53
+ return pipes
54
+ .map((p) => `#${p.id ?? p.iid} (${(p.status ?? "unknown")})`)
55
+ .join(", ");
56
+ }),
57
+ ];
58
+ const viewSchemaFull = viewSchema.map((f) => "as" in f && f.as === "description"
59
+ ? custom("description", (item) => typeof item.description === "string" ? item.description : "")
60
+ : f);
61
+ export const MR_HELP = `usage: glab-axi mr <subcommand> [flags]
62
+ subcommands[11]:
63
+ list, view <number>, create, edit <number>, close <number>, reopen <number>, merge <number>, approve <number>, note <number>, diff <number>, checkout <number>
64
+ flags{list}:
65
+ --state <opened|closed|merged|all>, --label, --assignee, --author, --source-branch, --target-branch, --per-page <n> (default 20), --fields <a,b,c>
66
+ flags{view}:
67
+ --comments, --full (show complete description without truncation)
68
+ flags{create}:
69
+ --title <text> (required), --description <text> or --body-file <path>, --source-branch, --target-branch, --draft, --label <name> (repeatable), --assignee <username>, --milestone
70
+ flags{edit}:
71
+ --title <text>, --description <text> or --body-file <path>, --add-label, --remove-label, --add-assignee, --remove-assignee, --milestone
72
+ flags{merge}:
73
+ --squash
74
+ flags{note}:
75
+ --body <text> or --body-file <path> (required)
76
+ examples:
77
+ glab-axi mr list --state opened --label bug
78
+ glab-axi mr view 42 --comments
79
+ glab-axi mr create --title "Fix login" --source-branch fix --target-branch main
80
+ glab-axi mr note 42 --body-file comment.md
81
+ glab-axi mr merge 42 --squash`;
82
+ async function mrList(args, ctx) {
83
+ const fieldsArg = takeFlag(args, "--fields");
84
+ const { extraDefs, extraJsonKeys } = parseFields(fieldsArg, MR_LIST_EXTRA_FIELDS);
85
+ const state = takeFlag(args, "--state") ?? "opened";
86
+ const label = takeFlag(args, "--label");
87
+ const assignee = takeFlag(args, "--assignee");
88
+ const author = takeFlag(args, "--author");
89
+ const sourceBranch = takeFlag(args, "--source-branch");
90
+ const targetBranch = takeFlag(args, "--target-branch");
91
+ const perPage = takeFlag(args, "--per-page") ?? "20";
92
+ const jsonFields = extraJsonKeys.length > 0
93
+ ? LIST_JSON_FIELDS + "," + extraJsonKeys.join(",")
94
+ : LIST_JSON_FIELDS;
95
+ const ghArgs = [
96
+ "mr",
97
+ "list",
98
+ "--json",
99
+ jsonFields,
100
+ "--state",
101
+ state,
102
+ "--per-page",
103
+ perPage,
104
+ ];
105
+ if (label)
106
+ ghArgs.push("--label", label);
107
+ if (assignee)
108
+ ghArgs.push("--assignee", assignee);
109
+ if (author)
110
+ ghArgs.push("--author", author);
111
+ if (sourceBranch)
112
+ ghArgs.push("--source-branch", sourceBranch);
113
+ if (targetBranch)
114
+ ghArgs.push("--target-branch", targetBranch);
115
+ const items = await glabJson(ghArgs, ctx);
116
+ const isEmpty = items.length === 0;
117
+ const limitNum = Number(perPage);
118
+ const countLine = formatCountLine({ count: items.length, limit: limitNum });
119
+ const extendedSchema = extraDefs.length > 0 ? [...listSchema, ...extraDefs] : listSchema;
120
+ return renderOutput([
121
+ countLine,
122
+ renderList("merge_requests", items, extendedSchema),
123
+ renderHelp(getSuggestions({ domain: "mr", action: "list", isEmpty, repo: ctx })),
124
+ ]);
125
+ }
126
+ async function mrView(args, ctx) {
127
+ const includeNotes = takeBoolFlag(args, "--comments");
128
+ const full = takeBoolFlag(args, "--full");
129
+ const num = takeNumber(args, "MR");
130
+ const fields = "iid,title,state,author,merge_status,description,labels,assignees,milestone,merge_error,merge_status,pipelines" +
131
+ (includeNotes ? ",notes" : "");
132
+ const mr = await glabJson(["mr", "view", String(num), "--json", fields], ctx);
133
+ const schema = [...(full ? viewSchemaFull : viewSchema)];
134
+ if (includeNotes && Array.isArray(mr.notes)) {
135
+ schema.push(custom("notes", (item) => (item.notes ?? []).map((n) => ({
136
+ author: n.author?.username ?? "unknown",
137
+ body: n.body ?? "",
138
+ created: n.created_at ?? "",
139
+ }))));
140
+ }
141
+ else {
142
+ const noteCount = Array.isArray(mr.notes) ? mr.notes.length : 0;
143
+ schema.push(custom("note_count", () => `${noteCount} — use --comments to see full notes`));
144
+ }
145
+ const stateLower = (mr.state ?? "").toLowerCase();
146
+ return renderOutput([
147
+ renderDetail("merge_request", mr, schema),
148
+ renderHelp(getSuggestions({
149
+ domain: "mr",
150
+ action: "view",
151
+ state: stateLower,
152
+ id: num,
153
+ repo: ctx,
154
+ })),
155
+ ]);
156
+ }
157
+ async function mrCreate(args, ctx) {
158
+ const title = takeFlag(args, "--title");
159
+ if (!title)
160
+ throw new AxiError("--title is required", "VALIDATION_ERROR");
161
+ const description = takeBody(args, {
162
+ inlineFlags: ["--description"],
163
+ fileFlags: ["--body-file"],
164
+ label: "description",
165
+ });
166
+ const sourceBranch = takeFlag(args, "--source-branch");
167
+ const targetBranch = takeFlag(args, "--target-branch");
168
+ const draft = takeBoolFlag(args, "--draft");
169
+ const labels = getAllFlags(args, "--label");
170
+ const assignee = takeFlag(args, "--assignee");
171
+ const milestone = takeFlag(args, "--milestone");
172
+ const ghArgs = ["mr", "create", "--title", title];
173
+ if (description !== undefined)
174
+ ghArgs.push("--description", description);
175
+ if (sourceBranch)
176
+ ghArgs.push("--source-branch", sourceBranch);
177
+ if (targetBranch)
178
+ ghArgs.push("--target-branch", targetBranch);
179
+ if (draft)
180
+ ghArgs.push("--draft");
181
+ for (const l of labels)
182
+ ghArgs.push("--label", l);
183
+ if (assignee)
184
+ ghArgs.push("--assignee", assignee);
185
+ if (milestone)
186
+ ghArgs.push("--milestone", milestone);
187
+ const stdout = await glabExec(ghArgs, ctx);
188
+ const urlMatch = stdout.match(/\/-\/merge_requests\/(\d+)/);
189
+ const num = urlMatch ? Number(urlMatch[1]) : undefined;
190
+ const url = stdout.trim().split("\n").pop()?.trim() ?? "";
191
+ return renderOutput([
192
+ renderDetail("created", { number: num ?? url, url }, [
193
+ field("number"),
194
+ field("url"),
195
+ ]),
196
+ renderHelp(getSuggestions({ domain: "mr", action: "create", id: num, repo: ctx })),
197
+ ]);
198
+ }
199
+ async function mrEdit(args, ctx) {
200
+ const num = takeNumber(args, "MR");
201
+ const title = takeFlag(args, "--title");
202
+ const description = takeBody(args, {
203
+ inlineFlags: ["--description"],
204
+ fileFlags: ["--body-file"],
205
+ label: "description",
206
+ });
207
+ const addLabel = takeFlag(args, "--add-label");
208
+ const removeLabel = takeFlag(args, "--remove-label");
209
+ const addAssignee = takeFlag(args, "--add-assignee");
210
+ const removeAssignee = takeFlag(args, "--remove-assignee");
211
+ const milestone = takeFlag(args, "--milestone");
212
+ const ghArgs = ["mr", "edit", String(num)];
213
+ if (title)
214
+ ghArgs.push("--title", title);
215
+ if (description !== undefined)
216
+ ghArgs.push("--description", description);
217
+ if (addLabel)
218
+ ghArgs.push("--add-label", addLabel);
219
+ if (removeLabel)
220
+ ghArgs.push("--remove-label", removeLabel);
221
+ if (addAssignee)
222
+ ghArgs.push("--add-assignee", addAssignee);
223
+ if (removeAssignee)
224
+ ghArgs.push("--remove-assignee", removeAssignee);
225
+ if (milestone)
226
+ ghArgs.push("--milestone", milestone);
227
+ await glabExec(ghArgs, ctx);
228
+ return renderOutput([
229
+ renderDetail("edited", { number: num, status: "ok" }, [
230
+ field("number"),
231
+ field("status"),
232
+ ]),
233
+ renderHelp(getSuggestions({ domain: "mr", action: "edit", id: num, repo: ctx })),
234
+ ]);
235
+ }
236
+ async function mrClose(args, ctx) {
237
+ const num = takeNumber(args, "MR");
238
+ const mr = await glabJson(["mr", "view", String(num), "--json", "state"], ctx);
239
+ const state = (mr.state ?? "").toUpperCase();
240
+ if (state === "CLOSED" || state === "MERGED") {
241
+ return renderOutput([
242
+ renderDetail("merge_request", { number: num, state: state.toLowerCase(), already: true }, [field("number"), field("state"), field("already")]),
243
+ renderHelp(getSuggestions({ domain: "mr", action: "close", id: num, repo: ctx })),
244
+ ]);
245
+ }
246
+ await glabExec(["mr", "close", String(num)], ctx);
247
+ return renderOutput([
248
+ renderDetail("closed", { number: num, status: "ok" }, [
249
+ field("number"),
250
+ field("status"),
251
+ ]),
252
+ renderHelp(getSuggestions({ domain: "mr", action: "close", id: num, repo: ctx })),
253
+ ]);
254
+ }
255
+ async function mrReopen(args, ctx) {
256
+ const num = takeNumber(args, "MR");
257
+ const mr = await glabJson(["mr", "view", String(num), "--json", "state"], ctx);
258
+ if ((mr.state ?? "").toUpperCase() === "OPENED") {
259
+ return renderOutput([
260
+ renderDetail("merge_request", { number: num, state: "opened", already: true }, [field("number"), field("state"), field("already")]),
261
+ renderHelp(getSuggestions({ domain: "mr", action: "reopen", id: num, repo: ctx })),
262
+ ]);
263
+ }
264
+ await glabExec(["mr", "reopen", String(num)], ctx);
265
+ return renderOutput([
266
+ renderDetail("reopened", { number: num, status: "ok" }, [
267
+ field("number"),
268
+ field("status"),
269
+ ]),
270
+ renderHelp(getSuggestions({ domain: "mr", action: "reopen", id: num, repo: ctx })),
271
+ ]);
272
+ }
273
+ async function mrMerge(args, ctx) {
274
+ const num = takeNumber(args, "MR");
275
+ const squash = takeBoolFlag(args, "--squash");
276
+ const ghArgs = ["mr", "merge", String(num)];
277
+ if (squash)
278
+ ghArgs.push("--squash");
279
+ await glabExec(ghArgs, ctx);
280
+ return renderOutput([
281
+ renderDetail("merged", { number: num, status: "ok" }, [
282
+ field("number"),
283
+ field("status"),
284
+ ]),
285
+ renderHelp(getSuggestions({ domain: "mr", action: "merge", id: num, repo: ctx })),
286
+ ]);
287
+ }
288
+ async function mrApprove(args, ctx) {
289
+ const num = takeNumber(args, "MR");
290
+ await glabExec(["mr", "approve", String(num)], ctx);
291
+ return renderOutput([
292
+ renderDetail("approved", { number: num, status: "ok" }, [
293
+ field("number"),
294
+ field("status"),
295
+ ]),
296
+ renderHelp(getSuggestions({ domain: "mr", action: "approve", id: num, repo: ctx })),
297
+ ]);
298
+ }
299
+ async function mrNote(args, ctx) {
300
+ const num = takeNumber(args, "MR");
301
+ const body = takeBody(args, { required: true });
302
+ await glabExec(["mr", "note", String(num), "--body", body], ctx);
303
+ return renderOutput([
304
+ renderDetail("noted", { number: num, status: "ok" }, [
305
+ field("number"),
306
+ field("status"),
307
+ ]),
308
+ renderHelp(getSuggestions({ domain: "mr", action: "note", id: num, repo: ctx })),
309
+ ]);
310
+ }
311
+ async function mrDiff(args, ctx) {
312
+ const num = takeNumber(args, "MR");
313
+ const diff = await glabExec(["mr", "diff", String(num)], ctx);
314
+ return renderOutput([encode({ mr_diff: { number: num, diff } })]);
315
+ }
316
+ async function mrCheckout(args, ctx) {
317
+ const num = takeNumber(args, "MR");
318
+ const stdout = await glabExec(["mr", "checkout", String(num)], ctx);
319
+ const branch = stdout.trim();
320
+ return renderOutput([
321
+ renderDetail("checkout", { number: num, branch, status: "ok" }, [
322
+ field("number"),
323
+ field("branch"),
324
+ field("status"),
325
+ ]),
326
+ ]);
327
+ }
328
+ export async function mrCommand(args, ctx) {
329
+ const sub = args[0];
330
+ const rest = args.slice(1);
331
+ switch (sub) {
332
+ case "list":
333
+ return mrList(rest, ctx);
334
+ case "view":
335
+ return mrView(rest, ctx);
336
+ case "create":
337
+ return mrCreate(rest, ctx);
338
+ case "edit":
339
+ return mrEdit(rest, ctx);
340
+ case "close":
341
+ return mrClose(rest, ctx);
342
+ case "reopen":
343
+ return mrReopen(rest, ctx);
344
+ case "merge":
345
+ return mrMerge(rest, ctx);
346
+ case "approve":
347
+ return mrApprove(rest, ctx);
348
+ case "note":
349
+ return mrNote(rest, ctx);
350
+ case "diff":
351
+ return mrDiff(rest, ctx);
352
+ case "checkout":
353
+ return mrCheckout(rest, ctx);
354
+ case "--help":
355
+ case "-h":
356
+ case "help":
357
+ case undefined:
358
+ return MR_HELP;
359
+ default:
360
+ return renderError(`Unknown mr subcommand: ${sub}`, "VALIDATION_ERROR", [
361
+ "Run `glab-axi mr --help` to see available subcommands",
362
+ ]);
363
+ }
364
+ }
365
+ //# sourceMappingURL=mr.js.map