Open ericmdantas opened 8 years ago
@georgeedwards, alright, I removed all the noise and only let the important stuff, here's how it goes:
That means everything else will have to be linked there to be called.
We start off extending our main generator class with Yeoman Generator, see https://github.com/ericmdantas/simple-yo/blob/master/app/index.js#L7 and https://github.com/ericmdantas/simple-yo/blob/master/app/index.js#L9 - that'll give us all the base API to copy files, directories and other public stuff, but it's mostly copying.
That means that if I have something like:
class X {
doIt1() {}
doIt2() {}
doIt3() {}
}
It'll be called as doIt1
, doIt2
and doIt3
, respectively. That's good to know because some bugs happen when you depend on a certain order to be called - it's rare, but happens sometimes.
https://github.com/ericmdantas/simple-yo/blob/master/app/index.js#L12 will show the yeoman logo with the message and nothing else, it'll skip to the next method, which is prompting()
.
https://github.com/ericmdantas/simple-yo/blob/master/app/index.js#L16 This is where the question is shown, type is default for "input", where the user has to type something. We use a default string to help the user to know what he has to do.
When the user chooses, we save the result in a prop in the generator instance, in this case, this.myName
.
https://github.com/ericmdantas/simple-yo/blob/master/app/index.js#L31 I guess this can the called the core of yeoman generators - where files and folders are copied left and right, with this and that parameter.
This is how it works: yeoman knows you're in the app folder. It's kinda obligatory that such folder have a template
folder inside of it. Everything that has to be copied left and right should be inside this template
folder. In this generator case, it's a simple dummyfile.txt
.
Having said that, we run this.template
with the following params: filePath
, destinationPath
and options
. It's pretty straight forward, templatePath will be the path to the file inside your template
folder and the destinationPath
is where such file will be created, by default it's in the root of your app. Lastly, the options
param is used to pass stuff to such file. In our case, we're passing the name the user chose to the dummyfile.txt
and we're putting the info there somewhere, see: https://github.com/ericmdantas/simple-yo/blob/master/app/templates/dummyfile.txt#L1.
https://github.com/ericmdantas/simple-yo/blob/master/app/index.js#L35
This is responsible for installing the deps in package.json and bower.json in the user computer. It's the last thing run.
There are different ways to test stuff with yeoman. I usually use two: Acceptance and unit.
Acceptance tests will take care of file creations, it'll check if paths and extensions are correct and such things. It's pretty straight forward, see here: https://github.com/ericmdantas/simple-yo/blob/master/test/app.js#L6.
Unit tests are much easier, it's what you're used to, really - import, mock and assert.
I guess that's the core idea, let me know if I made myself clear.
Thanks so much for this. It is making much more sense now - thanks! I am just trying to link through to the original generator, where is sayHello()
defined from the index.js?
@ericmdantas Oh I think I have found it, are they used from the subcomponent generators?
@georgeedwards not really.
What happens in the sayHello()
method is the following:
First, I create a property called generator and instantiate a class called MainGenerator
.
https://github.com/ericmdantas/generator-ng-fullstack/blob/master/app/index.js#L12
That decouples yeoman way of handling all the stuff and my code - it makes things incredibly easier to test, mock, etc.
So, everything you see as this.generator.something()
inside this app/index.js
file is based on that MainGenerator
class.
And when you go to _ng/full/generator.js
, the constructor does the following: https://github.com/ericmdantas/generator-ng-fullstack/blob/master/_ng/full/generator.js#L12, which is simply: "Give me this context - which is the yeoman generator - and assign it to wrapper", it could be any name, but wrapper made sense.
So, all the methods you'll see in app/index.js
are inside _ng/full/generator.js
, as you can see - sayHello()
, writing()
, install()
, etc.
That makes the yeoman layer incredibly thin and gives me all the power to control the behavior of the application, be it on tests or anything else.
@georgeedwards same will happen with component/index.js
- the only difference being it's not gonna use the MainGenerator
class, it'll use the class responsible to generate the stuff for components.
https://github.com/ericmdantas/generator-ng-fullstack/blob/master/component/index.js#L10
@ericmdantas Thanks very much. Where in the original generator is the bulk of the client / server files generated? I can see the karma.conf.js
and tasks/index.js
etc. but where are the other bits?
@georgeedwards They are separated in other folders, suchs as client_ng1
, client_ng2
, server_go
, server_node
, etc.
And the main generator and sub generators copy them like this:
Copying the whole directory: https://github.com/ericmdantas/generator-ng-fullstack/blob/master/_ng/full/generator.js#L51
Copying only a single file: https://github.com/ericmdantas/generator-ng-fullstack/blob/master/_ng/full/generator.js#L49
Same goes for sub generators:
https://github.com/ericmdantas/generator-ng-fullstack/blob/master/_ng/client/angular.js#L12
https://github.com/ericmdantas/generator-ng-fullstack/blob/master/_ng/client/angular.js#L48
Yes I saw the tests, but where are those Client folders copied?
This is called in the main Generator: https://github.com/ericmdantas/generator-ng-fullstack/blob/master/_ng/full/generator.js#L62, which calls this https://github.com/ericmdantas/generator-ng-fullstack/blob/master/_ng/client/client_factory.js#L14 and call the Angular Factory https://github.com/ericmdantas/generator-ng-fullstack/blob/master/_ng/client/angular.js#L184 aaaaand then copies the files https://github.com/ericmdantas/generator-ng-fullstack/blob/master/_ng/client/angular.js#L99
The factory pattern is used so that if we decide to add anything other than Angular, all we have to do is basically implement the copyClient
method.
@ericmdantas Is there anyway to test the generator locally?
Yes, in the generator folder, run npm link
.
@georgeedwards I'll update it later today, but feel free to fork this.