UNPKG

roc

Version:

Build modern web applications easily

357 lines (292 loc) 12.2 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = init; var _fsExtra = require('fs-extra'); var _fsExtra2 = _interopRequireDefault(_fsExtra); var _path = require('path'); var _path2 = _interopRequireDefault(_path); var _crossSpawn = require('cross-spawn'); var _inquirer = require('inquirer'); var _inquirer2 = _interopRequireDefault(_inquirer); var _replace = require('replace'); var _replace2 = _interopRequireDefault(_replace); var _chalk = require('chalk'); var _chalk2 = _interopRequireDefault(_chalk); var _github = require('./helpers/github'); var _general = require('./helpers/general'); var _style = require('../helpers/style'); var _helpers = require('../helpers'); var _unzip = require('./helpers/unzip'); var _unzip2 = _interopRequireDefault(_unzip); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /* This should be fetched from a server! */ const templates = [{ name: 'Simple Roc App', description: 'A simple start on a generic web application', identifier: 'web-app', repo: 'rocjs/roc-template-web-app' }, { name: 'Simple Roc React App', description: 'A simple start on a React web application', identifier: 'web-app-react', repo: 'rocjs/roc-template-web-app-react' }]; /** * Command used to init a new Roc project. * * @param {rocCommandObject} parsedArguments - The Roc command object, uses parsedArguments from it. * * @returns {Promise} - Promise for the command. */ function init(_ref) { let parsedArguments = _ref.parsedArguments; let parsedOptions = _ref.parsedOptions; let directory = _ref.directory; var _parsedOptions$option = parsedOptions.options; const list = _parsedOptions$option.list; const force = _parsedOptions$option.force; var _parsedArguments$argu = parsedArguments.arguments; const name = _parsedArguments$argu.name; const template = _parsedArguments$argu.template; const version = _parsedArguments$argu.version; // Get versions first if (template && list) { const toFetch = getTemplate(template); return getTemplateVersion(toFetch, list); } // Make sure the directory is empty! return checkFolder(force, name, directory).then(dir => { if (!template) { return interactiveMenu(dir, list); } return fetchTemplate(template, version, dir, list); }); } /* * Helpers */ function isLocalTemplate() { let template = arguments.length <= 0 || arguments[0] === undefined ? '' : arguments[0]; return template.indexOf('.zip') === template.length - 4; } function getTemplateVersion(toFetch, list) { return (0, _github.getVersions)(toFetch).then(versions => { // Add master so we always have a way to install it versions.push({ name: 'master' }); if (list) { console.log('The available versions are:'); console.log(Object.keys(versions).map(index => ` ${ versions[index].name }`).join('\n')); /* eslint-disable no-process-exit */ process.exit(0); /* eslint-enable */ } return Promise.resolve(versions); }); } function getTemplate(template) { if (isLocalTemplate(template)) { return template; } else if (template.indexOf('/') === -1) { const selectedTemplate = templates.find(elem => elem.identifier === template); if (!selectedTemplate) { console.log((0, _style.error)('Invalid template name given.')); /* eslint-disable no-process-exit */ process.exit(1); /* eslint-enable */ } return selectedTemplate.repo; } return template; } function fetchTemplate(toFetch, selectVersion, directory, list) { toFetch = getTemplate(toFetch); const templateFetcher = isLocalTemplate(toFetch) ? (0, _unzip2.default)(toFetch) : getTemplateVersion(toFetch, list).then(versions => { // If the name starts with a number we will automatically add 'v' infront of it to match Github default if (selectVersion && !isNaN(Number(selectVersion.charAt(0))) && selectVersion.charAt(0) !== 'v') { selectVersion = `v${ selectVersion }`; } const selectedVersion = versions.find(v => v.name === selectVersion); const actualVersion = selectedVersion && selectedVersion.name || versions[0] && versions[0].name || 'master'; if (!selectedVersion && selectVersion) { console.log((0, _style.warning)(`Selected template version not found, using ${ _chalk2.default.bold(actualVersion) }`)); } else if (!selectedVersion) { console.log((0, _style.info)(`Using ${ _chalk2.default.bold(actualVersion) } as template version`)); } return (0, _github.get)(toFetch, actualVersion); }); return templateFetcher.then(dirPath => { if (!(0, _general.validRocProject)(_path2.default.join(dirPath, 'template'))) { /* eslint-disable no-process-exit */ console.log((0, _style.error)('Seems like this is not a Roc template.')); process.exit(1); /* eslint-enable */ } else { console.log('\nInstalling template setup dependencies…'); return npmInstall(dirPath); } }).then(dirPath => { _inquirer2.default.prompt(getPrompt(dirPath), answers => { replaceTemplatedValues(answers, dirPath); configureFiles(dirPath, directory); console.log(`\nInstalling template dependencies… ` + `${ _chalk2.default.dim('(If this fails you can try to run npm install directly)') }`); return npmInstall(directory).then(() => { console.log((0, _style.ok)('\nSetup completed!\n')); showCompletionMessage(dirPath); }); }); }).catch(err => { console.log((0, _style.error)('\nAn error occured during init!\n')); console.error(err.message); /* eslint-disable no-process-exit */ process.exit(1); /* eslint-enable */ }); } function getPrompt(dirPath) { try { return require(_path2.default.join(dirPath, 'roc.setup.js')).prompt; } catch (err) { return require('./helpers/default-prompt').defaultPrompt; } } function showCompletionMessage(dirPath) { try { console.log(require(_path2.default.join(dirPath, 'roc.setup.js')).completionMessage); } catch (err) { // Do nothing } } function replaceTemplatedValues(answers, dirPath) { // 1. Replace content Object.keys(answers).map(key => { (0, _replace2.default)({ regex: `{{\\s*${ key }*\\s*}}`, replacement: answers[key], paths: [dirPath + '/template'], recursive: true, silent: true }); }); // 2. Replace filenames replaceTemplatedValuesInDirectory(answers, (0, _path.join)(dirPath, 'template')); } function replaceTemplatedValuesInDirectory(answers, dir) { const matchTemplate = /{{\s*([^\s]+)*\s*}}/; _fsExtra2.default.readdirSync(dir).forEach(file => { let currentPath = (0, _path.join)(dir, file); // Get potential "key" from filenames const match = file.match(matchTemplate); // Try to replace key if one was found if (match) { const toReplace = answers[match[1]]; if (!toReplace) { console.log(`Could not find a value for the template value: {{ key }}`); } else { const newFilename = file.replace(matchTemplate, toReplace); _fsExtra2.default.renameSync(currentPath, (0, _path.join)(dir, newFilename)); currentPath = (0, _path.join)(dir, newFilename); } } if (_fsExtra2.default.lstatSync(currentPath).isDirectory()) { replaceTemplatedValuesInDirectory(answers, currentPath); } }); } function configureFiles(dirPath, directory) { // Rename package.json to .roc for history purposes _fsExtra2.default.renameSync(_path2.default.join(dirPath, 'package.json'), _path2.default.join(dirPath, 'template', '.roc')); // Move everything inside template to the current working directory _fsExtra2.default.copySync(_path2.default.join(dirPath, 'template'), directory); } function npmInstall(dirPath) { return new Promise((resolve, reject) => { // Run npm install const npm = (0, _crossSpawn.spawn)('npm', ['install', '--loglevel=error'], { cwd: dirPath, stdio: 'inherit' }); npm.on('close', function (code) { if (code !== 0) { return reject(new Error('npm install failed with status code: ' + code)); } return resolve(dirPath); }); }); } function interactiveMenu(directory, list) { return new Promise(resolve => { const choices = templates.map(elem => ({ name: elem.name, value: elem.identifier })); _inquirer2.default.prompt([{ type: 'rawlist', name: 'option', message: 'Selected a type', choices: choices }], answers => { resolve(fetchTemplate(answers.option, undefined, directory, list)); }); }); } function checkFolder() { let force = arguments.length <= 0 || arguments[0] === undefined ? false : arguments[0]; let directoryName = arguments.length <= 1 || arguments[1] === undefined ? '' : arguments[1]; let directory = arguments.length <= 2 || arguments[2] === undefined ? '' : arguments[2]; return new Promise(resolve => { const directoryPath = (0, _helpers.getAbsolutePath)(_path2.default.join(directory, directoryName)); _fsExtra2.default.mkdir(directoryPath, err => { if (err) { console.log((0, _style.warning)(`Found a folder named ${ _chalk2.default.underline(directoryPath) }, will try to use it.`), '\n'); } if (!force && _fsExtra2.default.readdirSync(directoryPath).length > 0) { _inquirer2.default.prompt([{ type: 'list', name: 'selection', message: `The directory '${ directoryPath }' is not empty, what do you want to do?`, choices: [{ name: 'Create new folder', value: 'new' }, { name: 'Run anyway ' + (0, _style.warning)('Warning: Some files might be overwritten.'), value: 'force' }, { name: 'Abort', value: 'abort' }] }], _ref2 => { let selection = _ref2.selection; if (selection === 'abort') { /* eslint-disable no-process-exit */ process.exit(1); /* eslint-enable */ } else if (selection === 'new') { askForDirectory(directory, resolve); } else if (selection === 'force') { resolve(directoryPath); } }); } else { resolve(directoryPath); } }); }); } function askForDirectory(directory, resolve) { _inquirer2.default.prompt([{ type: 'input', name: 'name', message: `What do you want to name the directory? (It will be created in '${ directory || process.cwd() }')` }], _ref3 => { let name = _ref3.name; const directoryPath = (0, _helpers.getAbsolutePath)(name, directory); _fsExtra2.default.mkdir(directoryPath, err => { if (err) { console.log((0, _style.warning)('The directory did already exists or was not empty.'), '\n'); return askForDirectory(resolve); } resolve(directoryPath); }); }); } //# sourceMappingURL=init.js.map