- refactor logic of processing artifacts into their own classes
- introduce Container as the main class for bootstrapping and build a
registry of handlers during boot to organize them by a hierarchy
denoted by path
- adopt middleware like registration and invocation
- container.use(path, handler)
- container.run(context, done)
- allow more phases during boot
- boot is now asynchronous
When loading middleware configured in "middleware.json", loopback-boot
used to require() the full path to middleware's module main file,
for example "node_modules/strong-express-metrics/index.js".
This is breaking strong-agent probes, as it's difficult to detect
when the intercepted module (e.g. "strong-express-metrics") was loaded.
This commit modifies the compiler to omit the tail (the path to the
module main source file) when requiring middleware.
Extend the options argument of boot/compile to allow the developer
to supply custom model definitions (to replace the result of
findModelDefinitions). Together with the existing options.models,
it allows to specify all model-related data and still use the benefits
which loopback-boot provides (most notably loading models in order
defined by inheritance, i.e. base models are loaded before models that
are extending them).
Load configuration of components from `component-config`
and configure all components as specified.
Sample JSON:
{
"loopback-component-foobar": {
"option1": "value1",
"option2": "value2"
}
}
The component is expected to export the following function:
module.exports = function(app, options) { /* ... */ };
Remove duplicated entries in the array of boot scripts to run.
Because the bootDirs defaults to process.cwd(), if the user manually
includes scripts in the same directory, without specifying a bootDir,
those scripts will be included multiple times.
Introduce a convention for specifying relative paths in middleware
params: values prefixed with `$!` and starting with `./` or `../`
are resolved relatively to `middleware.json`.
Example:
{
"files": {
"loopback#static": {
"params": "$!../client"
},
"loopback#static": {
"params": "$!./public"
}
}
}
When the middleware name (path) is in the format {module}#{filename},
loopback-boot resolves the path by trying multiple locations and
using the first one that exists:
- {module} and check the {filename} property of the exports
-> e.g. loopback.rest
- {module}/server/middleware/{filename}
-> e.g. loopback/server/middleware/rest
- {module}/middleware/{filename}
-> e.g. loopback/middleware/rest
Values in any other format will bypass this resolution algorithm and
they will be used in the original form:
- a full path in a module: loopback/server/middleware/rest
- a relative path: ./middleware/custom, ./custom, ../logger
- an absolute path: /usr/local/lib/node_modules/compression
Sample JSON:
{
"routes:before": {
"morgan": {
"params": ["dev"]
}
},
"routes": {
"loopback/server/middleware/rest": {
}
},
"subapps": {
"./adminer": {
},
}
}
The JSON file can be customized using the usual conventions:
- middleware.local.{js|json}
- middleware.{env}.{js|json}
It is also possible to mount the same middleware in the same phase
multiple times with different configuration.
Example config:
{
"auth": {
"oauth2": [
{
"params": "first"
},
{
"params": "second"
}
]
},
});
Load models for any filetypes registered in require.extensions.
- Server side coffee-script requires a `require('coffee-script/register');`
- Client side coffee-script requires Coffeeify.
Interpret model sources in the same way how `require.resolve`
interprets the path:
- values starting with `./` and `../` are relative to the file
where they are specified
- other values are relative to node modules folders
This way it's possible to specify a source `loopback/common/models`
and have it resolved to whatever place the loopback is installed.
When executor passes the instruction to loopback methods,
loopback modifies the data. Since we are loading the data using
`require` such changes affects also code that calls
`require` for one of the instructions files.
This change adds a deep clone step to prevent this issue.
The new loopback project layout adds a concept of components like
'rest server' and 'isomorphic client', each component having its own set
of boot files. The name `app.json` is confusing, since it is configuring
a component, not the app (which is the whole project).
Rework the way how models are configured, the goal is to allow
loopback-boot to automatically determine the correct order
of the model definitions to ensure base models are defined
before they are extended.
1. The model .js file no longer creates the model, it exports
a config function instead:
```js
module.exports = function(Car, Base) {
// Car is the model constructor
// Base is the parent model (e.g. loopback.PersistedModel)
Car.prototype.honk = function(duration, cb) {
// make some noise for `duration` seconds
cb();
};
};
```
2. The model is created by loopback-boot from model .json file.
The .js file must have the same base file name.
3. The `boot()` function has a new parameter `modelSources` to
specify the list of directories where to look for model definitions.
The parameter defaults to `['./models']`.
As a side effect, only models configured in `models.json` and their
base clases are defined. This should keep the size of the browserified
bundle small, because unused models are not included.
Breaking change.
In the new 2.x project layout, definition of loopback Models is out of
scope of the boot process. The bootstrapper only configures existing
models - attaches them to a dataSource and the app object.
Split bootLoopBackApp into two steps:
- compile
- execute
Most of the changes are just shuffling the existing code around.
What has changed:
- `loopback.autoAttach()` is called after `models/*` are required.
The calls were made in the opposite order before this commit.