#!/usr/bin/env node const inquirer = require('inquirer'); const program = require('commander'); const childProcess = require('child_process'); const chalk = require('chalk'); const log = require('npmlog'); const { lstatSync, readdirSync } = require('fs'); const { join } = require('path'); const isTgz = source => lstatSync(source).isFile() && source.match(/.tgz$/); const getDirectories = source => readdirSync(source) .map(name => join(source, name)) .filter(isTgz); log.heading = 'storybook'; const prefix = 'bootstrap'; log.addLevel('aborted', 3001, { fg: 'red', bold: true }); const spawn = (command, options = {}) => { const out = childProcess.spawnSync( `${command}`, Object.assign( { shell: true, stdio: 'inherit', }, options ) ); if (out.status !== 0) { process.exit(out.status); } return out; }; const main = program .version('3.0.0') .option('--all', `Bootstrap everything ${chalk.gray('(all)')}`); const createTask = ({ defaultValue, option, name, check = () => true, command, pre = [] }) => ({ value: false, defaultValue: defaultValue || false, option: option || undefined, name: name || 'unnamed task', check: check || (() => true), command: () => { // run all pre tasks // eslint-disable-next-line no-use-before-define pre.map(key => tasks[key]).forEach(task => { if (!task.check()) { task.command(); } }); log.info(prefix, name); command(); }, }); const tasks = { reset: createTask({ name: `Clean and re-install dependencies ${chalk.red('(reset)')}`, defaultValue: false, option: '--reset', command: () => { log.info(prefix, 'git clean'); spawn('git clean -fdx --exclude=".vscode" --exclude=".idea"'); log.info(prefix, 'yarn install'); spawn('yarn install'); }, }), core: createTask({ name: `Core & Examples ${chalk.gray('(core)')}`, defaultValue: true, option: '--core', command: () => { log.info(prefix, 'yarn workspace'); spawn('yarn install'); log.info(prefix, 'prepare'); spawn('lerna run prepare -- --silent'); }, }), docs: createTask({ name: `Documentation ${chalk.gray('(docs)')}`, defaultValue: false, option: '--docs', command: () => { spawn('yarn bootstrap:docs'); }, }), packs: createTask({ name: `Build tarballs of packages ${chalk.gray('(build-packs)')}`, defaultValue: false, option: '--packs', command: () => { spawn('yarn build-packs'); }, check: () => getDirectories(join(__dirname, '..', 'packs')).length > 0, }), 'react-native-vanilla': createTask({ name: `React-Native example ${chalk.gray('(react-native-vanilla)')}`, defaultValue: false, option: '--reactnative', pre: ['packs'], command: () => { spawn('yarn bootstrap:react-native-vanilla'); }, }), 'crna-kitchen-sink': createTask({ name: `React-Native-App example ${chalk.gray('(crna-kitchen-sink)')}`, defaultValue: false, option: '--reactnativeapp', pre: ['packs'], command: () => { spawn('yarn bootstrap:crna-kitchen-sink'); }, }), }; Object.keys(tasks) .reduce((acc, key) => acc.option(tasks[key].option, tasks[key].name), main) .parse(process.argv); Object.keys(tasks).forEach(key => { tasks[key].value = program[tasks[key].option.replace('--', '')] || program.all; }); let selection; if ( !Object.keys(tasks) .map(key => tasks[key].value) .filter(Boolean).length ) { selection = inquirer .prompt([ { type: 'checkbox', message: 'Select which packages to bootstrap', name: 'todo', choices: Object.keys(tasks).map(key => ({ name: tasks[key].name, checked: tasks[key].defaultValue, })), }, ]) .then(({ todo }) => todo.map(name => tasks[Object.keys(tasks).find(i => tasks[i].name === name)]) ) .then(list => { if (list.find(i => i === tasks.reset)) { return inquirer .prompt([ { type: 'confirm', message: `${chalk.red('DESTRUCTIVE')} files not present in git ${chalk.underline( 'will get deleted' )}, except for .idea and .vscode, ${chalk.cyan('Continue?')}`, name: 'sure', }, ]) .then(({ sure }) => { if (sure) { return list; } throw new Error('problem is between keyboard and chair'); }); } return list; }); } else { selection = Promise.resolve( Object.keys(tasks) .map(key => tasks[key]) .filter(item => item.value === true) ); } selection .then(list => { if (list.length === 0) { log.warn(prefix, 'Nothing to bootstrap'); } else { list.forEach(key => { key.command(); }); process.stdout.write('\x07'); } }) .catch(e => { log.aborted(prefix, chalk.red(e.message)); log.silly(prefix, e); process.exit(1); });