intreface.cli
Version:
Intreface Dev Tools
403 lines (402 loc) • 24.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const command_1 = require("@oclif/command");
const cli_ux_1 = require("cli-ux");
const chalk_1 = require("chalk");
const system_1 = require("../@utility/system");
const io_1 = require("../@utility/io");
const inquirer = require("inquirer");
const fs = require("fs");
const path = require("path");
const child_process = require("child_process");
const objectPath = require("object-path");
const stringFormatter = require("string-format");
const notifier = require("node-notifier");
const fse = require("fs-extra");
const decamelize = require("decamelize");
const camelcase = require("camelcase");
const axios_1 = require("axios");
const bitrix_1 = require("../@utility/bitrix");
const slash = require('slash');
const terminalLink = require("terminal-link");
const questions_1 = require("../@utility/questions");
const questionMap = {
create: {
projectName: questions_1.projectName,
projectIp: questions_1.projectIp
},
remove: {
projectNameSelect: questions_1.projectNameSelect,
confirmRemove: questions_1.confirmRemove
},
link: {
projectNameSelect: questions_1.projectNameSelect,
gitRepositorySelect: questions_1.gitRepositorySelect,
linkTypeSelect: questions_1.linkTypeSelect
},
renew: {
projectNameSelect: questions_1.projectNameSelect,
},
update: {
projectNameSelect: questions_1.projectNameSelect,
},
lock: {
gitRepositorySelect: questions_1.gitRepositorySelect,
},
unlock: {},
license: {}
};
const validateServerEnvironment = (proc) => {
if (!system_1.isServiceRunning('mysql')) {
proc.error(`${chalk_1.default.red('💩')} service "mysql" is not ${chalk_1.default.red.underline('Running')}.`);
}
if (!system_1.isServiceRunning('php-cgi')) {
proc.error(`${chalk_1.default.red('💩')} service "php-cgi" is not ${chalk_1.default.red.underline('Running')}.`);
}
if (!system_1.isServiceRunning('nginx')) {
proc.error(`${chalk_1.default.red('💩')} service "nginx" is not ${chalk_1.default.red.underline('Running')}.`);
}
};
class Bitrix extends command_1.Command {
async run() {
const { args, flags } = this.parse(Bitrix);
const config = objectPath(system_1.readConfig());
const flagConfig = Object.assign({ config: '' }, flags).config.split(',');
switch (args.action) {
case 'list': {
let list = system_1.getDirectoryList(config.get('directory.bitrix'));
list.forEach(name => {
if (!io_1.isFileExist(path.join(config.get('directory.bitrix'), name, '.cli.ignore'))) {
let nginxConfigPath = slash(path.join(config.get('directory.server'), '/conf/nginx/sites/', `${name}.enabled`));
if (io_1.isFileExist(nginxConfigPath)) {
let nginxConfig = fs.readFileSync(nginxConfigPath, 'utf-8');
let bitrixIp = (nginxConfig.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/) || '');
console.log(`${name} [${terminalLink(bitrixIp, `http://${bitrixIp}`, { fallback(text, url) { return `\u200B${url}\u200B`; } })}]`);
}
}
});
break;
}
case 'lock': {
let questions = Object.values(questionMap[args.action]);
let responses = await inquirer.prompt(questions);
let isLocked = bitrix_1.lockBitrix(responses.gitRepository);
if (isLocked) {
console.log('Locked');
notifier.notify({
icon: path.join(__dirname, './../@assets/images/logo.png'),
title: 'Intreface CLI',
message: `Bitrix in the path "${process.cwd()}" locked to project "${responses.gitRepository}". 😎`,
});
}
else {
this.error(`${chalk_1.default.red('💩')} Bitrix in the path "${process.cwd()}" ${chalk_1.default.red.underline('Can not be locked')}.`);
}
break;
}
case 'unlock': {
let isUnLocked = bitrix_1.unLockBitrix();
if (isUnLocked) {
console.log('Unlocked');
notifier.notify({
icon: path.join(__dirname, './../@assets/images/logo.png'),
title: 'Intreface CLI',
message: `Bitrix in the path "${process.cwd()}" unlocked". 😎`,
});
}
else {
this.error(`${chalk_1.default.red('💩')} Bitrix in the path "${process.cwd()}" ${chalk_1.default.red.underline('Can not be unlocked')}.`);
}
break;
}
case 'update': {
// Validate server environment : Running
validateServerEnvironment(this);
let questions = Object.values(questionMap[args.action]);
let responses = await inquirer.prompt(questions);
responses.projectPath = slash(path.join(config.get('directory.bitrix'), responses.projectName, 'www'));
responses.nginxConfigPath = slash(path.join(config.get('directory.server'), '/conf/nginx/sites/', `${responses.projectName}.enabled`));
if (!io_1.isDirectoryExist(responses.projectPath)) {
this.error(`${chalk_1.default.red('💩')} bitrix project "${responses.projectPath}" ${chalk_1.default.red.underline('Does Not Exist')}.`);
}
if (!io_1.isFileExist(responses.nginxConfigPath)) {
this.error(`${chalk_1.default.red('💩')} nginx config "${responses.nginxConfigPath}" ${chalk_1.default.red.underline('Does Not Exist')}.`);
}
let nginxConfig = fs.readFileSync(responses.nginxConfigPath, 'utf-8');
responses.projectIp = nginxConfig.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/);
if (!responses.projectIp) {
this.error(`${chalk_1.default.red('💩')} IP in config "${responses.nginxConfigPath}" ${chalk_1.default.red.underline('Not Found')}.`);
}
responses.projectIp = responses.projectIp[0];
// START
cli_ux_1.default.action.start('processing');
const bitrixUpdatePath = path.join(responses.projectPath, 'demo.update.php');
await fse.copy(path.join(__dirname, './../@config/bitrix/demo.update.php'), bitrixUpdatePath);
const response = await axios_1.default.get(`http://${responses.projectIp}/demo.update.php`);
console.log(response.data);
// END
cli_ux_1.default.action.stop('done');
break;
}
case 'renew': {
// Validate server environment : Running
validateServerEnvironment(this);
let questions = Object.values(questionMap[args.action]);
let responses = await inquirer.prompt(questions);
responses.projectPath = slash(path.join(config.get('directory.bitrix'), responses.projectName, 'www'));
responses.nginxConfigPath = slash(path.join(config.get('directory.server'), '/conf/nginx/sites/', `${responses.projectName}.enabled`));
if (!io_1.isDirectoryExist(responses.projectPath)) {
this.error(`${chalk_1.default.red('💩')} bitrix project "${responses.projectPath}" ${chalk_1.default.red.underline('Does Not Exist')}.`);
}
if (!io_1.isFileExist(responses.nginxConfigPath)) {
this.error(`${chalk_1.default.red('💩')} nginx config "${responses.nginxConfigPath}" ${chalk_1.default.red.underline('Does Not Exist')}.`);
}
let nginxConfig = fs.readFileSync(responses.nginxConfigPath, 'utf-8');
responses.projectIp = nginxConfig.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/);
if (!responses.projectIp) {
this.error(`${chalk_1.default.red('💩')} IP in config "${responses.nginxConfigPath}" ${chalk_1.default.red.underline('Not Found')}.`);
}
responses.projectIp = responses.projectIp[0];
// Apply bitrix license
const license = await bitrix_1.getBitrixLicenseKey();
console.log(`Bitrix License Demo Key is ${chalk_1.default.green.bold(license)}.`);
const bitrixDemoLicensePath = path.join(responses.projectPath, 'bitrix/license_key.php');
let bitrixDemoLicense = fs.readFileSync(bitrixDemoLicensePath, 'utf-8');
fs.writeFileSync(bitrixDemoLicensePath, bitrixDemoLicense.replace(/".*"/, `"${license}"`), { flag: 'w', encoding: 'utf8' });
// Bitrix activate and adjust
const bitrixDemoActivatorPath = path.join(responses.projectPath, 'demo.activate.php');
await fse.copy(path.join(__dirname, './../@config/bitrix/demo.activate.php'), bitrixDemoActivatorPath);
await axios_1.default.get(`http://${responses.projectIp}/demo.activate.php`);
break;
}
case 'license': {
const license = await bitrix_1.getBitrixLicenseKey();
console.log(`Bitrix License Demo Key is ${chalk_1.default.green.bold(license)}.`);
break;
}
case 'create': {
// Validate server environment : Running
validateServerEnvironment(this);
let questions = Object.values(questionMap[args.action]);
let responses = await inquirer.prompt(questions);
responses.projectPath = slash(path.join(config.get('directory.bitrix'), responses.projectName, 'www'));
responses.nginxConfigPath = slash(path.join(config.get('directory.server'), '/conf/nginx/sites/', `${responses.projectName}.enabled`));
// Check if URL/IP available. Probably it means that something works there already
let urlAvailable = false;
try {
await axios_1.default.get(`http://${responses.projectIp}`, { timeout: 3000 });
urlAvailable = true;
}
catch (e) { }
if (urlAvailable) {
this.error(`${chalk_1.default.red('💩')} unknown project by "${responses.projectIp}" address ${chalk_1.default.red.underline('Already Exist')}.`);
}
if (io_1.isDirectoryExist(responses.projectPath)) {
this.error(`${chalk_1.default.red('💩')} bitrix project "${responses.projectPath}" ${chalk_1.default.red.underline('Already Exist')}.`);
}
if (io_1.isFileExist(responses.nginxConfigPath)) {
this.error(`${chalk_1.default.red('💩')} nginx config "${responses.nginxConfigPath}" ${chalk_1.default.red.underline('Already Exist')}.`);
}
let nginxConfig = fs.readFileSync(path.join(__dirname, './../@config/nginx/site.conf'), 'utf-8');
// START
cli_ux_1.default.action.start('processing');
// Create project directory
fs.mkdirSync(responses.projectPath, { recursive: true });
// Create nignx config
fs.writeFileSync(responses.nginxConfigPath, stringFormatter(nginxConfig, responses), { flag: 'w', encoding: 'utf8' });
// Clone bitrix repo
child_process.execSync(`git clone https://${encodeURIComponent(config.get('git.login'))}:${encodeURIComponent(config.get('git.password'))}@bitbucket.org/intreface/bx.bizpace.demo.20.5.extracted.git ${responses.projectPath}`, { stdio: 'inherit' });
// Delete .git
await fse.remove(path.join(responses.projectPath, '.git'));
// Initialize variables related to MySQL DB
const dbName = decamelize(camelcase(responses.projectName));
const dbPasswordOption = config.get('mysql.password', '').length > 0
? `-p"${config.get('mysql.password')}"`
: '';
const dbLoginOption = `-u${config.get('mysql.login')}`;
// Create MySQL database
child_process.execSync(`mysql ${dbLoginOption} ${dbPasswordOption} -e"CREATE DATABASE \`${dbName}\` DEFAULT CHARACTER SET utf8mb4 ;"`, { stdio: 'inherit' });
// Import bitrix repo DB to MySQL
child_process.execSync(`mysql ${dbLoginOption} ${dbPasswordOption} ${dbName} < ${path.join(responses.projectPath, 'bitrix.sql')}`, { stdio: 'inherit' });
// @todo implement restore
// CONFIG: restore
// if(!flagConfig.includes('restore')){
// const bitrixRestorePath = path.join(responses.projectPath, 'restore.php');
// await fse.copy(
// path.join(__dirname, './../@config/bitrix/bitrix.restore.php'),
// bitrixRestorePath
// );
//
// // Fetch bitrix license
// const license = await getBitrixLicenseKey();
// console.log(`Bitrix License Demo Key is ${chalk.green.bold(license)}.`);
//
// notifier.notify({
// icon: path.join(__dirname, './../@assets/images/logo.png'),
// title: 'Intreface CLI',
// message: `Open "http://${responses.projectIp}/restore.php" to start project restore "${responses.projectName}"`,
// });
//
// break;
// }
// Replace bitrix settings
const bitrixSettings = {
crypto_key: 123456,
db_host: 'localhost',
db_name: dbName,
db_login: config.get('mysql.login'),
db_password: config.get('mysql.password', '')
};
const bitrixSettingsConfigPath = path.join(responses.projectPath, '/bitrix/.settings.php');
let bitrixSettingsConfig = fs.readFileSync(bitrixSettingsConfigPath, 'utf-8');
fs.writeFileSync(bitrixSettingsConfigPath, stringFormatter(bitrixSettingsConfig, bitrixSettings), { flag: 'w', encoding: 'utf8' });
const bitrixDbconnConfigPath = path.join(responses.projectPath, '/bitrix/php_interface/dbconn.php');
let bitrixDbconnConfig = fs.readFileSync(bitrixDbconnConfigPath, 'utf-8');
fs.writeFileSync(bitrixDbconnConfigPath, stringFormatter(bitrixDbconnConfig, bitrixSettings), { flag: 'w', encoding: 'utf8' });
// Restart server
await system_1.serverNginxRestart();
// Apply bitrix license
const license = await bitrix_1.getBitrixLicenseKey();
console.log(`Bitrix License Demo Key is ${chalk_1.default.green.bold(license)}.`);
const bitrixDemoLicensePath = path.join(responses.projectPath, 'bitrix/license_key.php');
let bitrixDemoLicense = fs.readFileSync(bitrixDemoLicensePath, 'utf-8');
fs.writeFileSync(bitrixDemoLicensePath, bitrixDemoLicense.replace(/".*"/, `"${license}"`), { flag: 'w', encoding: 'utf8' });
// Wait
await system_1.timeout(3000);
// RUN: activate
const bitrixDemoActivatorPath = path.join(responses.projectPath, 'demo.activate.php');
await fse.copy(path.join(__dirname, './../@config/bitrix/demo.activate.php'), bitrixDemoActivatorPath);
await axios_1.default.get(`http://${responses.projectIp}/demo.activate.php`);
// RUN: adjust
const bitrixDemoInstallPath = path.join(responses.projectPath, 'demo.install.php');
await fse.copy(path.join(__dirname, './../@config/bitrix/demo.install.php'), bitrixDemoInstallPath);
await axios_1.default.get(`http://${responses.projectIp}/demo.install.php?project_title=${responses.projectName}`);
// RUN: update
if (!flagConfig.includes('no-update')) {
const bitrixUpdatePath = path.join(responses.projectPath, 'demo.update.php');
await fse.copy(path.join(__dirname, './../@config/bitrix/demo.update.php'), bitrixUpdatePath);
await axios_1.default.get(`http://${responses.projectIp}/demo.update.php`);
}
// Delete useless files
await fse.remove(path.join(responses.projectPath, 'bitrix.sql'));
await fse.remove(path.join(responses.projectPath, 'bitrix_after_connect.sql'));
// END
cli_ux_1.default.action.stop('done');
await cli_ux_1.default.url(responses.projectName, responses.projectIp);
notifier.notify({
icon: path.join(__dirname, './../@assets/images/logo.png'),
title: 'Intreface CLI',
message: `Bitrix project "${responses.projectName}" by address "http://${responses.projectIp}" has been created. 😎`,
});
break;
}
case 'remove': {
// Validate server environment : Running
validateServerEnvironment(this);
let questions = Object.values(questionMap[args.action]);
let responses = await inquirer.prompt(questions);
responses.projectRootPath = slash(path.join(config.get('directory.bitrix'), responses.projectName));
responses.nginxConfigPath = slash(path.join(config.get('directory.server'), '/conf/nginx/sites/', `${responses.projectName}.enabled`));
if (!responses.confirmRemove) {
this.exit();
}
// START
cli_ux_1.default.action.start('processing');
// Delete nginx config
if (io_1.isFileExist(responses.nginxConfigPath)) {
await fse.remove(responses.nginxConfigPath);
}
// Delete project
if (io_1.isDirectoryExist(responses.projectRootPath)) {
await fse.remove(responses.projectRootPath);
}
// Initialize variables related to MySQL DB
const dbName = decamelize(camelcase(responses.projectName));
const dbPasswordOption = config.get('mysql.password', '').length > 0
? `-p"${config.get('mysql.password')}"`
: '';
const dbLoginOption = `-u${config.get('mysql.login')}`;
// Create MySQL database
child_process.execSync(`mysql ${dbLoginOption} ${dbPasswordOption} -e"DROP DATABASE IF EXISTS \`${dbName}\` ;"`, { stdio: 'inherit' });
// Restart server
await system_1.serverNginxRestart();
// END
cli_ux_1.default.action.stop('done');
notifier.notify({
icon: path.join(__dirname, './../@assets/images/logo.png'),
title: 'Intreface CLI',
message: `Bitrix project "${responses.projectName}" has been removed.
🙈🙉🙊 💣💥`,
});
break;
}
case 'link': {
let questions = Object.values(questionMap[args.action]);
let responses = await inquirer.prompt(questions);
responses.symlinkTargetPath = path.join(config.get('directory.repository'), responses.gitRepository);
if (io_1.isDirectoryExist(path.join(responses.symlinkTargetPath, '#master'))) {
responses.symlinkTargetPath = path.join(responses.symlinkTargetPath, '#master');
if (io_1.isDirectoryExist(path.join(responses.symlinkTargetPath, responses.gitRepository))) {
responses.symlinkTargetPath = path.join(responses.symlinkTargetPath, responses.gitRepository);
}
}
responses.projectPath = slash(path.join(config.get('directory.bitrix'), responses.projectName, 'www'));
// Create directories if doesn't exist
if (!io_1.isDirectoryExist(path.join(responses.projectPath, 'local/projects'))) {
fs.mkdirSync(path.join(responses.projectPath, 'local/projects'), { recursive: true });
}
if (!io_1.isDirectoryExist(path.join(responses.projectPath, 'local/modules'))) {
fs.mkdirSync(path.join(responses.projectPath, 'local/modules'), { recursive: true });
}
if (!io_1.isDirectoryExist(path.join(responses.projectPath, 'local/php_interface/composer-dev'))) {
fs.mkdirSync(path.join(responses.projectPath, 'local/php_interface/composer-dev'), { recursive: true });
}
switch (responses.linkType) {
case 'Module': {
responses.symlinkDestinationPath = path.join(responses.projectPath, 'local/modules', responses.gitRepository);
break;
}
case 'Project': {
responses.symlinkDestinationPath = path.join(responses.projectPath, 'local/projects', responses.gitRepository);
break;
}
case 'Composer': {
responses.symlinkDestinationPath = path.join(responses.projectPath, 'local/php_interface/composer-dev', responses.gitRepository);
break;
}
default:
this.error(`${chalk_1.default.red('💩')} Link type "${responses.linkType}" is ${chalk_1.default.red.underline('Incorrect')}.`);
break;
}
fs.symlinkSync(responses.symlinkTargetPath, responses.symlinkDestinationPath, 'junction');
console.log(`Symlink of type "${chalk_1.default.magenta(responses.linkType)}" by address ${chalk_1.default.cyan.bold(responses.symlinkDestinationPath)} >> ${chalk_1.default.green.bold(responses.symlinkTargetPath)} has been created.`);
break;
}
default:
console.log(`💩`);
this.error(`${chalk_1.default.red(`💩`)} required argument is ${chalk_1.default.red.underline('Missing')}.`);
break;
}
}
}
exports.default = Bitrix;
Bitrix.description = 'Bitrix helper';
Bitrix.args = [
{ name: 'action' },
];
Bitrix.flags = {
config: command_1.flags.string(),
};
Bitrix.examples = [
`$ intreface bitrix create`,
`$ intreface bitrix create --config=no-update`,
`$ intreface bitrix create --config=restore`,
`$ intreface bitrix remove`,
`$ intreface bitrix list`,
`$ intreface bitrix link`,
`$ intreface bitrix renew`,
`$ intreface bitrix license`,
`$ intreface bitrix update`,
`$ intreface bitrix lock`,
`$ intreface bitrix unlock`,
];