-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
[SPIKE] Create @loopback/boot to support declarative JSON/YAML files #441
Comments
Cross-posting from #533:
|
Some suggestion from LoopBack3 user: the swagger module can also load dynamically created model, e.g. created in boot scripts. |
Yes, I think that dynamic discovery of the models on boot time is quite important. We also had an internal discussion at the company that I work and dynamic updates on database model would be a plus. How we can get involved in development. Is there any documentation that specifies the formal process of creating a pull request to the next version (v4) |
@twboc , thanks for your interest to create pull request to LB4! Here is our wiki page: https://github.com/strongloop/loopback-next/wiki/Contributing. |
Rejecting due to incomplete criteria! Questions:
|
@raymondfeng ^^ |
We can use LoopBack v3 as the baseline for declarative support. Artifacts include but not limit to:
The json/yaml files will be placed under corresponding folders corresponding to the artifact type. For example:
We should find out one file per artifact instance vs one file per artifact type (with keys for each artifact).
We should start with
Throw errors and abort.
If the validation can be expressed in JSON, such as a LB
Booters for different artifact types should follow similar conventions. |
This is a spike that we should aim for ASAP; let's figure out what we want this to look like and get some code out for review and compare it to our expected UX and architecture. |
Do we have a timebox for this task as well? Or its this issue falsely under 'Planning' at the moment? |
Closing as resolved. |
During the meeting with @raymondfeng and @bajtos , we decided to close this ticket as it's been done. We have @loopback/boot but that's only to boot the typescript classes not the declarative files. I thought we don't have the spec / schema for what the declarative files should look like. Reopening it to continue the discussion if it hasn't been done. |
I watched the recording of your presentation, @virkt25. Great work! I like how well-thought was your proposal, I agree with most of what you proposed at the high-level. I have a dozen of comments and discussion points, see below. 1+1 for preserving TypeScript classes for Models and DataSources, they are an integral part of test-first development process described in http://loopback.io/doc/en/lb4/Implementing-features.html. 2I agree with @raymondfeng that having a DataSource base class is too much and that we should scaffold a single user-editable DataSource class the first time a data source is created (edited). 3In your proposal, the configuration (loaded from JSON) is hard-coded in the generated (base) class. At the same time, we need to support different configurations for different environments (dev/test/production) and load configuration from environment variables (https://12factor.net). It was proposed to parse On a similar topic, @raymondfeng proposed a sort of a registry holding datasource configuration for all environments in the app-level Context. I don't think this is a good solution - consider the case where an application is deployed to different geo location and where each geo location requires different connection strings (to use a colocated database instance). In other words, a My conclusion is that we should decouple datasource configuration from datasource implementation class and leverage dependency injection to provide arbitrary runtime-specific configuration from the application level. IMO, this addressed both needs 1) have different datasource config depending on dev/test/prod environment 2) build datasource configuration dynamically, either from A mock-up app: class MyApp extends RestApplication {
async boot() {
const dbConfig =
// Figure out what config to use. @loopback/boot can provide
// helpers to load config from ENV variables
this.bind('datasources.db$config').to(dbConfig);
// etc.
}
} A mock-up datasource: // default config is used in tests
const defaultConfig = require('./db.datasource.json');
class DbDataSource extends juggler.DataSource {
constructor(
@inject('datasources.db$config')
config: DataSourceOptions = defaultConfig
) {
super(config);
}
} 4-1 for using in-memory datasources in acceptance tests. In my experience, acceptance tests need to run against a real database. Let me quote from our Best Practices, adding emphasis on my own:
Why is it important to run both acceptance and integration tests against a real database:
Having said that, I acknowledge the need to configure datasources differently in dev and production. I just don't think we should leverage this feature for acceptance tests. 5The generated model base class uses TypeScript decorators to describe model properties. I find this solution suboptimal, because it creates two places where model properties are defined. I am concerned that e.g. developers may forget to run Instead, I am proposing to leverage the existing static property My idea is to load model configuration from the JSON file and store it in this const definition: ModelDefinitionSyntax = require('./todo-definition.json');
export class TodoBase extends Entity {
static definition: ModelDefinition = new ModelDefinition(definition);
id?: number;
title: string;
desc?: string;
isComplete?: boolean;
} Please note that under the hood of the decorator-based approach, the Later on, 6Can we provide 7Regarding EJS usage for code generation: isn't this the situation well-known from server-rendered HTML pages? When there is a single piece of code responsible for processing data and building the string output (HTML page or TypeScript source), this code becomes difficult to understand, test and modify. One of the recommended solutions is Model-View-Controller design, where the code responsible for data manipulation (Model/Controller) is decoupled from the code responsible for rendering (View). The rendering code should have as little logic as possible. IMO, we should leverage the same pattern in CLI too:
In my experience from loopback-sdk-angular, EJS is well suited for generating JavaScript/TypeScript code, because the templating syntax does not interfere/conflict with JS/TS syntax. 8Formatting of generated code: it would be great if our tooling was able to pick up prettier version and configuration from the project we are running in and format the generated code accordingly. Imagine a user is using prettier in their project (as scaffolded by It is also important to run 9Regarding missing model base classes: I would personally keep these generated TypeScript files versioned in git. It will make it easier to read source code on GitHub, where auto-generated source files are not available, and also to review code changes made by our codegen tooling. I also like the idea of moving generated files out of sight into a their own directory ( 10What base model/entity classes to offer in
When creating IIRC, LB 3.x CLI offers app-defined models too. 11Where does
Ideally, I'd like to see
12The presentation mentioned few helper commands:
I consider this as a bad idea:
|
@virkt25 Would you consider this spike done? I remember there being follow up issues that can be estimated. |
Yea I would consider this spike done. Leaving this issue open till I have time to transfer @bajtos 's comments to issues tracking the follow-up work. The outcomes is to use CLI to generate a JSON file which can be edited by users / CLI tooling. The CLI will also generate a |
Staging goals:
Story
As a LoopBack developer, I'd like to declare my artifacts as JSON or YAML files so that I can continue enjoying the declarative experience.
Acceptance Criteria
src
for their corresponding artifacts (models, datasources, controllers, etc)Example
Given a src directory:
we'll want to parse the datasource artifact, which contains:
Once we've loaded the file, we'll want to ensure that it has all of the properties required for it to be a datasource (in this case, a "host" property might be required), and then bind it to the context.
Rules
foo.model.json
Questions to Answer
The text was updated successfully, but these errors were encountered: