upgrade generators to use the latest yeoman-generator - #363
Conversation
be709b0 to
379cdda
Compare
| }] | ||
| }, | ||
| "parserOptions": { | ||
| "ecmaVersion": 8 |
There was a problem hiding this comment.
We cannot use async functions in generator-loopback yet, we need to keep support for Node.js 6.x.
Please revert this change.
There was a problem hiding this comment.
That's great. I was going to update all the this.async() places to use async await.
Reverting it.
There was a problem hiding this comment.
I like the idea of getting rid of this.async() - if you like to do that then I fully support you in that change!
The trick is to use Promise APIs instead of async functions.
For example:
async function foo() {
await bar();
return 'result';
}needs to be written in Promise-only styler as follows:
function foo() {
return bar
.then(() => 'result');
}| // } | ||
|
|
||
| loadModels: actions.loadModels, | ||
| async ACLloadProject() { |
There was a problem hiding this comment.
Ditto, we cannot use async functions in generator-loopback yet.
379cdda to
6d79c28
Compare
| // Export it for strong-cli to use | ||
| module.exports._package = pkg.name + ': ' + pkg.version; | ||
| module.exports._yeoman = yeoman; | ||
| module.exports._yeomanEnv = require('yeoman-environment'); |
There was a problem hiding this comment.
This is related to strongloop and loopback-cli
| var bluemix = require('../bluemix/helpers'); | ||
| var fs = require('fs'); | ||
| var actions = require('../lib/actions'); | ||
| // var actions = require('../lib/actions'); |
There was a problem hiding this comment.
In the first commit, please DO NOT review the change in file app/index.js.
I have to update it to test the acl generator from cli, while the app generator is not finished.
dee08a4 to
8ee9be5
Compare
|
|
||
| // Export it for strong-cli to use | ||
| module.exports._package = pkg.name + ': ' + pkg.version; | ||
| module.exports._yeoman = yeoman; |
There was a problem hiding this comment.
Do we still need to export yeoman? Isn't _yeomanEnv all that loopback-cli needs?
|
FYI |
c522b4e to
bf89bdd
Compare
3d06c10 to
df36e65
Compare
| }] | ||
| } | ||
| } | ||
| } No newline at end of file |
| } | ||
|
|
||
| loadProject() { | ||
| debug('loading project...'); |
There was a problem hiding this comment.
do we need those debug messages?
There was a problem hiding this comment.
@dhmlau I think the progress info like ^ is fine, since it doesn't contain any variable.
I will double check all the places that prints variables....I don't see any sensitive info in the generator, while some probably prints long nested object. Will remove them.
There was a problem hiding this comment.
ok. I have this question because it may not seem useful in the future for debugging purpose. If you think it's needed, i'm ok to keep it. thanks.
|
|
||
| this.argument(g.f('name'), { | ||
| desc: g.f('Name of the application to scaffold.'), | ||
| this.argument('name', { |
There was a problem hiding this comment.
Need to keep g.f('name'), otherwise this issue #377 will appear again
|
|
||
| bluemix() { | ||
| if (this.options.bluemix) { | ||
| this.log('\nBluemix configuration:'); |
There was a problem hiding this comment.
I know this is out of scope for the task. Tthe string needs to be translated but can do it in another PR. i.e.
this.log(g.f('\nBluemix configuration:'));
| this.login.apply(this); | ||
| }; | ||
|
|
||
| BMpromptServiceName() { |
There was a problem hiding this comment.
nitpick: would it be better to have the function name as BMPromptServiceName instead of BMpromptServiceName?
Same for the functions below.
|
|
||
| this.argument(g.f('name'), { | ||
| desc: g.f('Name of the datasource to create.'), | ||
| this.argument('name', { |
There was a problem hiding this comment.
Need to keep g.f('name') instead of 'name'
| ygAssert.file('./server/datasources.bluemix.js'); | ||
| done(); | ||
| }); | ||
| it('should generate datasources.bluemix.js', function() { |
There was a problem hiding this comment.
we don't need to pass done in the parameter or call done() inside?
There was a problem hiding this comment.
@dhmlau ah, don't need to. same as I put in comment loopbackio/loopback-datasource-juggler#1616 (comment), mocha handles it if a Promise returned.
| @@ -0,0 +1,391 @@ | |||
| // Copyright IBM Corp. 2014,2016. All Rights Reserved. | |||
There was a problem hiding this comment.
the file name is called z-app.test.js. Is it possible to rename the file name to fit what it's supposed to do?
There was a problem hiding this comment.
@dhmlau run the app.test.js first causes other tests fail, unfortunately I couldn't figure it out within one day so I prefer to leave it out of the scope of this PR :( I can create an issue to fix it afterwards.
There was a problem hiding this comment.
i see. so the tests in this file is only a temp place to know what tests we're skipping now? i'm good with a follow up PR to handle the rest.
There was a problem hiding this comment.
I am not happy about moving renaming this test file from app.test.js to z-app.test.js and back, because it prevents git from rendering a useful diff showing the changes made alongside the transfer.
If it's too difficult to fix these test properly, then I am proposing the following workaround:
- In this pull request, keep the file name as
app.test.jsand mark the tests as skipped viadescribe.skipat top-level. - In the next pull request, rename the file to
z-app.test.jsand remove.skip.
Or maybe do both changes in the same pull request, but split them into two commits.
Thoughts?
Also BTW, the test name z-app.test.js does not make this test file the last one, there is still test/zosconnectee.test.js that's run after this one.
There was a problem hiding this comment.
@bajtos True the code compare is pretty bad :( skipping it makes sense to me 👌
e87d95f to
f351d26
Compare
shimks
left a comment
There was a problem hiding this comment.
Good work, as the Japanese would say 'Otsukaresama'.
Has linting been run btw? I don't know whether there are going to be any unused variables lying around. I'd also run the thing through prettier
| } | ||
|
|
||
| generateYoRc: function() { | ||
| commit() { |
There was a problem hiding this comment.
Could you please document what the point of this function is?
| // Export it for strong-cli to use | ||
| module.exports._package = pkg.name + ': ' + pkg.version; | ||
| module.exports._yeoman = yeoman; | ||
| // module.exports._yeoman = yeoman; |
There was a problem hiding this comment.
Should this be uncommented or removed?
| * @param {String} destination Destination file to write to. Relative to this.destinationRoot() | ||
| */ | ||
|
|
||
| copy(source, dest) { |
There was a problem hiding this comment.
I've noticed that this function and the ones below aren't in the original file. When are these used?
There was a problem hiding this comment.
@shimks good question. Let me elaborate this breaking change between yeoman-generator@0.x and yeoman-generator@3.x:
0.x has a function directory that copies the files from source to destination for you, see code here. While 3.x doesn't have it and leaves users to do the file moving.
That's why I added our implementation of directory in the actions.js file at the first place, then added the other nested functions it calls:
directory --> copy --> template
There was a problem hiding this comment.
Should we write tests for these functions or are they already tested as part of the generator specific tests?
There was a problem hiding this comment.
@b-admike We have tests for helper functions but not actions. Testing actions require complicated setup for generator and sandbox.
And honestly I would prefer to not add such overhead effort in this PR :-p
Also, every generator requires file moving, so we have plenty acceptance tests to prove those actions work well :)
| end: { | ||
| requireDriver: function() { | ||
| if (this.skip) return; | ||
| requireDriver() { |
There was a problem hiding this comment.
The previous file had the requireDriver function nested under an end object. Is this change ok?
There was a problem hiding this comment.
I think end is a phase that version 0.x allows multiple functions to be executed. So I just refactor it to be a function that gets called in the original sequence. And I don't see a difference from the old generator :-p
| "loopback-soap": "^1.0.0", | ||
| "loopback-swagger": "^5.4.0", | ||
| "loopback-workspace": "^4.0.0", | ||
| "mem-fs-editor": "^5.1.0", |
|
|
||
| // Jannyhou: to be fixed! | ||
| describe('prints right help message for each generator', function() { | ||
| // var CMD_NAMES = ['acl']; |
| var helpFilePath = '../fixtures/help-texts/' + helpFileName; | ||
| var output = fs.readFileSync(helpFilePath, 'utf8'); | ||
| assert.equal(output, helpText); | ||
| assert.equal(helpText, output); |
There was a problem hiding this comment.
@shimks Yep, the old code was wrong. Read the error message you will see, the first argument is expected result, while the second one is the actual result.
| }); | ||
|
|
||
| it('should set dataSource to db if it exists', function() { | ||
| return new Promise(function(resolve, reject) { |
There was a problem hiding this comment.
I think we can just return wsModels.DataSourceDefinition.create; I'm assuming the method has promise support
There was a problem hiding this comment.
Assuming loopback-workspace is depending on LB 3.x internally (and not on LB 2.x), then yes, methods like create should support promises out of the box.
| }); | ||
|
|
||
| describe('with --bluemix', function() { | ||
| describe.skip('with --bluemix', function() { |
There was a problem hiding this comment.
From what I remember, this test might supposed to fail when run locally. Try getting rid of the skip and see if the test passes in the CI
There was a problem hiding this comment.
oh...bad news. I just realized I only fixed the composed bluemix with app and datasource, while there is one with model. Sigh.
I am fixing them ^
| }); | ||
| }); | ||
|
|
||
| // requires generator-yeoman v0.17 |
There was a problem hiding this comment.
Can we get rid of these comments now?
virkt25
left a comment
There was a problem hiding this comment.
Amazing work @jannyHou !! Everything looks good to me, just some nitpicks ... I tried pointing them out but figured you can spot them yourselves ... if not let me know and I can point out all the other spots. (; issue and self and some alignment issues for comments).
| msgs.push(list.map(it => ' ' + it).join('\n')); | ||
| return msgs.join('') + '\n'; | ||
| }, | ||
| }; |
| type: 'confirm', | ||
| default: true, | ||
| when: !this.bluemix, | ||
| var done = this.async(); |
| help() { | ||
| return helpText.customHelp(this, 'loopback_bluemix_usage.txt'); | ||
| }, | ||
| }; |
| help() { | ||
| return helpText.customHelp(this, 'loopback_boot-script_usage.txt'); | ||
| }, | ||
| }; |
| done(); | ||
| }.bind(this)); | ||
| }, | ||
| }; |
| }, | ||
| ]).then(function(answers) { | ||
| var dir = answers.dir; | ||
| self.dir = dir; |
There was a problem hiding this comment.
Should be able to do this.dir as this function is bound to this.
| }; | ||
|
|
||
| /** | ||
| /** |
| }); | ||
| }; | ||
|
|
||
| /** |
| /** | ||
| * Modify the list of datasources created by {@link loadDataSources} | ||
| * and append an item for `null` datasource. | ||
| /** |
| data || this, | ||
| options | ||
| ); | ||
| // memfs.create().copyTpl( |
| @@ -65,11 +67,12 @@ module.exports = yeoman.Base.extend({ | |||
| this.option('version', { | |||
| desc: g.f('Display version information'), | |||
There was a problem hiding this comment.
I noticed the first argument, name, is using description property name; while all other options (not arguments!) are still using desc property name. Could you please check which form is the right one and ideally unify the implementation to use the same property name everywhere (if possible)?
There was a problem hiding this comment.
@bajtos either of them works, see options in yeoman-generator and arguments in yeoman-generator
And our help message generator
But I agree it's better to unify them. I will change description to desc.
| } | ||
| }; | ||
| printNextSteps() { | ||
| if (!this.options.initBluemix) { |
There was a problem hiding this comment.
Can we use early return here to reduce the level of indentation?
if (this.options.initBluemix) return;| } | ||
| }.bind(this)); | ||
| }, | ||
| }; |
There was a problem hiding this comment.
I am surprised that eslint and/or prettier did not catch these extra ;. Are we missing an eslint rule in our config?
| @@ -1,391 +0,0 @@ | |||
| // Copyright IBM Corp. 2014,2016. All Rights Reserved. | |||
There was a problem hiding this comment.
+1 for finding a more robust solution.
| // I manually verified that by choosing "install connector", | ||
| // the custom module is intalled | ||
| // Here it fails since folder `node_modules` is not created | ||
| it.skip('should support custom connector', function() { |
There was a problem hiding this comment.
Posting a line-level comment to remind us about a test that's skipped now.
// Jannyhou: To be fixed (3)!
// I manually verified that by choosing "install connector",
// the custom module is intalled
// Here it fails since folder `node_modules` is not createdThere was a problem hiding this comment.
Hmm @bajtos could you elaborate more about what does "line-level comment" mean?
There was a problem hiding this comment.
Sorry for the confusion. By line-level I meant that the comment was attached to a particular source code line (test/datasource.test.js:83) and will be hidden by GitHub once you change that code; as opposed to a "regular" comment that stays in the top-level discussion & expanded forever.
Anyhow, my intention was to point out a comment you have added and which says that a skipped test needs to be fixed. IMO, something needs to be done about that comment before landing this pull request.
If you think fixing the skipped test is out of scope of this PR, then I am totally fine with that, but please reword the comment so that it does not look like something that was slipped through the review process.
For example:
// FIXME(jannyHou) This test fails because folder `node_modules` is not created.
// For now, verify this functionality manually by choosing "install connector"
// and checking that the custom module is installed.| paths: ['/x', '/y'], | ||
| params: '{"z": 1}', | ||
| }).then(function() { | ||
| // eslint-disable-next-line max-len |
There was a problem hiding this comment.
Let's rewrite the next line so that it fits in our max line length.
const middlewareConfig = readMiddlewaresJsonSync('server');
const newSources = Object.keys(middlewareConfig.routes);| }); | ||
|
|
||
| it('should set dataSource to db if it exists', function() { | ||
| return new Promise(function(resolve, reject) { |
There was a problem hiding this comment.
Assuming loopback-workspace is depending on LB 3.x internally (and not on LB 2.x), then yes, methods like create should support promises out of the box.
| @@ -0,0 +1,391 @@ | |||
| // Copyright IBM Corp. 2014,2016. All Rights Reserved. | |||
There was a problem hiding this comment.
I am not happy about moving renaming this test file from app.test.js to z-app.test.js and back, because it prevents git from rendering a useful diff showing the changes made alongside the transfer.
If it's too difficult to fix these test properly, then I am proposing the following workaround:
- In this pull request, keep the file name as
app.test.jsand mark the tests as skipped viadescribe.skipat top-level. - In the next pull request, rename the file to
z-app.test.jsand remove.skip.
Or maybe do both changes in the same pull request, but split them into two commits.
Thoughts?
Also BTW, the test name z-app.test.js does not make this test file the last one, there is still test/zosconnectee.test.js that's run after this one.
3c25a00 to
c327ed1
Compare
|
@virkt25 Thank you for pointing out those extra semicolons! I feel the eslint definitely has some problem, having the semicolon/removing it both pass And according to If we decide to remove all extra semicolon, I can add rule |
69d1a70 to
3768a8f
Compare
|
I'm indifferent to the rule as long as it's applied consistently to the code base. |
b1a462e to
03bdc82
Compare
|
ok I figured out why And removed all extra semicolons in this commit, will keep it as a separate commit when merge PR. |
bajtos
left a comment
There was a problem hiding this comment.
Few more minor comments to address, none of them blocking this PR from being landed as far as I am concerned.
| "ignorePattern": "^\\s*var\\s.+=\\s*(require\\s*\\()|(/)" | ||
| }] | ||
| }], | ||
| "no-extra-semi": "error" |
There was a problem hiding this comment.
Please move this configuration to https://github.com/strongloop/eslint-config-loopback so that it's eventually enabled for all LB (3.x) projects/repositories.
| "node": ">=6" | ||
| }, | ||
| "scripts": { | ||
| "lint:fix": "eslint --ignore-path .gitignore --fix .", |
There was a problem hiding this comment.
Have you considered re-using the cli args from lint script via npm run lint --fix?
| expect(modelGen.abort).to.eql(true); | ||
| done(); | ||
| }); | ||
| var ctx = helpers.run(path.join(__dirname, '../model')); |
There was a problem hiding this comment.
Use const, not var - see https://loopback.io/doc/en/contrib/style-guide-es6.html
| expect(modelGen.abort).to.eql(true); | ||
| done(); | ||
| }); | ||
| var ctx = helpers.run(path.join(__dirname, '../model')); |
There was a problem hiding this comment.
Use const, not var - see https://loopback.io/doc/en/contrib/style-guide-es6.html
| .eql('cloudant-demo-service'); | ||
| done(); | ||
| }); | ||
| var ctx = helpers.run(path.join(__dirname, '../model')); |
There was a problem hiding this comment.
Use const, not var - see https://loopback.io/doc/en/contrib/style-guide-es6.html
|
|
||
| prompts.push(toolchainPrompt, dockerPrompt); | ||
|
|
||
| this.prompt(prompts).then(function(answers) { |
There was a problem hiding this comment.
A nitpick: can you rewrite this using an arrow function and remove .bind(this)?
return this.prompt(prompts).then(answers => {
// ...
});| * @param {String} destination Destination file to write to. Relative to this.destinationRoot() | ||
| */ | ||
|
|
||
| copy(source, dest) { |
There was a problem hiding this comment.
Should we write tests for these functions or are they already tested as part of the generator specific tests?
| } | ||
|
|
||
| copyFiles: function() { | ||
| writing() { |
There was a problem hiding this comment.
nitpick: can there be a better function name here?
There was a problem hiding this comment.
couldn't remember why I changed the name....reverted it.
| // from memory to destination folder. | ||
| commit() { | ||
| var done = this.async(); | ||
| this.fs.commit(done); |
There was a problem hiding this comment.
From Yeoman docs:
It is worth noting that although this.fs exposes commit, you should not call it in your generator. Yeoman calls this internally after the conflicts stage of the run loop.
http://yeoman.io/authoring/file-system.html. It's fine if we use it, but I was wondering whether there are alternatives.
There was a problem hiding this comment.
@b-admike yep it's a workaround. I eventually calls it because there is no easy better solution for finishing file move before invoke the composed generator :(
| this.login.apply(this); | ||
| } | ||
|
|
||
| BMPromptServiceName() { |
There was a problem hiding this comment.
The method names should be camelCase, such as bmPromptServiceName.
|
@jannyHou Thank you for the bold efforts! Mostly LGTM. |
f6566ae to
e39f97b
Compare
b-admike
left a comment
There was a problem hiding this comment.
LGTM; Great job Janny! This was a huge undertaking and I'm glad we have these tests up and running with the shiny new version of yeoman-generator 🎉
| var fs = require('fs'); | ||
| var rimraf = require('rimraf'); | ||
|
|
||
| // Rename it to run as the last test |
There was a problem hiding this comment.
nitpick: can we re-phrase this statement to start like this: The test file is named app.test.js as a workaround for...?
There was a problem hiding this comment.
good catch, it's fixed lol. Let me remove the comment.
a636ce9 to
7fcd77c
Compare
| // See https://github.com/strongloop/generator-loopback/issues/116 | ||
| this.invoke = require('yeoman-generator/lib/actions/invoke'); | ||
| }, | ||
| // this.invoke = require('yeoman-generator/lib/actions/invoke'); |
There was a problem hiding this comment.
Can this comment be removed?
There was a problem hiding this comment.
yep good catch, removed.
7fcd77c to
34d58cc
Compare
34d58cc to
21e6135
Compare
Review
Appreciate all your patient on reviewing the huge code change :)
Most of test cases pass except 4-5 to investigate(skipped at this moment), since the code change is huge I put the PR in review and am fixing the skipped ones at the same time.Description
Here is a list of items to do/finished:
aclgenerator to extend the latest yeoman generator classaclgenerator to useyeoman-testloopback-clito create theenvfromyeoman-environment, see PR feat: switch to yeoman-env loopback-cli#71helpoptionRelated issues
connect to #355
Checklist
guide