Skip to content

Commit

Permalink
Adds clone cli command
Browse files Browse the repository at this point in the history
Implements a slightly different version of build-blueprint-commands and build-blueprint-command.

If the cli will have more commands it might be a good idea to make those two files adaptable to different descriptions, usages, etc.
  • Loading branch information
walreyes committed Oct 27, 2017
1 parent 2e1ad51 commit fb32cd3
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 0 deletions.
35 changes: 35 additions & 0 deletions src/cli/cmds/clone.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import buildBlueprintCommands from './clone/build-blueprint-commands';

const usage = `Usage:
$0 clone <blueprint> <name>
$0 help clone <blueprint>`;

module.exports = {
command: 'clone <blueprint> <name>',
aliases: ['g', 'gen'],
describe: 'Clone a blueprint with a different name',
builder: yargs => {
yargs
.usage(usage)
.option('dry-run', {
alias: 'd',
describe: "List files but don't generate them",
type: 'boolean'
})
.option('verbose', {
alias: 'v',
describe: 'Verbose output, including file contents',
type: 'boolean'
})
.group(['dry-run', 'verbose', 'help'], 'Generate Options:')
.updateStrings({
'Commands:': 'Blueprints:',
'Options:': 'Blueprint Options:'
});
return buildBlueprintCommands().reduce(
(yargs, command) => yargs.command(command),
yargs
);
},
handler: argv => console.error(`Unrecognised blueprint '${argv.blueprint}'`)
};
96 changes: 96 additions & 0 deletions src/cli/cmds/clone/build-blueprint-command.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
Build a yargs command module object from options defined in the blueprint
https://github.com/yargs/yargs/blob/master/docs/advanced.md#providing-a-command-module
Target object structure:
{
command: 'blueprint <name>',
aliases: [],
describe: 'Generates a blueprint',
builder: yargs => yargs,
handler: argv => runner.run()
}
*/
const buildBlueprintCommand = (blueprint, runner) => {
// extract custom command pieces
let {
aliases = [],
options,
examples,
epilog,
epilogue,
check,
sanitize
} = blueprint.command;

// mandate the command name to guarantee name is passed to generate task
let command = `${blueprint.name} <name>`;

// rc aliases override blueprint configuration
aliases = [].concat(blueprint.settings.aliases || aliases);

// default usage
let usage = `Usage:\n $0 clone ${command}`;
aliases.forEach(
alias =>
(usage += `\n $0 clones ${command.replace(blueprint.name, alias)}`)
);

// default options from settings
if (options && blueprint.settings) {
Object.keys(options).forEach(option => {
if (blueprint.settings[option]) {
options[option].default = blueprint.settings[option];
}
});
}

// alterate epilogue keys
epilogue = epilogue || epilog;

// builder brings together multiple customizations, whilst keeping the
// options easy to parse for prompting in the init command
const builder = yargs => {
yargs.usage(usage).strict(false); // allow undocumented options through

if (options) yargs.options(options);
if (check) yargs.check(check, false);
if (examples) {
[].concat(examples).forEach(example => yargs.example(example));
}
if (epilogue) yargs.epilogue(epilogue);

return yargs;
};

// handler runs the generate blueprint task
const handler = argv => {
// merge command line options into rc options
let options = { ...blueprint.settings, ...argv };

// tidy up options before passing them on so that all hooks have access
// to the clean version
if (sanitize) options = sanitize(options);

const cliArgs = {
entity: {
name: argv.name,
options,
rawArgs: argv
},
debug: argv.verbose || false,
dryRun: argv.dryRun || false
};
runner.run(blueprint.name, cliArgs);
};

return {
command,
aliases,
describe: `Clones ${blueprint.name}`,
builder,
handler
};
};

export default buildBlueprintCommand;
26 changes: 26 additions & 0 deletions src/cli/cmds/clone/build-blueprint-commands.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import _merge from 'lodash/merge';
import _cloneDeep from 'lodash/cloneDeep';

import getEnvironment from '../../environment';
import Clone from '../../../sub-commands/clone';
import buildBlueprintCommand from './build-blueprint-command';

const loadBlueprintSettings = (blueprint, bp) =>
(blueprint.settings = _merge(
_cloneDeep(bp.common),
_cloneDeep(bp[blueprint.name])
));

const buildBlueprintCommands = () => {
const environment = getEnvironment();
const subCommand = new Clone(environment);

const { blueprints, settings: { bp = {} } } = environment.settings;

return blueprints.generators().map(blueprint => {
loadBlueprintSettings(blueprint, bp);
return buildBlueprintCommand(blueprint, subCommand);
});
};

export default buildBlueprintCommands;

0 comments on commit fb32cd3

Please sign in to comment.