UNPKG

workflow-cmd

Version:

Command line interface for workflow.

396 lines (343 loc) 10.3 kB
'use strict'; function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var shell = _interopDefault(require('shelljs')); var child_process = require('child_process'); var os = _interopDefault(require('os')); var path = require('path'); var WorkflowCore = require('workflow-core'); var readPkgUp = _interopDefault(require('read-pkg-up')); var execa = _interopDefault(require('execa')); var fs = _interopDefault(require('fs')); var prompt = _interopDefault(require('prompt')); var util = require('util'); var yargs = _interopDefault(require('yargs')); function args(args) { const parsedArgs = { named: {}, positional: [] }; const argsLength = args.length; for (let i = 2; i < argsLength; i++) { const arg = args[i]; if (arg[0] === '-') { const name = getArgName(arg); if (args[i + 1] === undefined) { parsedArgs.named[name] = true; } else { parsedArgs.named[name] = args[i + 1]; } i++; } else { parsedArgs.positional.push(arg); } } return parsedArgs; } function getArgName(arg) { let sliceIndex; const isWordArg = arg[1] === '-'; if (isWordArg) { if (arg.length === 3) throw new Error(`expected ${arg} to be a word arg`); sliceIndex = 2; } else { sliceIndex = 1; } return arg.slice(sliceIndex, arg.length); } /* eslint-disable import/prefer-default-export */ function which(cmd) { return shell.exec(`which ${cmd}`, { silent: true, async: false }); } /* eslint-env node */ const platform = process.platform; function isRunningI3() { try { child_process.execSync("i3-msg 'exec echo 1'", { stdio: 'ignore' }); return true; } catch (e) { return false; } } function isRunningWmctrl() { return which('wmctrl').code === 0; } const wm = (() => { switch (platform) { case 'win32': case 'darwin': return 'default'; case 'linux': { if (isRunningI3()) { return 'i3'; } else if (isRunningWmctrl()) { return 'wmctrl'; } return 'unknown'; } } return 'unknown'; })(); const dev = process.env.WORKFLOW_DEV_MODE === 'true'; const homedir = process.env.WORKFLOW_HOME; const devhomedir = process.env.WORKFLOW_DEV_HOME; const { config } = args(process.argv).named; let configPath; let baseFolder; (() => { if (dev) { if (devhomedir) { baseFolder = devhomedir; configPath = path.join(devhomedir, 'config.js'); } else { baseFolder = path.join(__dirname, '..', '..', 'workflow-template', 'config.js'); configPath = path.join(baseFolder, 'config.js'); } } else { if (config) { baseFolder = path.dirname(config); configPath = config; } else if (homedir) { baseFolder = homedir; configPath = path.join(baseFolder, 'config.js'); } else { configPath = path.join(os.homedir(), '.workflow', 'config.js'); baseFolder = `${os.homedir()}/.workflow`; } } })(); /* eslint-env node */ const { config: config$1 } = require(path.resolve(configPath)); const workflow = new WorkflowCore.workflow(config$1); async function resolveFlow(path$$1) { const absolutePath = await workflow.resolve(path$$1); const { flow } = await workflow.load(absolutePath); return flow; } async function apply(flow, args) { flow = await workflow.transform(flow, { args }); const screen = await workflow.screen(); const layout = await workflow.layout(flow, { screen }); await workflow.apply(layout); } /* eslint-env node */ async function version({ verbose }) { const { pkg } = await readPkgUp({ cwd: __dirname }); console.log('workflow:', pkg.version); if (verbose) { console.log(); console.log('Config:', configPath); console.log(); console.log(`Dependencies: `); await printDependenciesVersion(); } } async function printDependenciesVersion() { const { pkg } = await readPkgUp({ cwd: baseFolder }); for (let [key, value] of Object.entries(pkg.dependencies)) { console.log(` - ${key}: ${value}`); } } /* eslint-env node */ const promptGetAsync = util.promisify(prompt.get); async function update(args) { if (args.force || (await noUncommitChanges(baseFolder))) { if (args.force) { console.log('Ignoring uncommited changes with `--force` flag'); } await updateWorkflowCommand(); await updateWorkflowHome(args); } else { console.log('Uncommited changes was found in', baseFolder); console.log('Either commit the changes or re-run this command with `--force`.'); } } async function noUncommitChanges(folder) { if (which('git').code === 1) { console.log('`git` command was not found. Disabling uncommited changes check.'); return true; } if (!fs.existsSync(path.join(folder, '.git'))) { console.log(`Could not find a git repo in ${folder}. Disabling uncommited changes check.`); return true; } try { await execa('git', ['rev-parse', '--is-inside-work-tree']); } catch (e) { if (e.code !== 128) { console.error(e); process.exit(1); } else { return false; } } try { await execa('git', ['diff-index', '--quiet', 'HEAD', '--'], { cwd: folder }); return true; } catch (e) { if (e.code === 1) { return false; } else { console.error(e); process.exit(1); } } return false; } async function updateWorkflowCommand() { try { const { stdout: version } = await execa('workflow', ['--version']); const { stdout: latest } = await execa('npm', ['show', 'workflow', 'version']); if (version.toString() !== latest.toString()) { await execa('npm', ['install', '--global', 'workflow'], { stdio: 'inherit' }); } else { console.log('workflow is up to date at', version.trim()); } } catch (e) { console.error(e); process.exit(1); } } async function updateWorkflowHome(args) { try { await execa('npm', ['outdated'], { cwd: baseFolder, stdio: 'inherit' }); console.log('workflow home is up to date'); return; } catch (e) { if (e.code !== 1) { throw e; } } if (!args.force) { prompt.message = ''; prompt.start(); const { update } = await promptGetAsync({ properties: { update: { type: 'string', pattern: '^[ynYN]$', description: 'Are you sure? (Y/n)', default: 'y' } } }); if (update === 'n' || update === 'N') { console.log(); console.log('Exit without making changes to', baseFolder); process.exit(0); } } let stdout; try { await execa('npm', ['outdated'], { cwd: baseFolder }); } catch (e) { stdout = e.stdout; } const updatedPackages = parsePackages(stdout); try { for (let pkg of updatedPackages) { if (args.latest) { await execa('npm', ['install', `${pkg}@latest`], { cwd: baseFolder, stdio: 'inherit' }); } else { await execa('npm', ['update', pkg], { cwd: baseFolder, stdio: 'inherit' }); } } } catch (e) { console.error(e); process.exit(1); } try { await execa('npm', ['install'], { cwd: baseFolder, stdio: 'inherit' }); } catch (e) { console.error(e); process.exit(1); } } function parsePackages(outdatedOutput) { const packages = []; const lines = outdatedOutput.split('\n'); for (let line of lines) { if (!line.startsWith('Package')) { if (line.split(' ')[0]) { packages.push(line.split(' ')[0]); } } } return packages; } /* eslint-env node */ const [command, path$1] = args(process.argv).positional; const commands = ['update', 'version', 'help', 'apply']; const isApplyWithFlow = (command, path$$1) => command === 'apply' && path$$1; const isImplicitApplyWithFlow = command => !!command && !commands.includes(command); (async function exec() { let flow; try { if (isApplyWithFlow(command, path$1)) { flow = await resolveFlow(path$1); } else if (isImplicitApplyWithFlow(command)) { flow = await resolveFlow(command); } } catch (e) { console.error(e); process.exit(1); } yargs.scriptName('workflow').usage('$0 [<cmd>]').command('version', 'Show the version', () => {}, version).command('update', 'Update workflow and workflow-home dependencies', yargs$$1 => yargs$$1.option('latest', { type: 'boolean', description: 'Updates dependencies in workflow-home to @latest' }).option('force', { type: 'boolean', description: 'Ignore uncommited check when updating workflow-home' }), update).command(['apply <flow>' + positionalArguments(flow), '* <flow>' + positionalArguments(flow)], 'apply the flow', yargs$$1 => buildFlowArgs(yargs$$1, flow), async args$$1 => apply(flow, args$$1)).option('config', { alias: 'c', type: 'string', description: 'Set the workflow-home by path to config.js' }).option('verbose', { alias: 'vv', type: 'boolean', description: 'Set output mode to verbose' }).help().parse(); })().catch(err => console.error(err)); function positionalArguments(flow) { let args$$1 = ''; if (flow) { if (typeof flow.args === 'string') { args$$1 += ' <' + flow.args + '>'; } else if (Array.isArray(flow.args)) { for (let arg of flow.args) { args$$1 += ' <' + arg + '>'; } } } return args$$1; } function buildFlowArgs(yargs$$1, flow) { yargs$$1.positional('flow', { type: 'string', describe: 'the flow file to load' }); yargs$$1.require('flow'); if (!flow) { return; } if (typeof flow.args === 'string') { yargs$$1.positional(flow.args, { type: 'string', describe: flow.args }); yargs$$1.require(flow.args); } else if (Array.isArray(flow.args)) { for (let arg of flow.args) { yargs$$1.positional(arg, { type: 'string', describe: arg }); yargs$$1.require(arg); } } else if (flow.args !== null && typeof flow.args === 'object') { for (let [key, value] of Object.entries(flow.args)) { yargs$$1.option(key, { description: value }); yargs$$1.demandOption(key); } } else if (flow.args) { console.error('Misconfigured flow, unknown args property: ' + JSON.stringify(flow)); process.exit(1); } }