packages/basys-cli/utils.js
async function initProject(answers, install = true) {
  const inquirer = require('inquirer');
  let templateName;
  if (answers.name) {
    templateName = answers.name;
  } else {
    // If starter project is not provided in command arguments ask to select one
    templateName = (await inquirer.prompt([
      {
        type: 'list',
        name: 'name',
        message: 'Select a starter project',
        choices: [
          {name: 'Blank project', value: 'basys/basys-starter-project'},
          {name: 'Todo list sample web app', value: 'basys/basys-todomvc'},
        ],
      },
    ])).name;
  }

  const cwd = process.cwd();
  let destDir;

  function validateDestPath(dest) {
    if (!dest || !path.isAbsolute(dest)) {
      destDir = path.join(cwd, dest);
    } else {
      destDir = dest;
    }
    destDir = path.normalize(destDir);

    if (fs.pathExistsSync(destDir) && fs.readdirSync(destDir).length > 0)
      return 'Provided directory is not empty';
    if (detectBasysProject(destDir))
      return 'Provided location is already inside another Basys project';

    return true;
  }

  if (answers.dest) {
    const res = validateDestPath(answers.dest);
    if (typeof res === 'string') throw Error(res);
  } else {
    await inquirer.prompt([
      {
        type: 'input',
        name: 'dest',
        message: 'Project location',
        default: '.',
        validate: validateDestPath,
      },
    ]);
  }

  // Generate Visual Studio Code workspace settings
  let addVSCode;
  if (typeof answers.vscode === 'boolean') {
    addVSCode = answers.vscode;
  } else {
    addVSCode = (await inquirer.prompt([
      {
        type: 'confirm',
        name: 'vscode',
        message: 'Would you like to add Visual Studio Code settings?',
        default: true,
      },
    ])).vscode;
  }

  const ora = require('ora');
  const spinner = ora('Downloading starter project');
  if (
    path.isAbsolute(templateName) ||
    templateName.startsWith('.') ||
    templateName.startsWith('~')
  ) {
    // Local directory
    let templateDir;
    if (templateName.startsWith('.')) {
      templateDir = path.join(cwd, templateName);
    } else {
      templateDir = path.normalize(templateName);
    }
    await fs.copy(templateDir, destDir);
  } else {
    spinner.start();
    // Github repository
    const m = /^([^/]+)\/([^#]+)(#(.+))?$/.exec(templateName);
    const url = `https://github.com/${m[1]}/${m[2]}/archive/${m[4] || 'master'}.zip`;
    const downloadUrl = require('download');
    await downloadUrl(url, destDir, {
      extract: true,
      strip: 1,
      mode: '666',
      headers: {accept: 'application/zip'},
    });
    spinner.stop();
  }

  if (!detectBasysProject(destDir)) {
    await fs.remove(destDir); // BUG: don't remove the directory if it existed before
    throw new Error(
      'Project provided with starter template is missing basys.json or package.json file',
    );
  }

  await fs.ensureDir(path.join(destDir, 'assets'));

  if (!fs.existsSync(path.join(destDir, '.gitignore'))) {
    await fs.copy(path.join(__dirname, 'templates', 'gitignore'), path.join(destDir, '.gitignore'));
  }

  await fs.copy(
    path.join(__dirname, 'templates', 'jest.config.js'),
    path.join(destDir, 'jest.config.js'),
  );

  if (addVSCode) {
    await fs.copy(
      path.join(__dirname, 'templates', 'jsconfig.json'),
      path.join(destDir, 'jsconfig.json'),
    );
    await fs.copy(
      path.join(__dirname, 'templates', 'settings.json'),
      path.join(destDir, '.vscode', 'settings.json'),
    );
    await fs.copy(
      path.join(__dirname, 'templates', 'extensions.json'),
      path.join(destDir, '.vscode', 'extensions.json'),
    );
  }

  if (install) {
    console.log();
    try {
      await execShellCommand('npm', ['install'], destDir);
    } catch (e) {
      spinner.stop();
      exit('Installing npm packages failed');
    }
  }

  let commands = '';
  if (cwd !== destDir) {
    commands += `\`${chalk.green.bold(`cd ${path.relative(cwd, destDir)}`)}\`, then `;
  }
  // BUG: change commands to 'npm run/yarn basys dev' if a local basys-cli instance is used?
  commands += `\`${chalk.green.bold('basys dev')}\``;
  spinner.succeed(`Successfully generated the project. To start the dev server run ${commands}.`);
}
async function initProject(answers, install = true) {
  const inquirer = require('inquirer');
  let templateName;
  if (answers.name) {
    templateName = answers.name;
  } else {
    // If starter project is not provided in command arguments ask to select one
    templateName = (await inquirer.prompt([
      {
        type: 'list',
        name: 'name',
        message: 'Select a starter project',
        choices: [
          {name: 'Blank project', value: 'basys/basys-starter-project'},
          {name: 'Todo list sample web app', value: 'basys/basys-todomvc'},
        ],
      },
    ])).name;
  }

  const cwd = process.cwd();
  let destDir;

  function validateDestPath(dest) {
    if (!dest || !path.isAbsolute(dest)) {
      destDir = path.join(cwd, dest);
    } else {
      destDir = dest;
    }
    destDir = path.normalize(destDir);

    if (fs.pathExistsSync(destDir) && fs.readdirSync(destDir).length > 0)
      return 'Provided directory is not empty';
    if (detectBasysProject(destDir))
      return 'Provided location is already inside another Basys project';

    return true;
  }

  if (answers.dest) {
    const res = validateDestPath(answers.dest);
    if (typeof res === 'string') throw Error(res);
  } else {
    await inquirer.prompt([
      {
        type: 'input',
        name: 'dest',
        message: 'Project location',
        default: '.',
        validate: validateDestPath,
      },
    ]);
  }

  // Generate Visual Studio Code workspace settings
  let addVSCode;
  if (typeof answers.vscode === 'boolean') {
    addVSCode = answers.vscode;
  } else {
    addVSCode = (await inquirer.prompt([
      {
        type: 'confirm',
        name: 'vscode',
        message: 'Would you like to add Visual Studio Code settings?',
        default: true,
      },
    ])).vscode;
  }

  const ora = require('ora');
  const spinner = ora('Downloading starter project');
  if (
    path.isAbsolute(templateName) ||
    templateName.startsWith('.') ||
    templateName.startsWith('~')
  ) {
    // Local directory
    let templateDir;
    if (templateName.startsWith('.')) {
      templateDir = path.join(cwd, templateName);
    } else {
      templateDir = path.normalize(templateName);
    }
    await fs.copy(templateDir, destDir);
  } else {
    spinner.start();
    // Github repository
    const m = /^([^/]+)\/([^#]+)(#(.+))?$/.exec(templateName);
    const url = `https://github.com/${m[1]}/${m[2]}/archive/${m[4] || 'master'}.zip`;
    const downloadUrl = require('download');
    await downloadUrl(url, destDir, {
      extract: true,
      strip: 1,
      mode: '666',
      headers: {accept: 'application/zip'},
    });
    spinner.stop();
  }

  if (!detectBasysProject(destDir)) {
    await fs.remove(destDir); // BUG: don't remove the directory if it existed before
    throw new Error(
      'Project provided with starter template is missing basys.json or package.json file',
    );
  }

  await fs.ensureDir(path.join(destDir, 'assets'));

  if (!fs.existsSync(path.join(destDir, '.gitignore'))) {
    await fs.copy(path.join(__dirname, 'templates', 'gitignore'), path.join(destDir, '.gitignore'));
  }

  await fs.copy(
    path.join(__dirname, 'templates', 'jest.config.js'),
    path.join(destDir, 'jest.config.js'),
  );

  if (addVSCode) {
    await fs.copy(
      path.join(__dirname, 'templates', 'jsconfig.json'),
      path.join(destDir, 'jsconfig.json'),
    );
    await fs.copy(
      path.join(__dirname, 'templates', 'settings.json'),
      path.join(destDir, '.vscode', 'settings.json'),
    );
    await fs.copy(
      path.join(__dirname, 'templates', 'extensions.json'),
      path.join(destDir, '.vscode', 'extensions.json'),
    );
  }

  if (install) {
    console.log();
    try {
      await execShellCommand('npm', ['install'], destDir);
    } catch (e) {
      spinner.stop();
      exit('Installing npm packages failed');
    }
  }

  let commands = '';
  if (cwd !== destDir) {
    commands += `\`${chalk.green.bold(`cd ${path.relative(cwd, destDir)}`)}\`, then `;
  }
  // BUG: change commands to 'npm run/yarn basys dev' if a local basys-cli instance is used?
  commands += `\`${chalk.green.bold('basys dev')}\``;
  spinner.succeed(`Successfully generated the project. To start the dev server run ${commands}.`);
}
async function initProject ( answers , install = true ) { const inquirer = require ( 'inquirer' ) ; let templateName ; if ( answers . name ) { templateName = answers . name ; } else { // If starter project is not provided in command arguments ask to select one templateName = ( await inquirer . prompt ( [ { type : 'list' , name : 'name' , message : 'Select a starter project' , choices : [ { name : 'Blank project' , value : 'basys/basys-starter-project' } , { name : 'Todo list sample web app' , value : 'basys/basys-todomvc' } , ] , } , ] ) ) . name ; } const cwd = process . cwd ( ) ; let destDir ; function validateDestPath ( dest ) { if ( ! dest || ! path . isAbsolute ( dest ) ) { destDir = path . join ( cwd , dest ) ; } else { destDir = dest ; } destDir = path . normalize ( destDir ) ; if ( fs . pathExistsSync ( destDir ) && fs . readdirSync ( destDir ) . length > 0 ) return 'Provided directory is not empty' ; if ( detectBasysProject ( destDir ) ) return 'Provided location is already inside another Basys project' ; return true ; } if ( answers . dest ) { const res = validateDestPath ( answers . dest ) ; if ( typeof res === 'string' ) throw Error ( res ) ; } else { await inquirer . prompt ( [ { type : 'input' , name : 'dest' , message : 'Project location' , default : '.' , validate : validateDestPath , } , ] ) ; } // Generate Visual Studio Code workspace settings let addVSCode ; if ( typeof answers . vscode === 'boolean' ) { addVSCode = answers . vscode ; } else { addVSCode = ( await inquirer . prompt ( [ { type : 'confirm' , name : 'vscode' , message : 'Would you like to add Visual Studio Code settings?' , default : true , } , ] ) ) . vscode ; } const ora = require ( 'ora' ) ; const spinner = ora ( 'Downloading starter project' ) ; if ( path . isAbsolute ( templateName ) || templateName . startsWith ( '.' ) || templateName . startsWith ( '~' ) ) { // Local directory let templateDir ; if ( templateName . startsWith ( '.' ) ) { templateDir = path . join ( cwd , templateName ) ; } else { templateDir = path . normalize ( templateName ) ; } await fs . copy ( templateDir , destDir ) ; } else { spinner . start ( ) ; // Github repository const m = / ^([^/]+)\/([^#]+)(#(.+))?$ / . exec ( templateName ) ; const url = ` ${ m [ 1 ] } ${ m [ 2 ] } ${ m [ 4 ] || 'master' } ` ; const downloadUrl = require ( 'download' ) ; await downloadUrl ( url , destDir , { extract : true , strip : 1 , mode : '666' , headers : { accept : 'application/zip' } , } ) ; spinner . stop ( ) ; } if ( ! detectBasysProject ( destDir ) ) { await fs . remove ( destDir ) ; // BUG: don't remove the directory if it existed before throw new Error ( 'Project provided with starter template is missing basys.json or package.json file' , ) ; } await fs . ensureDir ( path . join ( destDir , 'assets' ) ) ; if ( ! fs . existsSync ( path . join ( destDir , '.gitignore' ) ) ) { await fs . copy ( path . join ( __dirname , 'templates' , 'gitignore' ) , path . join ( destDir , '.gitignore' ) ) ; } await fs . copy ( path . join ( __dirname , 'templates' , 'jest.config.js' ) , path . join ( destDir , 'jest.config.js' ) , ) ; if ( addVSCode ) { await fs . copy ( path . join ( __dirname , 'templates' , 'jsconfig.json' ) , path . join ( destDir , 'jsconfig.json' ) , ) ; await fs . copy ( path . join ( __dirname , 'templates' , 'settings.json' ) , path . join ( destDir , '.vscode' , 'settings.json' ) , ) ; await fs . copy ( path . join ( __dirname , 'templates' , 'extensions.json' ) , path . join ( destDir , '.vscode' , 'extensions.json' ) , ) ; } if ( install ) { console . log ( ) ; try { await execShellCommand ( 'npm' , [ 'install' ] , destDir ) ; } catch ( e ) { spinner . stop ( ) ; exit ( 'Installing npm packages failed' ) ; } } let commands = '' ; if ( cwd !== destDir ) { commands += ` \` ${ chalk . green . bold ( ` ${ path . relative ( cwd , destDir ) } ` ) } \` ` ; } // BUG: change commands to 'npm run/yarn basys dev' if a local basys-cli instance is used? commands += ` \` ${ chalk . green . bold ( 'basys dev' ) } \` ` ; spinner . succeed ( ` ${ commands } ` ) ; }
`answers.name` can be an absolute/relative directory path or a github repo (with an optional branch)
answers . name can be an absolute / relative directory path or a github repo ( with an optional branch )