UNPKG

6.8 kBJavaScriptView Raw
1#!/usr/bin/env node
2import Chalk from 'chalk';
3import Sywac from 'sywac';
4import * as Gitbeaker from '@gitbeaker/rest';
5import API_MAP from '@gitbeaker/core/map.json' assert { type: 'json' };
6import { decamelize, depascalize, camelize } from 'xcase';
7
8function param(value) {
9 let cleaned = value;
10 const exceptions = [
11 "GitLabCI",
12 "YML",
13 "GPG",
14 "SSH",
15 "IId",
16 "NPM",
17 "NuGet",
18 "DORA4",
19 "LDAP",
20 "CICD",
21 "SAML",
22 "SCIM",
23 "PyPI"
24 ];
25 exceptions.filter((e) => value.includes(e)).forEach((ex) => {
26 cleaned = cleaned.replace(ex, ex.charAt(0).toUpperCase() + ex.slice(1).toLowerCase());
27 });
28 const decamelized = decamelize(cleaned, "-");
29 return decamelized !== cleaned ? decamelized : depascalize(cleaned, "-");
30}
31function normalizeEnviromentVariables(env) {
32 const normalized = {};
33 const suffixes = [
34 "TOKEN",
35 "OAUTH_TOKEN",
36 "JOB_TOKEN",
37 "HOST",
38 "SUDO",
39 "CAMELIZE",
40 "REQUEST_TIMEOUT",
41 "PROFILE_TOKEN",
42 "PROFILE_MODE"
43 ];
44 suffixes.forEach((s) => {
45 if (env[`GITLAB_${s}`])
46 normalized[`GITBEAKER_${s}`] = env[`GITLAB_${s}`];
47 if (env[`GITBEAKER_${s}`])
48 normalized[`GITBEAKER_${s}`] = env[`GITBEAKER_${s}`];
49 });
50 return normalized;
51}
52function buildArgumentObjects(globalConfig, method, rawArgs) {
53 const ignoreOptions = ["_", "$0", "v", "version", "h", "help", "g", "global-args"];
54 const coreArgs = {};
55 const optionalArgs = {};
56 const initArgs = {};
57 Object.entries(rawArgs).forEach(([argName, value]) => {
58 if (ignoreOptions.includes(argName) || value == null)
59 return;
60 const camelCased = camelize(argName.replace("gb-", "").replace("gl-", ""), "-");
61 if (globalConfig[argName.replace("gl-", "gb-")]) {
62 initArgs[camelCased] = value;
63 } else if (method.args.includes(camelCased))
64 coreArgs[camelCased] = value;
65 else
66 optionalArgs[camelCased] = value;
67 });
68 return {
69 initArgs,
70 coreArgs,
71 optionalArgs
72 };
73}
74function getDisplayConfig(globalConfig) {
75 const display = {};
76 Object.entries(globalConfig).forEach(([k, v]) => {
77 if (v.defaultValue == null)
78 return;
79 display[k] = {
80 alias: v.alias,
81 description: v.desc,
82 value: v.defaultValue
83 };
84 });
85 return display;
86}
87function getGlobalConfig(env = process.env) {
88 const normalEnv = normalizeEnviromentVariables(env);
89 return {
90 "gb-token": {
91 alias: "gl-token",
92 desc: "Your Gitlab Personal Token",
93 type: "string",
94 defaultValue: normalEnv.GITBEAKER_TOKEN
95 },
96 "gb-oauth-token": {
97 alias: "gl-oauth-token",
98 desc: "Your Gitlab OAuth Token",
99 type: "string",
100 defaultValue: normalEnv.GITBEAKER_OAUTH_TOKEN
101 },
102 "gb-job-token": {
103 alias: "gl-job-token",
104 desc: "Your Gitlab Job Token",
105 type: "string",
106 defaultValue: normalEnv.GITBEAKER_JOB_TOKEN
107 },
108 "gb-host": {
109 alias: "gl-host",
110 desc: "Your Gitlab API host (Defaults to https://www.gitlab.com)",
111 type: "string",
112 defaultValue: normalEnv.GITBEAKER_HOST
113 },
114 "gb-sudo": {
115 alias: "gl-sudo",
116 desc: "[Sudo](https://docs.gitlab.com/ee/api/#sudo) query parameter",
117 type: "string",
118 defaultValue: normalEnv.GITBEAKER_SUDO
119 },
120 "gb-camelize": {
121 alias: "gl-camelize",
122 desc: "Camelizes all response body keys",
123 type: "boolean",
124 defaultValue: normalEnv.GITBEAKER_CAMELIZE
125 },
126 "gb-request-timeout": {
127 alias: "gl-request-timeout",
128 desc: "Timeout for API requests. Measured in ms",
129 type: "number",
130 defaultValue: normalEnv.GITBEAKER_REQUEST_TIMEOUT && parseInt(normalEnv.GITBEAKER_REQUEST_TIMEOUT, 10)
131 },
132 "gb-profile-token": {
133 alias: "gl-profile-token",
134 desc: "[Requests Profiles Token](https://docs.gitlab.com/ee/administration/monitoring/performance/request_profiling.html)",
135 type: "string",
136 defaultValue: normalEnv.GITBEAKER_PROFILE_TOKEN
137 },
138 "gb-profile-mode": {
139 alias: "gl-profile-mode",
140 desc: "[Requests Profiles Token](https://docs.gitlab.com/ee/administration/monitoring/performance/request_profiling.html)",
141 type: "string",
142 defaultValue: normalEnv.GITBEAKER_PROFILE_MODE
143 }
144 };
145}
146function getExposedAPIs(map) {
147 const { Gitlab, AccessLevel, ...exposed } = map;
148 return exposed;
149}
150
151// src/cli.ts
152function setupAPIMethods(setupArgs, methodArgs) {
153 methodArgs.forEach((name) => {
154 setupArgs.positional(`[--${param(name)}] <${param(name)}>`, {
155 group: "Required Options",
156 type: "string"
157 });
158 });
159 return setupArgs;
160}
161function runAPIMethod(ctx, args, apiName, method) {
162 const globalConfig = getGlobalConfig();
163 const { initArgs, coreArgs, optionalArgs } = buildArgumentObjects(globalConfig, method, args);
164 const s = new Gitbeaker[apiName](initArgs);
165 return s[method.name](...Object.values(coreArgs), optionalArgs).then((r) => {
166 ctx.output = JSON.stringify(r, null, 3);
167 }).catch((e) => {
168 ctx.output = e;
169 });
170}
171function setupAPIs(setupArgs, apiName, methods) {
172 const globalConfig = getGlobalConfig();
173 Object.entries(globalConfig).forEach(([k, v]) => {
174 setupArgs.option(`${k} <value>`, {
175 group: "Base Options",
176 ...v
177 });
178 });
179 for (let i = 1; i < methods.length; i += 1) {
180 const method = methods[i];
181 setupArgs.command(param(method.name), {
182 setup: (setupMethodArgs) => setupAPIMethods(setupMethodArgs, method.args),
183 run: (args, ctx) => runAPIMethod(ctx, args, apiName, method)
184 });
185 }
186 return setupArgs;
187}
188var commandStyle = Chalk.hex("#e34329").bold;
189var groupStyle = Chalk.hex("#fca325").bold;
190var usageStyle = Chalk.hex("#fc6e26").bold;
191var optionStyle = Chalk.white.bold;
192var descriptionStyle = Chalk.hex("#848484");
193var hintStyle = Chalk.hex("#6a5f88");
194var cli = Sywac.version("-v, --version").help("-h, --help").showHelpByDefault().epilogue("Copyright 2023").style({
195 usagePrefix: usageStyle,
196 group: groupStyle,
197 flags: optionStyle,
198 usageCommandPlaceholder: commandStyle,
199 usageOptionsPlaceholder: optionStyle,
200 desc: descriptionStyle,
201 hints: hintStyle
202});
203cli.boolean("-g --global-args", {
204 desc: "Show global arguments currently set in the environment variables"
205});
206cli.command("*", (argv, ctx) => {
207 if (!argv.g)
208 return;
209 const globalConfig = getGlobalConfig();
210 const display = getDisplayConfig(globalConfig);
211 ctx.output = Object.keys(display).length === 0 ? "No global variables have been set!" : JSON.stringify(display, null, 3);
212});
213var exposedAPIs = getExposedAPIs(API_MAP);
214Object.entries(exposedAPIs).forEach(([apiName, methods]) => {
215 cli.command(param(apiName), {
216 desc: `The ${apiName} API`,
217 setup: (setupArgs) => setupAPIs(setupArgs, apiName, methods)
218 });
219});
220
221// src/index.ts
222cli.parseAndExit();