UNPKG

intreface.cli

Version:

Intreface Dev Tools

403 lines (402 loc) 24.2 kB
"use strict"; 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`, ];