diff --git a/index.js b/index.js index 8a42eff..1f8ac22 100755 --- a/index.js +++ b/index.js @@ -7,14 +7,15 @@ const prompt = require('./lib/prompt') const chalk = require('chalk') const helpers = require('./lib/helpers') // const variables = require('./lib/variables') -// const git = require('./lib/git') +const git = require('./lib/git') const help = require('./lib/help') const check = require('./lib/check') -// const parse = require('./lib/parse') +const parse = require('./lib/parse') // const dep = require('./lib/dep') const argv = require('minimist')(process.argv.slice(2)) -// const cmd = require('./lib/cmd') +const cmd = require('./lib/cmd') // const subtheme = require('./lib/subtheme') +const text = require('./lib/text') var cache = {} @@ -22,21 +23,48 @@ var cache = {} // ==================================================== check.isInstalled() -// Clone MobileApp Template +// Generate subtheme t3kit template // ==================================================== -// function subtheme () { -// return helpers.promiseChainStarter(cache) -// .then((val) => { console.log(val) }) -// .catch(helpers.error) -// } +function generateSubtheme () { + return helpers.promiseChainStarter(cache) + .then(prompt.subthemeQuestions) + .then(prompt.siteName) + .then(prompt.dirName) + .then(cmd.mkdir) + .then(() => git.clone(cache, `https://github.com/t3kit/subtheme_t3kit_template.git`)) + .then(() => cmd.setWorkDir(cache, cache.dirName)) + .then(git.getLastTag) + .then(prompt.templateVersion) + .then(git.checkout) + .then(git.removeRepo) + .then(git.init) + .then(git.add) + .then(() => git.commit(cache, `initial commit, based on subtheme_t3kit_template v${cache.lastTag}`)) + .then(() => cmd.readFilesRecursively(cache, `Configuration`, `Resources/Private`, 'Meta')) + .then(() => parse.replaceString(cache, `subtheme_t3kit_template`, `subtheme_t3kit_${cache.siteName}`)) + .then(() => parse.replaceString(cache, `Subtheme t3kit template`, `Subtheme ${cache.siteName}`)) + .then(() => cmd.rmFile(cache, `LICENSE.txt`)) + .then(() => cmd.rmFile(cache, `CHANGELOG.md`)) + .then(() => cmd.rmFile(cache, `README.md`)) + .then(() => cmd.renameFile(cache, `readmeTemplate.md`, `README.md`)) + .then(() => cmd.appendFile(cache, `README.md`, `**Built on [subtheme_t3kit_template](https://github.com/t3kit/subtheme_t3kit_template) v${cache.lastTag}**`)) + + .then(git.add) + .then(() => git.commit(cache, `initialize new subtheme_t3kit_${cache.siteName}`)) + + // .then((val) => { console.log(val) }) + .catch(helpers.error) +} // main start point // ==================================================== function run () { prompt.whatToDo(cache) .then(() => { if (cache.whatToDo === 'subtheme') { - console.log(chalk.red('Under construction.')) + generateSubtheme() + } else if (cache.whatToDo === 'release') { + console.log(chalk.red(text.notReady)) process.exit(1) } else if (cache.whatToDo === 'help') { help.allHelp() @@ -59,7 +87,7 @@ if (_.size(argv) !== 1 || argv._.length) { // t3kit -s, --subtheme } else if (argv.s || argv.subtheme) { cache.whatToDo = 'subtheme' - console.log(chalk.red('Under construction.')) + console.log(chalk.red(text.notReady)) process.exit(1) } else { help.allHelp() diff --git a/lib/check/index.js b/lib/check/index.js index 9ec861e..ac8e61a 100644 --- a/lib/check/index.js +++ b/lib/check/index.js @@ -14,18 +14,6 @@ check.isInstalled = function isInstalled () { shell.exit(1) } - // Check is cordova installed - if (!shell.which('cordova')) { - console.log(chalk.red('Sorry, this script requires cordova')) - shell.exit(1) - } - - // Check is ionic installed - if (!shell.which('ionic')) { - console.log(chalk.red('Sorry, this script requires ionic')) - shell.exit(1) - } - // Check node version const nodeVer = variables.env.node if (Number(process.version.match(/^v(\d+\.\d+)/)[1]) < nodeVer) { diff --git a/lib/cmd/index.js b/lib/cmd/index.js index b75f1fa..c356aff 100644 --- a/lib/cmd/index.js +++ b/lib/cmd/index.js @@ -1,7 +1,8 @@ 'use strict' -var fs = require('fs') +const fs = require('fs') const boxen = require('boxen') +const helpers = require('../helpers') const cmd = module.exports = {} @@ -28,3 +29,62 @@ cmd.showMessage = function showMessage (cache, message) { resolve(cache) }) } + + +// remove file +cmd.rmFile = function rmFile (cache, file) { + return new Promise(function (resolve) { + fs.unlinkSync(file) + resolve(cache) + }) +} + +// rename file +cmd.renameFile = function renameFile (cache, oldPath, newPath) { + return new Promise(function (resolve) { + fs.renameSync(oldPath, newPath) + resolve(cache) + }) +} + + +// rename file +cmd.appendFile = function appendFile (cache, file, message) { + return new Promise(function (resolve, reject) { + fs.appendFile(file, message, function (err) { + if (err) { + reject(new Error(err)) + } + resolve(cache) + }) + }) +} + +// read dir recursively +cmd.readFilesRecursively = function readFilesRecursively (cache, ...dir) { + return new Promise(function (resolve) { + let files = {} + files.files = [] + let getFilesRecursively = function (path, files) { + fs.readdirSync(path).forEach(function (file) { + let subpath = path + '/' + file + if (fs.lstatSync(subpath).isDirectory()) { + getFilesRecursively(subpath, files) + } else { + files.push(path + '/' + file) + } + }) + } + dir.forEach(function (val) { + getFilesRecursively(val, files.files) + }) + // + 1-level files + fs.readdirSync(helpers.pwd()).forEach(function (file) { + if (!fs.lstatSync(file).isDirectory()) { + files.files.push(file) + } + }) + helpers.addTo(cache, files) + resolve(cache) + }) +} diff --git a/lib/git/index.js b/lib/git/index.js index 184eff5..6ef1b07 100644 --- a/lib/git/index.js +++ b/lib/git/index.js @@ -1,6 +1,89 @@ -// 'use strict' +'use strict' +const _ = require('lodash') // const variables = require('../variables') -// const helpers = require('../helpers') +const helpers = require('../helpers') +const exec = require('child_process').exec -// const git = module.exports = {} +const git = module.exports = {} + +// clone mobileApp_template +git.clone = function clone (cache, link) { + let cmd = { + spinner: `Cloning subtheme ${cache.whatToDo}`, + str: `git clone --single-branch -b master ${link} ${cache.dirName}`, + spinerSucceed: `${cache.whatToDo} template successfully cloned` + } + return helpers.execCMD(cmd, cache) +} + +// remove previous git repo +git.removeRepo = function removeRepo (cache) { + let cmd = { + // spinner: '', + str: `rm -rf .git` + // spinerSucceed: '' + } + return helpers.execCMD(cmd, cache) +} + +// git add +git.init = function init (cache) { + let cmd = { + // spinner: '', + str: `git init` + // spinerSucceed: '' + } + return helpers.execCMD(cmd, cache) +} + +// git add +git.add = function add (cache) { + let cmd = { + // spinner: '', + str: `git add .` + // spinerSucceed: '' + } + return helpers.execCMD(cmd, cache) +} + +// git commit +git.commit = function commit (cache, commitMessage) { + let cmd = { + // spinner: '', + str: `git commit -m "${commitMessage}"` + // spinerSucceed: '' + } + return helpers.execCMD(cmd, cache) +} + +// git checkout +git.checkout = function checkout (cache) { + let cmd = { + str: `git checkout ${cache.templateVersion}` + } + return helpers.execCMD(cmd, cache) +} + + +git.getLastTag = function getLastTag (cache) { + return new Promise(function (resolve, reject) { + let str = 'git describe --abbrev=0 --tags' + let lastTag = {} + exec(str, { maxBuffer: 2000 * 1024 }, (error, stdout) => { + if (error) { + reject(new Error(error)) + } else { + if (_.isEmpty(stdout)) { + lastTag = { lastTag: false } + } else { + var match = stdout.match(/\n/i) + lastTag = stdout.slice(0, match.index) + lastTag = { lastTag: lastTag } + } + helpers.addTo(cache, lastTag) + resolve(cache) + } + }) + }) +} diff --git a/lib/help/index.js b/lib/help/index.js index e10027d..58ce1ba 100644 --- a/lib/help/index.js +++ b/lib/help/index.js @@ -1,27 +1,13 @@ 'use strict' -const chalk = require('chalk') -const labels = require('../labels') +// const chalk = require('chalk') +const text = require('../text') const help = module.exports = {} // generator help message help.allHelp = function allHelp (cache) { - var pkgV = require('../../package.json') - let showHelp = ` - ${chalk.bold('t3kit-cli')} v${pkgV.version} - Command line interface - - ${chalk.bold.underline('Usage:')} - t3kit - t3kit [options] - - ${chalk.bold.underline('Options:')} - -h, --help Quick help. - -v, --version Print the t3kit-cli version. - -s, --subtheme ${labels.subtheme.description} - ` - console.log(showHelp) + console.log(text.showHelp) return cache } diff --git a/lib/helpers/index.js b/lib/helpers/index.js index 028f57f..b71e569 100644 --- a/lib/helpers/index.js +++ b/lib/helpers/index.js @@ -24,7 +24,7 @@ helpers.promiseChainStarter = function promiseChainStarter (val) { } helpers.error = function stats (err) { - let divider = '==========================================\n' + let divider = `==========================================\n` return console.log(divider + chalk.red(err.stack)) } diff --git a/lib/labels/index.js b/lib/labels/index.js deleted file mode 100644 index a9f297e..0000000 --- a/lib/labels/index.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict' - -const labels = module.exports = {} - -labels.subtheme = { - description: `Generate new subtheme_t3kit_name.` -} diff --git a/lib/parse/index.js b/lib/parse/index.js index b0cc13c..706db6b 100644 --- a/lib/parse/index.js +++ b/lib/parse/index.js @@ -1,7 +1,24 @@ -// 'use strict' +'use strict' -// const shell = require('shelljs') -// const helpers = require('../helpers') +const shell = require('shelljs') +const helpers = require('../helpers') // const variables = require('../variables') +// var fs = require('fs') -// const parse = module.exports = {} +const parse = module.exports = {} + +// replace string in files +parse.replaceString = function replaceString (cache, oldString, newString) { + return new Promise(function (resolve) { + shell.sed('-i', helpers.escapeRegExp(oldString), newString, cache.files) + // shell.sed('-i', oldString, newString, cache.files) + resolve(cache) + }) +} + +parse.replaceStringInFile = function replaceStringInFile (cache, oldString, newString, file) { + return new Promise(function (resolve) { + shell.sed('-i', helpers.escapeRegExp(oldString), newString, file) + resolve(cache) + }) +} diff --git a/lib/prompt/index.js b/lib/prompt/index.js index 8da025e..2788ae5 100644 --- a/lib/prompt/index.js +++ b/lib/prompt/index.js @@ -2,25 +2,29 @@ const inquirer = require('inquirer') const helpers = require('../helpers') -// const chalk = require('chalk') -// var fs = require('fs') -const labels = require('../labels') +const chalk = require('chalk') +var fs = require('fs') +const text = require('../text') const prompt = module.exports = {} -// ask about project type +// ask to select variants prompt.whatToDo = function whatToDo (cache) { return new Promise(function (resolve, reject) { let whatToDo = [ { - name: 'whatToDo', - type: 'list', - message: 'Select variants:', + name: `whatToDo`, + type: `list`, + message: `Select variants:`, choices: [ { - name: `${labels.subtheme.description}`, + name: `${text.subtheme.description}`, value: `subtheme` }, + { + name: `${text.release.description}`, + value: `release` + }, { name: `Help`, value: `help` @@ -29,14 +33,115 @@ prompt.whatToDo = function whatToDo (cache) { } ] inquirer.prompt(whatToDo) + .then(function (answers) { + helpers.addTo(cache, answers) + resolve(cache) + }) + }) +} + +// ask main subtheme_t3kit questions +prompt.siteName = function siteName (cache) { + return new Promise(function (resolve) { + let siteName = [ + { + type: 'input', + name: 'siteName', + message: `${text.subtheme.siteNameIsOk} ${chalk.dim(text.subtheme.hint.siteName)}`, + filter: function (value) { + return value.trim() + }, + validate: function (value) { + if (value.length === 0) { + return chalk.red(text.subtheme.err.noName) + } else if (/\s/g.test(value)) { + return chalk.red(text.subtheme.err.oneWord) + } else if (/[-_.]/g.test(value)) { + return chalk.red(text.subtheme.err.camelCase) + } else if (value[0] === value[0].toUpperCase()) { + return chalk.red(text.subtheme.err.capitalLetter) + } + return true + } + }, + { + type: 'confirm', + name: 'isOk', + message: text.subtheme.siteNameIsOk, + default: true + } + ] + function recursivePrompt () { + inquirer.prompt(siteName) + .then(function (answers) { + if (answers.isOk === false) { + recursivePrompt() + } else if (answers.isOk === true) { + helpers.addTo(cache, answers) + resolve(cache) + } + }) + } + recursivePrompt() + }) +} + +// ask folder name +prompt.dirName = function dirName (cache) { + return new Promise(function (resolve) { + let dirName = [ + { + type: 'imput', + name: 'dirName', + message: text.subtheme.dirName, + filter: function (value) { + return value.trim() + }, + default: function () { + return `subtheme_t3kit_${cache.siteName}` + }, + validate: function (value) { + if (!fs.existsSync(value)) { + return true + } + return chalk.red(text.subtheme.err.dirName) + } + } + ] + inquirer.prompt(dirName) .then(function (answers) { if (answers) { helpers.addTo(cache, answers) resolve(cache) - } else { - reject(Error(`in prompt.whatToDo fn`)) } }) }) } + +prompt.templateVersion = function templateVersion (cache) { + return new Promise(function (resolve, reject) { + let templateVersion = [ + { + name: `templateVersion`, + type: `list`, + message: text.subtheme.templateVersion, + choices: [ + { + name: text.subtheme.templateVersionMaster, + value: `master` + }, + { + name: `${text.subtheme.templateVersionTag} ${chalk.bold(cache.lastTag)}`, + value: `${cache.lastTag}` + } + ] + } + ] + inquirer.prompt(templateVersion) + .then(function (answers) { + helpers.addTo(cache, answers) + resolve(cache) + }) + }) +} diff --git a/lib/text/index.js b/lib/text/index.js new file mode 100644 index 0000000..912c5a7 --- /dev/null +++ b/lib/text/index.js @@ -0,0 +1,53 @@ +'use strict' + +const chalk = require('chalk') + +const text = module.exports = {} + +var pkgV = require('../../package.json') + +text.notReady = `Under construction...` + +text.subtheme = { + description: `Generate new subtheme_t3kit_name`, + + templateVersion: `Which subtheme_t3kit_template version you want to use?`, + templateVersionMaster: `Last commit on ${chalk.bold('master')} branch`, + templateVersionTag: `Last stable version of subtheme_t3kit_template`, + + siteName: `Site name:`, + siteNameIsOk: `Check site name. Is it correct?`, + + dirName: `Create a new folder with name:`, + + hint: { + siteName: `start with a small letter, one word, or use camelCase` + }, + err: { + noName: `Please enter site name`, + capitalLetter: `Do not use a capital first letter`, + oneWord: `Should be one word or use camelCase`, + camelCase: `Use camelCase`, + dirName: `Folder exists. Please choose another folder name.` + } +} + +text.release = { + description: `Generate new t3kit release` +} + + + +text.showHelp = ` + ${chalk.bold('t3kit-cli')} v${pkgV.version} + t3kit Command line interface + + ${chalk.bold.underline('Usage:')} + t3kit + t3kit [options] + + ${chalk.bold.underline('Options:')} + -h, --help Quick help. + -v, --version Print the t3kit-cli version. + -s, --subtheme ${text.subtheme.description} + `