Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion blueprints/addon-import/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const SilentError = require('silent-error');

module.exports = {
description: 'Generates an import wrapper.',

beforeInstall(options) {
if (options.originBlueprintName === 'addon-import') {
throw new SilentError('You cannot call the addon-import blueprint directly.');
Expand Down
8 changes: 6 additions & 2 deletions lib/models/command.js
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,9 @@ let Command = CoreObject.extend({
@return {Promise}
*/
async validateAndRun(args) {
if (this.beforeRun) {
await this.beforeRun(args);
}
let commandOptions = this.parseArgs(args);

// If the `help` option was passed, resolve with `callHelp` to call the `help` command:
Expand Down Expand Up @@ -353,8 +356,9 @@ let Command = CoreObject.extend({

if (duplicateOptions.length > 1) {
// TODO: warn on duplicates and overwriting
mergedAliases = duplicateOptions.flatMap((option) => option.aliases);

mergedAliases = duplicateOptions.flatMap((option) => {
return Array.isArray(option.aliases) ? option.aliases : [];
});
// merge duplicate options
mergedOption = Object.assign.apply(null, duplicateOptions);

Expand Down
41 changes: 29 additions & 12 deletions lib/utilities/merge-blueprint-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,43 @@

const SilentError = require('silent-error');
const Blueprint = require('../models/blueprint');
const normalizeBlueprint = require('./normalize-blueprint-option');

/*
* Helper for commands that use a blueprint to merge the blueprint's options
* into the command's options so they can be passed in. Needs to be invoked
* with `this` pointing to the command object, e.g.
*
* var mergeBlueprintOptions = require('../utilities/merge-blueprint-options');
*
* Command.extend({
* beforeRun: mergeBlueprintOptions
* })
*/
module.exports = function (rawArgs) {
if (rawArgs.length === 0) {
return;
}

// Default behavior:The first argument is the blueprint (e.g., 'ember generate component')
let blueprintName = rawArgs[0];

// FIX: The 'new' and 'addon' commands use the first arg as the Project Name, not Blueprint.
// We need to find the actual blueprint name.
if (this.name === 'new' || this.name === 'addon') {
//Start with the default (usually 'app' or 'addon')
let blueprintOption = this.availableOptions.find((o) => o.name === 'blueprint');
blueprintName = blueprintOption ? blueprintOption.default : 'app';

//Check if the user passed -b or --blueprint
for (let i = 0; i < rawArgs.length; i++) {
if (rawArgs[i] === '-b' || rawArgs[i] === '--blueprint') {
// The next argument is the value
if (rawArgs[i + 1]) {
blueprintName = rawArgs[i + 1];
}
} else if (rawArgs[i].startsWith('--blueprint=')) {
//Handle --blueprint=name style
blueprintName = rawArgs[i].split('=')[1];
}
}
}

blueprintName = normalizeBlueprint(blueprintName);

// merge in blueprint availableOptions
let blueprint;
try {
blueprint = Blueprint.lookup(rawArgs[0], {
blueprint = Blueprint.lookup(blueprintName, {
paths: this.project.blueprintLookupPaths(),
});
this.registerOptions(blueprint);
Expand Down
36 changes: 36 additions & 0 deletions tests/unit/models/command-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,42 @@ describe('models/command.js', function () {
expect(new ServeCommand(options).parseArgs(['--port', '80'])).to.have.nested.property('options.port', 80);
});

it('calls beforeRun before parsing args', async function () {
let beforeRunCalled = false;
let passedArgs;

let mockUi = { writeLine: () => {} };
let mockProject = {
isEmberCLIProject: () => true,
root: process.cwd(),
hasDependencies: () => true,
isEmberCLIAddon: () => false,
};

let command = new Command({
ui: mockUi,
project: mockProject,
name: 'fake-command',
settings: {},

availableOptions: [{ name: 'foo', type: String }],

run() {},

beforeRun(args) {
beforeRunCalled = true;
passedArgs = args;
this.registerOptions({
availableOptions: [{ name: 'bar', type: String }],
});
},
});

await command.validateAndRun(['--bar=baz']);
expect(beforeRunCalled).to.be.true;
expect(passedArgs).to.deep.equal(['--bar=baz']);
});

it('parseArgs() should get command options from the config file and command line', function () {
expect(
new ServeCommand(
Expand Down