-
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
Decouple application config from features (e.g. components) #975
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As long as we know it's okay to remove those deps, then I'm satisfied.
packages/core/README.md
Outdated
rest: { | ||
port: 3000, | ||
}, | ||
grpc: { | ||
port: 3001, | ||
}, | ||
}); | ||
app.components([RestComponent, GrpcComponent]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As long as there's a comment here to make it clear (that's why those other lines were commented in that way), I'm cool with this.
@@ -21,9 +21,7 @@ | |||
"copyright.owner": "IBM Corp.", | |||
"license": "MIT", | |||
"dependencies": { | |||
"@loopback/context": "^4.0.0-alpha.31", | |||
"lodash": "^4.17.4", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Was lodash supposed to be here? (I can't remember, but I think it was used somewhere at one point)
- Why is it being removed now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those dependencies weren't being used at all. Not really a part of the task, but I dropped them anyway
@@ -37,30 +37,13 @@ describe('RestApplication', () => { | |||
); | |||
}); | |||
|
|||
it('when attempting to bind servers via configuration', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should re-write this test in another way or remove the code that deals with it if it no longer applicable. I'm thinking we create an application instance and call app.server
after registering the rest component with app.component
to get the no multiple servers allowed
error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think your proposed test case is covered by the one below if you're concerned about making sure it errors out when RestComponent
is registered with RestApplication
. If you're concerned about throwing ERR_NO_MULTI_SERVER
when another server is registered, that case is covered by the test above. Or I could be misunderstanding what test you want to replace this one with.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep the coverage I want is already there :-).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. IMO the UX for our users would be easier with these changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job but in terms of UX I had a comment earlier in boot
PR from @bajtos IIRC (I'm unable to find a reference -- it might've been on the first PR I closed) ... but in essence we shouldn't be introducing methods where the distinguisher is an s
at the end of a similar function name.
It is possible for us to overload methods which keeping type-safety. You can find an example here: https://github.com/strongloop/loopback-next/blob/e6490389decf21e40558ffb131cc5c3de5b1622a/packages/core/src/application.ts#L70-L97
I think we should make the APIs (methods) consistent ... whether that's me adding a booters
or these functions dropping the s
.
Thoughts @strongloop/sq-lb-apex @bajtos @raymondfeng ?
Either way is fine with me. Originally, I planned on overloading the methods, but I discovered that there were already I'm for the overloading if I was forced to choose. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 on @virkt25's comment about avoiding method names differing by the last s
only (controller
vs controllers
).
I don't have a strong opinion whether it's better to have an overloaded controller
method accepting both a single controller and an array of controllers, or to rename controllers
to something more distinctive from singular controller()
method.
@@ -147,3 +137,5 @@ class FakeServer extends Context implements Server { | |||
this.running = false; | |||
} | |||
} | |||
|
|||
class FakerServer extends FakeServer {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FakeServer
and FakerServer
are difficult to distinguish. Can you rename this class to AnotherServer
please?
@shimks the rest of the proposed changes look great! 👍 |
2884dda
to
4dca2d1
Compare
My ideal signature will be something like: // Public signatures
controller(ctor: ControllerClass, name?: string): Binding;
controller(...ctors: ControllerClass[]): Bindings[];
// Implementation
controller(
ctor: ControllerClass, // First ctor
nameOrCtor?: string | ControllerClass, // Name or 2nd ctor
...moreCtors: ControllerClass[] // Other ctors
) {
const ctors: ControllerClass[] = [];
let name: string | undefined = undefined;
if (ctor) ctors.push(ctor);
if (nameOrCtor && typeof nameOrCtor !== 'string') {
ctors.push(nameOrCtor, ...moreCtors);
} else if (typeof nameOrCtor === 'string') {
name = nameOrCtor;
}
for (const c of ctors) {
// ...
} This way, we can call:
I admit the implementation is a bit tricky. Just an idea for consideration. |
I'd be ok with that kind of change as long as everybody else is. @strongloop/sq-lb-apex What do you think? |
Hmm ... so a few suggestions. Trying to think of this from a UX perspective ... As a user if I wanted to pass in multiple Controllers, passing it into a @raymondfeng I like your proposal to just pass in a list of Constructors instead of an Array since it's a much better UX, much cleaner than an array! +1 for that. I think to make it a little more cleaner, would it be better for us to completely get rid of the optional
|
I'm okay with either approaches. I see that as a user, if I try to register a bunch of controllers, using |
I vote for the singular form |
I think I'm ok with having both |
Usually, method names start with a verb (e.g. In this particular case, I am running out of ideas to be honest. I like the idea of using variable number of arguments instead of passing in an array. With ES2015+, one can use spread operator to easily convert between these two forms: const controllersList = [ProductController, CategoryController];
app.registerManyControllers(...controllersList);
// the line above is equivalent to the line below
app.registerManyControllers(ProductController, CategoryController); |
I am voting for this option too. // must have
app.controller(ProductController);
app.controller(MyProductController, 'ProductController');
// should have (?)
app.controller(ProductController, CategoryController); On the second thought, I am not convinced that it's necessary to a single method to register multiple controllers. Does anybody remember why this requirement was created? @raymondfeng @virkt25 @kjdelisle I am personally fine with a fluent API instead: app
.controller(ProductController)
.controller(CategoryController); If we want to allow the user to customize the binding instance created for the controller, then the following form is ok with me too: app.controller(ProductController);
app.controller(CategoryController); Most applications will be using convention-based It seems to me that this PR could benefit from splitting into two parts:
|
4dca2d1
to
0ab3d26
Compare
I've pulled backed the last two commits so that the decoupling of app config portion of the PR can be safely landed. The commits still include accepting arrays through |
Yes please, I would prefer it this way. But if everybody else thinks plural methods are ok, then I suppose I can live with them temporarily, until a better solution is found. I am afraid I was faster to land #968 than you finishing this pull request, please rebase your PR on top of the latest master and fix merge conflicts. I hope they won't be too difficult to resolve. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would be much much happier if we could leave app.controllers
and app.components
out of this pull request.
0ab3d26
to
cecf9ff
Compare
This requirement came about from something I might've said because when the issue was originally created, we hadn't figured out Now that said, since |
@slnode test please |
ef31f64
to
cecf9ff
Compare
8ed694a
to
cecf9ff
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is awesome now ✌️
I especially like the diff stats: 106 new lines, 247 lines removed.
If we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent".
-- E. W. Dijkstra
@@ -35,10 +35,10 @@ import { | |||
class LogApp extends LogLevelMixin(RestApplication) { | |||
constructor() { | |||
super({ | |||
components: [LogComponent], | |||
logLevel: LOG_LEVEL.ERROR, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logLevel
configuration may need update as part of #952 or after it's landed. I am not sure, I'd just like to bring this to our attention - I guess mostly yours, @raymondfeng .
cecf9ff
to
e22a717
Compare
e22a717
to
8d33bec
Compare
ApplicationConfig
so that it can no longer be used to set upcomponents
,controllers
, or serversapp.component(MyComponent)
.controller()
and.server()
Added in functionsOverloaded existing functions to take in multiple components/controllers/serverscomponent([My, List, Of, Components])
server([My, List, Of, Servers])
controller([My, List, Of, Controllers)
RepositoryMixin
so that repositories can no longer be set up through the constructorrepository
to also be able to take in an array ofRepository
iescomponent
to also be able to take in an array ofcomponent
sChecklist
npm test
passes on your machinepackages/cli
were updatedpackages/example-*
were updated