diff --git a/packages/cli/lib/commands/create.js b/packages/cli/lib/commands/create.js index e8f6cc5d7..33e1fd23b 100644 --- a/packages/cli/lib/commands/create.js +++ b/packages/cli/lib/commands/create.js @@ -37,8 +37,8 @@ const capitalize = str => str.charAt(0).toUpperCase() + str.substring(1); const options = [ { - name: '--name', - description: 'The application name', + name: '--template', + description: 'The template name', }, { name: '--cwd', @@ -78,11 +78,16 @@ const options = [ ]; // Formulate Questions if `create` args are missing -function requestParams(argv, templates) { +function requestParams(name, argv, templates) { const cwd = resolve(argv.cwd); return [ // Required data + { + type: name ? null : 'text', + name: 'name', + message: 'The name of your application', + }, { type: argv.template ? null : 'select', name: 'template', @@ -96,12 +101,7 @@ function requestParams(argv, templates) { message: 'Remote template to clone (user/repo#tag)', }, { - type: argv.dest ? null : 'text', - name: 'dest', - message: 'Directory to create the app', - }, - { - type: prev => (!dirExists(cwd, prev || argv.dest) ? null : 'confirm'), + type: !dirExists(cwd || name) ? null : 'confirm', name: 'force', message: 'The destination directory exists. Overwrite?', initial: false, @@ -114,11 +114,6 @@ function requestParams(argv, templates) { }, }, // Extra data / flags - { - type: argv.name ? null : 'text', - name: 'name', - message: 'The name of your application', - }, { type: 'confirm', name: 'install', @@ -206,12 +201,12 @@ async function copyFileToDestination(srcPath, destPath, force = false) { } } -async function command(repo, dest, argv) { +async function command(name, argv) { validateArgs(argv, options, 'create'); // Prompt if incomplete data - if (!repo || !dest) { + if (!name || !argv.template) { const templates = await fetchTemplates(); - const questions = requestParams(argv, templates); + const questions = requestParams(name, argv, templates); const onCancel = () => { info('Aborting execution'); process.exit(); @@ -219,18 +214,18 @@ async function command(repo, dest, argv) { const response = await prompt(questions, { onCancel }); Object.assign(argv, response); - repo = repo || response.template; - dest = dest || response.dest; + argv.template = argv.template || response.template; + name = name || response.name; } - if (!repo || !dest) { + if (!argv.template || !name) { warn('Insufficient arguments!'); info('Alternatively, run `preact create --help` for usage info.'); return; } let cwd = resolve(argv.cwd); - let target = resolve(cwd, dest); + let target = resolve(cwd, name); let isYarn = argv.yarn && hasCommand('yarn'); let exists = isDir(target); @@ -256,31 +251,28 @@ async function command(repo, dest, argv) { } } - // Use `--name` value or `dest` dir's name - argv.name = argv.name || dest; - - let { errors } = isValidName(argv.name); + let { errors } = isValidName(name); if (errors) { - errors.unshift(`Invalid package name: ${argv.name}`); + errors.unshift(`Invalid package name: ${name}`); return error(errors.map(capitalize).join('\n ~ '), 1); } - if (!repo.includes('/')) { - repo = `${ORG}/${repo}`; - info(`Assuming you meant ${repo}...`); + if (!argv.template.includes('/')) { + argv.template = `${ORG}/${argv.template}`; + info(`Assuming you meant ${argv.template}...`); } - if (!fs.existsSync(resolve(cwd, dest, 'src'))) { - mkdirp.sync(resolve(cwd, dest, 'src')); + if (!fs.existsSync(resolve(cwd, name, 'src'))) { + mkdirp.sync(resolve(cwd, name, 'src')); } // Attempt to fetch the `template` - let archive = await gittar.fetch(repo).catch(err => { + let archive = await gittar.fetch(argv.template).catch(err => { err = err || { message: 'An error occured while fetching template.' }; return error( err.code === 404 - ? `Could not find repository: ${repo}` + ? `Could not find repository: ${argv.template}` : (argv.verbose && err.stack) || err.message, 1 ); @@ -338,7 +330,7 @@ async function command(repo, dest, argv) { await fs.writeFile(entry, buf, enc); } } else { - return error(`No \`template\` directory found within ${repo}!`, 1); + return error(`No \`template\` directory found within ${argv.template}!`, 1); } spinner.text = 'Parsing `package.json` file'; @@ -359,17 +351,17 @@ async function command(repo, dest, argv) { // Update `package.json` key if (pkgData) { spinner.text = 'Updating `name` within `package.json` file'; - pkgData.name = argv.name.toLowerCase().replace(/\s+/g, '_'); + pkgData.name = name.toLowerCase().replace(/\s+/g, '_'); } // Find a `manifest.json`; use the first match, if any let files = await glob(target + '/**/manifest.json'); let manifest = files[0] && JSON.parse(await fs.readFile(files[0])); if (manifest) { spinner.text = 'Updating `name` within `manifest.json` file'; - manifest.name = manifest.short_name = argv.name; + manifest.name = manifest.short_name = name; // Write changes to `manifest.json` await fs.writeFile(files[0], JSON.stringify(manifest, null, 2)); - if (argv.name.length > 12) { + if (name.length > 12) { // @see https://developer.chrome.com/extensions/manifest/name#short_name process.stdout.write('\n'); warn('Your `short_name` should be fewer than 12 characters.'); @@ -381,7 +373,7 @@ async function command(repo, dest, argv) { await fs.writeFile(pkgFile, JSON.stringify(pkgData, null, 2)); } - const sourceDirectory = join(resolve(cwd, dest), 'src'); + const sourceDirectory = join(resolve(cwd, name), 'src'); // Copy over template.html const templateSrc = resolve( @@ -413,7 +405,7 @@ async function command(repo, dest, argv) { return ( trim(` To get started, cd into the new directory: - ${green('cd ' + dest)} + ${green('cd ' + name)} To start a development live-reload server: ${green(pfx + ' dev')} diff --git a/packages/cli/lib/index.js b/packages/cli/lib/index.js index 675b8726a..0f76b546a 100755 --- a/packages/cli/lib/index.js +++ b/packages/cli/lib/index.js @@ -41,7 +41,7 @@ commands.buildOptions.forEach(option => { buildCommand.action(commands.build); const createCommand = prog - .command('create [template] [dest]') + .command('create [name]') .describe('Create a new application'); commands.createOptions.forEach(option => { createCommand.option(option.name, option.description, option.default); diff --git a/packages/cli/tests/lib/cli.js b/packages/cli/tests/lib/cli.js index 2fe9a96ac..c207a12a6 100644 --- a/packages/cli/tests/lib/cli.js +++ b/packages/cli/tests/lib/cli.js @@ -21,18 +21,20 @@ const argv = { }; exports.create = async function (template, name) { - let dest = tmpDir(); + const cwd = tmpDir(); name = name || `test-${template}`; - await cmd.create(template, dest, { name, cwd: '.' }); + await cmd.create(name, { template, cwd, install: false }); + + const projectPath = join(cwd, name); // TODO: temporary – will resolve after 2.x->3.x release // Templates are using 2.x, which needs `.babelrc` for TEST modification. // The 3.x templates won't need `.babelrc` for { modules: commonjs } - let babelrc = join(dest, '.babelrc'); + let babelrc = join(projectPath, '.babelrc'); existsSync(babelrc) && unlinkSync(babelrc); - return dest; + return projectPath; }; exports.build = function (cwd, options, installNodeModules = false) {