ya-git-jira 2.0.0 → 2.1.1

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 (94) hide show
  1. package/.dockerignore +8 -0
  2. package/.opencode/skills/git-confluence/SKILL.md +18 -18
  3. package/.opencode/skills/git-jira/SKILL.md +18 -18
  4. package/.opencode/skills/git-lab/SKILL.md +30 -30
  5. package/Dockerfile +58 -0
  6. package/README.md +31 -12
  7. package/bin/git-api.ts +2 -4
  8. package/bin/git-bump.ts +2 -4
  9. package/bin/git-confluence-page-search.ts +4 -6
  10. package/bin/git-confluence-page-show.ts +3 -5
  11. package/bin/git-confluence-page-update.ts +3 -5
  12. package/bin/git-confluence-page.ts +2 -4
  13. package/bin/git-confluence-space-list.ts +3 -5
  14. package/bin/git-confluence-space.ts +2 -4
  15. package/bin/git-confluence-whoami.ts +3 -5
  16. package/bin/git-confluence.ts +11 -4
  17. package/bin/git-jira-issue-list.ts +2 -4
  18. package/bin/git-jira-issue-show.ts +3 -5
  19. package/bin/git-jira-issue.ts +2 -4
  20. package/bin/git-jira-start.ts +2 -4
  21. package/bin/git-jira-whoami.ts +3 -5
  22. package/bin/git-jira.ts +11 -4
  23. package/bin/git-lab-group-list.ts +4 -6
  24. package/bin/git-lab-group.ts +2 -4
  25. package/bin/git-lab-merge-active.ts +4 -6
  26. package/bin/git-lab-merge-todo.ts +4 -6
  27. package/bin/git-lab-merge-train-list.ts +3 -5
  28. package/bin/git-lab-merge-train.ts +2 -4
  29. package/bin/git-lab-merge.ts +2 -4
  30. package/bin/git-lab-namespace-list.ts +3 -5
  31. package/bin/git-lab-namespace.ts +2 -4
  32. package/bin/git-lab-project-list.ts +4 -6
  33. package/bin/git-lab-project-mr-list.ts +4 -6
  34. package/bin/git-lab-project-mr.ts +2 -4
  35. package/bin/git-lab-project-pipeline-jobs.ts +2 -4
  36. package/bin/git-lab-project-pipeline-latest.ts +2 -4
  37. package/bin/git-lab-project-pipeline-list.ts +4 -6
  38. package/bin/git-lab-project-pipeline-log.ts +2 -4
  39. package/bin/git-lab-project-pipeline.ts +2 -4
  40. package/bin/git-lab-project-whereami.ts +3 -5
  41. package/bin/git-lab-project.ts +2 -4
  42. package/bin/git-lab-whoami.ts +3 -5
  43. package/bin/git-lab.ts +11 -4
  44. package/bin/gitj-install-skills.ts +15 -12
  45. package/bin/gitj.ts +6 -1
  46. package/dist/bin/git-api.js +33 -5
  47. package/dist/bin/git-bump.js +32 -24
  48. package/dist/bin/git-confluence-page-search.js +46 -26
  49. package/dist/bin/git-confluence-page-show.js +24 -4
  50. package/dist/bin/git-confluence-page-update.js +24 -4
  51. package/dist/bin/git-confluence-page.js +30 -16
  52. package/dist/bin/git-confluence-space-list.js +45 -25
  53. package/dist/bin/git-confluence-space.js +46 -28
  54. package/dist/bin/git-confluence-whoami.js +45 -25
  55. package/dist/bin/git-confluence.js +45 -31
  56. package/dist/bin/git-jira-issue-list.js +36 -24
  57. package/dist/bin/git-jira-issue-show.js +16 -4
  58. package/dist/bin/git-jira-issue.js +18 -10
  59. package/dist/bin/git-jira-start.js +16 -4
  60. package/dist/bin/git-jira-whoami.js +37 -25
  61. package/dist/bin/git-jira.js +32 -22
  62. package/dist/bin/git-lab-group-list.js +18 -6
  63. package/dist/bin/git-lab-group.js +19 -9
  64. package/dist/bin/git-lab-merge-active.js +18 -6
  65. package/dist/bin/git-lab-merge-todo.js +18 -6
  66. package/dist/bin/git-lab-merge-train-list.js +17 -5
  67. package/dist/bin/git-lab-merge-train.js +18 -8
  68. package/dist/bin/git-lab-merge.js +25 -21
  69. package/dist/bin/git-lab-namespace-list.js +38 -26
  70. package/dist/bin/git-lab-namespace.js +39 -29
  71. package/dist/bin/git-lab-project-list.js +18 -6
  72. package/dist/bin/git-lab-project-mr-list.js +18 -6
  73. package/dist/bin/git-lab-project-mr.js +19 -9
  74. package/dist/bin/git-lab-project-pipeline-jobs.js +16 -4
  75. package/dist/bin/git-lab-project-pipeline-latest.js +16 -4
  76. package/dist/bin/git-lab-project-pipeline-list.js +18 -6
  77. package/dist/bin/git-lab-project-pipeline-log.js +16 -4
  78. package/dist/bin/git-lab-project-pipeline.js +22 -18
  79. package/dist/bin/git-lab-project-whereami.js +17 -5
  80. package/dist/bin/git-lab-project.js +32 -38
  81. package/dist/bin/git-lab-whoami.js +17 -5
  82. package/dist/bin/git-lab.js +61 -81
  83. package/dist/bin/gitj-install-skills.js +21 -11
  84. package/dist/bin/gitj.js +154 -153
  85. package/dist/index.js +32 -1
  86. package/install-docker-gitj.sh +77 -0
  87. package/lib/api.ts +19 -1
  88. package/lib/confluence/api.ts +12 -0
  89. package/lib/confluence/config.ts +3 -3
  90. package/lib/gitlab/api.ts +4 -0
  91. package/lib/gitlab/config.ts +2 -2
  92. package/lib/is_main.ts +11 -0
  93. package/lib/jira.ts +7 -3
  94. package/package.json +1 -1
