|
|
|
@ -1,9 +1,10 @@
|
|
|
|
|
## API
|
|
|
|
|
## Node.js API
|
|
|
|
|
|
|
|
|
|
### App
|
|
|
|
|
|
|
|
|
|
Create a Loopback application.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
var loopback = require('loopback');
|
|
|
|
|
var app = loopback();
|
|
|
|
|
|
|
|
|
@ -12,17 +13,19 @@ Create a Loopback application.
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
app.listen(3000);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Notes:**
|
|
|
|
|
|
|
|
|
|
- extends [express](http://expressjs.com/api.html#express)
|
|
|
|
|
- see [express docs](http://expressjs.com/api.html) for details
|
|
|
|
|
- supports [express / connect middleware](http://expressjs.com/api.html#middleware)
|
|
|
|
|
> **Notes**
|
|
|
|
|
>
|
|
|
|
|
> - extends [express](http://expressjs.com/api.html#express)
|
|
|
|
|
> - see [express docs](http://expressjs.com/api.html) for details
|
|
|
|
|
> - supports [express / connect middleware](http://expressjs.com/api.html#middleware)
|
|
|
|
|
|
|
|
|
|
#### app.model(Model)
|
|
|
|
|
|
|
|
|
|
Expose a `Model` to remote clients.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
// create a testing data source
|
|
|
|
|
var memory = loopback.memory();
|
|
|
|
|
var Color = memory.createModel('color', {name: String});
|
|
|
|
@ -30,18 +33,21 @@ Expose a `Model` to remote clients.
|
|
|
|
|
|
|
|
|
|
app.model(Color);
|
|
|
|
|
app.use(loopback.rest());
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Note:** this will expose all [shared methods](#shared-methods) on the model.
|
|
|
|
|
> **Note** - this will expose all [shared methods](#shared-methods) on the model.
|
|
|
|
|
|
|
|
|
|
#### app.models()
|
|
|
|
|
|
|
|
|
|
Get the app's exposed models.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
var models = app.models();
|
|
|
|
|
|
|
|
|
|
models.forEach(function (Model) {
|
|
|
|
|
console.log(Model.modelName); // color
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### app.docs(options)
|
|
|
|
|
|
|
|
|
@ -53,8 +59,10 @@ Enable swagger REST api documentation.
|
|
|
|
|
|
|
|
|
|
**Example**
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
// enable docs
|
|
|
|
|
app.docs({basePath: 'http://localhost:3000'});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Run your app then navigate to [the api explorer](http://petstore.swagger.wordnik.com/). Enter your API basepath to view your generated docs.
|
|
|
|
|
|
|
|
|
@ -62,6 +70,7 @@ Run your app then navigate to [the api explorer](http://petstore.swagger.wordnik
|
|
|
|
|
|
|
|
|
|
A Loopback `Model` is a vanilla JavaScript class constructor with an attached set of properties and options. A `Model` instance is created by passing a data object containing properties to the `Model` constructor. A `Model` constructor will clean the object passed to it and only set the values matching the properties you define.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
// valid color
|
|
|
|
|
var Color = loopback.createModel('color', {name: String});
|
|
|
|
|
var red = new Color({name: 'red'});
|
|
|
|
@ -70,6 +79,7 @@ A Loopback `Model` is a vanilla JavaScript class constructor with an attached se
|
|
|
|
|
// invalid color
|
|
|
|
|
var foo = new Color({bar: 'bat baz'});
|
|
|
|
|
console.log(foo.bar); // undefined
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Properties**
|
|
|
|
|
|
|
|
|
@ -81,55 +91,71 @@ Some [DataSources](#data-source) may support additional `Model` options.
|
|
|
|
|
|
|
|
|
|
Define A Loopbackmodel.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
var User = loopback.createModel('user', {
|
|
|
|
|
first: String,
|
|
|
|
|
last: String,
|
|
|
|
|
age: Number
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Validation (expiremental)
|
|
|
|
|
#### Validation (expiremental)
|
|
|
|
|
|
|
|
|
|
#### Model.validatesFormatOf(property, options)
|
|
|
|
|
##### Model.validatesFormatOf(property, options)
|
|
|
|
|
|
|
|
|
|
Require a model to include a property that matches the given format.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
User.validatesFormat('name', {with: /\w+/});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Model.validatesPresenceOf(properties...)
|
|
|
|
|
##### Model.validatesPresenceOf(properties...)
|
|
|
|
|
|
|
|
|
|
Require a model to include a property to be considered valid.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
User.validatesPresenceOf('first', 'last', 'age');
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Model.validatesLengthOf(property, options)
|
|
|
|
|
##### Model.validatesLengthOf(property, options)
|
|
|
|
|
|
|
|
|
|
Require a property length to be within a specified range.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
User.validatesLengthOf('password', {min: 5, message: {min: 'Password is too short'}});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Model.validatesInclusionOf(property, options)
|
|
|
|
|
##### Model.validatesInclusionOf(property, options)
|
|
|
|
|
|
|
|
|
|
Require a value for `property` to be in the specified array.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
User.validatesInclusionOf('gender', {in: ['male', 'female']});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Model.validatesExclusionOf(property, options)
|
|
|
|
|
##### Model.validatesExclusionOf(property, options)
|
|
|
|
|
|
|
|
|
|
Require a value for `property` to not exist in the specified array.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
User.validatesExclusionOf('domain', {in: ['www', 'billing', 'admin']});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Model.validatesNumericalityOf(property, options)
|
|
|
|
|
##### Model.validatesNumericalityOf(property, options)
|
|
|
|
|
|
|
|
|
|
Require a value for `property` to be a specific type of `Number`.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
User.validatesNumericalityOf('age', {int: true});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Model.validatesUniquenessOf(property, options)
|
|
|
|
|
##### Model.validatesUniquenessOf(property, options)
|
|
|
|
|
|
|
|
|
|
Ensure the value for `property` is unique in the collection of models.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
User.validatesUniquenessOf('email', {message: 'email is not unique'});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Note:** not available for all [connectors](#connectors).
|
|
|
|
|
|
|
|
|
@ -139,15 +165,22 @@ Currently supported in these connectors:
|
|
|
|
|
- [Oracle](http://github.com/strongloop/loopback-connector-oracle)
|
|
|
|
|
- [MongoDB](http://github.com/strongloop/loopback-connector-mongodb)
|
|
|
|
|
|
|
|
|
|
#### myModel.isValid()
|
|
|
|
|
##### myModel.isValid()
|
|
|
|
|
|
|
|
|
|
Validate the model instance.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
user.isValid(function (valid) {
|
|
|
|
|
if (!valid) {
|
|
|
|
|
user.errors // hash of errors {attr: [errmessage, errmessage, ...], attr: ...}
|
|
|
|
|
console.log(user.errors);
|
|
|
|
|
// => hash of errors
|
|
|
|
|
// => {
|
|
|
|
|
// => username: [errmessage, errmessage, ...],
|
|
|
|
|
// => email: ...
|
|
|
|
|
// => }
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Model.properties
|
|
|
|
|
|
|
|
|
@ -155,6 +188,7 @@ An object containing a normalized set of properties supplied to `loopback.create
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
var props = {
|
|
|
|
|
a: String,
|
|
|
|
|
b: {type: 'Number'},
|
|
|
|
@ -166,9 +200,11 @@ Example:
|
|
|
|
|
var MyModel = loopback.createModel('foo', props);
|
|
|
|
|
|
|
|
|
|
console.log(MyModel.properties);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Outputs:
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
{
|
|
|
|
|
"a": {type: String},
|
|
|
|
|
"b": {type: Number},
|
|
|
|
@ -183,11 +219,13 @@ Outputs:
|
|
|
|
|
"id": 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Model.attachTo(dataSource)
|
|
|
|
|
|
|
|
|
|
Attach a model to a [DataSource](#data-source). Attaching a [DataSource](#data-source) updates the model with additional methods and behaviors.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
var oracle = loopback.createDataSource({
|
|
|
|
|
connector: require('loopback-connector-oracle'),
|
|
|
|
|
host: '111.22.333.44',
|
|
|
|
@ -197,6 +235,7 @@ Attach a model to a [DataSource](#data-source). Attaching a [DataSource](#data-s
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
User.attachTo(oracle);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Note:** until a model is attached to a data source it will **not** have any **attached methods**.
|
|
|
|
|
|
|
|
|
@ -206,14 +245,17 @@ Mixins are added by attaching a vanilla model to a [data source](#data-source) w
|
|
|
|
|
|
|
|
|
|
Log the available methods for a memory data source.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
var ops = loopback
|
|
|
|
|
.createDataSource({connector: loopback.Memory})
|
|
|
|
|
.operations();
|
|
|
|
|
|
|
|
|
|
console.log(Object.keys(ops));
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Outputs:
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
[ 'create',
|
|
|
|
|
'updateOrCreate',
|
|
|
|
|
'upsert',
|
|
|
|
@ -238,15 +280,18 @@ Outputs:
|
|
|
|
|
'updateAttribute',
|
|
|
|
|
'updateAttributes',
|
|
|
|
|
'reload' ]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Here is the definition of the `count()` operation.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
{
|
|
|
|
|
accepts: [ { arg: 'where', type: 'object' } ],
|
|
|
|
|
http: { verb: 'get', path: '/count' },
|
|
|
|
|
remoteEnabled: true,
|
|
|
|
|
name: 'count'
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Static Methods
|
|
|
|
|
|
|
|
|
@ -256,9 +301,11 @@ Here is the definition of the `count()` operation.
|
|
|
|
|
|
|
|
|
|
Create an instance of Model with given data and save to the attached data source. Callback is optional.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
User.create({first: 'Joe', last: 'Bob'}, function(err, user) {
|
|
|
|
|
console.log(user instanceof User); // true
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Note:** You must include a callback and use the created model provided in the callback if your code depends on your model being saved or having an `id`.
|
|
|
|
|
|
|
|
|
@ -266,9 +313,11 @@ Create an instance of Model with given data and save to the attached data source
|
|
|
|
|
|
|
|
|
|
Query count of Model instances in data source. Optional query param allows to count filtered set of Model instances.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
User.count({approved: true}, function(err, count) {
|
|
|
|
|
console.log(count); // 2081
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
##### Model.find(filter, callback)
|
|
|
|
|
|
|
|
|
@ -289,6 +338,7 @@ Find all instances of Model, matched by query. Fields used for filter and sort s
|
|
|
|
|
|
|
|
|
|
Find the second page of 10 users over age 21 in descending order exluding the password property.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
User.find({
|
|
|
|
|
where: {
|
|
|
|
|
age: {gt: 21}},
|
|
|
|
@ -299,6 +349,7 @@ Find the second page of 10 users over age 21 in descending order exluding the pa
|
|
|
|
|
},
|
|
|
|
|
console.log
|
|
|
|
|
);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Note:** See the specific connector's [docs](#connectors) for more info.
|
|
|
|
|
|
|
|
|
@ -310,17 +361,21 @@ Delete all Model instances from data source. **Note:** destroyAll method does no
|
|
|
|
|
|
|
|
|
|
Find instance by id.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
User.findById(23, function(err, user) {
|
|
|
|
|
console.info(user.id); // 23
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
##### Model.findOne(where, callback)
|
|
|
|
|
|
|
|
|
|
Find a single instance that matches the given where expression.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
User.findOne({id: 23}, function(err, user) {
|
|
|
|
|
console.info(user.id); // 23
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
##### Model.upsert(data, callback)
|
|
|
|
|
|
|
|
|
@ -330,6 +385,7 @@ Update when record with id=data.id found, insert otherwise. **Note:** no setters
|
|
|
|
|
|
|
|
|
|
Define a static model method.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
User.login = function (username, password, fn) {
|
|
|
|
|
var passwordHash = hashPassword(password);
|
|
|
|
|
this.findOne({username: username}, function (err, user) {
|
|
|
|
@ -348,9 +404,11 @@ Define a static model method.
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Setup the static model method to be exposed to clients as a [remote method](#remote-method).
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
loopback.remoteMethod(
|
|
|
|
|
User.login,
|
|
|
|
|
{
|
|
|
|
@ -362,6 +420,7 @@ Setup the static model method to be exposed to clients as a [remote method](#rem
|
|
|
|
|
http: {path: '/sign-in'}
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Instance Methods
|
|
|
|
|
|
|
|
|
@ -371,6 +430,7 @@ Setup the static model method to be exposed to clients as a [remote method](#rem
|
|
|
|
|
|
|
|
|
|
Save an instance of a Model to the attached data source.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
var joe = new User({first: 'Joe', last: 'Bob'});
|
|
|
|
|
joe.save(function(err, user) {
|
|
|
|
|
if(user.errors) {
|
|
|
|
@ -379,44 +439,54 @@ Save an instance of a Model to the attached data source.
|
|
|
|
|
console.log(user.id);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
##### model.updateAttributes(data, [callback])
|
|
|
|
|
|
|
|
|
|
Save specified attributes to the attached data source.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
user.updateAttributes({
|
|
|
|
|
first: 'updatedFirst',
|
|
|
|
|
name: 'updatedLast'
|
|
|
|
|
}, fn);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
##### model.destroy([callback])
|
|
|
|
|
|
|
|
|
|
Remove a model from the attached data source.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
model.destroy(function(err) {
|
|
|
|
|
// model instance destroyed
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
##### Custom Instance Methods
|
|
|
|
|
|
|
|
|
|
Define an instance method.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
User.prototype.logout = function (fn) {
|
|
|
|
|
MySessionModel.destroyAll({userId: this.id}, fn);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Define a remote model instance method.
|
|
|
|
|
|
|
|
|
|
loopback.remoteMethod(User.prototype.logout);
|
|
|
|
|
```js
|
|
|
|
|
loopback.remoteMethod(User.prototype.logout)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Remote Methods
|
|
|
|
|
|
|
|
|
|
Both instance and static methods can be exposed to clients. A remote method must accept a callback with the conventional `fn(err, result, ...)` signature.
|
|
|
|
|
|
|
|
|
|
##### loopback.remoteMethod(fn, [options]);
|
|
|
|
|
##### loopback.remoteMethod(fn, [options])
|
|
|
|
|
|
|
|
|
|
Expose a remote method.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
Product.stats = function(fn) {
|
|
|
|
|
var calc = require('./stats');
|
|
|
|
|
|
|
|
|
@ -433,10 +503,11 @@ Expose a remote method.
|
|
|
|
|
http: {path: '/info', verb: 'get'}
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Options**
|
|
|
|
|
|
|
|
|
|
- **accepts** - (optional) an arguments description specifying the remote method's arguments. A
|
|
|
|
|
- **accepts** - (optional) an arguments description specifying the remote method's arguments.
|
|
|
|
|
- **returns** - (optional) an arguments description specifying the remote methods callback arguments.
|
|
|
|
|
- **http** - (advanced / optional, object) http routing info
|
|
|
|
|
- **http.path** - the path relative to the model the method will be exposed at. May be a path fragment (eg. '/:myArg') which will be populated by an arg of the same name in the accepts description. For example the stats method above will be at the whole path `/products/stats`.
|
|
|
|
@ -446,6 +517,7 @@ Expose a remote method.
|
|
|
|
|
|
|
|
|
|
An arguments description defines either a single argument as an object or an ordered set of arguments as an array.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
// examples
|
|
|
|
|
{arg: 'myArg', type: 'number'}
|
|
|
|
|
|
|
|
|
@ -453,6 +525,7 @@ An arguments description defines either a single argument as an object or an ord
|
|
|
|
|
{arg: 'arg1', type: 'number', required: true},
|
|
|
|
|
{arg: 'arg2', type: 'array'}
|
|
|
|
|
]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Types**
|
|
|
|
|
|
|
|
|
@ -467,6 +540,7 @@ Each argument may define any of the [loopback types](#loopback-types).
|
|
|
|
|
|
|
|
|
|
Run a function before or after a remote method is called by a client.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
// *.save === prototype.save
|
|
|
|
|
User.beforeRemote('*.save', function(ctx, user, next) {
|
|
|
|
|
if(ctx.user) {
|
|
|
|
@ -480,17 +554,21 @@ Run a function before or after a remote method is called by a client.
|
|
|
|
|
console.log('user has been saved', user);
|
|
|
|
|
next();
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Remote hooks also support wildcards. Run a function before any remote method is called.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
// ** will match both prototype.* and *.*
|
|
|
|
|
User.beforeRemote('**', function(ctx, user, next) {
|
|
|
|
|
console.log(ctx.methodString, 'was invoked remotely'); // users.prototype.save was invoked remotely
|
|
|
|
|
next();
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Other wildcard examples
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
// run before any static method eg. User.find
|
|
|
|
|
User.beforeRemote('*', ...);
|
|
|
|
|
|
|
|
|
@ -511,6 +589,7 @@ Other wildcard examples
|
|
|
|
|
|
|
|
|
|
next();
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Context
|
|
|
|
|
|
|
|
|
@ -536,21 +615,22 @@ The express ServerRequest object. [See full documentation](http://expressjs.com/
|
|
|
|
|
|
|
|
|
|
The express ServerResponse object. [See full documentation](http://expressjs.com/api.html#res).
|
|
|
|
|
|
|
|
|
|
Access the raw `req` object for the remote method call.
|
|
|
|
|
|
|
|
|
|
#### Relationships
|
|
|
|
|
|
|
|
|
|
##### Model.hasMany(Model)
|
|
|
|
|
|
|
|
|
|
Define a "one to many" relationship.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
// by referencing model
|
|
|
|
|
Book.hasMany(Chapter);
|
|
|
|
|
// specify the name
|
|
|
|
|
Book.hasMany('chapters', {model: Chapter});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Query and create the related models.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
Book.create(function(err, book) {
|
|
|
|
|
// create a chapter instance
|
|
|
|
|
// ready to be saved in the data source
|
|
|
|
@ -577,6 +657,7 @@ Query and create the related models.
|
|
|
|
|
console.log(chapters);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Shared Methods
|
|
|
|
|
|
|
|
|
@ -588,6 +669,7 @@ A Loopback `DataSource` provides [Models](#model) with the ability to manipulate
|
|
|
|
|
|
|
|
|
|
Define a data source for persisting models.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
var oracle = loopback.createDataSource({
|
|
|
|
|
connector: 'oracle',
|
|
|
|
|
host: '111.22.333.44',
|
|
|
|
@ -595,17 +677,21 @@ Define a data source for persisting models.
|
|
|
|
|
username: 'username',
|
|
|
|
|
password: 'password'
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### dataSource.createModel(name, properties, options)
|
|
|
|
|
|
|
|
|
|
Define a model and attach it to a `DataSource`.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
var Color = oracle.createModel('color', {name: String});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### dataSource.discoverModelDefinitions([username], fn)
|
|
|
|
|
|
|
|
|
|
Discover a set of model definitions (table or collection names) based on tables or collections in a data source.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
oracle.discoverModelDefinitions(function (err, models) {
|
|
|
|
|
models.forEach(function (def) {
|
|
|
|
|
// def.name ~ the model name
|
|
|
|
@ -614,6 +700,7 @@ Discover a set of model definitions (table or collection names) based on tables
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### dataSource.discoverSchema([owner], name, fn)
|
|
|
|
|
|
|
|
|
@ -621,6 +708,7 @@ Discover the schema of a specific table or collection.
|
|
|
|
|
|
|
|
|
|
**Example schema from oracle connector:**
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
{
|
|
|
|
|
"name": "Product",
|
|
|
|
|
"options": {
|
|
|
|
@ -711,6 +799,7 @@ Discover the schema of a specific table or collection.
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### dataSource.enableRemote(operation)
|
|
|
|
|
|
|
|
|
@ -721,6 +810,7 @@ Enable remote access to a data source operation. Each [connector](#connector) ha
|
|
|
|
|
|
|
|
|
|
Disable remote access to a data source operation. Each [connector](#connector) has its own set of set enabled and disabled operations. You can always list these by calling `dataSource.operations()`.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
// all rest data source operations are
|
|
|
|
|
// disabled by default
|
|
|
|
|
var oracle = loopback.createDataSource({
|
|
|
|
@ -731,6 +821,7 @@ Disable remote access to a data source operation. Each [connector](#connector) h
|
|
|
|
|
|
|
|
|
|
// or only disable it as a remote method
|
|
|
|
|
oracle.disableRemote('destroyAll');
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Notes:**
|
|
|
|
|
|
|
|
|
@ -746,6 +837,7 @@ List the enabled and disabled operations.
|
|
|
|
|
|
|
|
|
|
Output:
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
{
|
|
|
|
|
find: {
|
|
|
|
|
remoteEnabled: true,
|
|
|
|
@ -762,14 +854,17 @@ Output:
|
|
|
|
|
},
|
|
|
|
|
...
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Connectors
|
|
|
|
|
|
|
|
|
|
Create a data source with a specific connector. See **available connectors** for specific connector documentation.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
var memory = loopback.createDataSource({
|
|
|
|
|
connector: loopback.Memory
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Available Connectors**
|
|
|
|
|
|
|
|
|
@ -788,16 +883,19 @@ Create a data source with a specific connector. See **available connectors** for
|
|
|
|
|
|
|
|
|
|
Include the connector in your package.json dependencies and run `npm install`.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
{
|
|
|
|
|
"dependencies": {
|
|
|
|
|
"loopback-connector-oracle": "latest"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
##### Memory Connector
|
|
|
|
|
|
|
|
|
|
The built-in memory connector allows you to test your application without connecting to an actual persistent data source, such as a database. Although the memory connector is very well tested it is not recommended to be used in production. Creating a data source using the memory connector is very simple.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
// use the built in memory function
|
|
|
|
|
// to create a memory data source
|
|
|
|
|
var memory = loopback.memory();
|
|
|
|
@ -826,6 +924,7 @@ The built-in memory connector allows you to test your application without connec
|
|
|
|
|
function count() {
|
|
|
|
|
Product.count(console.log); // 3
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
###### Operations
|
|
|
|
|
|
|
|
|
@ -841,37 +940,47 @@ The memory connector also supports geo-filtering when using the `find()` operati
|
|
|
|
|
|
|
|
|
|
Use the `GeoPoint` class.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
var GeoPoint = require('loopback').GeoPoint;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Embed a latitude / longitude point in a [Model](#model).
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
var CoffeeShop = loopback.createModel('coffee-shop', {
|
|
|
|
|
location: 'GeoPoint'
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Loopback Model's with a GeoPoint property and an attached DataSource may be queried using geo spatial filters and sorting.
|
|
|
|
|
|
|
|
|
|
Find the 3 nearest coffee shops.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
CoffeeShop.attachTo(oracle);
|
|
|
|
|
var here = new GeoPoint({lat: 10.32424, lng: 5.84978});
|
|
|
|
|
CoffeeShop.find({where: {location: {near: here}}, limit:3}, function(err, nearbyShops) {
|
|
|
|
|
console.info(nearbyShops); // [CoffeeShop, ...]
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### geoPoint.distanceTo(geoPoint, options)
|
|
|
|
|
|
|
|
|
|
Get the distance to another `GeoPoint`.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
var here = new GeoPoint({lat: 10, lng: 10});
|
|
|
|
|
var there = new GeoPoint({lat: 5, lng: 5});
|
|
|
|
|
console.log(here.distanceTo(there, {type: 'miles'})); // 438
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### GeoPoint.distanceBetween(a, b, options)
|
|
|
|
|
|
|
|
|
|
Get the distance between two points.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
GeoPoint.distanceBetween(here, there, {type: 'miles'}) // 438
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Distance Types
|
|
|
|
|
|
|
|
|
@ -924,6 +1033,7 @@ Register and authenticate users of your app locally or against 3rd party service
|
|
|
|
|
|
|
|
|
|
Extend a vanilla Loopback model using the built in User model.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
// create a data source
|
|
|
|
|
var memory = loopback.memory();
|
|
|
|
|
|
|
|
|
@ -938,6 +1048,7 @@ Extend a vanilla Loopback model using the built in User model.
|
|
|
|
|
|
|
|
|
|
// expose over the app's api
|
|
|
|
|
app.model(User);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Note:** By default the `loopback.User` model uses the `loopback.Session` model to persist sessions. You can change this by setting the `session` property.
|
|
|
|
|
|
|
|
|
@ -947,10 +1058,12 @@ Extend a vanilla Loopback model using the built in User model.
|
|
|
|
|
|
|
|
|
|
Create a user like any other model.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
// username and password are not required
|
|
|
|
|
User.create({email: 'foo@bar.com', password: 'bar'}, function(err, user) {
|
|
|
|
|
console.log(user);
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
##### Login a User
|
|
|
|
@ -959,14 +1072,17 @@ Create a session for a user using the local auth strategy.
|
|
|
|
|
|
|
|
|
|
**Node.js**
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
User.login({username: 'foo', password: 'bar'}, function(err, session) {
|
|
|
|
|
console.log(session);
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**REST**
|
|
|
|
|
|
|
|
|
|
You must provide a username and password over rest. To ensure these values are encrypted, include these as part of the body and make sure you are serving your app over https (through a proxy or using the https node server).
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
POST
|
|
|
|
|
|
|
|
|
|
/users/login
|
|
|
|
@ -983,11 +1099,13 @@ You must provide a username and password over rest. To ensure these values are e
|
|
|
|
|
"sid": "1234abcdefg",
|
|
|
|
|
"uid": "123"
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
##### Logout a User
|
|
|
|
|
|
|
|
|
|
**Node.js**
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
// login a user and logout
|
|
|
|
|
User.login({"email": "foo@bar.com", "password": "bar"}, function(err, session) {
|
|
|
|
|
User.logout(session.id, function(err) {
|
|
|
|
@ -999,19 +1117,23 @@ You must provide a username and password over rest. To ensure these values are e
|
|
|
|
|
User.findOne({email: 'foo@bar.com'}, function(err, user) {
|
|
|
|
|
user.logout();
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**REST**
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
POST /users/logout
|
|
|
|
|
...
|
|
|
|
|
{
|
|
|
|
|
"sid": "<session id from user login>"
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
##### Verify Email Addresses
|
|
|
|
|
|
|
|
|
|
Require a user to verify their email address before being able to login. This will send an email to the user containing a link to verify their address. Once the user follows the link they will be redirected to `/` and be able to login normally.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
User.requireEmailVerfication = true;
|
|
|
|
|
User.afterRemote('create', function(ctx, user, next) {
|
|
|
|
|
var options = {
|
|
|
|
@ -1026,35 +1148,41 @@ Require a user to verify their email address before being able to login. This wi
|
|
|
|
|
|
|
|
|
|
user.verify(options, next);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
##### Send Reset Password Email
|
|
|
|
|
|
|
|
|
|
Send an email to the user's supplied email address containing a link to reset their password.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
User.reset(email, function(err) {
|
|
|
|
|
console.log('email sent');
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
##### Remote Password Reset
|
|
|
|
|
|
|
|
|
|
The password reset email will send users to a page rendered by loopback with fields required to reset the user's password. You may customize this template by defining a `resetTemplate` setting.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
User.settings.resetTemplate = 'reset.ejs';
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
##### Remote Password Reset Confirmation
|
|
|
|
|
|
|
|
|
|
Confirm the password reset.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
User.confirmReset(token, function(err) {
|
|
|
|
|
console.log(err || 'your password was reset');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Session Model
|
|
|
|
|
|
|
|
|
|
Identify users by creating sessions when they connect to your loopback app. By default the `loopback.User` model uses the `loopback.Session` model to persist sessions. You can change this by setting the `session` property.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
// define a custom session model
|
|
|
|
|
var MySession = loopback.Session.extend('my-session');
|
|
|
|
|
|
|
|
|
@ -1067,6 +1195,7 @@ Identify users by creating sessions when they connect to your loopback app. By d
|
|
|
|
|
// attach both Session and User to a data source
|
|
|
|
|
User.attachTo(loopback.memory());
|
|
|
|
|
MySession.attachTo(loopback.memory());
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Email Model
|
|
|
|
|
|
|
|
|
@ -1076,7 +1205,9 @@ Send emails from your loopback app.
|
|
|
|
|
|
|
|
|
|
Expose models over rest using the `loopback.rest` router.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
app.use(loopback.rest());
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**REST Documentation**
|
|
|
|
|
|
|
|
|
@ -1086,5 +1217,6 @@ View generated REST documentation by visiting: [http://localhost:3000/_docs](htt
|
|
|
|
|
|
|
|
|
|
**Coming Soon** - Expose models over socket.io using the `loopback.sio()` middleware.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
app.use(loopback.sio);
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|