-
Notifications
You must be signed in to change notification settings - Fork 73
Description
LoopBack provides two kinds of mixins which we need to support in loopback-boot too:
- A regular LoopBack model - mixing process copies all properties and methods to the target model.
- A function - mixing process calls the function after the model has been attached.
Mixin as a model - NOT IMPLEMENTED
loopback-boot already has mechanism for defining arbitrary models, we should reuse this mechanism for defining mixins too. Benefits: developers can apply their knowledge about how to create models to create mixins too. Tools like yo loopback:model and Studio will support mixin definitions OOTB.
// common/models/timestamp-mixin.json
{
"name": "TimeStampMixin",
"properties": {
"timestamp": "Date"
}
}
// common/models/timestamp-mixin.js
module.exports = function(TimeStampMixin) {
// setup auto-update of timestamp on save
}
To support this kind of mixins, we need to extend addAllBaseModels() and sortByInheritance() to take into account mixed-in models in addition to base models. Once that is done, model-like mixins will work both on the server and in the browserified client.
Note that this is can be implemented independently (and should be).
Mixin as a function
This is the part where we need to come up with a new convention.
Ultimately, I'd like to see a solution similar to what we have for models, where the compiler understands relations between model definitions and mixin definitions, and can build optimised instructions to load only those mixins that are actually used in the app.
Another thing to consider is the new component architecture as outlined here.
I am trying to come up with a small solution that can be incrementally extended in next PRs.
How about this:
compilertakes two new options:mixinScriptsthat contains a list of source files to load,normalizeNamesthat defines the algorithm for converting file names into mixin/model names.- mixin names are built from file names by the compiler, using
normalizeNames executoris extended to define mixins per instructions from the compiler
Usage:
boot(app, {
appRootDir: __dirname,
mixins: [ './mixins/timestamp.js' ]
});The next step is to implement clever auto-loading of mixins from directories, as described earlier. That way the usage would become
// explicit
boot(app, {
appRootDir: __dirname,
mixinSources: [ './mixins' ]
});
// relying on the default mixinSources value
boot(app, __dirname)
To summarise the next steps as I see them now:
- Support mixins defined as models
- Support mixins defined as functions via
mixinsoption - Support mixins defined as functions via
mixinSourcesoption
Random notes:
- It seems to me that the
setupis not handled correctly by the current mixing architecture. Imagine aTimeStampMixinas outlined above that adds asetupmethod to configure hooks to update the timestamp. Suchsetupmethod would override anysetupmethod provided by the target class. This is most likely a problem of Model hooks in general as the same applies tobeforeSave. - How can a Model that is being mixed in access the mixin options provided by the app? It seems to me these options are discarded when the mixin is a Model instead of a function.
This issue is a follow-up for the unfinished pull request #33, the discussion there contains useful bits of information too.