Skip to content

Commit

Permalink
feat: support --blueprint arg for specifying a path to a blueprint,
Browse files Browse the repository at this point in the history
rather than relying on blueprint lookup/resolver rules
  • Loading branch information
NullVoxPopuli committed Dec 17, 2020
1 parent 7c0e785 commit 39a2f90
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 18 deletions.
27 changes: 19 additions & 8 deletions lib/commands/generate.js
Expand Up @@ -9,6 +9,11 @@ const _ = require('ember-cli-lodash-subset');
const EOL = require('os').EOL;
const SilentError = require('silent-error');

const UNKNOWN_BLUEPRINT_ERROR =
'The `ember generate` command requires a ' +
'blueprint name or path (via --blueprint) to be specified. ' +
'For more details, use `ember help`.';

module.exports = Command.extend({
name: 'generate',
description: 'Generates new code from blueprints.',
Expand All @@ -22,6 +27,13 @@ module.exports = Command.extend({
{ name: 'classic', type: Boolean, default: false, aliases: ['c'] },
{ name: 'dummy', type: Boolean, default: false, aliases: ['dum', 'id'] },
{ name: 'in-repo-addon', type: String, default: null, aliases: ['in-repo', 'ir'] },
{
name: 'blueprint',
type: String,
default: null,
description:
'Specifies a path to a local blueprint to use instead of using a resolved blueprint matching the name',
},
{
name: 'in',
type: String,
Expand All @@ -37,15 +49,10 @@ module.exports = Command.extend({

run(commandOptions, rawArgs) {
let blueprintName = rawArgs[0];
let blueprintPath = commandOptions.blueprint;

if (!blueprintName) {
return Promise.reject(
new SilentError(
'The `ember generate` command requires a ' +
'blueprint name to be specified. ' +
'For more details, use `ember help`.'
)
);
if (!blueprintName && !blueprintPath) {
return Promise.reject(new SilentError(UNKNOWN_BLUEPRINT_ERROR));
}

let taskArgs = {
Expand Down Expand Up @@ -165,3 +172,7 @@ module.exports = Command.extend({
}
},
});

module.exports.ERRORS = {
UNKNOWN_BLUEPRINT_ERROR,
};
14 changes: 14 additions & 0 deletions lib/models/blueprint.js
Expand Up @@ -1279,6 +1279,20 @@ let Blueprint = CoreObject.extend({
Blueprint.lookup = function (name, options) {
options = options || {};

if (options.blueprintPath) {
let blueprintPath = path.resolve(options.blueprintPath);

if (Blueprint._existsSync(blueprintPath)) {
return Blueprint.load(blueprintPath);
}

if (!options.ignoreMissing) {
throw new SilentError(`Unknown blueprint: ${name}`);
}

return;
}

let lookupPaths = generateLookupPaths(options.paths);

let lookupPath;
Expand Down
12 changes: 7 additions & 5 deletions lib/tasks/generate-from-blueprint.js
Expand Up @@ -13,20 +13,21 @@ class GenerateTask extends Task {

async run(options) {
let name = options.args[0];
let blueprintPath = options.blueprint;
let noAddonBlueprint = ['mixin', 'blueprint-test'];

let mainBlueprint = this.lookupBlueprint(name, options.ignoreMissingMain);
let testBlueprint = this.lookupBlueprint(`${name}-test`, true);
let mainBlueprint = this.lookupBlueprint(name, options.ignoreMissingMain, blueprintPath);
let testBlueprint = this.lookupBlueprint(`${name}-test`, true, `${blueprintPath}-test`);

// lookup custom addon blueprint
let addonBlueprint = this.lookupBlueprint(`${name}-addon`, true);
let addonBlueprint = this.lookupBlueprint(`${name}-addon`, true, `${blueprintPath}-addon`);

// otherwise, use default addon-import
if (noAddonBlueprint.indexOf(name) < 0 && !addonBlueprint && options.args[1]) {
let mainBlueprintSupportsAddon = mainBlueprint && mainBlueprint.supportsAddon();

if (mainBlueprintSupportsAddon) {
addonBlueprint = this.lookupBlueprint('addon-import', true);
addonBlueprint = this.lookupBlueprint('addon-import', true, `${blueprintPath}-addon-import`);
}
}

Expand Down Expand Up @@ -91,10 +92,11 @@ class GenerateTask extends Task {
return addonBlueprint[this.blueprintFunction](addonBlueprintOptions);
}

lookupBlueprint(name, ignoreMissing) {
lookupBlueprint(name, ignoreMissing, blueprintPath) {
return Blueprint.lookup(name, {
paths: this.project.blueprintLookupPaths(),
ignoreMissing,
blueprintPath,
});
}
}
Expand Down
16 changes: 16 additions & 0 deletions tests/acceptance/generate-test.js
Expand Up @@ -268,6 +268,22 @@ describe('Acceptance: ember generate', function () {
expect(file('app/controllers/foo.js')).to.contain('custom: true');
});

it('allows a path to be specified to a blueprint', async function () {
await outputFile(
'blueprints/http-proxy/files/server/proxies/__name__.js',
"import Ember from 'ember';\n" + 'export default Ember.Object.extend({ foo: true });\n'
);
await generate([
'http-proxy',
'foo',
'http://localhost:5000',
'--blueprint',
path.resolve(`${__dirname}/../../blueprints/http-proxy`),
]);

expect(file('server/index.js')).to.not.contain('foo: true', 'the local blueprint is not used');
});

it('passes custom cli arguments to blueprint options', async function () {
await initApp();

Expand Down
7 changes: 2 additions & 5 deletions tests/unit/commands/generate-test.js
Expand Up @@ -11,6 +11,7 @@ const GenerateCommand = require('../../../lib/commands/generate');
const td = require('testdouble');
const ROOT = process.cwd();
const { createTempDir } = require('broccoli-test-helper');
const { ERRORS } = GenerateCommand;

describe('generate command', function () {
let input, options, command;
Expand Down Expand Up @@ -98,11 +99,7 @@ describe('generate command', function () {

it('complains if no blueprint name is given', function () {
return expect(command.validateAndRun([])).to.be.rejected.then((error) => {
expect(error.message).to.equal(
'The `ember generate` command requires a ' +
'blueprint name to be specified. ' +
'For more details, use `ember help`.'
);
expect(error.message).to.equal(ERRORS.UNKNOWN_BLUEPRINT_ERROR);
});
});

Expand Down

0 comments on commit 39a2f90

Please sign in to comment.