UNPKG

@gitbeaker/cli

Version:

CLI implementation of the GitLab API.

232 lines (227 loc) 7.38 kB
#!/usr/bin/env node // 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();