Merge pull request #658 from rhalff:master
Fix basic jshint errors Close #658
This commit is contained in:
commit
97a8c3acb2
|
@ -5,8 +5,10 @@
|
||||||
"indent": 2,
|
"indent": 2,
|
||||||
"undef": true,
|
"undef": true,
|
||||||
"quotmark": "single",
|
"quotmark": "single",
|
||||||
"maxlen": 80,
|
"maxlen": 150,
|
||||||
"trailing": true,
|
"trailing": true,
|
||||||
"newcap": true,
|
"newcap": true,
|
||||||
"nonew": true
|
"nonew": true,
|
||||||
|
"laxcomma": true,
|
||||||
|
"laxbreak": true
|
||||||
}
|
}
|
||||||
|
|
19
Gruntfile.js
19
Gruntfile.js
|
@ -30,8 +30,11 @@ module.exports = function(grunt) {
|
||||||
gruntfile: {
|
gruntfile: {
|
||||||
src: 'Gruntfile.js'
|
src: 'Gruntfile.js'
|
||||||
},
|
},
|
||||||
lib_test: {
|
lib: {
|
||||||
src: ['lib/**/*.js', 'test/**/*.js']
|
src: ['lib/**/*.js']
|
||||||
|
},
|
||||||
|
test: {
|
||||||
|
src: ['test/**/*.js']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
@ -39,9 +42,13 @@ module.exports = function(grunt) {
|
||||||
files: '<%= jshint.gruntfile.src %>',
|
files: '<%= jshint.gruntfile.src %>',
|
||||||
tasks: ['jshint:gruntfile']
|
tasks: ['jshint:gruntfile']
|
||||||
},
|
},
|
||||||
lib_test: {
|
lib: {
|
||||||
files: '<%= jshint.lib_test.src %>',
|
files: ['<%= jshint.lib.src %>'],
|
||||||
tasks: ['jshint:lib_test']
|
tasks: ['jshint:lib']
|
||||||
|
},
|
||||||
|
test: {
|
||||||
|
files: ['<%= jshint.test.src %>'],
|
||||||
|
tasks: ['jshint:test']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
browserify: {
|
browserify: {
|
||||||
|
@ -104,7 +111,7 @@ module.exports = function(grunt) {
|
||||||
|
|
||||||
// list of files to exclude
|
// list of files to exclude
|
||||||
exclude: [
|
exclude: [
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
// test results reporter to use
|
// test results reporter to use
|
||||||
|
|
|
@ -39,15 +39,15 @@ function AccessContext(context) {
|
||||||
this.sharedMethod = context.sharedMethod;
|
this.sharedMethod = context.sharedMethod;
|
||||||
this.sharedClass = this.sharedMethod && this.sharedMethod.sharedClass;
|
this.sharedClass = this.sharedMethod && this.sharedMethod.sharedClass;
|
||||||
if(this.sharedMethod) {
|
if(this.sharedMethod) {
|
||||||
this.methodNames = this.sharedMethod.aliases.concat([this.sharedMethod.name]);
|
this.methodNames = this.sharedMethod.aliases.concat([this.sharedMethod.name]);
|
||||||
} else {
|
} else {
|
||||||
this.methodNames = [];
|
this.methodNames = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.sharedMethod) {
|
if(this.sharedMethod) {
|
||||||
this.accessType = this.model._getAccessTypeForMethod(this.sharedMethod);
|
this.accessType = this.model._getAccessTypeForMethod(this.sharedMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.accessType = context.accessType || AccessContext.ALL;
|
this.accessType = context.accessType || AccessContext.ALL;
|
||||||
assert(loopback.AccessToken,
|
assert(loopback.AccessToken,
|
||||||
'AccessToken model must be defined before AccessContext model');
|
'AccessToken model must be defined before AccessContext model');
|
||||||
|
@ -157,9 +157,9 @@ AccessContext.prototype.debug = function() {
|
||||||
if(debug.enabled) {
|
if(debug.enabled) {
|
||||||
debug('---AccessContext---');
|
debug('---AccessContext---');
|
||||||
if(this.principals && this.principals.length) {
|
if(this.principals && this.principals.length) {
|
||||||
debug('principals:')
|
debug('principals:');
|
||||||
this.principals.forEach(function(principal) {
|
this.principals.forEach(function(principal) {
|
||||||
debug('principal: %j', principal)
|
debug('principal: %j', principal);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
debug('principals: %j', this.principals);
|
debug('principals: %j', this.principals);
|
||||||
|
@ -170,14 +170,14 @@ AccessContext.prototype.debug = function() {
|
||||||
debug('method %s', this.method);
|
debug('method %s', this.method);
|
||||||
debug('accessType %s', this.accessType);
|
debug('accessType %s', this.accessType);
|
||||||
if(this.accessToken) {
|
if(this.accessToken) {
|
||||||
debug('accessToken:')
|
debug('accessToken:');
|
||||||
debug(' id %j', this.accessToken.id);
|
debug(' id %j', this.accessToken.id);
|
||||||
debug(' ttl %j', this.accessToken.ttl);
|
debug(' ttl %j', this.accessToken.ttl);
|
||||||
}
|
}
|
||||||
debug('getUserId() %s', this.getUserId());
|
debug('getUserId() %s', this.getUserId());
|
||||||
debug('isAuthenticated() %s', this.isAuthenticated());
|
debug('isAuthenticated() %s', this.isAuthenticated());
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents the abstract notion of a principal, which can be used
|
* This class represents the abstract notion of a principal, which can be used
|
||||||
|
@ -273,17 +273,17 @@ AccessRequest.prototype.exactlyMatches = function(acl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the request for access allowed?
|
* Is the request for access allowed?
|
||||||
*
|
*
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AccessRequest.prototype.isAllowed = function() {
|
AccessRequest.prototype.isAllowed = function() {
|
||||||
return this.permission !== loopback.ACL.DENY;
|
return this.permission !== loopback.ACL.DENY;
|
||||||
}
|
};
|
||||||
|
|
||||||
AccessRequest.prototype.debug = function() {
|
AccessRequest.prototype.debug = function() {
|
||||||
if(debug.enabled) {
|
if(debug.enabled) {
|
||||||
|
@ -295,7 +295,7 @@ AccessRequest.prototype.debug = function() {
|
||||||
debug(' isWildcard() %s', this.isWildcard());
|
debug(' isWildcard() %s', this.isWildcard());
|
||||||
debug(' isAllowed() %s', this.isAllowed());
|
debug(' isAllowed() %s', this.isAllowed());
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
module.exports.AccessContext = AccessContext;
|
module.exports.AccessContext = AccessContext;
|
||||||
module.exports.Principal = Principal;
|
module.exports.Principal = Principal;
|
||||||
|
|
|
@ -14,22 +14,22 @@ var DataSource = require('loopback-datasource-juggler').DataSource
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `App` object represents a Loopback application.
|
* The `App` object represents a Loopback application.
|
||||||
*
|
*
|
||||||
* The App object extends [Express](http://expressjs.com/api.html#express) and
|
* The App object extends [Express](http://expressjs.com/api.html#express) and
|
||||||
* supports Express middleware. See
|
* supports Express middleware. See
|
||||||
* [Express documentation](http://expressjs.com/) for details.
|
* [Express documentation](http://expressjs.com/) for details.
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* var loopback = require('loopback');
|
* var loopback = require('loopback');
|
||||||
* var app = loopback();
|
* var app = loopback();
|
||||||
*
|
*
|
||||||
* app.get('/', function(req, res){
|
* app.get('/', function(req, res){
|
||||||
* res.send('hello world');
|
* res.send('hello world');
|
||||||
* });
|
* });
|
||||||
*
|
*
|
||||||
* app.listen(3000);
|
* app.listen(3000);
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @class LoopBackApplication
|
* @class LoopBackApplication
|
||||||
* @header var app = loopback()
|
* @header var app = loopback()
|
||||||
*/
|
*/
|
||||||
|
@ -59,10 +59,10 @@ app.remotes = function () {
|
||||||
if(this.get) {
|
if(this.get) {
|
||||||
options = this.get('remoting');
|
options = this.get('remoting');
|
||||||
}
|
}
|
||||||
|
|
||||||
return (this._remotes = RemoteObjects.create(options));
|
return (this._remotes = RemoteObjects.create(options));
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Remove a route by reference.
|
* Remove a route by reference.
|
||||||
|
@ -76,7 +76,7 @@ app.disuse = function (route) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attach a model to the app. The `Model` will be available on the
|
* Attach a model to the app. The `Model` will be available on the
|
||||||
|
@ -92,7 +92,7 @@ app.disuse = function (route) {
|
||||||
* var User = loopback.User;
|
* var User = loopback.User;
|
||||||
* app.model(User, { dataSource: 'db' });
|
* app.model(User, { dataSource: 'db' });
|
||||||
*```
|
*```
|
||||||
*
|
*
|
||||||
* @param {Object|String} Model The model to attach.
|
* @param {Object|String} Model The model to attach.
|
||||||
* @options {Object} config The model's configuration.
|
* @options {Object} config The model's configuration.
|
||||||
* @property {String|DataSource} dataSource The `DataSource` to which to attach the model.
|
* @property {String|DataSource} dataSource The `DataSource` to which to attach the model.
|
||||||
|
@ -207,7 +207,7 @@ app.model = function (Model, config) {
|
||||||
|
|
||||||
app.models = function () {
|
app.models = function () {
|
||||||
return this._models || (this._models = []);
|
return this._models || (this._models = []);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a DataSource.
|
* Define a DataSource.
|
||||||
|
@ -221,7 +221,7 @@ app.dataSource = function (name, config) {
|
||||||
this.dataSources[classify(name)] =
|
this.dataSources[classify(name)] =
|
||||||
this.dataSources[camelize(name)] = ds;
|
this.dataSources[camelize(name)] = ds;
|
||||||
return ds;
|
return ds;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a connector.
|
* Register a connector.
|
||||||
|
@ -254,30 +254,30 @@ app.remoteObjects = function () {
|
||||||
this.remotes().classes().forEach(function(sharedClass) {
|
this.remotes().classes().forEach(function(sharedClass) {
|
||||||
result[sharedClass.name] = sharedClass.ctor;
|
result[sharedClass.name] = sharedClass.ctor;
|
||||||
});
|
});
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Get a handler of the specified type from the handler cache.
|
* Get a handler of the specified type from the handler cache.
|
||||||
* @triggers `mounted` events on shared class constructors (models)
|
* @triggers `mounted` events on shared class constructors (models)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
app.handler = function (type, options) {
|
app.handler = function (type, options) {
|
||||||
var handlers = this._handlers || (this._handlers = {});
|
var handlers = this._handlers || (this._handlers = {});
|
||||||
if(handlers[type]) {
|
if(handlers[type]) {
|
||||||
return handlers[type];
|
return handlers[type];
|
||||||
}
|
}
|
||||||
|
|
||||||
var remotes = this.remotes();
|
var remotes = this.remotes();
|
||||||
var handler = this._handlers[type] = remotes.handler(type, options);
|
var handler = this._handlers[type] = remotes.handler(type, options);
|
||||||
|
|
||||||
remotes.classes().forEach(function(sharedClass) {
|
remotes.classes().forEach(function(sharedClass) {
|
||||||
sharedClass.ctor.emit('mounted', app, sharedClass, remotes);
|
sharedClass.ctor.emit('mounted', app, sharedClass, remotes);
|
||||||
});
|
});
|
||||||
|
|
||||||
return handler;
|
return handler;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object to store dataSource instances.
|
* An object to store dataSource instances.
|
||||||
|
@ -342,7 +342,7 @@ app.enableAuth = function() {
|
||||||
app.boot = function(options) {
|
app.boot = function(options) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'`app.boot` was removed, use the new module loopback-boot instead');
|
'`app.boot` was removed, use the new module loopback-boot instead');
|
||||||
}
|
};
|
||||||
|
|
||||||
function classify(str) {
|
function classify(str) {
|
||||||
return stringUtils.classify(str);
|
return stringUtils.classify(str);
|
||||||
|
@ -355,7 +355,7 @@ function camelize(str) {
|
||||||
function dataSourcesFromConfig(config, connectorRegistry) {
|
function dataSourcesFromConfig(config, connectorRegistry) {
|
||||||
var connectorPath;
|
var connectorPath;
|
||||||
|
|
||||||
assert(typeof config === 'object',
|
assert(typeof config === 'object',
|
||||||
'cannont create data source without config object');
|
'cannont create data source without config object');
|
||||||
|
|
||||||
if(typeof config.connector === 'string') {
|
if(typeof config.connector === 'string') {
|
||||||
|
@ -459,7 +459,7 @@ app.listen = function(cb) {
|
||||||
});
|
});
|
||||||
|
|
||||||
var useAppConfig =
|
var useAppConfig =
|
||||||
arguments.length == 0 ||
|
arguments.length === 0 ||
|
||||||
(arguments.length == 1 && typeof arguments[0] == 'function');
|
(arguments.length == 1 && typeof arguments[0] == 'function');
|
||||||
|
|
||||||
if (useAppConfig) {
|
if (useAppConfig) {
|
||||||
|
@ -469,4 +469,4 @@ app.listen = function(cb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return server;
|
return server;
|
||||||
}
|
};
|
||||||
|
|
|
@ -7,13 +7,13 @@ module.exports = Connector;
|
||||||
/**
|
/**
|
||||||
* Module dependencies.
|
* Module dependencies.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var EventEmitter = require('events').EventEmitter
|
var EventEmitter = require('events').EventEmitter
|
||||||
, debug = require('debug')('connector')
|
, debug = require('debug')('connector')
|
||||||
, util = require('util')
|
, util = require('util')
|
||||||
, inherits = util.inherits
|
, inherits = util.inherits
|
||||||
, assert = require('assert');
|
, assert = require('assert');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new `Connector` with the given `options`.
|
* Create a new `Connector` with the given `options`.
|
||||||
*
|
*
|
||||||
|
@ -24,7 +24,7 @@ var EventEmitter = require('events').EventEmitter
|
||||||
function Connector(options) {
|
function Connector(options) {
|
||||||
EventEmitter.apply(this, arguments);
|
EventEmitter.apply(this, arguments);
|
||||||
this.options = options;
|
this.options = options;
|
||||||
|
|
||||||
debug('created with options', options);
|
debug('created with options', options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,12 +43,12 @@ Connector._createJDBAdapter = function (jdbModule) {
|
||||||
jdbModule.initialize(fauxSchema, function () {
|
jdbModule.initialize(fauxSchema, function () {
|
||||||
// connected
|
// connected
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Add default crud operations from a JugglingDB adapter.
|
* Add default crud operations from a JugglingDB adapter.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Connector.prototype._addCrudOperationsFromJDBAdapter = function (connector) {
|
Connector.prototype._addCrudOperationsFromJDBAdapter = function (connector) {
|
||||||
|
|
||||||
}
|
};
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
var mailer = require('nodemailer')
|
var mailer = require('nodemailer')
|
||||||
, assert = require('assert')
|
, assert = require('assert')
|
||||||
, debug = require('debug')('loopback:connector:mail')
|
, debug = require('debug')('loopback:connector:mail')
|
||||||
, loopback = require('../loopback')
|
, loopback = require('../loopback');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Export the MailConnector class.
|
* Export the MailConnector class.
|
||||||
|
@ -44,7 +44,7 @@ function MailConnector(settings) {
|
||||||
MailConnector.initialize = function(dataSource, callback) {
|
MailConnector.initialize = function(dataSource, callback) {
|
||||||
dataSource.connector = new MailConnector(dataSource.settings);
|
dataSource.connector = new MailConnector(dataSource.settings);
|
||||||
callback();
|
callback();
|
||||||
}
|
};
|
||||||
|
|
||||||
MailConnector.prototype.DataAccessObject = Mailer;
|
MailConnector.prototype.DataAccessObject = Mailer;
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ MailConnector.prototype.setupTransport = function(setting) {
|
||||||
|
|
||||||
connector.transportsIndex[setting.type] = transport;
|
connector.transportsIndex[setting.type] = transport;
|
||||||
connector.transports.push(transport);
|
connector.transports.push(transport);
|
||||||
}
|
};
|
||||||
|
|
||||||
function Mailer() {
|
function Mailer() {
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ function Mailer() {
|
||||||
|
|
||||||
MailConnector.prototype.transportForName = function(name) {
|
MailConnector.prototype.transportForName = function(name) {
|
||||||
return this.transportsIndex[name];
|
return this.transportsIndex[name];
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the default transport.
|
* Get the default transport.
|
||||||
|
@ -111,7 +111,7 @@ MailConnector.prototype.transportForName = function(name) {
|
||||||
|
|
||||||
MailConnector.prototype.defaultTransport = function() {
|
MailConnector.prototype.defaultTransport = function() {
|
||||||
return this.transports[0] || this.stubTransport;
|
return this.transports[0] || this.stubTransport;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send an email with the given `options`.
|
* Send an email with the given `options`.
|
||||||
|
@ -166,7 +166,7 @@ Mailer.send = function (options, fn) {
|
||||||
fn(null, options);
|
fn(null, options);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send an email instance using `modelInstance.send()`.
|
* Send an email instance using `modelInstance.send()`.
|
||||||
|
@ -174,7 +174,7 @@ Mailer.send = function (options, fn) {
|
||||||
|
|
||||||
Mailer.prototype.send = function (fn) {
|
Mailer.prototype.send = function (fn) {
|
||||||
this.constructor.send(this, fn);
|
this.constructor.send(this, fn);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access the node mailer object.
|
* Access the node mailer object.
|
||||||
|
|
|
@ -7,14 +7,14 @@ module.exports = Memory;
|
||||||
/**
|
/**
|
||||||
* Module dependencies.
|
* Module dependencies.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var Connector = require('./base-connector')
|
var Connector = require('./base-connector')
|
||||||
, debug = require('debug')('memory')
|
, debug = require('debug')('memory')
|
||||||
, util = require('util')
|
, util = require('util')
|
||||||
, inherits = util.inherits
|
, inherits = util.inherits
|
||||||
, assert = require('assert')
|
, assert = require('assert')
|
||||||
, JdbMemory = require('loopback-datasource-juggler/lib/connectors/memory');
|
, JdbMemory = require('loopback-datasource-juggler/lib/connectors/memory');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new `Memory` connector with the given `options`.
|
* Create a new `Memory` connector with the given `options`.
|
||||||
*
|
*
|
||||||
|
|
|
@ -20,20 +20,20 @@ function createMiddlewareNotInstalled(memberName, moduleName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var middlewareModules = {
|
var middlewareModules = {
|
||||||
"compress": "compression",
|
'compress': 'compression',
|
||||||
"timeout": "connect-timeout",
|
'timeout': 'connect-timeout',
|
||||||
"cookieParser": "cookie-parser",
|
'cookieParser': 'cookie-parser',
|
||||||
"cookieSession": "cookie-session",
|
'cookieSession': 'cookie-session',
|
||||||
"csrf": "csurf",
|
'csrf': 'csurf',
|
||||||
"errorHandler": "errorhandler",
|
'errorHandler': 'errorhandler',
|
||||||
"session": "express-session",
|
'session': 'express-session',
|
||||||
"methodOverride": "method-override",
|
'methodOverride': 'method-override',
|
||||||
"logger": "morgan",
|
'logger': 'morgan',
|
||||||
"responseTime": "response-time",
|
'responseTime': 'response-time',
|
||||||
"favicon": "serve-favicon",
|
'favicon': 'serve-favicon',
|
||||||
"directory": "serve-index",
|
'directory': 'serve-index',
|
||||||
// "static": "serve-static",
|
// 'static': 'serve-static',
|
||||||
"vhost": "vhost"
|
'vhost': 'vhost'
|
||||||
};
|
};
|
||||||
|
|
||||||
middlewares.bodyParser = safeRequire('body-parser');
|
middlewares.bodyParser = safeRequire('body-parser');
|
||||||
|
|
|
@ -14,7 +14,7 @@ module.exports = status;
|
||||||
* "uptime": 9.394
|
* "uptime": 9.394
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @header loopback.status()
|
* @header loopback.status()
|
||||||
*/
|
*/
|
||||||
function status() {
|
function status() {
|
||||||
|
@ -25,6 +25,6 @@ function status() {
|
||||||
started: started,
|
started: started,
|
||||||
uptime: (Date.now() - Number(started)) / 1000
|
uptime: (Date.now() - Number(started)) / 1000
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,22 +11,22 @@ var assert = require('assert');
|
||||||
|
|
||||||
module.exports = token;
|
module.exports = token;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check for an access token in cookies, headers, and query string parameters.
|
* Check for an access token in cookies, headers, and query string parameters.
|
||||||
* This function always checks for the following:
|
* This function always checks for the following:
|
||||||
*
|
*
|
||||||
* - `access_token` (params only)
|
* - `access_token` (params only)
|
||||||
* - `X-Access-Token` (headers only)
|
* - `X-Access-Token` (headers only)
|
||||||
* - `authorization` (headers and cookies)
|
* - `authorization` (headers and cookies)
|
||||||
*
|
*
|
||||||
* It checks for these values in cookies, headers, and query string parameters _in addition_ to the items
|
* It checks for these values in cookies, headers, and query string parameters _in addition_ to the items
|
||||||
* specified in the options parameter.
|
* specified in the options parameter.
|
||||||
*
|
*
|
||||||
* **NOTE:** This function only checks for [signed cookies](http://expressjs.com/api.html#req.signedCookies).
|
* **NOTE:** This function only checks for [signed cookies](http://expressjs.com/api.html#req.signedCookies).
|
||||||
*
|
*
|
||||||
* The following example illustrates how to check for an `accessToken` in a custom cookie, query string parameter
|
* The following example illustrates how to check for an `accessToken` in a custom cookie, query string parameter
|
||||||
* and header called `foo-auth`.
|
* and header called `foo-auth`.
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* app.use(loopback.token({
|
* app.use(loopback.token({
|
||||||
* cookies: ['foo-auth'],
|
* cookies: ['foo-auth'],
|
||||||
|
@ -47,13 +47,13 @@ function token(options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
var TokenModel = options.model || loopback.AccessToken;
|
var TokenModel = options.model || loopback.AccessToken;
|
||||||
assert(TokenModel, 'loopback.token() middleware requires a AccessToken model');
|
assert(TokenModel, 'loopback.token() middleware requires a AccessToken model');
|
||||||
|
|
||||||
return function (req, res, next) {
|
return function (req, res, next) {
|
||||||
if (req.accessToken !== undefined) return next();
|
if (req.accessToken !== undefined) return next();
|
||||||
TokenModel.findForRequest(req, options, function(err, token) {
|
TokenModel.findForRequest(req, options, function(err, token) {
|
||||||
req.accessToken = token || null;
|
req.accessToken = token || null;
|
||||||
next(err);
|
next(err);
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,5 +15,5 @@ function urlNotFound() {
|
||||||
var error = new Error('Cannot ' + req.method + ' ' + req.url);
|
var error = new Error('Cannot ' + req.method + ' ' + req.url);
|
||||||
error.status = 404;
|
error.status = 404;
|
||||||
next(error);
|
next(error);
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
106
lib/model.js
106
lib/model.js
|
@ -9,7 +9,7 @@ var extend = require('util')._extend;
|
||||||
var stringUtils = require('underscore.string');
|
var stringUtils = require('underscore.string');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base class for **all models**.
|
* The base class for **all models**.
|
||||||
*
|
*
|
||||||
* **Inheriting from `Model`**
|
* **Inheriting from `Model`**
|
||||||
*
|
*
|
||||||
|
@ -18,7 +18,7 @@ var stringUtils = require('underscore.string');
|
||||||
* var options = {...};
|
* var options = {...};
|
||||||
* var MyModel = loopback.Model.extend('MyModel', properties, options);
|
* var MyModel = loopback.Model.extend('MyModel', properties, options);
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* **Options**
|
* **Options**
|
||||||
*
|
*
|
||||||
* - `trackChanges` - If true, changes to the model will be tracked. **Required
|
* - `trackChanges` - If true, changes to the model will be tracked. **Required
|
||||||
|
@ -27,7 +27,7 @@ var stringUtils = require('underscore.string');
|
||||||
* **Events**
|
* **Events**
|
||||||
*
|
*
|
||||||
* #### Event: `changed`
|
* #### Event: `changed`
|
||||||
*
|
*
|
||||||
* Emitted after a model has been successfully created, saved, or updated.
|
* Emitted after a model has been successfully created, saved, or updated.
|
||||||
* Argument: `inst`, model instance, object
|
* Argument: `inst`, model instance, object
|
||||||
*
|
*
|
||||||
|
@ -37,10 +37,10 @@ var stringUtils = require('underscore.string');
|
||||||
* // => model with id 1 has been changed
|
* // => model with id 1 has been changed
|
||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* #### Event: `deleted`
|
* #### Event: `deleted`
|
||||||
*
|
*
|
||||||
* Emitted after an individual model has been deleted.
|
* Emitted after an individual model has been deleted.
|
||||||
* Argument: `id`, model ID (number).
|
* Argument: `id`, model ID (number).
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
|
@ -51,7 +51,7 @@ var stringUtils = require('underscore.string');
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* #### Event: `deletedAll`
|
* #### Event: `deletedAll`
|
||||||
*
|
*
|
||||||
* Emitted after an individual model has been deleted.
|
* Emitted after an individual model has been deleted.
|
||||||
* Argument: `where` (optional), where filter, JSON object.
|
* Argument: `where` (optional), where filter, JSON object.
|
||||||
*
|
*
|
||||||
|
@ -65,27 +65,27 @@ var stringUtils = require('underscore.string');
|
||||||
* }
|
* }
|
||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* #### Event: `attached`
|
* #### Event: `attached`
|
||||||
*
|
*
|
||||||
* Emitted after a `Model` has been attached to an `app`.
|
* Emitted after a `Model` has been attached to an `app`.
|
||||||
*
|
*
|
||||||
* #### Event: `dataSourceAttached`
|
* #### Event: `dataSourceAttached`
|
||||||
*
|
*
|
||||||
* Emitted after a `Model` has been attached to a `DataSource`.
|
* Emitted after a `Model` has been attached to a `DataSource`.
|
||||||
*
|
*
|
||||||
* #### Event: set
|
* #### Event: set
|
||||||
*
|
*
|
||||||
* Emitted when model property is set.
|
* Emitted when model property is set.
|
||||||
* Argument: `inst`, model instance, object
|
* Argument: `inst`, model instance, object
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* MyModel.on('set', function(inst) {
|
* MyModel.on('set', function(inst) {
|
||||||
* console.log('model with id %s has been changed', inst.id);
|
* console.log('model with id %s has been changed', inst.id);
|
||||||
* // => model with id 1 has been changed
|
* // => model with id 1 has been changed
|
||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @property {String} modelName The name of the model. Static property.
|
* @property {String} modelName The name of the model. Static property.
|
||||||
* @property {DataSource} dataSource Data source to which the model is connected, if any. Static property.
|
* @property {DataSource} dataSource Data source to which the model is connected, if any. Static property.
|
||||||
|
@ -128,7 +128,7 @@ Model.setup = function () {
|
||||||
id = null;
|
id = null;
|
||||||
} else if (typeof id === 'function') {
|
} else if (typeof id === 'function') {
|
||||||
fn = id;
|
fn = id;
|
||||||
|
|
||||||
if(typeof data !== 'object') {
|
if(typeof data !== 'object') {
|
||||||
id = data;
|
id = data;
|
||||||
data = null;
|
data = null;
|
||||||
|
@ -136,7 +136,7 @@ Model.setup = function () {
|
||||||
id = null;
|
id = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(id && data) {
|
if(id && data) {
|
||||||
var model = new ModelCtor(data);
|
var model = new ModelCtor(data);
|
||||||
model.id = id;
|
model.id = id;
|
||||||
|
@ -152,14 +152,14 @@ Model.setup = function () {
|
||||||
} else {
|
} else {
|
||||||
err = new Error('could not find a model with id ' + id);
|
err = new Error('could not find a model with id ' + id);
|
||||||
err.statusCode = 404;
|
err.statusCode = 404;
|
||||||
|
|
||||||
fn(err);
|
fn(err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
fn(new Error('must specify an id or data'));
|
fn(new Error('must specify an id or data'));
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
var idDesc = ModelCtor.modelName + ' id';
|
var idDesc = ModelCtor.modelName + ' id';
|
||||||
ModelCtor.sharedCtor.accepts = [
|
ModelCtor.sharedCtor.accepts = [
|
||||||
|
@ -171,7 +171,7 @@ Model.setup = function () {
|
||||||
ModelCtor.sharedCtor.http = [
|
ModelCtor.sharedCtor.http = [
|
||||||
{path: '/:id'}
|
{path: '/:id'}
|
||||||
];
|
];
|
||||||
|
|
||||||
ModelCtor.sharedCtor.returns = {root: true};
|
ModelCtor.sharedCtor.returns = {root: true};
|
||||||
|
|
||||||
// before remote hook
|
// before remote hook
|
||||||
|
@ -190,7 +190,7 @@ Model.setup = function () {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// after remote hook
|
// after remote hook
|
||||||
ModelCtor.afterRemote = function (name, fn) {
|
ModelCtor.afterRemote = function (name, fn) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -280,7 +280,7 @@ Model.checkAccess = function(token, modelId, sharedMethod, ctx, callback) {
|
||||||
callback = ctx;
|
callback = ctx;
|
||||||
ctx = {};
|
ctx = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
aclModel.checkAccessForContext({
|
aclModel.checkAccessForContext({
|
||||||
accessToken: token,
|
accessToken: token,
|
||||||
model: this,
|
model: this,
|
||||||
|
@ -308,7 +308,7 @@ Model._getAccessTypeForMethod = function(method) {
|
||||||
method = {name: method};
|
method = {name: method};
|
||||||
}
|
}
|
||||||
assert(
|
assert(
|
||||||
typeof method === 'object',
|
typeof method === 'object',
|
||||||
'method is a required argument and must be a RemoteMethod object'
|
'method is a required argument and must be a RemoteMethod object'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -340,7 +340,7 @@ Model._getAccessTypeForMethod = function(method) {
|
||||||
default:
|
default:
|
||||||
return ACL.EXECUTE;
|
return ACL.EXECUTE;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the `Application` the Model is attached to.
|
* Get the `Application` the Model is attached to.
|
||||||
|
@ -361,7 +361,7 @@ Model.getApp = function(callback) {
|
||||||
callback(null, Model.app);
|
callback(null, Model.app);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable remote invocation for the method with the given name.
|
* Enable remote invocation for the method with the given name.
|
||||||
|
@ -382,7 +382,7 @@ Model.remoteMethod = function(name, options) {
|
||||||
options.isStatic = true;
|
options.isStatic = true;
|
||||||
}
|
}
|
||||||
this.sharedClass.defineMethod(name, options);
|
this.sharedClass.defineMethod(name, options);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disable remote invocation for the method with the given name.
|
* Disable remote invocation for the method with the given name.
|
||||||
|
@ -395,7 +395,7 @@ Model.remoteMethod = function(name, options) {
|
||||||
|
|
||||||
Model.disableRemoteMethod = function(name, isStatic) {
|
Model.disableRemoteMethod = function(name, isStatic) {
|
||||||
this.sharedClass.disableMethod(name, isStatic || false);
|
this.sharedClass.disableMethod(name, isStatic || false);
|
||||||
}
|
};
|
||||||
|
|
||||||
Model.belongsToRemoting = function(relationName, relation, define) {
|
Model.belongsToRemoting = function(relationName, relation, define) {
|
||||||
var modelName = relation.modelTo && relation.modelTo.modelName;
|
var modelName = relation.modelTo && relation.modelTo.modelName;
|
||||||
|
@ -409,7 +409,7 @@ Model.belongsToRemoting = function(relationName, relation, define) {
|
||||||
description: 'Fetches belongsTo relation ' + relationName,
|
description: 'Fetches belongsTo relation ' + relationName,
|
||||||
returns: {arg: relationName, type: modelName, root: true}
|
returns: {arg: relationName, type: modelName, root: true}
|
||||||
}, fn);
|
}, fn);
|
||||||
}
|
};
|
||||||
|
|
||||||
Model.hasOneRemoting = function(relationName, relation, define) {
|
Model.hasOneRemoting = function(relationName, relation, define) {
|
||||||
var fn = this.prototype[relationName];
|
var fn = this.prototype[relationName];
|
||||||
|
@ -421,22 +421,22 @@ Model.hasOneRemoting = function(relationName, relation, define) {
|
||||||
description: 'Fetches hasOne relation ' + relationName,
|
description: 'Fetches hasOne relation ' + relationName,
|
||||||
returns: {arg: relationName, type: relation.modelTo.modelName, root: true}
|
returns: {arg: relationName, type: relation.modelTo.modelName, root: true}
|
||||||
}, fn);
|
}, fn);
|
||||||
}
|
};
|
||||||
|
|
||||||
Model.hasManyRemoting = function (relationName, relation, define) {
|
Model.hasManyRemoting = function (relationName, relation, define) {
|
||||||
var pathName = (relation.options.http && relation.options.http.path) || relationName;
|
var pathName = (relation.options.http && relation.options.http.path) || relationName;
|
||||||
var toModelName = relation.modelTo.modelName;
|
var toModelName = relation.modelTo.modelName;
|
||||||
|
|
||||||
function convertNullToNotFoundError(ctx, cb) {
|
function convertNullToNotFoundError(ctx, cb) {
|
||||||
if (ctx.result !== null) return cb();
|
if (ctx.result !== null) return cb();
|
||||||
|
|
||||||
var fk = ctx.getArgByName('fk');
|
var fk = ctx.getArgByName('fk');
|
||||||
var msg = 'Unknown "' + toModelName + '" id "' + fk + '".';
|
var msg = 'Unknown "' + toModelName + '" id "' + fk + '".';
|
||||||
var error = new Error(msg);
|
var error = new Error(msg);
|
||||||
error.statusCode = error.status = 404;
|
error.statusCode = error.status = 404;
|
||||||
cb(error);
|
cb(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
var findByIdFunc = this.prototype['__findById__' + relationName];
|
var findByIdFunc = this.prototype['__findById__' + relationName];
|
||||||
define('__findById__' + relationName, {
|
define('__findById__' + relationName, {
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
|
@ -568,9 +568,9 @@ Model.scopeRemoting = function(scopeName, scope, define) {
|
||||||
http: {verb: 'get', path: '/' + pathName + '/count'},
|
http: {verb: 'get', path: '/' + pathName + '/count'},
|
||||||
accepts: {arg: 'where', type: 'object', description: 'Criteria to match model instances'},
|
accepts: {arg: 'where', type: 'object', description: 'Criteria to match model instances'},
|
||||||
description: 'Counts ' + scopeName + ' of ' + this.modelName + '.',
|
description: 'Counts ' + scopeName + ' of ' + this.modelName + '.',
|
||||||
returns: {arg: 'count', type: 'number'}
|
returns: {arg: 'count', type: 'number'}
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Model.nestRemoting = function(relationName, options, cb) {
|
Model.nestRemoting = function(relationName, options, cb) {
|
||||||
|
@ -579,7 +579,7 @@ Model.nestRemoting = function(relationName, options, cb) {
|
||||||
options = {};
|
options = {};
|
||||||
}
|
}
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
var regExp = /^__([^_]+)__([^_]+)$/;
|
var regExp = /^__([^_]+)__([^_]+)$/;
|
||||||
var relation = this.relations[relationName];
|
var relation = this.relations[relationName];
|
||||||
if (relation && relation.modelTo && relation.modelTo.sharedClass) {
|
if (relation && relation.modelTo && relation.modelTo.sharedClass) {
|
||||||
|
@ -587,17 +587,17 @@ Model.nestRemoting = function(relationName, options, cb) {
|
||||||
var sharedClass = this.sharedClass;
|
var sharedClass = this.sharedClass;
|
||||||
var sharedToClass = relation.modelTo.sharedClass;
|
var sharedToClass = relation.modelTo.sharedClass;
|
||||||
var toModelName = relation.modelTo.modelName;
|
var toModelName = relation.modelTo.modelName;
|
||||||
|
|
||||||
var pathName = options.pathName || relation.options.path || relationName;
|
var pathName = options.pathName || relation.options.path || relationName;
|
||||||
var paramName = options.paramName || 'nk';
|
var paramName = options.paramName || 'nk';
|
||||||
|
|
||||||
var http = [].concat(sharedToClass.http || [])[0];
|
var http = [].concat(sharedToClass.http || [])[0];
|
||||||
|
|
||||||
if (relation.multiple) {
|
if (relation.multiple) {
|
||||||
var httpPath = pathName + '/:' + paramName;
|
var httpPath = pathName + '/:' + paramName;
|
||||||
var acceptArgs = [
|
var acceptArgs = [
|
||||||
{
|
{
|
||||||
arg: paramName, type: 'any', http: { source: 'path' },
|
arg: paramName, type: 'any', http: { source: 'path' },
|
||||||
description: 'Foreign key for ' + relation.name,
|
description: 'Foreign key for ' + relation.name,
|
||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
|
@ -606,7 +606,7 @@ Model.nestRemoting = function(relationName, options, cb) {
|
||||||
var httpPath = pathName;
|
var httpPath = pathName;
|
||||||
var acceptArgs = [];
|
var acceptArgs = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// A method should return the method name to use, if it is to be
|
// A method should return the method name to use, if it is to be
|
||||||
// included as a nested method - a falsy return value will skip.
|
// included as a nested method - a falsy return value will skip.
|
||||||
var filter = cb || options.filterMethod || function(method, relation) {
|
var filter = cb || options.filterMethod || function(method, relation) {
|
||||||
|
@ -615,31 +615,31 @@ Model.nestRemoting = function(relationName, options, cb) {
|
||||||
return '__' + matches[1] + '__' + relation.name + '__' + matches[2];
|
return '__' + matches[1] + '__' + relation.name + '__' + matches[2];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
sharedToClass.methods().forEach(function(method) {
|
sharedToClass.methods().forEach(function(method) {
|
||||||
var methodName;
|
var methodName;
|
||||||
if (!method.isStatic && (methodName = filter(method, relation))) {
|
if (!method.isStatic && (methodName = filter(method, relation))) {
|
||||||
var prefix = relation.multiple ? '__findById__' : '__get__';
|
var prefix = relation.multiple ? '__findById__' : '__get__';
|
||||||
var getterName = options.getterName || (prefix + relationName);
|
var getterName = options.getterName || (prefix + relationName);
|
||||||
|
|
||||||
var getterFn = relation.modelFrom.prototype[getterName];
|
var getterFn = relation.modelFrom.prototype[getterName];
|
||||||
if (typeof getterFn !== 'function') {
|
if (typeof getterFn !== 'function') {
|
||||||
throw new Error('Invalid remote method: `' + getterName + '`');
|
throw new Error('Invalid remote method: `' + getterName + '`');
|
||||||
}
|
}
|
||||||
|
|
||||||
var nestedFn = relation.modelTo.prototype[method.name];
|
var nestedFn = relation.modelTo.prototype[method.name];
|
||||||
if (typeof nestedFn !== 'function') {
|
if (typeof nestedFn !== 'function') {
|
||||||
throw new Error('Invalid remote method: `' + method.name + '`');
|
throw new Error('Invalid remote method: `' + method.name + '`');
|
||||||
}
|
}
|
||||||
|
|
||||||
var opts = {};
|
var opts = {};
|
||||||
|
|
||||||
opts.accepts = acceptArgs.concat(method.accepts || []);
|
opts.accepts = acceptArgs.concat(method.accepts || []);
|
||||||
opts.returns = [].concat(method.returns || []);
|
opts.returns = [].concat(method.returns || []);
|
||||||
opts.description = method.description;
|
opts.description = method.description;
|
||||||
opts.rest = extend({}, method.rest || {});
|
opts.rest = extend({}, method.rest || {});
|
||||||
opts.rest.delegateTo = method.name;
|
opts.rest.delegateTo = method.name;
|
||||||
|
|
||||||
opts.http = [];
|
opts.http = [];
|
||||||
var routes = [].concat(method.http || []);
|
var routes = [].concat(method.http || []);
|
||||||
routes.forEach(function(route) {
|
routes.forEach(function(route) {
|
||||||
|
@ -649,7 +649,7 @@ Model.nestRemoting = function(relationName, options, cb) {
|
||||||
opts.http.push(copy);
|
opts.http.push(copy);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (relation.multiple) {
|
if (relation.multiple) {
|
||||||
sharedClass.defineMethod(methodName, opts, function(fkId) {
|
sharedClass.defineMethod(methodName, opts, function(fkId) {
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
var args = Array.prototype.slice.call(arguments, 1);
|
||||||
|
@ -681,17 +681,17 @@ Model.nestRemoting = function(relationName, options, cb) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (options.hooks === false) return; // don't inherit before/after hooks
|
if (options.hooks === false) return; // don't inherit before/after hooks
|
||||||
|
|
||||||
self.once('mounted', function(app, sc, remotes) {
|
self.once('mounted', function(app, sc, remotes) {
|
||||||
var listenerTree = extend({}, remotes.listenerTree || {});
|
var listenerTree = extend({}, remotes.listenerTree || {});
|
||||||
listenerTree.before = listenerTree.before || {};
|
listenerTree.before = listenerTree.before || {};
|
||||||
listenerTree.after = listenerTree.after || {};
|
listenerTree.after = listenerTree.after || {};
|
||||||
|
|
||||||
var beforeListeners = remotes.listenerTree.before[toModelName] || {};
|
var beforeListeners = remotes.listenerTree.before[toModelName] || {};
|
||||||
var afterListeners = remotes.listenerTree.after[toModelName] || {};
|
var afterListeners = remotes.listenerTree.after[toModelName] || {};
|
||||||
|
|
||||||
sharedClass.methods().forEach(function(method) {
|
sharedClass.methods().forEach(function(method) {
|
||||||
var delegateTo = method.rest && method.rest.delegateTo;
|
var delegateTo = method.rest && method.rest.delegateTo;
|
||||||
if (delegateTo) {
|
if (delegateTo) {
|
||||||
|
@ -711,7 +711,7 @@ Model.nestRemoting = function(relationName, options, cb) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Relation `' + relationName + '` does not exist for model `' + this.modelName + '`');
|
throw new Error('Relation `' + relationName + '` does not exist for model `' + this.modelName + '`');
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,9 +43,9 @@ PersistedModel.setup = function setupPersistedModel() {
|
||||||
PersistedModel.enableChangeTracking();
|
PersistedModel.enableChangeTracking();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
PersistedModel.setupRemoting();
|
PersistedModel.setupRemoting();
|
||||||
}
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Throw an error telling the user that the method is not available and why.
|
* Throw an error telling the user that the method is not available and why.
|
||||||
|
@ -260,7 +260,7 @@ PersistedModel.destroyById = function deleteById(id, cb) {
|
||||||
/**
|
/**
|
||||||
* Alias for destroyById.
|
* Alias for destroyById.
|
||||||
*/
|
*/
|
||||||
PersistedModel.removeById = PersistedModel.destroyById
|
PersistedModel.removeById = PersistedModel.destroyById;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Alias for destroyById.
|
* Alias for destroyById.
|
||||||
|
@ -338,7 +338,7 @@ PersistedModel.prototype.save = function (options, callback) {
|
||||||
// then save
|
// then save
|
||||||
function save() {
|
function save() {
|
||||||
inst.trigger('save', function (saveDone) {
|
inst.trigger('save', function (saveDone) {
|
||||||
inst.trigger('update', function (updateDone) {
|
inst.trigger('update', function (updateDone) {
|
||||||
Model.upsert(inst, function(err) {
|
Model.upsert(inst, function(err) {
|
||||||
inst._initProperties(data);
|
inst._initProperties(data);
|
||||||
updateDone.call(inst, function () {
|
updateDone.call(inst, function () {
|
||||||
|
@ -430,7 +430,7 @@ PersistedModel.prototype.reload = function reload(callback) {
|
||||||
PersistedModel.prototype.setId = function(val) {
|
PersistedModel.prototype.setId = function(val) {
|
||||||
var ds = this.getDataSource();
|
var ds = this.getDataSource();
|
||||||
this[this.getIdName()] = val;
|
this[this.getIdName()] = val;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the `id` value for the `PersistedModel`.
|
* Get the `id` value for the `PersistedModel`.
|
||||||
|
@ -442,7 +442,7 @@ PersistedModel.prototype.getId = function() {
|
||||||
var data = this.toObject();
|
var data = this.toObject();
|
||||||
if(!data) return;
|
if(!data) return;
|
||||||
return data[this.getIdName()];
|
return data[this.getIdName()];
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the id property name of the constructor.
|
* Get the id property name of the constructor.
|
||||||
|
@ -452,7 +452,7 @@ PersistedModel.prototype.getId = function() {
|
||||||
|
|
||||||
PersistedModel.prototype.getIdName = function() {
|
PersistedModel.prototype.getIdName = function() {
|
||||||
return this.constructor.getIdName();
|
return this.constructor.getIdName();
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the id property name of the constructor.
|
* Get the id property name of the constructor.
|
||||||
|
@ -469,7 +469,7 @@ PersistedModel.getIdName = function() {
|
||||||
} else {
|
} else {
|
||||||
return 'id';
|
return 'id';
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
PersistedModel.setupRemoting = function() {
|
PersistedModel.setupRemoting = function() {
|
||||||
var PersistedModel = this;
|
var PersistedModel = this;
|
||||||
|
@ -597,7 +597,7 @@ PersistedModel.setupRemoting = function() {
|
||||||
{arg: 'since', type: 'number', description: 'Find deltas since this checkpoint'},
|
{arg: 'since', type: 'number', description: 'Find deltas since this checkpoint'},
|
||||||
{arg: 'remoteChanges', type: 'array', description: 'an array of change objects',
|
{arg: 'remoteChanges', type: 'array', description: 'an array of change objects',
|
||||||
http: {source: 'body'}}
|
http: {source: 'body'}}
|
||||||
],
|
],
|
||||||
returns: {arg: 'result', type: 'object', root: true},
|
returns: {arg: 'result', type: 'object', root: true},
|
||||||
http: {verb: 'post', path: '/diff'}
|
http: {verb: 'post', path: '/diff'}
|
||||||
});
|
});
|
||||||
|
@ -612,7 +612,7 @@ PersistedModel.setupRemoting = function() {
|
||||||
returns: {arg: 'changes', type: 'array', root: true},
|
returns: {arg: 'changes', type: 'array', root: true},
|
||||||
http: {verb: 'get', path: '/changes'}
|
http: {verb: 'get', path: '/changes'}
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'checkpoint', {
|
setRemoting(PersistedModel, 'checkpoint', {
|
||||||
description: 'Create a checkpoint.',
|
description: 'Create a checkpoint.',
|
||||||
returns: {arg: 'checkpoint', type: 'object', root: true},
|
returns: {arg: 'checkpoint', type: 'object', root: true},
|
||||||
|
@ -649,22 +649,22 @@ PersistedModel.setupRemoting = function() {
|
||||||
http: {verb: 'post', path: '/:id/rectify-change'}
|
http: {verb: 'post', path: '/:id/rectify-change'}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a set of deltas and conflicts since the given checkpoint.
|
* Get a set of deltas and conflicts since the given checkpoint.
|
||||||
*
|
*
|
||||||
* See `Change.diff()` for details.
|
* See `Change.diff()` for details.
|
||||||
*
|
*
|
||||||
* @param {Number} since Find deltas since this checkpoint
|
* @param {Number} since Find deltas since this checkpoint
|
||||||
* @param {Array} remoteChanges An array of change objects
|
* @param {Array} remoteChanges An array of change objects
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PersistedModel.diff = function(since, remoteChanges, callback) {
|
PersistedModel.diff = function(since, remoteChanges, callback) {
|
||||||
var Change = this.getChangeModel();
|
var Change = this.getChangeModel();
|
||||||
Change.diff(this.modelName, since, remoteChanges, callback);
|
Change.diff(this.modelName, since, remoteChanges, callback);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the changes to a model since a given checkpoint. Provide a filter object
|
* Get the changes to a model since a given checkpoint. Provide a filter object
|
||||||
|
@ -720,11 +720,11 @@ PersistedModel.changes = function(since, filter, callback) {
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a checkpoint.
|
* Create a checkpoint.
|
||||||
*
|
*
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -736,11 +736,11 @@ PersistedModel.checkpoint = function(cb) {
|
||||||
sourceId: sourceId
|
sourceId: sourceId
|
||||||
}, cb);
|
}, cb);
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current checkpoint id.
|
* Get the current checkpoint id.
|
||||||
*
|
*
|
||||||
* @callback {Function} callback
|
* @callback {Function} callback
|
||||||
* @param {Error} err
|
* @param {Error} err
|
||||||
* @param {Number} currentCheckpointId
|
* @param {Number} currentCheckpointId
|
||||||
|
@ -750,7 +750,7 @@ PersistedModel.checkpoint = function(cb) {
|
||||||
PersistedModel.currentCheckpoint = function(cb) {
|
PersistedModel.currentCheckpoint = function(cb) {
|
||||||
var Checkpoint = this.getChangeModel().getCheckpointModel();
|
var Checkpoint = this.getChangeModel().getCheckpointModel();
|
||||||
Checkpoint.current(cb);
|
Checkpoint.current(cb);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replicate changes since the given checkpoint to the given target model.
|
* Replicate changes since the given checkpoint to the given target model.
|
||||||
|
@ -793,7 +793,7 @@ PersistedModel.replicate = function(since, targetModel, options, callback) {
|
||||||
|
|
||||||
callback = callback || function defaultReplicationCallback(err) {
|
callback = callback || function defaultReplicationCallback(err) {
|
||||||
if(err) throw err;
|
if(err) throw err;
|
||||||
}
|
};
|
||||||
|
|
||||||
var tasks = [
|
var tasks = [
|
||||||
getSourceChanges,
|
getSourceChanges,
|
||||||
|
@ -848,13 +848,13 @@ PersistedModel.replicate = function(since, targetModel, options, callback) {
|
||||||
|
|
||||||
callback && callback(null, conflicts);
|
callback && callback(null, conflicts);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an update list (for `Model.bulkUpdate()`) from a delta list
|
* Create an update list (for `Model.bulkUpdate()`) from a delta list
|
||||||
* (result of `Change.diff()`).
|
* (result of `Change.diff()`).
|
||||||
*
|
*
|
||||||
* @param {Array} deltas
|
* @param {Array} deltas
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -899,13 +899,13 @@ PersistedModel.createUpdates = function(deltas, cb) {
|
||||||
if(err) return cb(err);
|
if(err) return cb(err);
|
||||||
cb(null, updates);
|
cb(null, updates);
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply an update list.
|
* Apply an update list.
|
||||||
*
|
*
|
||||||
* **Note: this is not atomic**
|
* **Note: this is not atomic**
|
||||||
*
|
*
|
||||||
* @param {Array} updates An updates list (usually from Model.createUpdates())
|
* @param {Array} updates An updates list (usually from Model.createUpdates())
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
|
@ -937,11 +937,11 @@ PersistedModel.bulkUpdate = function(updates, callback) {
|
||||||
});
|
});
|
||||||
|
|
||||||
async.parallel(tasks, callback);
|
async.parallel(tasks, callback);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the `Change` model.
|
* Get the `Change` model.
|
||||||
*
|
*
|
||||||
* @throws {Error} Throws an error if the change model is not correctly setup.
|
* @throws {Error} Throws an error if the change model is not correctly setup.
|
||||||
* @return {Change}
|
* @return {Change}
|
||||||
*/
|
*/
|
||||||
|
@ -953,11 +953,11 @@ PersistedModel.getChangeModel = function() {
|
||||||
assert(isSetup, 'Cannot get a setup Change model');
|
assert(isSetup, 'Cannot get a setup Change model');
|
||||||
|
|
||||||
return changeModel;
|
return changeModel;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the source identifier for this model / dataSource.
|
* Get the source identifier for this model / dataSource.
|
||||||
*
|
*
|
||||||
* @callback {Function} callback
|
* @callback {Function} callback
|
||||||
* @param {Error} err
|
* @param {Error} err
|
||||||
* @param {String} sourceId
|
* @param {String} sourceId
|
||||||
|
@ -969,12 +969,12 @@ PersistedModel.getSourceId = function(cb) {
|
||||||
this.once('dataSourceAttached', this.getSourceId.bind(this, cb));
|
this.once('dataSourceAttached', this.getSourceId.bind(this, cb));
|
||||||
}
|
}
|
||||||
assert(
|
assert(
|
||||||
dataSource.connector.name,
|
dataSource.connector.name,
|
||||||
'Model.getSourceId: cannot get id without dataSource.connector.name'
|
'Model.getSourceId: cannot get id without dataSource.connector.name'
|
||||||
);
|
);
|
||||||
var id = [dataSource.connector.name, this.modelName].join('-');
|
var id = [dataSource.connector.name, this.modelName].join('-');
|
||||||
cb(null, id);
|
cb(null, id);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable the tracking of changes made to the model. Usually for replication.
|
* Enable the tracking of changes made to the model. Usually for replication.
|
||||||
|
@ -993,11 +993,11 @@ PersistedModel.enableChangeTracking = function() {
|
||||||
|
|
||||||
Model.afterSave = function afterSave(next) {
|
Model.afterSave = function afterSave(next) {
|
||||||
Model.rectifyChange(this.getId(), next);
|
Model.rectifyChange(this.getId(), next);
|
||||||
}
|
};
|
||||||
|
|
||||||
Model.afterDestroy = function afterDestroy(next) {
|
Model.afterDestroy = function afterDestroy(next) {
|
||||||
Model.rectifyChange(this.getId(), next);
|
Model.rectifyChange(this.getId(), next);
|
||||||
}
|
};
|
||||||
|
|
||||||
Model.on('deletedAll', cleanup);
|
Model.on('deletedAll', cleanup);
|
||||||
|
|
||||||
|
@ -1017,7 +1017,7 @@ PersistedModel.enableChangeTracking = function() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
PersistedModel._defineChangeModel = function() {
|
PersistedModel._defineChangeModel = function() {
|
||||||
var BaseChangeModel = registry.getModel('Change');
|
var BaseChangeModel = registry.getModel('Change');
|
||||||
|
@ -1030,11 +1030,11 @@ PersistedModel._defineChangeModel = function() {
|
||||||
trackModel: this
|
trackModel: this
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
PersistedModel.rectifyAllChanges = function(callback) {
|
PersistedModel.rectifyAllChanges = function(callback) {
|
||||||
this.getChangeModel().rectifyAll(callback);
|
this.getChangeModel().rectifyAll(callback);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a change error. Override this method in a subclassing model to customize
|
* Handle a change error. Override this method in a subclassing model to customize
|
||||||
|
@ -1048,7 +1048,7 @@ PersistedModel.handleChangeError = function(err) {
|
||||||
console.error(Model.modelName + ' Change Tracking Error:');
|
console.error(Model.modelName + ' Change Tracking Error:');
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tell loopback that a change to the model with the given id has occurred.
|
* Tell loopback that a change to the model with the given id has occurred.
|
||||||
|
@ -1061,6 +1061,6 @@ PersistedModel.handleChangeError = function(err) {
|
||||||
PersistedModel.rectifyChange = function(id, callback) {
|
PersistedModel.rectifyChange = function(id, callback) {
|
||||||
var Change = this.getChangeModel();
|
var Change = this.getChangeModel();
|
||||||
Change.rectifyModelChanges(this.modelName, [id], callback);
|
Change.rectifyModelChanges(this.modelName, [id], callback);
|
||||||
}
|
};
|
||||||
|
|
||||||
PersistedModel.setup();
|
PersistedModel.setup();
|
||||||
|
|
Loading…
Reference in New Issue