@@ -1914,6 +1914,10 @@ async function jiraApi(endpoint) {
1914
1914
  };
1915
1915
  const request = new Request(uri, options);
1916
1916
  const response = await fetch(request);
1917
+ if (!response.ok) {
1918
+ const text = await response.text();
1919
+ throw new Error(`Jira API ${endpoint} failed (${response.status}): ${text}`);
1920
+ }
1917
1921
  const result = await response.json();
1918
1922
  return result;
1919
1923
  }
@@ -1946,11 +1950,21 @@ function isMain(self) {
1946
1950
  const result = argv1Base === selfBase;
1947
1951
  return result;
1948
1952
  }
1953
+ async function runMain(self, create) {
1954
+ if (!isMain(self))
1955
+ return;
1956
+ try {
1957
+ await create().parseAsync(Bun.argv);
1958
+ } catch (err) {
1959
+ console.error(`error: ${err instanceof Error ? err.message : String(err)}`);
1960
+ process.exit(1);
1961
+ }
1962
+ }
1949
1963
 
1950
1964
  // bin/git-jira-start.ts
1951
1965
  var version = await getPackageVersion();
1952
1966
  function toKebab(s) {
1953
- return s.replace(/([a-z]+)([A-Z]+)/g, "$1_2").toLowerCase().replace(/(\W+)/g, "-").replace(/-$/, "");
1967
+ return s.replace(/([a-z]+)([A-Z]+)/g, "$1_$2").toLowerCase().replace(/(\W+)/g, "-").replace(/-$/, "");
1954
1968
  }
