LoopBack Boot is a convention-based bootstrapper for LoopBack applications.
For full documentation, see the official StrongLoop documentation:
npm install loopback-boot
var loopback = require('loopback');
var boot = require('loopback-boot');
var app = loopback();
boot(app, __dirname);
app.use(loopback.rest());
app.listen();
See API docs for complete API reference.
The version range 1.x
is backwards compatible with app.boot
provided
by LoopBack 1.x versions and the project layout scaffolded by slc lb project
up to slc version 2.5.
The version range 2.x
supports the new project layout as scaffolded by
yo loopback
.
This document describes the configuration conventions of the 2.x
versions.
See Migrating from 1.x to 2.x
for step-by-step instructions on how to upgrade existing projects.
The bootstrapping process takes care of the following tasks:
host
, port
or restApiRoot
.Below is the typical project layout. See the following sections for description of the project files.
project/
app.js
config.json
datasources.json
models.json
models/
boot/
The settings are loaded from the file config.json
in the project root directory
and can be accessed via app.get('option-name')
from the code.
Additionally, the following files can provide values to override config.json
:
config.local.js
or config.local.json
config.{env}.js
or config.{env}.json
, where {env}
is the value of NODE_ENV
(typically development
or production
)NOTE: The additional files can override the top-level keys with value-types (strings, numbers) only. Nested objects and arrays are not supported at the moment.
config.json
{
"host": "localhost",
"port": 3000,
"restApiRoot": "/api"
}
config.production.js
module.exports = {
host: process.env.CUSTOM_HOST,
port: process.env.CUSTOM_PORT
};
The configuration of data sources is loaded from the file datasources.json
in the project root directory, the data sources can be accessed via
app.datasources['datasource-name']
from the code.
Additionally, the following files can provide values to override
datasources.json
:
datasources.local.js
or datasources.local.json
datasources.{env}.js
or datasources.{env}.json
,
where {env}
is the value of NODE_ENV
(typically development
or production
)NOTE: The additional files can override the top-level data-source options with value-types (strings, numbers) only. Nested objects and arrays are not supported at the moment.
datasources.json
{
// the key is the datasource name
// the value is the config object to pass to
// app.dataSource(name, config).
db: {
connector: 'memory'
}
}
datasources.production.json
{
db: {
connector: 'mongodb',
database: 'myapp',
user: 'myapp',
password: 'secret'
}
}
Custom models are defined using JSON files in models/
directory,
one JSON file per model.
The following are example JSON files for two Model
definitions:
Dealership
and Location
.
models/dealership.json
{
// the model name
"name": "Dealership",
// the options passed to Model.extend(name, properties, options)
"options": {
"relations": {
"cars": {
"type": "hasMany",
"model": "Car",
"foreignKey": "dealerId"
}
}
},
// the properties passed to Model.extend(name, properties, options)
"properties": {
"id": {"id": true},
"name": "String",
"zip": "Number",
"address": "String"
}
}
models/car.json
{
"name": "Car",
// options can be specified at the top level too
"relations": {
"dealer": {
"type": "belongsTo",
"model": "Dealership",
"foreignKey": "dealerId"
},
}
"properties": {
"id": {
"type": "String",
"required": true,
"id": true
},
"make": {
"type": "String",
"required": true
},
"model": {
"type": "String",
"required": true
}
}
}
The models created from JSON files come with the set of built-in methods
like find
and create
. To implement your custom methods, you should
create a javascript file in models/
directory with the same base-name
as the JSON file containing model definition (e.g. models/car.js
for
models/car.json
) and define the methods there.
Example:
models/car.js
// Car is the model constructor
// Base is the parent model (e.g. loopback.PersistedModel)
module.exports = function(Car, Base) {
// Define a static method
Car.customMethod = function(cb) {
// do some work
cb();
};
// Define an instance (prototype) method
Car.prototype.honk = function(duration, cb) {
// make some noise for `duration` seconds
cb();
};
// Provide a custom setup method
Car.setup = function() {
Base.setup.call(this);
// configure validations,
// configure remoting for methods, etc.
};
};
Before the models can be used in a loopback application, they have to be configured - attached to a data-source, exposed via the REST API, and so on.
The configuration is described in the file models.json
:
{
// the key is the model name
"Dealership": {
// a reference, by name, to a dataSource definition
"dataSource": "my-db"
},
"Car": {
"dataSource": "my-db",
// do not expose Car over the REST API
"public": false
}
}
The bootstrapper will automatically load definition of every custom model
configured in models.json
. By default, the definition files are loaded from
models/
subdirectory. However, it is possible to specify a different location
(or even multiple locations) via _meta.sources
:
{
"_meta": {
"sources": [
// all paths are relative to models.json
"./models"
"./node_modules/foobar/models"
]
},
// use the `FooBar` model from the `foobar` module
"FooBar": {
"dataSource": "db"
}
}
When the data sources and models are configured, the bootstrapper invokes
all scripts in the boot/
folder. The scripts are sorted lexicographically
ingoring case.
boot/authentication.js
module.exports = function(app) {
app.enableAuth();
};
The bootstrap process is implemented in two steps that can be called independently.
The first step loads all configuration files, merges values from additional
config files like app.local.js
and produces a set of instructions
that can be used to boot the application.
These instructions must be included in the browser bundle together
with all configuration scripts from models/
and boot/
.
Don't worry, you don't have to understand these details.
Just call boot.compileToBrowserify
, it will take care of everything for you.
build file (Gruntfile.js, gulpfile.js)
var browserify = require('browserify');
var boot = require('loopback-boot');
var b = browserify({
basedir: appDir,
});
// add the main application file
b.require('./browser-app.js', { expose: 'loopback-app' });
// add boot instructions
boot.compileToBrowserify(appDir, b);
// create the bundle
var out = fs.createWriteStream('browser-bundle.js');
b.bundle().pipe(out);
// handle out.on('error') and out.on('close')
In the browser, the main application file should call loopback-boot to setup the loopback application by executing the instructions contained in the browser bundle:
browser-app.js
var loopback = require('loopback');
var boot = require('loopback-boot');
var app = module.exports = loopback();
boot(app);
The app object created above can be accessed via require('loopback-app')
,
where loopback-app
is the identifier used for the main app file in
the browserify build shown above.
Here is a simple example demonstrating the concept:
index.html
<script src="app.bundle.js"></script>
<script>
var app = require('loopback-app');
var User = app.models.User;
User.login(
{ email: 'test@example.com', password: '12345' },
function(err, res) {
if (err) {
console.error('Login failed: ', err);
} else {
console.log('Logged in.');
}
}
);
</script>
Initialize an application from an options object or a set of JSON and JavaScript files.
NOTE: This module is primarily intended for use with LoopBack 2.0. It does work with LoopBack 1.x applications, but none of the LoopBack 1.x examples or generated code (scaffolding) use it.
This function takes an optional argument that is either a string or an object.
If the argument is a string, then it sets the application root directory based on the string value. Then it:
Creates DataSources from the datasources.json
file in the application
root directory.
Configures Models from the models.json
file in the application
root directory.
If the argument is an object, then it looks for models
, dataSources
,
and appRootDir
properties of the object.
If the object has no appRootDir
property then it sets the current working
directory as the application root directory.
Then it:
Creates DataSources from the options.dataSources
object.
Configures Models from the options.models
object.
In both cases, the function loads JavaScript files in the
/boot
subdirectory of the application root directory with require()
.
NOTE: The version 2.0 of loopback-boot changed the way how models
are created. The models.json
file contains only configuration options like
dataSource and extra relations. To define a model, create a per-model
JSON file in models/
directory.
NOTE: Mixing bootLoopBackApp(app, bootConfig)
and
app.model(name, modelConfig)
in multiple
files may result in models being undefined due to race conditions.
To avoid this when using bootLoopBackApp()
make sure all models are passed
as part of the models
definition.
Throws an error if the config object is not valid or if boot fails.
Name | Type | Description |
---|---|---|
app |
|
LoopBack application created by |
options |
String or Object
|
Boot options; If String, this is the application root directory; if object, has below properties. |
Name | Type | Description |
---|---|---|
[appRootDir] |
String
|
Directory to use when loading JSON and JavaScript files.
Defaults to the current directory ( |
[models] |
Object
|
Object containing |
[dataSources] |
Object
|
Object containing |
[modelsRootDir] |
String
|
Directory to use when loading |
[dsRootDir] |
String
|
Directory to use when loading |
[env] |
String
|
Environment type, defaults to |
[modelSources] |
Array.<String>
|
List of directories where to look for files containing model definitions. |
Compile boot instructions and add them to a browserify bundler.
Name | Type | Description |
---|---|---|
options |
Object or String
|
as described in |
bundler |
Object
|
A browserify bundler created by |
The browser version of bootLoopBackApp
.
When loopback-boot is loaded in browser, the module exports this
function instead of bootLoopBackApp
.
The function expects the boot instructions to be included in
the browser bundle, see boot.compileToBrowserify
.
Name | Type | Description |
---|---|---|
app |
Object
|
The loopback app to boot, as returned by |
Starting point: a sample 1.x project
models.json
{
"car": {
"properties": {
"color": "string",
},
"dataSource": "db"
}
}
models/car.js
var app = require('../app');
var Car = app.models.Car;
Car.prototype.honk = function(duration, cb) {
// make some noise for `duration` seconds
cb();
};
app.js
var loopback = require('loopback');
var boot = require('loopback-boot');
var app = loopback();
boot(app, __dirname);
The files with applications settings were renamed from app.*
to config.*
.
Rename the following files to upgrade a 1.x project for loopback-boot 2.x:
app.json
to config.json
app.local.json
to config.local.json
app.local.js
to config.local.js
The configuration of data sources remains the same in both 1.x and 2.x versions.
The 2.x version of loopback-boot no longer creates Models, it's up to the developer to create them before booting the app.
The folder models/
has a different semantincs in 2.x than in 1.x. Instead
of extending Models already defined by app.boot
and models.json
,
it provides a set of Model definitions that do not depend on
any application that may use them.
Perform the following steps to update a 1.x project for loopback-boot 2.x. All code samples are referring to the sample project described above.
Move all Model-definition metadata from models.json
to new per-model json files in models/
directory.
models/car.json
{
"name": "car",
"properties": {
"color": "string",
}
}
models.json
{
"car": {
"dataSource": "db"
}
}
Change per-model javascript files to export a function that adds custom methods to the model class.
models/car.js
module.exports = function(Car, Base) {
Car.prototype.honk = function(duration, cb) {
// make some noise for `duration` seconds
cb();
};
};
If your model definitions are not in ./models
, then add an entry
to models.json
to specify the paths where to look for model definitions.
models.json
{
"_meta": {
"sources": ["./custom/path/to/models"]
},
"Car": {
"dataSource": "db"
}
}
Models provided by LoopBack, such as User
or Role
, are no longer
automatically attached to default data-sources. The data-source configuration
entry defaultForType
is silently ignored.
You have to explicitly configure all built-in models used by your application
in the models.json
file.
{
"Role": { "dataSource": "db" }
}