diff --git a/lib/commands/generate.js b/lib/commands/generate.js index 92a7ffe165..53d4de4c3b 100644 --- a/lib/commands/generate.js +++ b/lib/commands/generate.js @@ -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 to be specified. ' + + 'For more details, use `ember help`'; + module.exports = Command.extend({ name: 'generate', description: 'Generates new code from blueprints.', @@ -40,13 +45,7 @@ module.exports = Command.extend({ let blueprintName = rawArgs[0]; if (!blueprintName) { - return Promise.reject( - new SilentError( - 'The `ember generate` command requires a ' + - 'blueprint name to be specified. ' + - 'For more details, use `ember help`.' - ) - ); + return Promise.reject(new SilentError(UNKNOWN_BLUEPRINT_ERROR)); } let taskArgs = { @@ -166,3 +165,7 @@ module.exports = Command.extend({ } }, }); + +module.exports.ERRORS = { + UNKNOWN_BLUEPRINT_ERROR, +}; diff --git a/lib/models/blueprint.js b/lib/models/blueprint.js index 55e8a67ab8..1e8cf21ba5 100644 --- a/lib/models/blueprint.js +++ b/lib/models/blueprint.js @@ -1318,6 +1318,23 @@ let Blueprint = CoreObject.extend({ Blueprint.lookup = function (name, options) { options = options || {}; + if (name.includes(path.sep)) { + let blueprintPath = path.resolve(name); + let isNameAPath = Boolean(blueprintPath); + + if (isNameAPath) { + 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; diff --git a/tests/acceptance/destroy-test.js b/tests/acceptance/destroy-test.js index 0857a61cee..1d813c56fe 100644 --- a/tests/acceptance/destroy-test.js +++ b/tests/acceptance/destroy-test.js @@ -101,6 +101,13 @@ describe('Acceptance: ember destroy', function () { return assertDestroyAfterGenerate(commandArgs, files); }); + it('deletes files generated using blueprint paths', function () { + let commandArgs = [`${__dirname}/../../blueprints/http-proxy`, 'foo', 'bar']; + let files = ['server/proxies/foo.js']; + + return assertDestroyAfterGenerate(commandArgs, files); + }); + it('deletes files generated using blueprints from the project directory', async function () { let commandArgs = ['foo', 'bar']; let files = ['app/foos/bar.js']; diff --git a/tests/acceptance/generate-test.js b/tests/acceptance/generate-test.js index b698cd124b..734b0dee7d 100755 --- a/tests/acceptance/generate-test.js +++ b/tests/acceptance/generate-test.js @@ -144,6 +144,16 @@ 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([path.resolve(`${__dirname}/../../blueprints/http-proxy`), 'foo', 'http://localhost:5000']); + + 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(); diff --git a/tests/unit/commands/generate-test.js b/tests/unit/commands/generate-test.js index 6a978151c8..1c13163378 100644 --- a/tests/unit/commands/generate-test.js +++ b/tests/unit/commands/generate-test.js @@ -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; @@ -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); }); });