cli-stash
Version:
CLI application to manage and work with Atlassian Stash. Work with your Stash project and repositories from Command lines.
373 lines (372 loc) • 13.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseCommand = exports.BuildFlags = void 0;
const core_1 = require("@oclif/core");
const fileSystem_1 = require("../fileSystem");
const config_1 = require("./config");
const ux_1 = require("./ux");
class BuildFlags {
static async parseArray(str) {
if (!str || str.length === 0) {
return [];
}
const regex = new RegExp(`"(.*?)"|\'(.*?)\'|,`);
return str.split(regex).filter((i) => !!i).map((i) => i.trim());
}
static async parseKeyValue(str) {
const obj = {};
const keyValueRegexp = new RegExp(`"(.*?)"|\'(.*?)\'|=`);
const arrayValues = await BuildFlags.parseArray(str);
for (const value of arrayValues) {
const keyValuePair = value.split(keyValueRegexp).filter((i) => !!i).map((i) => i.trim());
obj[keyValuePair[0]] = keyValuePair[1];
}
return obj;
}
}
exports.BuildFlags = BuildFlags;
BuildFlags.alias = core_1.Flags.string({
description: 'The Stash instance alias to identify user and instance to connect with',
required: true,
char: 'a',
name: 'Alias'
});
BuildFlags.csv = core_1.Flags.boolean({
description: 'Format output as CSV format',
required: false,
name: 'CSV',
exclusive: ['json']
});
BuildFlags.extended = core_1.Flags.boolean({ char: 'x', description: 'Show extra columns when format output as table. (Format by default)', name: 'Extended' });
BuildFlags.filter = (description) => {
return core_1.Flags.string({
description: description,
required: false,
name: 'Filter'
});
};
BuildFlags.context = (description) => {
return core_1.Flags.string({
description: description,
required: false,
name: 'Context'
});
};
BuildFlags.input = {
keyvalue: (doc, required, exclusive) => {
const exclusives = ['file', 'data'];
if (exclusive && exclusive.length) {
exclusives.push(...exclusive);
}
return core_1.Flags.string({
description: 'Key-Value pair data. (key1=value1,key2=value2...). ' + (exclusives && exclusives.length ? ux_1.UX.cannotUseWith(exclusives) + '. ' : '') + ux_1.UX.processDocumentation(doc),
required: required,
name: 'Keyvalue',
char: 'k',
exclusive: exclusives,
parse: (input, context) => {
return BuildFlags.parseKeyValue(input);
}
});
},
jsonData: (doc, required, exclusive) => {
const exclusives = ['file', 'keyvalue'];
if (exclusive && exclusive.length) {
exclusives.push(...exclusive);
}
return core_1.Flags.string({
description: 'JSON Input data. ' + (exclusives && exclusives.length ? ux_1.UX.cannotUseWith(exclusives) + '. ' : '') + ux_1.UX.processDocumentation(doc),
required: required,
name: 'Data',
char: 'd',
exclusive: exclusives,
parse: (input, context) => {
return eval('(' + input + ')');
}
});
},
data: (doc, required, exclusive) => {
const exclusives = ['file', 'keyvalue'];
if (exclusive && exclusive.length) {
exclusives.push(...exclusive);
}
return core_1.Flags.string({
description: 'Input data. ' + (exclusives && exclusives.length ? ux_1.UX.cannotUseWith(exclusives) + '. ' : '') + ux_1.UX.processDocumentation(doc),
required: required,
name: 'Data',
char: 'd',
exclusive: exclusives,
});
},
jsonFile: (doc, required, exclusive) => {
const exclusives = ['data', 'keyvalue'];
if (exclusive && exclusive.length) {
exclusives.push(...exclusive);
}
return core_1.Flags.file({
description: 'JSON Input data file path. ' + (exclusives && exclusives.length ? ux_1.UX.cannotUseWith(exclusives) + '. ' : '') + ux_1.UX.processDocumentation(doc),
required: required,
exclusive: exclusives,
name: 'File',
char: 'f'
});
},
file: (doc, required, exclusive) => {
const exclusives = ['data', 'keyvalue'];
if (exclusive && exclusive.length) {
exclusives.push(...exclusive);
}
return core_1.Flags.file({
description: 'Input data file path. ' + (exclusives && exclusives.length ? ux_1.UX.cannotUseWith(exclusives) + '. ' : '') + ux_1.UX.processDocumentation(doc),
required: required,
exclusive: exclusives,
name: 'File',
char: 'f'
});
},
};
BuildFlags.output = {
file: (doc, required, exclusive) => {
return core_1.Flags.file({
description: 'Output file path. ' + (exclusive && exclusive.length ? ux_1.UX.cannotUseWith(exclusive) + '. ' : '') + ux_1.UX.processDocumentation(doc),
required: required,
exclusive: exclusive,
name: 'Output File',
});
},
folder: (doc, required, exclusive) => {
return core_1.Flags.directory({
description: 'Output folder path. ' + (exclusive && exclusive.length ? ux_1.UX.cannotUseWith(exclusive) + '. ' : '') + ux_1.UX.processDocumentation(doc),
required: required,
exclusive: exclusive,
name: 'Output Folder',
});
},
};
BuildFlags.pagination = {
all: core_1.Flags.boolean({
description: 'Return all records on the same page (instead paginate results)',
required: false,
name: 'All',
exclusive: ['limit'],
default: false,
}),
limit: core_1.Flags.integer({
description: 'Indicates how many results to return per page',
required: false,
name: 'Limit',
char: 'l',
exclusive: [],
default: 25,
}),
start: core_1.Flags.integer({
description: 'Indicates which item should be used as the first item in the page of results',
required: false,
name: 'Start',
char: 's',
exclusive: [],
default: 0,
}),
};
class BaseCommand extends core_1.Command {
constructor() {
super(...arguments);
this.localConfig = new config_1.Config(this.config.dataDir);
this.ux = new ux_1.UX();
}
get statics() {
return this.constructor;
}
get pageOptions() {
if (!this.flags.all) {
return {
limit: this.flags.limit,
start: this.flags.start
};
}
return undefined;
}
get allPageOptions() {
if (this.flags.all) {
return {
limit: 100,
start: this.flags.start
};
}
return undefined;
}
validateRequiredAndExclusives(flagsConfig) {
for (const flagName of Object.keys(flagsConfig)) {
if (flagName === 'csv' || flagName === 'json')
continue;
const flagConfig = flagsConfig[flagName];
if (!this.flags[flagName] && flagConfig.exclusive && flagConfig.exclusive.length) {
let nExclusives = 0;
let flags = ['--' + flagName];
for (const exclusive of flagConfig.exclusive) {
if (this.flags[exclusive]) {
nExclusives++;
}
else {
flags.push('--' + exclusive);
}
}
if (nExclusives === 0) {
throw new Error('Missing Required flags. Must indicate at least one of the following: ' + flags.join(', '));
}
}
}
}
hasInputData() {
return this.flags.data || this.flags.file || this.flags.keyvalue;
}
getJSONInputData() {
return this.flags.data || (this.flags.file ? JSON.parse(fileSystem_1.FileReader.readFileSync(this.flags.file)) : undefined) || this.flags.keyvalue;
}
getInputData() {
return this.flags.data || (this.flags.file ? fileSystem_1.FileReader.readFileSync(this.flags.file) : undefined);
}
parseArray(str) {
const regex = new RegExp(`"(.*?)"|\'(.*?)\'|,`);
return str
.split(regex)
.filter((i) => !!i)
.map((i) => i.trim());
}
getRecordsFoundText(recordSize, recordName) {
if (recordSize > 0) {
return recordSize + ' ' + recordName + ' records found';
}
else {
return 'Not ' + recordName + ' records found';
}
}
getRecordRetrievedText(recordName) {
return recordName + ' retrieved successfully';
}
getRecordCreatedText(recordName) {
return recordName + ' created successfully';
}
getRecordDeletedText(recordName) {
return recordName + ' deleted successfully';
}
getRecordUpdatedText(recordName) {
return recordName + ' updated successfully';
}
checkLogin() {
if (this.flags.alias && this.localConfig.instances) {
if (!this.localConfig.instances[this.flags.alias]) {
throw new Error('Not found instance with alias ' + this.flags.alias + '. Check spelling name or login as new instance');
}
}
}
log(message, level) {
switch (this.flags.loglevel) {
case 'error':
if (level === 'error') {
this.error(message);
}
break;
case 'debug':
if (level === 'debug') {
this.ux.log(message);
}
break;
case 'warn':
if (level === 'warn') {
this.warn(message);
}
break;
case 'info':
if (level === 'info') {
this.warn(message);
}
break;
}
}
/*public async _run<T>(): Promise<any> {
// If a result is defined for the command, use that. Otherwise check for a
// tableColumnData definition directly on the command.
let err: any;
try {
await this.init();
return await this.run();
} catch (e) {
err = e as Error;
await this.catch(e);
} finally {
await this.finally(err);
}
}*/
async init() {
// do some initialization
this.localConfig.load();
super.init();
const { args, flags } = await this.parse(this.statics);
this.flags = flags;
this.args = args;
this.ux = new ux_1.UX(this.flags);
if (this.statics.loginRequired) {
this.checkLogin();
}
this.validateRequiredAndExclusives(this.statics.flags);
}
processError(response, error) {
const err = error;
if (err.name === 'StashError') {
const stashError = error;
response.status = -1;
response.message = stashError.message || stashError.statusText;
response.error = stashError;
console.error(response.message);
if (stashError.errors) {
this.ux.table(stashError.errors, {
id: {
header: 'ID',
},
name: {
header: 'Name',
},
address: {
header: 'Address',
get: (row) => { row.hostName + ':' + row.port; }
},
local: {
header: 'Local',
},
}, {
csv: this.flags.csv
});
}
}
else {
throw err;
}
}
async catch(err) {
if (err.code === 'EEXIT') {
throw err;
}
if (err instanceof Error) {
err.name = err.name === 'StashError' ? 'StashError' : err.name.replace(/Error$/, '');
}
process.exitCode = process.exitCode || err.exitCode || 1;
console.error('ERROR: ' + err.message);
}
async finally(err) {
// called after run and catch regardless of whether or not the command errored
return super.finally(err);
}
async run() {
}
}
exports.BaseCommand = BaseCommand;
BaseCommand.flags = {
loglevel: core_1.Flags.string({
description: 'The logging level for this command execution',
type: "option",
options: ['error', 'warn', 'info', 'debug'],
}),
};
BaseCommand.loginRequired = true;
BaseCommand.enableJsonFlag = true;