@modyo/cli
Version:
Modyo Command Line Interface
336 lines (316 loc) • 10.6 kB
JavaScript
const chalk = require('chalk')
const fs = require('fs-extra')
const path = require('path')
const os = require('os')
const inquirer = require('inquirer')
const lodash = require('lodash')
const { spawn } = require('child_process')
const fetch = require('node-fetch')
const modyoPrefix = {
8: 'api/v1',
9: 'api/admin'
}
/*
* INTERNAL METHOD
* Run a command line asynchronously returning a new Promise
*/
const runCommand = (cmd, args, options) => new Promise((resolve, _) => {
const spawnx = spawn(
cmd,
args,
{
cwd: process.cwd(),
stdio: 'inherit',
shell: true,
...options
}
)
spawnx.on('exit', () => {
resolve()
})
})
/*
* Get Site Id
*/
const selectSite = ({ accountUrl, modyoVersion }, token) => new Promise((resolve, reject) => {
try {
fetch(`${accountUrl}/${modyoPrefix[modyoVersion]}/sites?per_page=500`, {
headers: {
'User-Agent': 'Modyo-CLI',
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
}
})
.then((response) => {
if (!response.ok && response.status === 401) {
reject(new Error('Unauthorized to get the site\'s list of the account'))
}
response.json()
.then((jsonResponse) => {
const { sites } = jsonResponse
const question = [
{
type: 'list',
name: 'site',
message: 'Select the destination site',
choices: sites.map((s) => s.name)
}
]
inquirer.prompt(question).then((answers) => {
resolve(sites.find((obj) => obj.name === answers.site).id)
})
})
.catch((err) => reject(err))
})
.catch((err) => reject(err))
} catch (error) {
reject(error)
}
})
/*
* Copy templates to the target directory depends on the type of the template
*/
const ensureFoldersAndFiles = (type, to) => {
let from = ''
switch (type) {
case 'widget':
from = path.resolve(__dirname, '../', 'widget/create/templates/widget')
break
case 'project':
from = path.resolve(__dirname, '../', 'project/create/templates/project')
break
case 'blank_vue_widget':
from = path.resolve(__dirname, '../', 'widget/create/templates/vue-webpack-simple-widget')
break
case 'vue_retail_bank_accounts_widget':
from = path.resolve(__dirname, '../', 'widget/create/templates/vue-retail-bank-accounts-widget')
break
case 'vue_retail_bank_cash_advance_widget':
from = path.resolve(__dirname, '../', 'widget/create/templates/vue-retail-bank-cash-advance-widget')
break
case 'vue_retail_bank_confirm_widget':
from = path.resolve(__dirname, '../', 'widget/create/templates/vue-retail-bank-confirm-widget')
break
case 'vue_retail_bank_consumer_loan_widget':
from = path.resolve(__dirname, '../', 'widget/create/templates/vue-retail-bank-consumer-loan-widget')
break
case 'vue_retail_bank_credit_cards_widget':
from = path.resolve(__dirname, '../', 'widget/create/templates/vue-retail-bank-credit-cards-widget')
break
case 'vue_retail_bank_credit_cards_payment_widget':
from = path.resolve(__dirname, '../', 'widget/create/templates/vue-retail-bank-credit-cards-payment-widget')
break
case 'vue_retail_bank_loans_widget':
from = path.resolve(__dirname, '../', 'widget/create/templates/vue-retail-bank-loans-widget')
break
case 'vue_retail_bank_mortgage_loan_widget':
from = path.resolve(__dirname, '../', 'widget/create/templates/vue-retail-bank-mortgage-loan-widget')
break
case 'vue_retail_bank_rewards_widget':
from = path.resolve(__dirname, '../', 'widget/create/templates/vue-retail-bank-rewards-widget')
break
case 'vue_retail_bank_security_widget':
from = path.resolve(__dirname, '../', 'widget/create/templates/vue-retail-bank-security-widget')
break
case 'vue_retail_bank_summary_widget':
from = path.resolve(__dirname, '../', 'widget/create/templates/vue-retail-bank-summary-widget')
break
case 'vue_retail_bank_transfer_widget':
from = path.resolve(__dirname, '../', 'widget/create/templates/vue-retail-bank-transfer-widget')
break
case 'vue_retail_bank_transfers_widget':
from = path.resolve(__dirname, '../', 'widget/create/templates/vue-retail-bank-transfers-widget')
break
case 'vue_retail_bank_voucher_widget':
from = path.resolve(__dirname, '../', 'widget/create/templates/vue-retail-bank-voucher-widget')
break
default:
from = path.resolve(__dirname, '../', 'widget/create/templates/vue-webpack-simple-widget')
break
}
fs.copySync(from, to)
}
/*
* Generate the full path to the widget to be created
*/
const resolveWidgetSrcPath = (name) => path.resolve(lodash.snakeCase(name), 'src')
/*
* Generate the full path to the project to be created
*/
const resolveWidgetPath = (name) => path.resolve(lodash.snakeCase(name) || '.')
/*
* Fetch site attributes
*/
const getModyoSiteConfiguration = ({ accountUrl, selectedSite, modyoVersion }, token) => fetch(`${accountUrl}/${modyoPrefix[modyoVersion]}/sites/${selectedSite}`, {
headers: {
'User-Agent': 'ModyoDX-CLI',
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
}
})
.then((response) => {
if (!response.ok && response.status === 401) {
throw Error(`Unauthorized to get the site's information${accountUrl}/${modyoPrefix[modyoVersion]}/sites/${selectedSite}`)
}
return response.json()
.then((jsonResponse) => jsonResponse)
.catch((err) => {
throw (err)
})
})
.catch((err) => {
throw (err)
})
/*
* Check and retrieve .modyorc
*/
const getModyoProjectConfiguration = (logger) => {
if (fs.existsSync(path.resolve('.modyorc'))) {
return JSON.parse(fs.readFileSync('.modyorc', 'utf-8'))
}
logger.info(`${chalk.red('ERROR: ')} No .modyorc file found, please add the widget in a project directory`)
return null
}
/*
* Check and retrieve promise to get project configuration
*/
const getModyoProjectConfigurationPromise = () => new Promise((resolve, reject) => {
if (fs.existsSync(path.resolve('.modyorc'))) {
const conf = JSON.parse(fs.readFileSync('.modyorc', 'utf-8'))
resolve(conf)
} else {
reject(new Error('No .modyorc file found, please add the widget in a project directory'))
}
})
/*
* Add widget json object to modyo.rc
*/
const addWidgetToConfig = (key, name) => new Promise((resolve, reject) => {
const modyorcPath = path.resolve(lodash.snakeCase(name), '.modyorc')
if (fs.existsSync(modyorcPath)) {
const conf = fs.readJSONSync(modyorcPath, 'utf-8')
conf.widget = { key, name, entrypoint: `./${path.relative('.', 'src/main.js')}` }
fs.writeFileSync(modyorcPath, JSON.stringify(conf, null, 4), 'utf-8')
resolve()
}
reject(new Error('No .modyorc file found, please add the widget and its path manually to webpack.config.js'))
})
/*
* Get widget webpack setup
*/
const webpackProjectSetup = () => {
const projectWebpackPath = path.resolve('webpack.modyo.js')
if (fs.existsSync(projectWebpackPath)) {
// eslint-disable-next-line global-require,import/no-dynamic-require
return require(projectWebpackPath)
}
return {}
}
/*
* Install dependencies
*/
const installDependencies = (cwd, packageManager, logger) => {
logger.info(`\n\n# ${chalk.green('Installing project dependencies ...')}`)
logger.info('# ========================\n')
return runCommand(packageManager, ['install', '--silent'], {
cwd
})
}
/*
* Print finish message given instructions
*/
const printFinishedMessage = (projectDir, logger, needInstall = false, packageManager = 'yarn') => {
const installMessage = !needInstall ? `${packageManager} install` : ''
const message = `
# ${chalk.green('Widget initialization finished!')}
# ========================
To get started:
${chalk.yellow(`cd ${projectDir}\n ${installMessage}\n modyo-cli login\n modyo-cli widget start`)}
\n
`
logger.info(message)
}
/*
* Get access token from user directory
*/
const getAccessTokens = () => new Promise((resolve, reject) => {
const confFilePath = `${os.homedir()}/.modyo/modyo-cli.conf`
if (fs.existsSync(confFilePath)) {
const conf = JSON.parse(fs.readFileSync(confFilePath, 'utf-8'))
resolve(conf)
} else {
reject(new Error('Modyo accees tokens configuration doesn\'t exist'))
}
})
/*
* Write access token on user directory
*/
const writeAccessTokensConfiguration = (conf) => {
const confFilePath = `${os.homedir()}/.modyo/modyo-cli.conf`
fs.writeFileSync(confFilePath, JSON.stringify(conf, null, 4), 'utf-8')
}
/*
* Get Auth Token from Modyo platform
*/
const getAuthToken = ({ accountUrl } = null, options = { token: null }) => new Promise((resolve, _) => {
if (options.token) {
return resolve(options.token)
}
let url = ''
if (accountUrl === null) {
if (!fs.existsSync('.modyorc')) {
throw (new Error('no .modyorc file found, please run command from a valid ModyoCLI project path'))
}
const rcConf = JSON.parse(fs.readFileSync('.modyorc', 'utf-8'))
if (rcConf.accountUrl) {
url = rcConf.accountUrl
}
} else { url = accountUrl }
const confFilePath = `${os.homedir()}/.modyo/modyo-cli.conf`
let hConf = { accessTokens: {} }
if (fs.existsSync(confFilePath)) {
hConf = JSON.parse(fs.readFileSync(confFilePath, 'utf-8'))
if (hConf.accessTokens && hConf.accessTokens[url]) {
return resolve(hConf.accessTokens[url])
}
}
const question = [
{
type: 'input',
name: 'token',
message: 'Please insert your Modyo CLI Api Access Token.',
validate: (value) => {
if (value.match(/^[a-f0-9]{64}$$/i)) { return true }
return 'Please enter a valid Modyo Oauth2 Token'
}
}
]
return inquirer.prompt(question).then((answers) => {
fs.ensureFileSync(confFilePath)
if (hConf.accessTokens) {
hConf.accessTokens[url] = answers.token
} else {
hConf.accessTokens = {}
hConf.accessTokens[url] = answers.token
}
fs.writeFileSync(confFilePath, JSON.stringify(hConf, null, 4), 'utf-8')
return resolve(answers.token)
})
})
module.exports = {
getAuthToken,
writeAccessTokensConfiguration,
getAccessTokens,
printFinishedMessage,
installDependencies,
webpackProjectSetup,
addWidgetToConfig,
getModyoProjectConfigurationPromise,
getModyoProjectConfiguration,
getModyoSiteConfiguration,
resolveWidgetPath,
resolveWidgetSrcPath,
ensureFoldersAndFiles,
selectSite,
modyoPrefix
}