UNPKG

wpauto

Version:

[![NPM Version][npm-image]][npm-url] [![NPM Downloads][downloads-image]][downloads-url]

380 lines (347 loc) 10.8 kB
'use strict'; function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var child_process = require('child_process'); var rl = _interopDefault(require('readline')); var https = _interopDefault(require('https')); var fs = _interopDefault(require('fs')); var util = require('util'); /** * Runs a command with the passed arguments or --version * @param {String} cmd the command that will be checked. * @param {Array} args the command that will be checked. * @return {Promise} */ const run = function run(cmd, args = ['--version']) { return new Promise((resolve, reject) => { const command = child_process.spawn(cmd, args, {cwd: process.cwd()}); command.on('close', (status) => { if (status == 0) { resolve(); } }); command.on('error', (error) => { return reject(cmd); }); }); }; /** * Prompts the user for input and returns the input as a Promise. * @param {Object} options * @param {String} defaultAnswer * @param {Function} completer * @param {Array} validation * @return {answer} */ const ask = function ask(options) { const question = typeof options === 'string' ? options : options.question; const defaultAnswer = options.default ? options.default : null; const validation = options.validation ? options.validation : null; const completer = options.completer ? options.completer : null; const write = rl.createInterface({ input: process.stdin, output: process.stdout, completer: completer, }); return new Promise((resolve, reject) => { write.question(question + '\n', (answer) => { write.close(); if (validation) { reject(answer); } resolve(answer); }); write.write(defaultAnswer); }); }; /** * Downloads the requested url and returns it as a string. * @param {string} url * @return {promise} */ const download = function download(url) { return new Promise((resolve, reject) => { https.get(url, (res) => { res.on('data', (data) => { return resolve(data); }); }).on('error', (error) => { reject(error); }); }); }; /** * Adds a tabbable Autocomplete for the user to find a directory. * @param {string} line * @return {string} */ const directoryTree = function directoryTree(line) { let strike = []; const currAddingDir = line.substr(line.lastIndexOf('/') + 1); const currAddedDir = (line.indexOf('/') != - 1) ? line.substring(0, line.lastIndexOf('/') + 1) : ''; const path = process.cwd() + '/' + currAddedDir; const completions = fs.readdirSync(path); const hits = completions.filter(function(c) { return c.indexOf(currAddingDir) === 0; }); if (hits.length === 1) strike.push(currAddedDir + hits[0] + '/'); return (strike.length) ? [strike, line] : [hits.length ? hits : completions, line]; }; const readFile = util.promisify(fs.readFile); const writeFile = util.promisify(fs.writeFile); const renameFile = util.promisify(fs.rename); const fileExists = fs.existsSync; const init = async function init() { await checkRequirements(['git', 'composer', 'php', 'npm']); const config = await setup(); const valet = await valetExists(config.directory); await cloneProject(config.directory); try { await process.chdir(config.directory); } catch (error) { throw (error); } if (config.theme !== 'yes') { await removeThemeFromComposer(); } await setupWpConfig(); await installPackages(); setupEnv(config.env); if (config.theme) { await removeThemeFromComposer(); } await run('rm', ['-rf', '.git', 'composer.lock', 'package-lock.json']); await run('git', ['init', '.']); await run('git', ['add', '.']); await run('git', ['commit', '-m "Initial Commit."']); if (valet !== null || valet !== true) { console.log('Now running valet link.'); try { await process.chdir('public'); } catch (error) { throw (error); } await run('valet', [ 'link', config.foldername, ]); } console.log( 'CD into the project', `'cd ${config.directory}'`, `and run 'npm run watch' to begin.`, ); process.exit(); }; const checkRequirements = function checkRequirements(requirements) { return Promise.all( requirements.map((requirement) => { return run(requirement); }) ); }; const setup = async function setup() { const directory = process.argv.slice(2)[0] ? process.argv.slice(2)[0] : await ask({ question: 'Please enter project path: ', completer: directoryTree, }); const foldername = directory.match(/([^\/]*)\/*$/)[1]; const theme = await ask({ question: 'Would you like to install the starter theme?', default: 'yes', }); const env = { WP_HOME: await ask({ question: 'Please enter the site URL: ', default: `http://${foldername}.test`, }), WP_DEFAULT_THEME: await ask({ question: 'What would you like to name your theme?: ', default: foldername, }), DB_NAME: await ask({ question: 'Database name: ', default: foldername.replace(new RegExp('-', 'g'), '_'), }), DB_USER: await ask({ question: 'Database user: ', default: 'root', }), DB_PASSWORD: await ask({ question: 'Database password: ', default: '', }), DB_HOST: await ask({ question: 'Database host: ', default: 'localhost', }), DB_PREFIX: await ask({ question: 'Database prefix: ', default: 'wp_', }), DB_CHARSET: await ask({ question: 'Database charset: ', default: 'utf8mb4', }), DB_COLLATE: await ask({ question: 'Database collate: ', default: 'utf8mb4_general_ci', }), WP_ENV: await ask({ question: 'What is the environment: ', default: 'local', }), WP_DEBUG: await ask({ question: 'Enable Debugging?: ', default: 'false', }), }; const config = { directory, foldername, theme, env, }; return config; }; const cloneProject = function cloneProject(directory) { return run('git', [ 'clone', '-b', 'develop', 'git@github.com:michaelmano/wordpress.git', directory, ]); }; const downloadSalts = function downloadSalts() { return new Promise(async (resolve, reject) => { try { await download('https://api.wordpress.org/secret-key/1.1/salt/') .then((data) => { return resolve(data.toString().split('\n')); }); } catch (error) { reject(error); throw error; } }); }; const setupWpConfig = async function setupWpConfig() { return new Promise(async (resolve, reject) => { try { await readFile('public/wp-config.php', {encoding: 'utf8'}) .then(async (data) => { let salts = await downloadSalts(); data = data.split('\r\n'); for (let count = 0; count < salts.length; ++count) { data[count+38] = salts[count]; if (count === salts.length-1) { await writeFile('public/wp-config.php', data.join('\r\n')); resolve(); } } }); } catch (error) { reject(error); throw error; } }); }; const installPackages = function installPackages() { return new Promise((resolve, reject) => { console.log('Now Installing composer and node packages.'); Promise.all([ run('npm', ['install']), run('composer', ['install']), ]).then(() => { resolve(); }).catch((error) => { reject(error); }); }); }; const removeThemeFromComposer = async function removeThemeFromComposer() { let composerData = null; try { composerData = await readFile('composer.json', {encoding: 'utf8'}) .then((data) => { data = JSON.parse(data); data.repositories = data.repositories.filter( (repository, index) => { return index !== 1; }); delete data.require['michaelmano/starter-theme']; return data; }); } catch (error) { throw (error); } try { await writeFile('composer.json', JSON.stringify(composerData, null, 2)); } catch (error) { throw (error); } }; const setupEnv = async function setupEnv(env) { let file = ''; let count = 0; Object.keys(env).forEach(async (key, index) => { count++; file += `${key}=${env[key]}\r\n`; if (count === Object.keys(env).length) { try { await writeFile('.env', file); } catch (error) { throw (error); } } }); if (env.DB_HOST === 'localhost') { const query = ` CREATE DATABASE ${env.DB_NAME} CHARACTER SET ${env.DB_CHARSET} COLLATE ${env.DB_COLLATE};`; run('mysql', [ `-u${env.DB_USER}`, (env.DB_PASSWORD !== '' ? ` -p${env.DB_PASSWORD}` : ''), `-Bse ${query}`, ]); } if (env.WP_DEFAULT_THEME !== 'starter-theme') { try { renameFile( 'public/wp-content/themes/starter-theme', `public/wp-content/themes/${env.WP_DEFAULT_THEME}` ); } catch (error) { throw (error); } } try { await writeFile( 'style.scss', `/*!\r\n * Theme Name: ${env.WP_DEFAULT_THEME}\r\n*/\r\n` ); } catch (error) { throw (error); } }; const valetExists = async function valetExists(directory) { const config = process.env.HOME + '/.valet/config.json'; try { return await readFile(config).then((data) => { return JSON.parse(data).paths.every((path) => { return directory.indexOf(path) > -1; }); }); } catch (error) { return null; } return false; }; init();