imq-cli
Version:
Command Line Interface for IMQ
326 lines • 13.3 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
/*!
* IMQ-CLI command: config init
*
* Copyright (c) 2018, Mykhailo Stadnyk <mikhus@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
const inquirer = require("inquirer");
const lib_1 = require("../../lib");
const chalk_1 = require("chalk");
const fs = require("fs");
// we are going to ignore almost all code here because it's very hard to test
// command line user interaction
// istanbul ignore next
async function selectTemplate(type) {
let name = 'custom';
let path = '';
if (type === 'existing') {
const defaultTemplates = await lib_1.loadTemplates();
let answer = await inquirer.prompt([{
type: 'list',
name: 'tplName',
message: 'Select one of existing templates:',
choices: Object.keys(defaultTemplates)
}]);
return { [answer.tplName]: defaultTemplates[answer.tplName] };
}
if (type === 'repo') {
let answer = await inquirer.prompt([{
type: 'input',
name: 'repoUrl',
message: 'Enter git repository URL:'
}]);
if (!(answer.repoUrl && answer.repoUrl.trim())) {
throw new TypeError('Repository URL expected, but was not given!');
}
path = await lib_1.loadTemplate(answer.repoUrl);
}
else if (type === 'directory') {
let answer = await inquirer.prompt([{
type: 'input',
name: 'tplDir',
message: 'Enter path to directory:'
}]);
if (!(answer.tplDir && answer.tplDir.trim())) {
throw new TypeError('Template directory path expected, ' +
'but was not given!');
}
if (!fs.existsSync(lib_1.resolve(answer.tplDir))) {
throw new Error('Given template directory does not exist!');
}
path = lib_1.resolve(answer.tplDir);
}
return { [name]: path };
}
exports.selectTemplate = selectTemplate;
// istanbul ignore next
async function templateOptions(config) {
let answer = await inquirer.prompt([{
type: 'confirm',
name: 'useDefault',
message: 'Do you want to use default template for newly created ' +
'services?',
default: true
}]);
let templates;
let tplName = 'default';
if (!answer.useDefault) {
answer = await inquirer.prompt([{
type: 'list',
name: 'tplType',
message: 'Select required template:',
choices: [{
name: 'From a list of existing templates',
value: 'existing'
}, {
name: 'From a git repository',
value: 'repo'
}, {
name: 'From file system directory',
value: 'directory'
}]
}]);
templates = await selectTemplate(answer.tplType);
tplName = Object.keys(templates).shift() || '';
}
else {
templates = await lib_1.loadTemplates();
}
if (templates[tplName]) {
config.template = templates[tplName];
return console.log(chalk_1.default.green(`New services set to be created from template "${tplName}" (${config.template})`));
}
else {
throw new Error(`Template ${tplName} does not exists!`);
}
}
exports.templateOptions = templateOptions;
// istanbul ignore next
async function versionSystemOptions(config) {
let answer = await inquirer.prompt([{
type: 'confirm',
name: 'autoCreateRepo',
message: 'Would you like IMQ automatically create git ' +
'repository for new services when generate?',
default: true,
}]);
if (!answer.autoCreateRepo) {
config.useGit = false;
return;
}
config.useGit = true;
console.log(chalk_1.default.cyan(lib_1.wrap('\nTo publish git repository you need to provide base url ' +
'where your git repositories published to. It is recommended ' +
'also to set-up git SSH access on your machine to ' +
'make publishing process run smoothly.\n\nFor example, if ' +
'you are using GitHub for your repositories, you need to enter ' +
'git@github.com:[user_or_org] as base URL and setup SSH ' +
'access as described at https://help.github.com/articles/' +
'adding-a-new-ssh-key-to-your-github-account/\n')));
answer = await inquirer.prompt([{
type: 'input',
name: 'url',
message: 'Enter github organization or user name:',
}]);
if (!/^[-_a-z0-9]+$/i.test(answer.url)) {
console.log(chalk_1.default.red('Wrong user or organization name.'));
return await versionSystemOptions(config);
}
config.gitBaseUrl = `git@github.com:${answer.url}`;
console.log(chalk_1.default.green(`Base git URL is set to "${config.gitBaseUrl}"`));
answer = await inquirer.prompt([{
type: 'confirm',
name: 'saveGitHubToken',
message: 'Would you like to save GitHub auth token in a local config ' +
'to prevent imq to ask it any time service is created?',
default: false,
}]);
if (!answer.saveGitHubToken) {
return;
}
console.log(chalk_1.default.cyan(lib_1.wrap('To make GitHub integration work you must provide a valid token ' +
'which grants permission to create repository for a specified ' +
'organization or user name.\nUsually you can generate the token ' +
'on this page: https://github.com/settings/tokens')));
answer = await inquirer.prompt([{
type: 'input',
name: 'gitHubAuthToken',
message: 'Enter GitHub auth token:',
}]);
if (!answer.gitHubAuthToken.trim()) {
console.log(chalk_1.default.red('Given token is empty, you will be prompted to enter it on ' +
'service create command'));
return;
}
config.gitHubAuthToken = answer.gitHubAuthToken.trim();
console.log(chalk_1.default.green('GitHub auth token stored in local config file'));
answer = await inquirer.prompt([{
type: 'confirm',
name: 'isPrivate',
message: 'Does created service should a private repository on GitHub?',
default: true,
}]);
config.gitRepoPrivate = answer.isPrivate;
console.log(chalk_1.default.green(`Service on GitHub will be created as ${config.gitRepoPrivate ?
'private' : 'public'} repository.`));
}
exports.versionSystemOptions = versionSystemOptions;
// istanbul ignore next
async function authorName(config) {
const answer = await inquirer.prompt([{
type: 'input',
name: 'author',
message: 'Enter author\'s full name (user or organization):'
}]);
if (!answer.author.trim()) {
console.log(chalk_1.default.red(`Given name is invalid, please, try again.`));
return await authorName(config);
}
config.author = answer.author.trim();
console.log(chalk_1.default.green(`Auto-generated code will be authored by "${config.author}"`));
}
exports.authorName = authorName;
// istanbul ignore next
async function authorEmail(config) {
const answer = await inquirer.prompt([{
type: 'input',
name: 'email',
message: 'Enter user or organization email:'
}]);
if (!/^[-a-z0-9.]+@[-a-z0-9.]+$/i.test(answer.email.trim())) {
console.log(chalk_1.default.red(`Given email is invalid, please, try again.`));
return await authorName(config);
}
config.email = answer.email.trim();
console.log(chalk_1.default.green(`Generated code will be referred to given contact: ${config.email}`));
}
exports.authorEmail = authorEmail;
// istanbul ignore next
async function authorOptions(config) {
await authorName(config);
await authorEmail(config);
}
exports.authorOptions = authorOptions;
// istanbul ignore next
async function dockerCredentials(config) {
const answer = await inquirer.prompt([{
type: 'input',
name: 'dockerHubUser',
message: 'Docker hub user:'
}, {
type: 'password',
name: 'dockerHubPassword',
message: 'Docker hub password:'
}]);
if (!answer.dockerHubUser.trim()) {
console.log(chalk_1.default.red('Given docker hub user name is empty, please try again'));
return dockerCredentials(config);
}
if (!answer.dockerHubPassword.trim()) {
console.log(chalk_1.default.red('Given docker hub password is empty, please try again'));
return dockerCredentials(config);
}
config.dockerHubUser = answer.dockerHubUser.trim();
config.dockerHubPassword = answer.dockerHubPassword.trim();
console.log(chalk_1.default.green('Docker hub credentials saved in a local config file.'));
}
exports.dockerCredentials = dockerCredentials;
// istanbul ignore next
async function dockerQuestions(config) {
let answer = await inquirer.prompt([{
type: 'confirm',
name: 'useDocker',
message: 'Would you like to dockerize created imq services?',
default: true
}]);
if (!answer.useDocker) {
config.useDocker = false;
return;
}
answer = await inquirer.prompt([{
type: 'input',
name: 'dockerHubNamespace',
message: 'Docker hub namespace:'
}]);
if (!answer.dockerHubNamespace.trim()) {
console.log(chalk_1.default.red('Given docker hub namespace is invalid, please, try again...'));
return await dockerQuestions(config);
}
config.useDocker = true;
config.dockerHubNamespace = answer.dockerHubNamespace.trim();
answer = await inquirer.prompt([{
type: 'confirm',
name: 'saveDockerCredentials',
message: 'Would you like to store docker credentials locally to ' +
'allow imq create CI-Docker secrets without prompt?',
default: false
}]);
if (!answer.saveDockerCredentials) {
return;
}
await dockerCredentials(config);
}
exports.dockerQuestions = dockerQuestions;
// istanbul ignore next
async function serviceQuestions(config) {
await authorOptions(config);
await templateOptions(config);
const { id, name } = await lib_1.licensingOptions();
config.license = id;
console.log(chalk_1.default.green(`Selected "${name}" to be a license for IMQ generated code and services`));
await versionSystemOptions(config);
await dockerQuestions(config);
}
exports.serviceQuestions = serviceQuestions;
// noinspection JSUnusedGlobalSymbols
_a = {
command: 'init',
describe: 'Interactively initializes IMQ CLI configuration file',
async handler() {
try {
if (!lib_1.configEmpty()) {
process.stdout.write(chalk_1.default.bold.yellow('Config already initialized, path: ') +
chalk_1.default.cyan(lib_1.CONFIG_PATH) + '\n');
const answer = await inquirer.prompt([{
type: 'confirm',
name: 'reInit',
message: 'Do you want to re-init?',
default: false
}]);
if (!answer.reInit) {
return;
}
}
console.log(chalk_1.default.cyan(lib_1.wrap('Let\'s define global config options ' +
'for IMQ command line runs. These options will be used as ' +
'default parameters and will help you shorten your ' +
'commands.\n\n')));
console.log(chalk_1.default.yellow(lib_1.wrap('- You can skip this step by pressing ' +
'[^C].\n- You can proceed to this step later by running:')));
console.log(chalk_1.default.magenta('\n $ imq config init\n'));
const config = lib_1.loadConfig();
await serviceQuestions(config);
lib_1.saveConfig(config);
console.log(chalk_1.default.magenta('IMQ-CLI successfully configured!'));
}
catch (err) {
lib_1.printError(err);
console.error(err);
}
}
}, exports.command = _a.command, exports.describe = _a.describe, exports.handler = _a.handler;
//# sourceMappingURL=init.js.map