UNPKG

roc

Version:

Build modern web applications easily

189 lines (164 loc) 6.65 kB
import 'source-map-support/register'; import fs from 'fs-extra'; import path from 'path'; import { spawn } from 'child_process'; import inquirer from 'inquirer'; import replace from 'replace'; import chalk from 'chalk'; import { get, getVersions } from './helpers/github'; import { validRocProject } from './helpers/general'; import { error as styleError, warning, important, ok } from '../helpers/style'; /* This should be fetched from a server! */ const templates = [{ name: 'Simple Roc App', description: 'A simple start on a generic web application', identifier: 'web', repo: 'vgno/roc-template-web' }, { name: 'Simple Roc React App', description: 'A simple start on a React web application', identifier: 'web-react', repo: 'vgno/roc-template-web-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. */ export default function init({ parsedOptions }) { const { template, version } = parsedOptions.options; // Make sure the directory is empty! assertEmptyDir(); if (!template) { return interativeMenu(); } return fetchTemplate(template, version); /* * Helpers */ function fetchTemplate(toFetch, selectVersion) { if (toFetch.indexOf('/') === -1) { const selectedTemplate = templates.find((elem) => elem.identifier === toFetch); if (!selectedTemplate) { console.log(styleError('Invalid template name given.')); /* eslint-disable no-process-exit */ process.exit(1); /* eslint-enable */ } toFetch = selectedTemplate.repo; } return getVersions(toFetch) .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( warning(`Selected template version not found, using ${chalk.bold(actualVersion)}`) ); } else if (!selectedVersion) { console.log(important(`Using ${chalk.bold(actualVersion)} as template version`)); } return get(toFetch, actualVersion); }) .then((dirPath) => { if (!validRocProject(path.join(dirPath, 'template'))) { /* eslint-disable no-process-exit */ console.log(styleError('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) => { inquirer.prompt(getPrompt(dirPath), (answers) => { replaceTemplatedValues(answers, dirPath); configureFiles(dirPath); console.log(`\nInstalling template dependencies… ` + `${chalk.dim('(If this fails you can always try to run npm install directly)')}`); return npmInstall().then(() => { console.log(ok('\nSetup completed!\n')); console.log(`Start in dev mode by typing ${chalk.bold('roc dev')}`); }); }); }) .catch((error) => { console.log(styleError('\nAn error occured during init!\n')); console.error(error.stack); /* eslint-disable no-process-exit */ process.exit(1); /* eslint-enable */ }); } function getPrompt(dirPath) { try { return require(path.join(dirPath, 'roc.setup.js')).prompt; } catch (error) { return require('./helpers/default-prompt').defaultPrompt; } } function replaceTemplatedValues(answers, dirPath) { Object.keys(answers).map((key) => { replace({ regex: `{{\\s*${key}*\\s*}}`, replacement: answers[key], paths: [dirPath + '/template'], recursive: true, silent: true }); }); } function configureFiles(dirPath) { // Rename package.json to .roc for history purposes fs.renameSync(path.join(dirPath, 'package.json'), path.join(dirPath, 'template', '.roc')); // Move everything inside template to the current working directory fs.copySync(path.join(dirPath, 'template'), process.cwd()); } function npmInstall(dirPath) { return new Promise((resolve, reject) => { dirPath = dirPath || process.cwd(); // Run npm install const npm = spawn('npm', ['install'], { 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 interativeMenu() { return new Promise((resolve) => { const choices = templates.map((elem) => ({ name: elem.name, value: elem.identifier })); inquirer.prompt([{ type: 'rawlist', name: 'option', message: 'Selected a type', choices: choices }], answers => { resolve(fetchTemplate(answers.option)); }); }); } function assertEmptyDir() { if (fs.readdirSync(process.cwd()).length > 0) { console.log(styleError('You need to call this command from an empty directory.')); /* eslint-disable no-process-exit */ process.exit(1); /* eslint-enable */ } } }