@gitbeaker/cli
Version:
CLI implementation of the GitLab API.
232 lines (227 loc) • 7.38 kB
JavaScript
// src/cli.ts
import Chalk from "chalk";
import Sywac from "sywac";
import * as Gitbeaker from "@gitbeaker/rest";
import API_MAP from "@gitbeaker/core/map.json" with { type: "json" };
// src/utils.ts
import { camelize, decamelize } from "xcase";
var NORMALIZED_EXCEPTION_TERMS = [
"GitLabCI",
"YML",
"GPG",
"SSH",
"IId",
"NPM",
"NuGet",
"DORA4",
"LDAP",
"CICD",
"SAML",
"SCIM",
"PyPI"
].reduce((prev, cur) => {
return { ...prev, [cur]: cur.charAt(0).toUpperCase() + cur.slice(1).toLowerCase() };
}, {});
function getCLISafeNormalizedTerm(term) {
if (term.length === 0) return term;
let normalized = term;
Object.entries(NORMALIZED_EXCEPTION_TERMS).filter(([k]) => term.includes(k)).forEach(([k, v]) => {
normalized = normalized.replace(k, v);
});
normalized = normalized.charAt(0).toLowerCase() + normalized.slice(1);
return decamelize(normalized, "-");
}
function getAPISafeNormalizedTerm(term) {
if (term.length === 0) return term;
let normalized = camelize(term.replace(/(gb|gl)-/g, ""), "-");
Object.entries(NORMALIZED_EXCEPTION_TERMS).filter(([, v]) => normalized.includes(v)).forEach(([k, v]) => {
normalized = normalized.replace(v, k);
});
return normalized;
}
function normalizeEnvVariables(env) {
const normalized = {};
const suffixes = [
"TOKEN",
"OAUTH_TOKEN",
"JOB_TOKEN",
"HOST",
"SUDO",
"CAMELIZE",
"REQUEST_TIMEOUT",
"PROFILE_TOKEN",
"PROFILE_MODE"
];
suffixes.forEach((s) => {
if (env[`GITLAB_${s}`]) normalized[`GITBEAKER_${s}`] = env[`GITLAB_${s}`];
if (env[`GITBEAKER_${s}`]) normalized[`GITBEAKER_${s}`] = env[`GITBEAKER_${s}`];
});
return normalized;
}
function buildArgumentObjects(globalConfig, method, rawArgs) {
const ignoreOptions = ["_", "$0", "v", "version", "h", "help", "g", "global-args"];
const coreArgs = {};
const optionalArgs = {};
const initArgs = {};
Object.entries(rawArgs).forEach(([argName, value]) => {
if (ignoreOptions.includes(argName) || value == null) return;
const term = argName.replace("gl-", "gb-");
const normalized = getAPISafeNormalizedTerm(term);
if (globalConfig[term]) {
initArgs[normalized] = value;
} else if (method.args.includes(normalized)) coreArgs[normalized] = value;
else optionalArgs[normalized] = value;
});
return {
initArgs,
coreArgs,
optionalArgs
};
}
function getDisplayConfig(globalConfig) {
const display = {};
Object.entries(globalConfig).forEach(([k, v]) => {
if (v.defaultValue == null) return;
display[k] = {
alias: v.alias,
description: v.desc,
value: v.defaultValue
};
});
return display;
}
function getGlobalConfig(env = process.env) {
const normalEnv = normalizeEnvVariables(env);
return {
"gb-token": {
alias: "gl-token",
desc: "Your GitLab Personal Token",
type: "string",
defaultValue: normalEnv.GITBEAKER_TOKEN
},
"gb-oauth-token": {
alias: "gl-oauth-token",
desc: "Your GitLab OAuth Token",
type: "string",
defaultValue: normalEnv.GITBEAKER_OAUTH_TOKEN
},
"gb-job-token": {
alias: "gl-job-token",
desc: "Your GitLab Job Token",
type: "string",
defaultValue: normalEnv.GITBEAKER_JOB_TOKEN
},
"gb-host": {
alias: "gl-host",
desc: "Your GitLab API host (Defaults to https://www.gitlab.com)",
type: "string",
defaultValue: normalEnv.GITBEAKER_HOST
},
"gb-sudo": {
alias: "gl-sudo",
desc: "Sudo query parameter - https://docs.gitlab.com/api/#sudo",
type: "string",
defaultValue: normalEnv.GITBEAKER_SUDO
},
"gb-camelize": {
alias: "gl-camelize",
desc: "Camelizes all response body keys",
type: "boolean",
defaultValue: normalEnv.GITBEAKER_CAMELIZE
},
"gb-request-timeout": {
alias: "gl-request-timeout",
desc: "Timeout for API requests. Measured in ms",
type: "number",
defaultValue: normalEnv.GITBEAKER_REQUEST_TIMEOUT && parseInt(normalEnv.GITBEAKER_REQUEST_TIMEOUT, 10)
},
"gb-profile-token": {
alias: "gl-profile-token",
desc: `Requests Profiles Token - https://docs.gitlab.com/administration/monitoring/performance/request_profiling.html`,
type: "string",
defaultValue: normalEnv.GITBEAKER_PROFILE_TOKEN
},
"gb-profile-mode": {
alias: "gl-profile-mode",
desc: "Requests Profiles Token - https://docs.gitlab.com/administration/monitoring/performance/request_profiling.html",
type: "string",
defaultValue: normalEnv.GITBEAKER_PROFILE_MODE
}
};
}
function getExposedAPIs(map) {
const { Gitlab, AccessLevel, ...exposed } = map;
return exposed;
}
// src/cli.ts
function setupAPIMethods(setupArgs, methodArgs) {
methodArgs.forEach((name) => {
setupArgs.positional(
`[--${getCLISafeNormalizedTerm(name)}] <${getCLISafeNormalizedTerm(name)}>`,
{
group: "Required Options",
type: "string"
}
);
});
return setupArgs;
}
function runAPIMethod(ctx, args, apiName, method) {
const globalConfig = getGlobalConfig();
const { initArgs, coreArgs, optionalArgs } = buildArgumentObjects(globalConfig, method, args);
const s = new Gitbeaker[apiName](initArgs);
return s[method.name](...Object.values(coreArgs), optionalArgs).then((r) => {
ctx.output = JSON.stringify(r, null, 3);
});
}
function setupAPIs(setupArgs, apiName, methods) {
const globalConfig = getGlobalConfig();
Object.entries(globalConfig).forEach(([k, v]) => {
setupArgs.option(`--${k} <value>`, {
group: "Base Options",
...v
});
});
for (let i = 0; i < methods.length; i += 1) {
const method = methods[i];
setupArgs.command(getCLISafeNormalizedTerm(method.name), {
setup: (setupMethodArgs) => setupAPIMethods(setupMethodArgs, method.args),
run: (args, ctx) => runAPIMethod(ctx, args, apiName, method)
});
}
return setupArgs;
}
var commandStyle = Chalk.hex("#e34329").bold;
var groupStyle = Chalk.hex("#fca325").bold;
var usageStyle = Chalk.hex("#fc6e26").bold;
var optionStyle = Chalk.white.bold;
var descriptionStyle = Chalk.hex("#848484");
var hintStyle = Chalk.hex("#6a5f88");
var cli = Sywac.version("-v, --version").help("-h, --help").showHelpByDefault().epilogue(`Copyright ${(/* @__PURE__ */ new Date()).getFullYear()}`).style({
usagePrefix: (s) => usageStyle(s),
group: (s) => groupStyle(s),
usageCommandPlaceholder: (s) => commandStyle(s),
flags: (s) => optionStyle(s),
usageOptionsPlaceholder: (s) => optionStyle(s),
desc: (s) => descriptionStyle(s),
hints: (s) => hintStyle(s)
});
cli.boolean("-g --global-args", {
desc: "Show global arguments currently set in the environment variables"
});
cli.command("*", (argv, ctx) => {
if (!argv.g) return;
const globalConfig = getGlobalConfig();
const display = getDisplayConfig(globalConfig);
ctx.output = Object.keys(display).length === 0 ? "No global variables have been set!" : JSON.stringify(display, null, 3);
});
var exposedAPIs = getExposedAPIs(API_MAP);
Object.entries(exposedAPIs).forEach(([apiName, methods]) => {
cli.command(getCLISafeNormalizedTerm(apiName), {
desc: `The ${apiName} API`,
setup: (setupArgs) => setupAPIs(setupArgs, apiName, methods)
});
});
// src/index.ts
cli.parseAndExit();