world webapp node hello example javascript yeoman yeoman-generator

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 ;-).



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''); } });