import Chalk from 'chalk' ; import Sywac from 'sywac' ; import { camelize , decamelize , depascalize } from 'xcase' ; import * as Gitbeaker from '@gitbeaker/node' ; import { getAPIMap } from '@gitbeaker/core' ; const commandStyle = Chalk . hex ( '#e34329' ) . bold ; const groupStyle = Chalk . hex ( '#fca325' ) . bold ; const usageStyle = Chalk . hex ( '#fc6e26' ) . bold ; const optionStyle = Chalk . white . bold ; const descriptionStyle = Chalk . hex ( '#848484' ) ; const hintStyle = Chalk . hex ( '#6a5f88' ) ; function globalConfig ( env = process . env ) { return { 'gb-token' : { alias : 'gl-token' , desc : 'Your Gitlab Personal Token' , type : 'string' , defaultValue : env . GITBEAKER_TOKEN || env . GITLAB_TOKEN , } , 'gb-oauth-token' : { alias : 'gl-oauth-token' , desc : 'Your Gitlab OAuth Token' , type : 'string' , defaultValue : env . GITBEAKER_OAUTH_TOKEN || env . GITLAB_OAUTH_TOKEN , } , 'gb-job-token' : { alias : 'gl-job-token' , desc : 'Your Gitlab Job Token' , type : 'string' , defaultValue : env . GITBEAKER_JOB_TOKEN || env . GITLAB_JOB_TOKEN , } , 'gb-host' : { alias : 'gl-host' , desc : 'Your Gitlab API host (Defaults to https://www.gitlab.com)' , type : 'string' , defaultValue : env . GITBEAKER_HOST || env . GITLAB_HOST , } , 'gb-version' : { alias : 'gl-version' , desc : 'The targetted Gitlab API version (Defaults to 4)' , type : 'number' , defaultValue : ( env . GITBEAKER_VERSION && parseInt ( env . GITBEAKER_VERSION , 10 ) ) || ( env . GITLAB_VERSION && parseInt ( env . GITLAB_VERSION , 10 ) ) , } , 'gb-sudo' : { alias : 'gl-sudo' , desc : '[Sudo](https://docs.gitlab.com/ee/api/#sudo) query parameter' , type : 'string' , defaultValue : env . GITBEAKER_SUDO || env . GITLAB_SUDO , } , 'gb-camelize' : { alias : 'gl-camelize' , desc : 'Camelizes all response body keys' , type : 'boolean' , defaultValue : ( env . GITBEAKER_CAMELIZE && env . GITBEAKER_CAMELIZE === 'true' ) || ( env . GITLAB_CAMELIZE && env . GITLAB_CAMELIZE === 'true' ) , } , 'gb-request-timeout' : { alias : 'gl-request-timeout' , desc : 'Timeout for API requests. Measured in ms' , type : 'number' , defaultValue : ( env . GITBEAKER_REQUEST_TIMEOUT && parseInt ( env . GITBEAKER_REQUEST_TIMEOUT , 10 ) ) || ( env . GITBEAKER_REQUEST_TIMEOUT && parseInt ( env . GITBEAKER_REQUEST_TIMEOUT , 10 ) ) , } , 'gb-profile-token' : { alias : 'gl-profile-token' , desc : '[Requests Profiles Token](https://docs.gitlab.com/ee/administration/monitoring/performance/request_profiling.html)' , type : 'string' , defaultValue : env . GITBEAKER_PROFILE_TOKEN || env . GITLAB_PROFILE_TOKEN , } , 'gb-profile-mode' : { alias : 'gl-profile-mode' , desc : '[Requests Profiles Token](https://docs.gitlab.com/ee/administration/monitoring/performance/request_profiling.html)' , type : 'string' , defaultValue : env . GITBEAKER_PROFILE_MODE || env . GITLAB_PROFILE_MODE , } , } ; } const ignoreOptions = [ '_' , '$0' , 'v' , 'version' , 'h' , 'help' , 'g' , 'global-args' ] ; function param ( string ) { let cleaned = string ; const exceptions = [ 'GitLabCI' , 'YML' , 'GPG' , 'SSH' ] ; const ex = exceptions . find ( ( e ) => string . includes ( e ) ) ; if ( ex ) cleaned = cleaned . replace ( ex , ex . charAt ( 0 ) . toUpperCase ( ) + ex . slice ( 1 ) ) ; const decamelized = decamelize ( cleaned , '-' ) ; return decamelized !== cleaned ? decamelized : depascalize ( cleaned , '-' ) ; } function setupAPIMethods ( setupArgs , methodArgs ) { methodArgs . forEach ( ( name ) => { if ( typeof name !== 'string' ) return ; setupArgs . positional ( `[--${ param ( name ) }] <${ param ( name ) }>` , { group : 'Required Options' , type : 'string' , } ) ; } ) ; return setupArgs ; } function runAPIMethod ( ctx , args , apiName , method ) { const coreArgs = { } ; const optionalArgs = { } ; const initArgs = { } ; Object . entries ( args ) . forEach ( ( [ argName , value ] ) => { if ( ignoreOptions . includes ( argName ) || value == null ) return ; const camelCased = camelize ( argName . replace ( 'gb-' , '' ) . replace ( 'gl-' , '' ) , '-' ) ; if ( globalConfig ( ) [ argName . replace ( 'gl-' , 'gb-' ) ] ) { initArgs [ camelCased ] = value ; } else if ( method . args . includes ( camelCased ) ) coreArgs [ camelCased ] = value ; else optionalArgs [ camelCased ] = value ; } ) ; const s = new Gitbeaker [ apiName ] ( initArgs ) ; return s [ method . name ] ( ... Object . values ( coreArgs ) , optionalArgs ) . then ( ( r ) => { ctx . output = JSON . stringify ( r , null , 3 ) ; } ) . catch ( ( e ) => { ctx . output = e ; } ) ; } function setupAPIs ( setupArgs , apiName , methods ) { Object . entries ( globalConfig ( ) ) . forEach ( ( [ k , v ] ) => { setupArgs . option ( `${ k } <value>` , { group : 'Base Options' , ... v , } ) ; } ) ; for ( let i = 1 ; i < methods . length ; i += 1 ) { const method = methods [ i ] ; setupArgs . command ( param ( method . name ) , { setup : ( setupMethodArgs ) => setupAPIMethods ( setupMethodArgs , method . args ) , run : ( args , ctx ) => runAPIMethod ( ctx , args , apiName , method ) , } ) ; } return setupArgs ; } const cli = Sywac . version ( '-v, --version' ) . help ( '-h, --help' ) . showHelpByDefault ( ) . epilogue ( 'Copyright 2019' ) . style ( { usagePrefix : ( s ) => usageStyle ( s ) , group : ( s ) => groupStyle ( s ) , flags : ( s ) => optionStyle ( s ) , usageCommandPlaceholder : ( s ) => commandStyle ( 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 enviroment variables' , } ) ; cli . command ( '*' , ( argv , ctx ) => { if ( ! argv . g ) return ; const display = { } ; Object . entries ( globalConfig ( ) ) . forEach ( ( [ k , v ] ) => { if ( v . defaultValue == null ) return ; display [ k ] = { alias : v . alias , description : v . desc , value : v . defaultValue , } ; } ) ; ctx . output = Object . keys ( display ) . length === 0 ? 'No global variables have been set!' : JSON . stringify ( display , null , 3 ) ; } ) ; Object . entries ( getAPIMap ( ) ) . forEach ( ( [ apiName , methods ] ) => { if ( apiName === 'Gitlab' ) return ; cli . command ( param ( apiName ) , { desc : `The ${ apiName } API` , setup : ( setupArgs ) => setupAPIs ( setupArgs , apiName , methods ) , } ) ; } ) ; export { cli } ;