1955
1969
  function create() {
1956
1970
  const program2 = new Command;
@@ -1967,9 +1981,7 @@ function create() {
1967
1981
  return program2;
1968
1982
  }
1969
1983
  var git_jira_start_default = create;
1970
- if (isMain("git-jira-start")) {
1971
- await create().parseAsync(Bun.argv);
1972
- }
1984
+ await runMain("git-jira-start", create);
1973
1985
  export {
1974
1986
  git_jira_start_default as default,
1975
1987
  create
@@ -600,7 +600,7 @@ var require_command = __commonJS((exports) => {
600
600
  var childProcess = __require("child_process");
601
601
  var path = __require("path");
602
602
  var fs = __require("fs");
603
- var process = __require("process");
603
+ var process2 = __require("process");
604
604
  var { Argument, humanReadableArgName } = require_argument();
605
605
  var { CommanderError } = require_error();
606
606
  var { Help } = require_help();
@@ -641,10 +641,10 @@ var require_command = __commonJS((exports) => {
641
641
  this._showHelpAfterError = false;
642
642
  this._showSuggestionAfterError = true;
643
643
  this._outputConfiguration = {
644
- writeOut: (str) => process.stdout.write(str),
645
- writeErr: (str) => process.stderr.write(str),
646
- getOutHelpWidth: () => process.stdout.isTTY ? process.stdout.columns : undefined,
647
- getErrHelpWidth: () => process.stderr.isTTY ? process.stderr.columns : undefined,
644
+ writeOut: (str) => process2.stdout.write(str),
645
+ writeErr: (str) => process2.stderr.write(str),
646
+ getOutHelpWidth: () => process2.stdout.isTTY ? process2.stdout.columns : undefined,
647
+ getErrHelpWidth: () => process2.stderr.isTTY ? process2.stderr.columns : undefined,
648
648
  outputError: (str, write) => write(str)
649
649
  };
650
650
  this._hidden = false;
@@ -826,7 +826,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
826
826
  if (this._exitCallback) {
827
827
  this._exitCallback(new CommanderError(exitCode, code, message));
828
828
  }
829
- process.exit(exitCode);
829
+ process2.exit(exitCode);
830
830
  }
831
831
  action(fn) {
832
832
  const listener = (args) => {
@@ -991,8 +991,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
991
991
  }
992
992
  parseOptions = parseOptions || {};
993
993
  if (argv === undefined) {
994
- argv = process.argv;
995
- if (process.versions && process.versions.electron) {
994
+ argv = process2.argv;
995
+ if (process2.versions && process2.versions.electron) {
996
996
  parseOptions.from = "electron";
997
997
  }
998
998
  }
@@ -1005,7 +1005,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1005
1005
  userArgs = argv.slice(2);
1006
1006
  break;
1007
1007
  case "electron":
1008
- if (process.defaultApp) {
1008
+ if (process2.defaultApp) {
1009
1009
  this._scriptPath = argv[1];
1010
1010
  userArgs = argv.slice(2);
1011
1011
  } else {
@@ -1073,23 +1073,23 @@ Expecting one of '${allowedValues.join("', '")}'`);
1073
1073
  }
1074
1074
  launchWithNode = sourceExt.includes(path.extname(executableFile));
1075
1075
  let proc;
1076
- if (process.platform !== "win32") {
1076
+ if (process2.platform !== "win32") {
1077
1077
  if (launchWithNode) {
1078
1078
  args.unshift(executableFile);
1079
- args = incrementNodeInspectorPort(process.execArgv).concat(args);
1080
- proc = childProcess.spawn(process.argv[0], args, { stdio: "inherit" });
1079
+ args = incrementNodeInspectorPort(process2.execArgv).concat(args);
1080
+ proc = childProcess.spawn(process2.argv[0], args, { stdio: "inherit" });
1081
1081
  } else {
1082
1082
  proc = childProcess.spawn(executableFile, args, { stdio: "inherit" });
1083
1083
  }
1084
1084
  } else {
1085
1085
  args.unshift(executableFile);
1086
- args = incrementNodeInspectorPort(process.execArgv).concat(args);
1087
- proc = childProcess.spawn(process.execPath, args, { stdio: "inherit" });
1086
+ args = incrementNodeInspectorPort(process2.execArgv).concat(args);
1087
+ proc = childProcess.spawn(process2.execPath, args, { stdio: "inherit" });
1088
1088
  }
1089
1089
  if (!proc.killed) {
1090
1090
  const signals = ["SIGUSR1", "SIGUSR2", "SIGTERM", "SIGINT", "SIGHUP"];
1091
1091
  signals.forEach((signal) => {
1092
- process.on(signal, () => {
1092
+ process2.on(signal, () => {
1093
1093
  if (proc.killed === false && proc.exitCode === null) {
1094
1094
  proc.kill(signal);
1095
1095
  }
@@ -1098,10 +1098,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
1098
1098
  }
1099
1099
  const exitCallback = this._exitCallback;
1100
1100
  if (!exitCallback) {
1101
- proc.on("close", process.exit.bind(process));
1101
+ proc.on("close", process2.exit.bind(process2));
1102
1102
  } else {
1103
1103
  proc.on("close", () => {
1104
- exitCallback(new CommanderError(process.exitCode || 0, "commander.executeSubCommandAsync", "(close)"));
1104
+ exitCallback(new CommanderError(process2.exitCode || 0, "commander.executeSubCommandAsync", "(close)"));
1105
1105
  });
1106
1106
  }
1107
1107
  proc.on("error", (err) => {
@@ -1116,7 +1116,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1116
1116
  throw new Error(`'${executableFile}' not executable`);
1117
1117
  }
1118
1118
  if (!exitCallback) {
1119
- process.exit(1);
1119
+ process2.exit(1);
1120
1120
  } else {
1121
1121
  const wrappedError = new CommanderError(1, "commander.executeSubCommandAsync", "(error)");
1122
1122
  wrappedError.nestedError = err;
@@ -1471,11 +1471,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
1471
1471
  }
1472
1472
  _parseOptionsEnv() {
1473
1473
  this.options.forEach((option) => {
1474
- if (option.envVar && option.envVar in process.env) {
1474
+ if (option.envVar && option.envVar in process2.env) {
1475
1475
  const optionKey = option.attributeName();
1476
1476
  if (this.getOptionValue(optionKey) === undefined || ["default", "config", "env"].includes(this.getOptionValueSource(optionKey))) {
1477
1477
  if (option.required || option.optional) {
1478
- this.emit(`optionEnv:${option.name()}`, process.env[option.envVar]);
1478
+ this.emit(`optionEnv:${option.name()}`, process2.env[option.envVar]);
1479
1479
  } else {
1480
1480
  this.emit(`optionEnv:${option.name()}`);
1481
1481
  }
@@ -1702,7 +1702,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1702
1702
  }
1703
1703
  help(contextOptions) {
1704
1704
  this.outputHelp(contextOptions);
1705
- let exitCode = process.exitCode || 0;
1705
+ let exitCode = process2.exitCode || 0;
1706
1706
  if (exitCode === 0 && contextOptions && typeof contextOptions !== "function" && contextOptions.error) {
1707
1707
  exitCode = 1;
1708
1708
  }
@@ -1914,6 +1914,10 @@ async function jiraApi(endpoint) {
1914
1914
  };
1915
1915
  const request = new Request(uri, options);
1916
1916
  const response = await fetch(request);
1917
+ if (!response.ok) {
1918
+ const text = await response.text();
1919
+ throw new Error(`Jira API ${endpoint} failed (${response.status}): ${text}`);
1920
+ }
1917
1921
  const result = await response.json();
1918
1922
  return result;
1919
1923
  }
@@ -1946,6 +1950,16 @@ function isMain(self) {
1946
1950
  const result = argv1Base === selfBase;
1947
1951
  return result;
1948
1952
  }
1953
+ async function runMain(self, create) {
1954
+ if (!isMain(self))
1955
+ return;
1956
+ try {
1957
+ await create().parseAsync(Bun.argv);
1958
+ } catch (err) {
1959
+ console.error(`error: ${err instanceof Error ? err.message : String(err)}`);
1960
+ process.exit(1);
1961
+ }
1962
+ }
1949
1963
 
1950
1964
  // bin/git-jira-whoami.ts
1951
1965
  var version = await getPackageVersion();
@@ -1954,7 +1968,7 @@ function create() {
1954
1968
  program2.version(version).name("whoami").description("Show the current Jira user").option("-v, --verbose", "Verbose output").action(async (options) => {
1955
1969
  const myself = await getMyself();
1956
1970
  if (options.verbose) {
1957
- console.log(myself);
1971
+ console.log(JSON.stringify(myself, null, 2));
1958
1972
  } else {
1959
1973
  const { displayName, emailAddress, accountId } = myself;
1960
1974
  console.log({ displayName, emailAddress, accountId });
@@ -1963,9 +1977,7 @@ function create() {
1963
1977
  return program2;
1964
1978
  }
1965
1979
  var git_jira_whoami_default = create;
1966
- if (isMain("git-jira-whoami")) {
1967
- await create().parseAsync(Bun.argv);
1968
- }
1980
+ await runMain("git-jira-whoami", create);
1969
1981
  export {
1970
1982
  git_jira_whoami_default as default,
1971
1983
  create
@@ -1914,6 +1914,10 @@ async function jiraApi(endpoint) {
1914
1914
  };
1915
1915
  const request = new Request(uri, options);
1916
1916
  const response = await fetch(request);
1917
+ if (!response.ok) {
1918
+ const text = await response.text();
1919
+ throw new Error(`Jira API ${endpoint} failed (${response.status}): ${text}`);
1920
+ }
1917
1921
  const result = await response.json();
1918
1922
  return result;
1919
1923
  }
@@ -1946,11 +1950,21 @@ function isMain(self) {
1946
1950
  const result = argv1Base === selfBase;
1947
1951
  return result;
1948
1952
  }
1953
+ async function runMain(self, create) {
1954
+ if (!isMain(self))
1955
+ return;
1956
+ try {
1957
+ await create().parseAsync(Bun.argv);
1958
+ } catch (err) {
1959
+ console.error(`error: ${err instanceof Error ? err.message : String(err)}`);
1960
+ process.exit(1);
1961
+ }
1962
+ }
1949
1963
 
1950
1964
  // bin/git-jira-start.ts
1951
1965
  var version = await getPackageVersion();
1952
1966
  function toKebab(s) {
1953
- return s.replace(/([a-z]+)([A-Z]+)/g, "$1_2").toLowerCase().replace(/(\W+)/g, "-").replace(/-$/, "");
1967
+ return s.replace(/([a-z]+)([A-Z]+)/g, "$1_$2").toLowerCase().replace(/(\W+)/g, "-").replace(/-$/, "");
1954
1968
  }
1955
1969
  function create() {
1956
1970
  const program2 = new Command;
@@ -1967,9 +1981,7 @@ function create() {
1967
1981
  return program2;
1968
1982
  }
1969
1983
  var git_jira_start_default = create;
1970
- if (isMain("git-jira-start")) {
1971
- await create().parseAsync(Bun.argv);
1972
- }
1984
+ await runMain("git-jira-start", create);
1973
1985
 
1974
1986
  // bin/git-jira-issue-list.ts
1975
1987
  var version2 = await getPackageVersion();
@@ -1985,9 +1997,7 @@ function create2() {
1985
1997
  return program2;
1986
1998
  }
1987
1999
  var git_jira_issue_list_default = create2;
1988
- if (isMain("git-jira-issue-list")) {
1989
- await create2().parseAsync(Bun.argv);
1990
- }
2000
+ await runMain("git-jira-issue-list", create2);
1991
2001
 
1992
2002
  // bin/git-jira-issue-show.ts
1993
2003
  var version3 = await getPackageVersion();
@@ -2000,7 +2010,7 @@ function create3() {
2000
2010
  process.exit(1);
2001
2011
  }
2002
2012
  if (options.verbose) {
2003
- console.log(issue);
2013
+ console.log(JSON.stringify(issue, null, 2));
2004
2014
  } else {
2005
2015
  const { host } = await getJiraConfig();
2006
2016
  const summary = issue.fields.summary;
@@ -2011,9 +2021,7 @@ function create3() {
2011
2021
  return program2;
2012
2022
  }
2013
2023
  var git_jira_issue_show_default = create3;
2014
- if (isMain("git-jira-issue-show")) {
2015
- await create3().parseAsync(Bun.argv);
2016
- }
2024
+ await runMain("git-jira-issue-show", create3);
2017
2025
 
2018
2026
  // bin/git-jira-issue.ts
2019
2027
  var version4 = await getPackageVersion();
@@ -2023,9 +2031,7 @@ function create4() {
2023
2031
  return program2;
2024
2032
  }
2025
2033
  var git_jira_issue_default = create4;
2026
- if (isMain("git-jira-issue")) {
2027
- await create4().parseAsync(Bun.argv);
2028
- }
2034
+ await runMain("git-jira-issue", create4);
2029
2035
 
2030
2036
  // bin/git-jira-whoami.ts
2031
2037
  var version5 = await getPackageVersion();
@@ -2034,7 +2040,7 @@ function create5() {
2034
2040
  program2.version(version5).name("whoami").description("Show the current Jira user").option("-v, --verbose", "Verbose output").action(async (options) => {
2035
2041
  const myself = await getMyself();
2036
2042
  if (options.verbose) {
2037
- console.log(myself);
2043
+ console.log(JSON.stringify(myself, null, 2));
2038
2044
  } else {
2039
2045
  const { displayName, emailAddress, accountId } = myself;
2040
2046
  console.log({ displayName, emailAddress, accountId });
@@ -2043,21 +2049,25 @@ function create5() {
2043
2049
  return program2;
2044
2050
  }
2045
2051
  var git_jira_whoami_default = create5;
2046
- if (isMain("git-jira-whoami")) {
2047
- await create5().parseAsync(Bun.argv);
2048
- }
2052
+ await runMain("git-jira-whoami", create5);
2049
2053
 
2050
2054
  // bin/git-jira.ts
2051
2055
  var version6 = await getPackageVersion();
2052
2056
  function create6() {
2053
2057
  const program2 = new Command;
2054
- program2.version(version6).name("jira").description("Commands for working with Jira").addCommand(git_jira_start_default()).addCommand(git_jira_issue_default()).addCommand(git_jira_issue_list_default()).addCommand(git_jira_whoami_default());
2058
+ program2.version(version6).name("jira").description("Commands for working with Jira").addCommand(git_jira_start_default()).addCommand(git_jira_issue_default()).addCommand(git_jira_issue_list_default()).addCommand(git_jira_whoami_default()).addHelpText("after", `
2059
+ Required git config:
2060
+ jira.host your Jira hostname (e.g. yourcompany.atlassian.net)
2061
+ jira.token your Atlassian API token
2062
+
2063
+ Optional git config:
2064
+ jira.user your Jira email (falls back to user.email)
2065
+
2066
+ Set with: git config --global jira.host <value>`);
2055
2067
  return program2;
2056
2068
  }
2057
2069
  var git_jira_default = create6;
2058
- if (isMain("git-jira")) {
2059
- await create6().parseAsync(Bun.argv);
2060
- }
2070
+ await runMain("git-jira", create6);
2061
2071
  export {
2062
2072
  git_jira_default as default,
2063
2073
  create6 as create
@@ -2463,6 +2463,16 @@ function isMain(self) {
2463
2463
  const result = argv1Base === selfBase;
2464
2464
  return result;
2465
2465
  }
2466
+ async function runMain(self, create) {
2467
+ if (!isMain(self))
2468
+ return;
2469
+ try {
2470
+ await create().parseAsync(Bun.argv);
2471
+ } catch (err) {
2472
+ console.error(`error: ${err instanceof Error ? err.message : String(err)}`);
2473
+ process.exit(1);
2474
+ }
2475
+ }
2466
2476
 
2467
2477
  // lib/spawn.ts
2468
2478
  var defaultOptions = {
@@ -2512,7 +2522,7 @@ async function getGitlabConfig() {
2512
2522
  const host = await hostP || "gitlab.com";
2513
2523
  const user = await gitEmailP || await gitlabEmailP;
2514
2524
  if (!user)
2515
- throw new Error("Neither user.email nor gitlab.email in git config");
2525
+ throw new Error("Neither user.email nor gitlab.user in git config");
2516
2526
  const token = await tokenP;
2517
2527
  if (!token)
2518
2528
  throw new Error("gitlab.token not in git config");
@@ -2549,6 +2559,10 @@ async function gitlabApi(endpoint) {
2549
2559
  };
2550
2560
  let request = new Request(uri, options);
2551
2561
  const response = await fetch(request);
2562
+ if (!response.ok) {
2563
+ const text = await response.text();
2564
+ throw new Error(`GitLab API ${endpoint} failed (${response.status}): ${text}`);
2565
+ }
2552
2566
  let link = getNextLink(response.headers.get("Link"));
2553
2567
  let partial = await response.json();
2554
2568
  let result = partial;
@@ -2704,21 +2718,19 @@ function create() {
2704
2718
  program2.version(version).name("list").description("List groups for the current user").option("-v, --verbose", "Verbose output").action(async (options) => {
2705
2719
  const groups = await getGroups();
2706
2720
  if (options.verbose)
2707
- console.log(groups);
2721
+ console.log(JSON.stringify(groups, null, 2));
2708
2722
  else {
2709
2723
  const filtered = groups.map((g) => {
2710
2724
  const { id, name, full_path } = g;
2711
2725
  return { id, name, full_path };
2712
2726
  });
2713
- console.log(filtered);
2727
+ console.log(JSON.stringify(filtered, null, 2));
2714
2728
  }
2715
2729
  });
2716
2730
  return program2;
2717
2731
  }
2718
2732
  var git_lab_group_list_default = create;
2719
- if (isMain("git-lab-group-list")) {
2720
- await create().parseAsync(Bun.argv);
2721
- }
2733
+ await runMain("git-lab-group-list", create);
2722
2734
  export {
2723
2735
  git_lab_group_list_default as default,
2724
2736
  create
@@ -2463,6 +2463,16 @@ function isMain(self) {
2463
2463
  const result = argv1Base === selfBase;
2464
2464
  return result;
2465
2465
  }
2466
+ async function runMain(self, create) {
2467
+ if (!isMain(self))
2468
+ return;
2469
+ try {
2470
+ await create().parseAsync(Bun.argv);
2471
+ } catch (err) {
2472
+ console.error(`error: ${err instanceof Error ? err.message : String(err)}`);
2473
+ process.exit(1);
2474
+ }
2475
+ }
2466
2476
 
2467
2477
  // lib/spawn.ts
2468
2478
  var defaultOptions = {
@@ -2512,7 +2522,7 @@ async function getGitlabConfig() {
2512
2522
  const host = await hostP || "gitlab.com";
2513
2523
  const user = await gitEmailP || await gitlabEmailP;
2514
2524
  if (!user)
2515
- throw new Error("Neither user.email nor gitlab.email in git config");
2525
+ throw new Error("Neither user.email nor gitlab.user in git config");
2516
2526
  const token = await tokenP;
2517
2527
  if (!token)
2518
2528
  throw new Error("gitlab.token not in git config");
@@ -2549,6 +2559,10 @@ async function gitlabApi(endpoint) {
2549
2559
  };
2550
2560
  let request = new Request(uri, options);
2551
2561
  const response = await fetch(request);
2562
+ if (!response.ok) {
2563
+ const text = await response.text();
2564
+ throw new Error(`GitLab API ${endpoint} failed (${response.status}): ${text}`);
2565
+ }
2552
2566
  let link = getNextLink(response.headers.get("Link"));
2553
2567
  let partial = await response.json();
2554
2568
  let result = partial;
@@ -2704,21 +2718,19 @@ function create() {
2704
2718
  program2.version(version).name("list").description("List groups for the current user").option("-v, --verbose", "Verbose output").action(async (options) => {
2705
2719
  const groups = await getGroups();
2706
2720
  if (options.verbose)
2707
- console.log(groups);
2721
+ console.log(JSON.stringify(groups, null, 2));
2708
2722
  else {
2709
2723
  const filtered = groups.map((g) => {
2710
2724
  const { id, name, full_path } = g;
2711
2725
  return { id, name, full_path };
2712
2726
  });
2713
- console.log(filtered);
2727
+ console.log(JSON.stringify(filtered, null, 2));
2714
2728
  }
2715
2729
  });
2716
2730
  return program2;
2717
2731
  }
2718
2732
  var git_lab_group_list_default = create;
2719
- if (isMain("git-lab-group-list")) {
2720
- await create().parseAsync(Bun.argv);
2721
- }
2733
+ await runMain("git-lab-group-list", create);
2722
2734
 
2723
2735
  // bin/git-lab-group.ts
2724
2736
  var version2 = await getPackageVersion();
@@ -2728,9 +2740,7 @@ function create2() {
2728
2740
  return program2;
2729
2741
  }
2730
2742
  var git_lab_group_default = create2;
2731
- if (isMain("git-lab-group")) {
2732
- await create2().parseAsync(Bun.argv);
2733
- }
2743
+ await runMain("git-lab-group", create2);
2734
2744
  export {
2735
2745
  git_lab_group_default as default,
2736
2746
  create2 as create
@@ -2497,7 +2497,7 @@ async function getGitlabConfig() {
2497
2497
  const host = await hostP || "gitlab.com";
2498
2498
  const user = await gitEmailP || await gitlabEmailP;
2499
2499
  if (!user)
2500
- throw new Error("Neither user.email nor gitlab.email in git config");
2500
+ throw new Error("Neither user.email nor gitlab.user in git config");
2501
2501
  const token = await tokenP;
2502
2502
  if (!token)
2503
2503
  throw new Error("gitlab.token not in git config");
@@ -2534,6 +2534,10 @@ async function gitlabApi(endpoint) {
2534
2534
  };
2535
2535
  let request = new Request(uri, options);
2536
2536
  const response = await fetch(request);
2537
+ if (!response.ok) {
2538
+ const text = await response.text();
2539
+ throw new Error(`GitLab API ${endpoint} failed (${response.status}): ${text}`);
2540
+ }
2537
2541
  let link = getNextLink(response.headers.get("Link"));
2538
2542
  let partial = await response.json();
2539
2543
  let result = partial;
@@ -2696,6 +2700,16 @@ function isMain(self) {
2696
2700
  const result = argv1Base === selfBase;
2697
2701
  return result;
2698
2702
  }
2703
+ async function runMain(self, create) {
2704
+ if (!isMain(self))
2705
+ return;
2706
+ try {
2707
+ await create().parseAsync(Bun.argv);
2708
+ } catch (err) {
2709
+ console.error(`error: ${err instanceof Error ? err.message : String(err)}`);
2710
+ process.exit(1);
2711
+ }
2712
+ }
2699
2713
 
2700
2714
  // bin/git-lab-merge-active.ts
2701
2715
  var version = await getPackageVersion();
@@ -2708,22 +2722,20 @@ function create() {
2708
2722
  process.exit(1);
2709
2723
  }
2710
2724
  if (options.verbose) {
2711
- console.log(merges);
2725
+ console.log(JSON.stringify(merges, null, 2));
2712
2726
  process.exit(0);
2713
2727
  } else {
2714
2728
  const filtered = merges.map((m) => {
2715
2729
  const { title, web_url, source_branch, target_branch } = m;
2716
2730
  return { title, web_url, source_branch, target_branch };
2717
2731
  });
2718
- console.log(filtered);
2732
+ console.log(JSON.stringify(filtered, null, 2));
2719
2733
  }
2720
2734
  });
2721
2735
  return program2;
2722
2736
  }
2723
2737
  var git_lab_merge_active_default = create;
2724
- if (isMain("git-lab-merge-active")) {
2725
- await create().parseAsync(Bun.argv);
2726
- }
2738
+ await runMain("git-lab-merge-active", create);
2727
2739
  export {
2728
2740
  git_lab_merge_active_default as default,
2729
2741
  create
@@ -2497,7 +2497,7 @@ async function getGitlabConfig() {
2497
2497
  const host = await hostP || "gitlab.com";
2498
2498
  const user = await gitEmailP || await gitlabEmailP;
2499
2499
  if (!user)
2500
- throw new Error("Neither user.email nor gitlab.email in git config");
2500
+ throw new Error("Neither user.email nor gitlab.user in git config");
2501
2501
  const token = await tokenP;
2502
2502
  if (!token)
2503
2503
  throw new Error("gitlab.token not in git config");
@@ -2534,6 +2534,10 @@ async function gitlabApi(endpoint) {
2534
2534
  };
2535
2535
  let request = new Request(uri, options);
2536
2536
  const response = await fetch(request);
2537
+ if (!response.ok) {
2538
+ const text = await response.text();
2539
+ throw new Error(`GitLab API ${endpoint} failed (${response.status}): ${text}`);
2540
+ }
2537
2541
  let link = getNextLink(response.headers.get("Link"));
2538
2542
  let partial = await response.json();
2539
2543
  let result = partial;
@@ -2696,6 +2700,16 @@ function isMain(self) {
2696
2700
  const result = argv1Base === selfBase;
2697
2701
  return result;
2698
2702
  }
2703
+ async function runMain(self, create) {
2704
+ if (!isMain(self))
2705
+ return;
2706
+ try {
2707
+ await create().parseAsync(Bun.argv);
2708
+ } catch (err) {
2709
+ console.error(`error: ${err instanceof Error ? err.message : String(err)}`);
2710
+ process.exit(1);
2711
+ }
2712
+ }
2699
2713
 
2700
2714
  // bin/git-lab-merge-todo.ts
2701
2715
  var version = await getPackageVersion();
@@ -2704,21 +2718,19 @@ function create() {
2704
2718
  program2.version(version).name("todo").description("MRs needing my review").option("-v, --verbose", "Verbose output").action(async (options) => {
2705
2719
  const mrs = await getMyMergeRequestsToReview();
2706
2720
  if (options.verbose) {
2707
- console.log(mrs);
2721
+ console.log(JSON.stringify(mrs, null, 2));
2708
2722
  } else {
2709
2723
  const filtered = mrs.map((mr) => {
2710
2724
  const { title, web_url, source_branch, target_branch } = mr;
2711
2725
  return { title, web_url, source_branch, target_branch };
2712
2726
  });
2713
- console.log(filtered);
2727
+ console.log(JSON.stringify(filtered, null, 2));
2714
2728
  }
2715
2729
  });
2716
2730
  return program2;
2717
2731
  }
2718
2732
  var git_lab_merge_todo_default = create;
2719
- if (isMain("git-lab-merge-todo")) {
2720
- await create().parseAsync(Bun.argv);
2721
- }
2733
+ await runMain("git-lab-merge-todo", create);
2722
2734
  export {
2723
2735
  git_lab_merge_todo_default as default,
2724
2736
  create
@@ -2463,6 +2463,16 @@ function isMain(self) {
2463
2463
  const result = argv1Base === selfBase;
2464
2464
  return result;
2465
2465
  }
2466
+ async function runMain(self, create) {
2467
+ if (!isMain(self))
2468
+ return;
2469
+ try {
2470
+ await create().parseAsync(Bun.argv);
2471
+ } catch (err) {
2472
+ console.error(`error: ${err instanceof Error ? err.message : String(err)}`);
2473
+ process.exit(1);
2474
+ }
2475
+ }
2466
2476
 
2467
2477
  // lib/spawn.ts
2468
2478
  var defaultOptions = {
@@ -2512,7 +2522,7 @@ async function getGitlabConfig() {
2512
2522
  const host = await hostP || "gitlab.com";
2513
2523
  const user = await gitEmailP || await gitlabEmailP;
2514
2524
  if (!user)
2515
- throw new Error("Neither user.email nor gitlab.email in git config");
2525
+ throw new Error("Neither user.email nor gitlab.user in git config");
2516
2526
  const token = await tokenP;
2517
2527
  if (!token)
2518
2528
  throw new Error("gitlab.token not in git config");
@@ -2549,6 +2559,10 @@ async function gitlabApi(endpoint) {
2549
2559
  };
2550
2560
  let request = new Request(uri, options);
2551
2561
  const response = await fetch(request);
2562
+ if (!response.ok) {
2563
+ const text = await response.text();
2564
+ throw new Error(`GitLab API ${endpoint} failed (${response.status}): ${text}`);
2565
+ }
2552
2566
  let link = getNextLink(response.headers.get("Link"));
2553
2567
  let partial = await response.json();
2554
2568
  let result = partial;
@@ -2646,14 +2660,12 @@ function create() {
2646
2660
  const program2 = new Command;
2647
2661
  program2.version(version).name("list").description("List merge trains for the current project").action(async () => {
2648
2662
  const trains = await getMergeTrains();
2649
- console.log(trains);
2663
+ console.log(JSON.stringify(trains, null, 2));
2650
2664
  });
2651
2665
  return program2;
2652
2666
  }
2653
2667
  var git_lab_merge_train_list_default = create;
2654
- if (isMain("git-lab-merge-train-list")) {
2655
- await create().parseAsync(Bun.argv);
2656
- }
2668
+ await runMain("git-lab-merge-train-list", create);
2657
2669
  export {
2658
2670
  git_lab_merge_train_list_default as default,
2659
2671
  create