javascript - webapp - yeoman git
Yeoman: llame al sub-generador con argumentos provistos por el usuario (3)
Estoy escribiendo mi primer generador Yeoman, que solicita al usuario varias entradas y crea archivos de forma condicional según sus respuestas. Necesito poder llamar a una subrutina (podría ser un subgenerador Yeoman) en base a la entrada del usuario, y pasarle argumentos.
La razón por la que quiero usar funciones nombradas (que no se ejecutan automáticamente) es que a veces la respuesta del usuario debería invocar una serie de funciones combinadas, y algunas veces la función debería ejecutarse sola.
Lo que he intentado:
Pensé que los sub-generadores eran el camino a seguir, ya que estoy creando conjuntos de archivos solo si el usuario los solicita. Pero estoy teniendo problemas para llamarlos condicionalmente y pasarles la entrada proporcionada por el usuario. He intentado usar hookFor
, pero recibo el error de aserción: hookFor must be used within the constructor only
. (Como no quiero que se ejecute de forma predeterminada, estoy llamando al this.prompt(prompts, function (props)
desde mi this.prompt(prompts, function (props)
).
La pregunta:
¿Cómo llamo a una rutina solo si el usuario la solicita (a través de un aviso) y le paso esa rutina a la información suministrada por el usuario?
Si tiene la amabilidad de responder, no asuma que he intentado algo obvio ;-).
Actualización 2015-04: la API de yeoman ahora incluye this.composeWith
como el método preferido para vincular generadores.
Consideremos que tiene un Generador generator-blog
(BlogGenerator) con dos sub generadores (blog-server y blog-client):
app/index.js
client/index.js
server/index.js
Entonces, cuando ejecuta el yo blog
le pregunta a el usuario qué opciones tiene y ejecuta (opcionalmente) los generadores secundarios, ¿verdad?
Para ejecutar un subgenerador, debe llamar a this.invoke("generator_namespace", {options: {}})
. El segundo argumento que pasamos puede tener un campo de options
: es el objeto de opciones que se pasará al generador.
En la aplicación / index.js:
BlogGenerator.prototype.askFor = function askFor() {
var cb = this.async();
// have Yeoman greet the user.
console.log(this.yeoman);
var prompts = [{
name: ''appName'',
message: ''Enter your app name'',
default: ''MyBlog''
}, {
type: ''confirm'',
name: ''createServer'',
message: ''Would you like to create server project?'',
default: true
}, {
type: ''confirm'',
name: ''createClient'',
message: ''Whould you like to create client project?'',
default: true
}];
this.prompt(prompts, function (props) {
this.appName = props.appName;
this.createServer = props.createServer;
this.createClient = props.createClient;
cb();
}.bind(this));
}
BlogGenerator.prototype.main = function app() {
if (this.createClient) {
// Here: we''are calling the nested generator (via ''invoke'' with options)
this.invoke("blog:client", {options: {nested: true, appName: this.appName}});
}
if (this.createServer) {
this.invoke("blog:server", {options: {nested: true, appName: this.appName}});
}
};
En client / index.js:
var BlogGenerator = module.exports = function BlogGenerator(args, options, config) {
var that = this;
yeoman.Base.apply(this, arguments);
// in this.options we have the object passed to ''invoke'' in app/index.js:
this.appName = that.options.appName;
this.nested = that.options.nested;
};
BlogGenerator .prototype.askFor = function askFor() {
var cb = this.async();
if (!this.options.nested) {
console.log(this.yeoman);
}
}
ACTUALIZACIÓN 2015-12-21 :
El uso de invoke
está obsoleto ahora y debe reemplazarse con composeWith
. Pero no es tan fácil como podría ser. La principal diferencia entre invoke
y composeWith
es que ahora no tiene capacidad para controlar subgeneradores. Solo puedes declarar usarlos.
Así es como debería verse el método main
de arriba:
BlogGenerator.prototype.main = function app() {
if (this.createClient) {
this.composeWith("blog:client", {
options: {
nested: true,
appName: this.appName
}
}, {
local: require.resolve("./../client")
});
}
if (this.createServer) {
this.composeWith("blog:server", {
options: {
nested: true,
appName: this.appName
}
}, {
local: require.resolve("./../server")
});
}
};
También he eliminado los yeoman.generators.Base
reemplazados con yeoman.Base
.
Puede abarcar todos los posibles escenarios de ejecución, verificación de estado, indicaciones al componer generadores juntos si desacopla generadores y utiliza un "generador principal", el ciclo de contexto de ejecución lo ayudará. Use las options
de .composeWith(''my-genertor'', { ''options'' : options })
para pasar las configuraciones a los generadores compuestos.
Cuando se usa .composeWith
una función de grupo de prioridad (p. Ej .: prompting
, writing
...) se ejecutará para todos los generadores, luego el siguiente grupo de prioridad. Si llama a .composeWith
a generatorB desde dentro de un generador A , entonces la ejecución será, por ejemplo:
generatorA.prompting => generatorB.prompting => generatorA.writing => generatorB.writing
Si desea controlar la ejecución entre diferentes generadores, le aconsejo que cree un generador "principal" que los componga juntos, como está escrito en http://yeoman.io/authoring/composability.html#order :
// In my-generator/generators/turbo/index.js
module.exports = require(''yeoman-generator'').Base.extend({
''prompting'' : function () {
console.log(''prompting - turbo'');
},
''writing'' : function () {
console.log(''prompting - turbo'');
}
});
// In my-generator/generators/electric/index.js
module.exports = require(''yeoman-generator'').Base.extend({
''prompting'' : function () {
console.log(''prompting - zap'');
},
''writing'' : function () {
console.log(''writing - zap'');
}
});
// In my-generator/generators/app/index.js
module.exports = require(''yeoman-generator'').Base.extend({
''initializing'' : function () {
this.composeWith(''my-generator:turbo'');
this.composeWith(''my-generator:electric'');
}
});