Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Model Discovery #2245

Merged
merged 1 commit into from
Apr 10, 2019
Merged

Model Discovery #2245

merged 1 commit into from
Apr 10, 2019

Conversation

marvinirwin
Copy link
Contributor

@marvinirwin marvinirwin commented Jan 13, 2019

Adds the command lb4 discover command and its documentation.

The command has a schemaDefs option (the path to a file which contains a schema definition, or array of lb3 schema definitions) which overrides everything and simply creates the corresponding typescript file. It's used for the integration test, and could also solve #2224

It's a piece of #2090
Implements #1921

Checklist

  • npm test passes on your machine
  • New tests added or existing tests modified to cover all changes
  • Code conforms with the style guide
  • API Documentation in code was updated
  • Documentation in /docs/site was updated
  • Affected artifact templates in packages/cli were updated
  • Affected example projects in examples/* were updated

Copy link
Member

@bajtos bajtos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @marvinirwin for the pull request!

I am not very familiar with this part of our codebase, I'd like @raymondfeng and @jannyHou to review the changes.

@marioestradarosa IIRC, you were interested in generating LB4 models from database schema too, what is your opinion on the implementation proposed in this pull request?

packages/cli/lib/model-discoverer.js Outdated Show resolved Hide resolved
docs/site/Discovering-models-from-relational-databases.md Outdated Show resolved Hide resolved
packages/cli/generators/model/templates/model.ts.ejs Outdated Show resolved Hide resolved
packages/cli/test/fixtures/discover/index.js Outdated Show resolved Hide resolved
packages/cli/test/fixtures/discover/index.js Outdated Show resolved Hide resolved
packages/cli/test/fixtures/discover/index.js Outdated Show resolved Hide resolved
@raymondfeng
Copy link
Contributor

@marvinirwin Great effort! Please see my comments.

@marvinirwin
Copy link
Contributor Author

@raymondfeng @bajtos Is there anything else I can do to help this get merged? I think I've addressed all the reviewers' concerns.

Copy link
Member

@dhmlau dhmlau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marvinirwin, I've added some comments mostly on the docs.
I'm thinking:

It can be in a follow-up PR.

docs/site/Discovering-models-from-relational-databases.md Outdated Show resolved Hide resolved
docs/site/Discovering-models-from-relational-databases.md Outdated Show resolved Hide resolved
docs/site/Discovering-models-from-relational-databases.md Outdated Show resolved Hide resolved
packages/cli/generators/discover/index.js Outdated Show resolved Hide resolved
@marvinirwin
Copy link
Contributor Author

@raymondfeng @dhmlau @bajtos Got anything else?

@dhmlau
Copy link
Member

dhmlau commented Feb 5, 2019

@marvinirwin, thanks for updating the PR. I've added one minor comment.
It looks good to me in terms of the documentation. We need to get the technical reviews from @bajtos @raymondfeng and team. Thanks!

@dhmlau dhmlau mentioned this pull request Feb 7, 2019
1 task
@bajtos
Copy link
Member

bajtos commented Feb 8, 2019

Merge branch 'master' into pr-model-discovery

We don't merge branches and use rebase instead. That way the git history remains neatly linear. Could you please run git rebase master in your feature branch? See How to rebase your branch.

Copy link
Member

@bajtos bajtos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great patch, @marvinirwin! Please see my comments below for things to improve.

@jannyHou @raymondfeng PTAL too

docs/site/Discovering-models-from-relational-databases.md Outdated Show resolved Hide resolved
`--schema`: Specify the schema which the datasource will find the models to
discover

`--schemaDefs`: The path to a `.json` file containing a model definition, like
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we find a better name for this option, what that will convey the fact that we are loading models from JSON files instead of the database?

Few ideas to consider:

  • --import
  • --import-definition
  • --from-definition
  • --from-file
  • --from-lb3-models

Also please make mention that the JSON file can contain either a single model definition object or an array with multiple definitions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the second thought, I am not sure if it's a good idea to mix lb4 discover with importing models from JSON definitions. I find it little bit confusing as a user, plus it makes the implementation more complex because of all those if (importing from file) return statements at the top of many generator steps.

Have you considered moving this functionality into lb4 model generator? I think it will give us CLI that feels pretty natural too.

lb4 model --import definition.json
# or perhaps
lb4 model --from-definition definition.json

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it's dramatically more intuitive, I'll move it to the model generator.

Slightly related: The .json loading was used to give me a way of testing the model discovery, which I still have a bit of trouble doing thoroughly. A couple of solutions:

The memory datasource could be given discoverModelDefinitions and discoverSchema, but that might be out of the scope of this PR.

Docker could also be used in the unit tests, but that definitely out of scope of this PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bajtos After looking around the code a bit I'm proposing keeping the --schemaDefs option. And that I submit a seperate PR for adding the --import option to the model generator.

The current discover --schemaDefs path accepts an array of objects, which mimics how the discover command discovers multiple models. I also need a way to mock data for the integration test.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's discuss testing and user experience independently.

For testing, I think you should mock discoverModelDefinitions and/or discoverSchema in such way that your tests sees the model schema you are interested in. I'll try to find time to create a code snippet showing how to mock those two methods.

For user experience, I still prefer importing via lb4 model over --schemaDefs. I am fine with leaving this option out of this initial pull request, as long as --schemaDefs is removed too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am thinking about the following solution for testing:

  • Modify the datasource class used by your tests (mem.datasource.js.txt) to override discovery methods provided by juggler.DataSource.
  • In these overridden methods, load schema from test-schema-defs.json and return the relevant parts depending on which discovery method was called.

A mock-up to illustrate what I mean:

export class MemDataSource extends juggler.DataSource {
  async discoverSchema(name, options) {
    await ensureSchemaDefsLoaded();
    const schema = this.schemas.find(s => s.name === name);
    if (schema) return schema;
    throw new Error(`Schema not found: ${name}`);
  }

  private schemas;
  private async ensureSchemaDefsLoaded() {
    if (schemas) return;
    const schemaFile = path.resolve(__dirname, 'test-schema-defs.json');
    _schemas = JSON.parse(await fs.readFile(schemaFile, 'utf-8'));
  }
}    

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty embarrassed I didn't think of implementing my own DataSource. The testing is now much easier.

https://github.com/strongloop/loopback-next/blob/5445c58c09760df39f5d010a136979f36c57b217/packages/cli/test/fixtures/discover/mem.datasource.js.txt

docs/site/Model.md Outdated Show resolved Hide resolved
docs/site/Discovering-models-from-relational-databases.md Outdated Show resolved Hide resolved
packages/cli/generators/discover/index.js Show resolved Hide resolved
packages/cli/lib/model-discoverer.js Outdated Show resolved Hide resolved
{
"name": "@loopback/cli",
"version": "1.2.2",
"lockfileVersion": 1,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we are intentionally not using package-lock files. Please remove it from the pull request.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still see the package-lock file included in the PR. PTAL again.

@@ -0,0 +1,29 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, keeping versioning JS files is not pretty. It makes me wonder how are tests for other generators (e.g. lb4 repository) dealing with datasource discovery? Could you PTAL and see if there is a way how to use an existing approach? Do we actually need this .js file? Isn't it enough to have datasource .json file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, I'm going to try and do this with the legacy.Datasource constructor and a JSON file. The only downside I can see is that if any config is defined inserver/datasources/datasource.ts it won't be loaded properly

Copy link
Contributor Author

@marvinirwin marvinirwin Feb 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tried this, but if I only use a .json file it will crash because the lb4 command doesn't have the connector. Is it worth it to try and load the connectors found in the discovering node_modules?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please create a new feature branch in your repo where you will commit the code showing what have you tried, so that I can run that version myself and better understand what's going on under the hood? I am afraid I am not able to build a good picture in my head just from our discussion.

Copy link
Contributor Author

@marvinirwin marvinirwin Feb 15, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compare loading from name.datasource.json, to loading name.datasource.js

(requires lb4 project with non-memory datasource in dist, it doesn't have to connect successfully)

git clone https://github.com/marvinirwin/loopback-next --single-branch --branch discovering-from-json  .;
cd packages/cli;
npm run build;
npm link;
cd SOME_LB4_PROJECT;
# new DataSource(JSON.parse(fs.readFileSync(pathToJson).toString()))
# This should tell you to npm install the connector
LOAD_JSON_DATASOURCES=true lb4 discover;
# new require(pathToJavascript);
# This will not tell you to npm install the connector
LOAD_JSON_DATASOURCES= lb4 discover;

packages/cli/test/test-utils.js Outdated Show resolved Hide resolved
packages/cli/test/test-utils.js Outdated Show resolved Hide resolved
@bajtos
Copy link
Member

bajtos commented Feb 12, 2019

@marvinirwin I see that you pushed new commits. Is the patch ready for another review? Most of us are not receiving notifications when a new commit is pushed into a pull request, please post a comment when it's time to review the changes again.

@marvinirwin
Copy link
Contributor Author

@bajtos New fixes

  1. mentioned exclusivity of --schemaDefs
  2. added --import option to the model cli tool
  3. renamed from Discovering-models-from-relational-databases.md to Discovering-models.md
  4. moved Discovering Models below Definition of a model.

@marvinirwin
Copy link
Contributor Author

@bajtos New commit!

  1. Removed --import and --schemaDefs
  2. Testing lb4 discover is now done with a custom DataSource
  3. Submitted fix: model id type is now boolean|number instead of boolean #2406

@marvinirwin
Copy link
Contributor Author

@bajtos I think I understand what you mean about the duplication of logic in loading datasources now.

DEFAULT_DATASOURCE_DIRECTORY will be replaced with utils.distRootDir = 'dist'.
loadDataSourceByName will be replaced with loading via path with [dataSourceToJSONFilename] (https://github.com/strongloop/loopback-next/blob/861256c4e893f6b26e1d2b81d69e614ab5de9e9f/packages/cli/lib/utils.js#L507)

Once these changes are implemented both the Repository and Discovery generator can create their datasource prompts in the exact same way.

I'll begin that PR once this one has been merged.

@bajtos
Copy link
Member

bajtos commented Mar 18, 2019

@marvinirwin

I'll begin that PR once this one has been merged.

Sounds good.

I noticed that our code coverage dropped by 0.4% with your patch in place, which is more than we usually accept.

I reviewed the code coverage data, it looks like you pull request is missing tests for datasource prompt when discovering a single model (see e.g. https://coveralls.io/builds/22183916/source?filename=packages/cli/generators/discover/index.js)) and for the code mapping discovered types to TypeScript snippets (see https://coveralls.io/builds/22183916/source?filename=packages/cli/generators/model/index.js#L457).

How easy or difficult it is to write tests covering these two areas?

@marvinirwin
Copy link
Contributor Author

@bajtos Thanks for reminding me about the discovering single models. I added tests for that and some tests ensuring nicer error messages.

I'm not sure about the loopback->typescript mapping parts. I think I can hit them all in a more exhaustive test, but I think that's out of the scope of this PR.

Copy link
Member

@bajtos bajtos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @marvinirwin for the improvements, the patch LGTM now.

@raymondfeng @jannyHou could you PTAL too?

If there are no objections then I'd like to proceed with landing this great feature early next week.

@@ -0,0 +1,106 @@
const DataSource = require('loopback-datasource-juggler').DataSource;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to avoid direct dependency on loopback-datasource-juggler and import DataSource class constructor from @loopback/repository.

Not a big deal, we can improve this in a follow-up pull request.

packages/cli/test/fixtures/discover/mem.datasource.js.txt Outdated Show resolved Hide resolved
@emonddr emonddr added this to the April 2019 milestone milestone Apr 1, 2019
Copy link
Contributor

@nabdelgadir nabdelgadir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just have a few comments but LGTM otherwise. Can you also add this command to the CLI README?

docs/site/Discovering-models.md Outdated Show resolved Hide resolved
docs/site/Model.md Outdated Show resolved Hide resolved
packages/cli/generators/discover/index.js Outdated Show resolved Hide resolved
@dhmlau dhmlau mentioned this pull request Apr 2, 2019
@bajtos
Copy link
Member

bajtos commented Apr 4, 2019

@marvinirwin could you please address the comments raised by @nabdelgadir above, and also add this new command to the CLI README? I'd like to get them fixed before we land this patch.

@marvinirwin
Copy link
Contributor Author

@bajtos done

@raymondfeng
Copy link
Contributor

add this new command to the CLI README?

You can run packages/cli/bin/cli-main.js discover --help to print out the command help that can be added to README.

@marvinirwin
Copy link
Contributor Author

@raymondfeng

The first line of my output is not correct, but I'm not sure how to change it. (discover does not have a name parameter)

Usage:
  lb4 discover [<name>] [options]

Options:
  -h,    --help           # Print the generator's options and usage
         --skip-cache     # Do not remember prompt answers                                              Default: false
         --skip-install   # Do not automatically install dependencies                                   Default: false
         --force-install  # Fail on install dependencies error                                          Default: false
  -c,    --config         # JSON file name or value to configure options
  -y,    --yes            # Skip all confirmation prompts with default or provided value
         --format         # Format generated code using npm run lint:fix
  -ds,   --dataSource     # The name of the datasource to discover
         --views          # Boolean to discover views                                                   Default: true
         --schema         # Schema to discover
         --all            # Discover all models without prompting users to select                       Default: false
         --outDir         # Specify the directory into which the `model.model.ts` files will be placed

Arguments:
  name  # Name for the discover  Type: String  Required: false

packages/cli/README.md Outdated Show resolved Hide resolved
@bajtos
Copy link
Member

bajtos commented Apr 5, 2019

The first line of my output is not correct, but I'm not sure how to change it. (discover does not have a name parameter)

@raymondfeng could you please help here? I think you now the internal CLI architecture best.

Personally, I can live with incorrect help message for the time being, I see much more value in having the command lb4 discover available to all users.

@marvinirwin
Copy link
Contributor Author

@bajtos Alright I've put the mildly incorrect output from lb4 discover --help in the readme. The Travis is failing right now, though I'm not sure if it's my fault or not

@bajtos
Copy link
Member

bajtos commented Apr 8, 2019

The Travis is failing right now, though I'm not sure if it's my fault or not

See https://travis-ci.org/strongloop/loopback-next/jobs/516258539. Your feature branch seems to contain a bunch of commits that are violating our Commit Message Guidelines.

Could you please try to rebase your feature branch on top of the latest master? See https://loopback.io/doc/en/lb4/submitting_a_pr.html#6-rebasing

We can help you with this last step if you like, just let us know.

@marvinirwin
Copy link
Contributor Author

@bajtos Done, I think

@nabdelgadir
Copy link
Contributor

@marvinirwin one last thing, can you squash your commits into one commit? If you need any help, let us know (see here for reference, if needed).

@dhmlau
Copy link
Member

dhmlau commented Apr 10, 2019

@slnode test please

@b-admike
Copy link
Contributor

@marvinirwin I've rebased your branch and resolved some conflicts, PTAL and if you are satisfied, we can land your patch.

@marvinirwin
Copy link
Contributor Author

@b-admike

LGTM

@b-admike b-admike merged commit 35f719c into loopbackio:master Apr 10, 2019
@Royedc4
Copy link

Royedc4 commented Apr 11, 2019

Awwwwwesome, Finally 🎉
When will this be available in loopback for everyone?

@dhmlau
Copy link
Member

dhmlau commented Apr 11, 2019

There're some changes we want to go in for the same release. Once that's approved, we'll release. Hopefully very soon 🤞

Copy link

@shadyanwar shadyanwar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bajtos Is './dist/datasources' the default datasource directory and not './dist/src/datasources'?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

10 participants