Merge branch 'release/1.2.13' into production
This commit is contained in:
commit
758cea9f5c
|
@ -4,7 +4,9 @@ LoopBack DataSource Juggler is an ORM that provides a common set of interfaces
|
|||
for interacting with databases, REST APIs, and other data sources. It was
|
||||
initially forked from [JugglingDB](https://github.com/1602/jugglingdb).
|
||||
|
||||
For full documentation, see [StrongLoop Suite Documentation](http://docs.strongloop.com/display/DOC/Data+Source+Juggler).
|
||||
**For full documentation, see the official StrongLoop documentation**:
|
||||
* [Data sources and connectors](http://docs.strongloop.com/display/DOC/Data+sources+and+connectors)
|
||||
* [Data Source Juggler](http://docs.strongloop.com/display/DOC/Data+Source+Juggler).
|
||||
|
||||
## Installation
|
||||
|
||||
|
|
|
@ -58,12 +58,15 @@ The `DataSource` constructor is available from `loopback-datasource-juggler` mod
|
|||
- connector: The name or instance of the connector module
|
||||
- settings: An object of properties to configure the connector
|
||||
|
||||
|
||||
```
|
||||
var dataSource = new DataSource({
|
||||
connector: require('loopback-connector-mongodb'),
|
||||
host: 'localhost',
|
||||
port: 27017,
|
||||
database: 'mydb'
|
||||
});
|
||||
```
|
||||
|
||||
#### connector
|
||||
|
||||
|
@ -75,10 +78,11 @@ The `connector` argument passed the DataSource constructor can be one of the fol
|
|||
to 'loopback-connector-<shortName>'
|
||||
* A local module under ./connectors/<connectorName> folder
|
||||
|
||||
|
||||
```
|
||||
var ds1 = new DataSource('memory');
|
||||
var ds2 = new DataSource('loopback-connector-mongodb'));
|
||||
var ds3 = new DataSource(require('loopback-connector-oracle'));
|
||||
```
|
||||
|
||||
**Note**: LoopBack provides a built-in connector named as `memory` to use in-memory
|
||||
store for CRUD operations.
|
||||
|
|
|
@ -4,12 +4,14 @@ var modelBuilder = new ModelBuilder();
|
|||
var Post = modelBuilder.define('Post', {
|
||||
title: { type: String, length: 255 },
|
||||
content: { type: ModelBuilder.Text },
|
||||
date: { type: Date, default: function () { return new Date;} },
|
||||
date: { type: Date, default: function () {
|
||||
return new Date();
|
||||
} },
|
||||
timestamp: { type: Number, default: Date.now },
|
||||
published: { type: Boolean, default: false, index: true }
|
||||
});
|
||||
|
||||
// simplier way to describe model
|
||||
// simpler way to describe model
|
||||
var User = modelBuilder.define('User', {
|
||||
name: String,
|
||||
bio: ModelBuilder.Text,
|
||||
|
|
|
@ -15,14 +15,18 @@ var User = modelBuilder.define('User', {
|
|||
zipCode: String,
|
||||
country: String
|
||||
},
|
||||
emails: [{
|
||||
emails: [
|
||||
{
|
||||
label: String,
|
||||
email: String
|
||||
}],
|
||||
}
|
||||
],
|
||||
friends: [String]
|
||||
});
|
||||
|
||||
var user = new User({name: 'Joe', age: 20, address: {street: '123 Main St', 'city': 'San Jose', state: 'CA'},
|
||||
emails: [{label: 'work', email: 'xyz@sample.com'}],
|
||||
emails: [
|
||||
{label: 'work', email: 'xyz@sample.com'}
|
||||
],
|
||||
friends: ['John', 'Mary']});
|
||||
console.log(user.toObject());
|
||||
|
|
|
@ -24,7 +24,6 @@ Customer.create({name: 'John'}, function (err, customer) {
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
Customer.hasMany(Order, {as: 'orders', foreignKey: 'customerId'});
|
||||
|
||||
Customer.create({name: 'Ray'}, function (err, customer) {
|
||||
|
@ -41,7 +40,6 @@ Customer.create({name: 'Ray'}, function (err, customer) {
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
var Physician = ds.createModel('Physician', {
|
||||
name: String
|
||||
});
|
||||
|
@ -72,7 +70,6 @@ Physician.create({name: 'Smith'}, function (err, physician) {
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
var Assembly = ds.createModel('Assembly', {
|
||||
name: String
|
||||
});
|
||||
|
|
|
@ -27,7 +27,6 @@ Connector.prototype.execute = function (command, params, callback) {
|
|||
throw new Error('query method should be declared in connector');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Look up the data source by model name
|
||||
* @param {String} model The model name
|
||||
|
@ -59,7 +58,6 @@ Connector.prototype.idNames = function (model) {
|
|||
return this.getDataSource(model).idNames(model);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the id index (sequence number, starting from 1)
|
||||
* @param {String} model The model name
|
||||
|
@ -126,6 +124,10 @@ Connector.prototype.setIdValue = function(model, data, value) {
|
|||
}
|
||||
};
|
||||
|
||||
Connector.prototype.getType = function () {
|
||||
return this.type;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -16,8 +16,14 @@ function CradleAdapter(client) {
|
|||
function createdbif(client, callback) {
|
||||
client.exists(function (err, exists) {
|
||||
if (err) callback(err);
|
||||
if (!exists) { client.create(function() { callback(); }); }
|
||||
else { callback(); }
|
||||
if (!exists) {
|
||||
client.create(function () {
|
||||
callback();
|
||||
});
|
||||
}
|
||||
else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -278,7 +284,8 @@ CradleAdapter.prototype.models = function(model, filter, callback, func) {
|
|||
}
|
||||
}
|
||||
}, function () {
|
||||
self.client.view(model+'/all', {include_docs:true, limit:limit, skip:skip}, errorHandler(callback, function(res, cb) {
|
||||
self.client.view(model + '/all', {include_docs: true, limit: limit, skip: skip},
|
||||
errorHandler(callback, function (res, cb) {
|
||||
var docs = res.map(function (doc) {
|
||||
return idealize(doc);
|
||||
});
|
||||
|
|
|
@ -24,7 +24,8 @@ WebService.prototype.installPostProcessor = function installPostProcessor(descr)
|
|||
if (model[column]) {
|
||||
model[column] = new Date(model[column]);
|
||||
}
|
||||
};
|
||||
}
|
||||
;
|
||||
};
|
||||
|
||||
descr.postProcessor = postProcessor;
|
||||
|
@ -55,7 +56,8 @@ WebService.prototype.postProcessMultiple = function postProcessMultiple(model, d
|
|||
if (data[i]) {
|
||||
postProcessor(data[i]);
|
||||
}
|
||||
};
|
||||
}
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -190,6 +190,7 @@ Neo4j.prototype.updateIndexes = function updateIndexes(model, node, cb) {
|
|||
done();
|
||||
|
||||
var error = false;
|
||||
|
||||
function done(err) {
|
||||
error = error || err;
|
||||
if (--wait === 0) {
|
||||
|
|
22
lib/dao.js
22
lib/dao.js
|
@ -19,7 +19,6 @@ var utils = require('./utils');
|
|||
var fieldsToArray = utils.fieldsToArray;
|
||||
var removeUndefined = utils.removeUndefined;
|
||||
|
||||
|
||||
/**
|
||||
* DAO class - base class for all persist objects
|
||||
* provides **common API** to access any database connector.
|
||||
|
@ -94,7 +93,8 @@ DataAccessObject.create = function (data, callback) {
|
|||
}
|
||||
|
||||
if (typeof callback !== 'function') {
|
||||
callback = function () {};
|
||||
callback = function () {
|
||||
};
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
|
@ -130,7 +130,6 @@ DataAccessObject.create = function (data, callback) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
var obj;
|
||||
// if we come from save
|
||||
if (data instanceof Model && !getIdValue(this, data)) {
|
||||
|
@ -250,7 +249,6 @@ setRemoting(DataAccessObject.upsert, {
|
|||
http: {verb: 'put', path: '/'}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Find one record, same as `all`, limited by 1 and return object, not collection,
|
||||
* if not found, create using data provided as second argument
|
||||
|
@ -268,7 +266,8 @@ DataAccessObject.findOrCreate = function findOrCreate(query, data, callback) {
|
|||
data = query && query.where;
|
||||
}
|
||||
if (typeof callback === 'undefined') {
|
||||
callback = function () {};
|
||||
callback = function () {
|
||||
};
|
||||
}
|
||||
|
||||
var t = this;
|
||||
|
@ -599,7 +598,6 @@ setRemoting(DataAccessObject.findOne, {
|
|||
http: {verb: 'get', path: '/findOne'}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Destroy all matching records
|
||||
* @param {Object} [where] An object that defines the criteria
|
||||
|
@ -652,7 +650,6 @@ setRemoting(DataAccessObject.deleteById, {
|
|||
http: {verb: 'del', path: '/:id'}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Return count of matched records
|
||||
*
|
||||
|
@ -671,7 +668,6 @@ DataAccessObject.count = function (where, cb) {
|
|||
this.getDataSource().connector.count(this.modelName, cb, where);
|
||||
};
|
||||
|
||||
|
||||
// count ~ remoting attributes
|
||||
setRemoting(DataAccessObject.count, {
|
||||
description: 'Count instances of the model matched by where from the data source',
|
||||
|
@ -680,7 +676,6 @@ setRemoting(DataAccessObject.count, {
|
|||
http: {verb: 'get', path: '/count'}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Save instance. When instance haven't id, create method called instead.
|
||||
* Triggers: validate, save, update | create
|
||||
|
@ -695,7 +690,8 @@ DataAccessObject.prototype.save = function (options, callback) {
|
|||
options = {};
|
||||
}
|
||||
|
||||
callback = callback || function () {};
|
||||
callback = callback || function () {
|
||||
};
|
||||
options = options || {};
|
||||
|
||||
if (!('validate' in options)) {
|
||||
|
@ -752,7 +748,6 @@ DataAccessObject.prototype.save = function (options, callback) {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
DataAccessObject.prototype.isNewRecord = function () {
|
||||
return !getIdValue(this.constructor, this);
|
||||
};
|
||||
|
@ -788,7 +783,6 @@ DataAccessObject.prototype.destroy = function (cb) {
|
|||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Update single attribute
|
||||
*
|
||||
|
@ -851,7 +845,8 @@ DataAccessObject.prototype.updateAttributes = function updateAttributes(data, cb
|
|||
// update $was attrs
|
||||
for (var key in data) {
|
||||
inst.__dataWas[key] = inst.__data[key];
|
||||
};
|
||||
}
|
||||
;
|
||||
}
|
||||
done.call(inst, function () {
|
||||
saveDone.call(inst, function () {
|
||||
|
@ -873,7 +868,6 @@ setRemoting(DataAccessObject.prototype.updateAttributes, {
|
|||
http: {verb: 'put', path: '/'}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Reload object from persistence
|
||||
*
|
||||
|
|
|
@ -15,8 +15,6 @@ var fs = require('fs');
|
|||
var assert = require('assert');
|
||||
var async = require('async');
|
||||
|
||||
var existsSync = fs.existsSync || path.existsSync;
|
||||
|
||||
/**
|
||||
* Export public API
|
||||
*/
|
||||
|
@ -91,7 +89,8 @@ function DataSource(name, settings, modelBuilder) {
|
|||
|
||||
// DataAccessObject - connector defined or supply the default
|
||||
var dao = (connector && connector.DataAccessObject) || this.constructor.DataAccessObject;
|
||||
this.DataAccessObject = function() {};
|
||||
this.DataAccessObject = function () {
|
||||
};
|
||||
|
||||
// define DataAccessObject methods
|
||||
Object.keys(dao).forEach(function (name) {
|
||||
|
@ -129,15 +128,11 @@ function DataSource(name, settings, modelBuilder) {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
util.inherits(DataSource, EventEmitter);
|
||||
|
||||
// allow child classes to supply a data access object
|
||||
DataSource.DataAccessObject = DataAccessObject;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set up the connector instance for backward compatibility with JugglingDB schema/adapter
|
||||
* @private
|
||||
|
@ -351,7 +346,6 @@ function isModelClass(cls) {
|
|||
|
||||
DataSource.relationTypes = ['belongsTo', 'hasMany', 'hasAndBelongsToMany'];
|
||||
|
||||
|
||||
function isModelDataSourceAttached(model) {
|
||||
return model && (!model.settings.unresolved) && (model.dataSource instanceof DataSource);
|
||||
}
|
||||
|
@ -524,7 +518,6 @@ DataSource.prototype.createModel = DataSource.prototype.define = function define
|
|||
return modelClass;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Mixin DataAccessObject methods.
|
||||
*
|
||||
|
@ -684,7 +677,6 @@ DataSource.prototype.discoverModelDefinitions = function (options, cb) {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The synchronous version of discoverModelDefinitions
|
||||
* @param {Object} options The options
|
||||
|
@ -881,7 +873,7 @@ DataSource.prototype.discoverExportedForeignKeysSync= function(modelName, option
|
|||
return this.connector.discoverExportedForeignKeysSync(modelName, options);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
function capitalize(str) {
|
||||
if (!str) {
|
||||
|
@ -1102,7 +1094,6 @@ DataSource.prototype.discoverSchemas = function (modelName, options, cb) {
|
|||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Discover schema from a given table/view synchronously
|
||||
*
|
||||
|
@ -1419,7 +1410,6 @@ DataSource.prototype.idNames = function (modelName) {
|
|||
return this.getModelDefinition(modelName).idNames();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Define foreign key to another model
|
||||
* @param {String} className The model name that owns the key
|
||||
|
@ -1430,11 +1420,19 @@ DataSource.prototype.defineForeignKey = function defineForeignKey(className, key
|
|||
// quit if key already defined
|
||||
if (this.getModelDefinition(className).rawProperties[key]) return;
|
||||
|
||||
var defaultType = Number;
|
||||
if (foreignClassName) {
|
||||
var foreignModel = this.getModelDefinition(foreignClassName);
|
||||
var pkName = foreignModel && foreignModel.idName();
|
||||
if (pkName) {
|
||||
defaultType = foreignModel.properties[pkName].type;
|
||||
}
|
||||
}
|
||||
if (this.connector.defineForeignKey) {
|
||||
var cb = function (err, keyType) {
|
||||
if (err) throw err;
|
||||
// Add the foreign key property to the data source _models
|
||||
this.defineProperty(className, key, {type: keyType || Number});
|
||||
this.defineProperty(className, key, {type: keyType || defaultType});
|
||||
}.bind(this);
|
||||
switch (this.connector.defineForeignKey.length) {
|
||||
case 4:
|
||||
|
@ -1447,7 +1445,7 @@ DataSource.prototype.defineForeignKey = function defineForeignKey(className, key
|
|||
}
|
||||
} else {
|
||||
// Add the foreign key property to the data source _models
|
||||
this.defineProperty(className, key, {type: Number});
|
||||
this.defineProperty(className, key, {type: defaultType});
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -1662,7 +1660,6 @@ DataSource.prototype.ready = function(obj, args) {
|
|||
return true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Define a hidden property
|
||||
* @param {Object} obj The property owner
|
||||
|
@ -1694,7 +1691,6 @@ function defineReadonlyProp(obj, key, value) {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
// Carry over a few properties/methods from the ModelBuilder as some tests use them
|
||||
DataSource.Text = ModelBuilder.Text;
|
||||
DataSource.JSON = ModelBuilder.JSON;
|
||||
|
|
|
@ -28,8 +28,10 @@ Hookable.afterDestroy = null;
|
|||
// TODO: Evaluate https://github.com/bnoguchi/hooks-js/
|
||||
Hookable.prototype.trigger = function trigger(actionName, work, data) {
|
||||
var capitalizedName = capitalize(actionName);
|
||||
var beforeHook = this.constructor["before" + capitalizedName] || this.constructor["pre" + capitalizedName];
|
||||
var afterHook = this.constructor["after" + capitalizedName] || this.constructor["post" + capitalizedName];
|
||||
var beforeHook = this.constructor["before" + capitalizedName]
|
||||
|| this.constructor["pre" + capitalizedName];
|
||||
var afterHook = this.constructor["after" + capitalizedName]
|
||||
|| this.constructor["post" + capitalizedName];
|
||||
if (actionName === 'validate') {
|
||||
beforeHook = beforeHook || this.constructor.beforeValidation;
|
||||
afterHook = afterHook || this.constructor.afterValidation;
|
||||
|
|
|
@ -87,7 +87,8 @@ Inclusion.include = function (objects, include, cb) {
|
|||
|
||||
if (!relation) {
|
||||
return function () {
|
||||
cb(new Error('Relation "' + relationName + '" is not defined for ' + self.modelName + ' model'));
|
||||
cb(new Error('Relation "' + relationName + '" is not defined for '
|
||||
+ self.modelName + ' model'));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,7 +111,8 @@ Inclusion.include = function (objects, include, cb) {
|
|||
var inValues = [];
|
||||
for (var j = 0; j < keyVals[relation.keyFrom].length; j++) {
|
||||
keysToBeProcessed[keyVals[relation.keyFrom][j]] = true;
|
||||
if (keyVals[relation.keyFrom][j] !== 'null' && keyVals[relation.keyFrom][j] !== 'undefined') {
|
||||
if (keyVals[relation.keyFrom][j] !== 'null'
|
||||
&& keyVals[relation.keyFrom][j] !== 'undefined') {
|
||||
inValues.push(keyVals[relation.keyFrom][j]);
|
||||
}
|
||||
}
|
||||
|
@ -145,7 +147,8 @@ Inclusion.include = function (objects, include, cb) {
|
|||
if (!objectsFrom[j].__cachedRelations) {
|
||||
objectsFrom[j].__cachedRelations = {};
|
||||
}
|
||||
objectsFrom[j].__cachedRelations[relationName] = relation.multiple ? [] : null;
|
||||
objectsFrom[j].__cachedRelations[relationName] =
|
||||
relation.multiple ? [] : null;
|
||||
}
|
||||
}
|
||||
cb(err, objsIncluded);
|
||||
|
@ -153,7 +156,6 @@ Inclusion.include = function (objects, include, cb) {
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
10
lib/jutil.js
10
lib/jutil.js
|
@ -14,7 +14,8 @@ exports.inherits = function (newClass, baseClass, options) {
|
|||
|
||||
if (options.staticProperties) {
|
||||
Object.keys(baseClass).forEach(function (classProp) {
|
||||
if (classProp !== 'super_' && (!newClass.hasOwnProperty(classProp) || options.override)) {
|
||||
if (classProp !== 'super_' && (!newClass.hasOwnProperty(classProp)
|
||||
|| options.override)) {
|
||||
var pd = Object.getOwnPropertyDescriptor(baseClass, classProp);
|
||||
Object.defineProperty(newClass, classProp, pd);
|
||||
}
|
||||
|
@ -22,7 +23,6 @@ exports.inherits = function (newClass, baseClass, options) {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Mix in the a class into the new class
|
||||
* @param newClass The target class to receive the mixin
|
||||
|
@ -57,9 +57,11 @@ exports.mixin = function (newClass, mixinClass, options) {
|
|||
if (options.staticProperties) {
|
||||
var staticProxies = [];
|
||||
Object.keys(mixinClass).forEach(function (classProp) {
|
||||
if (classProp !== 'super_' && classProp !== '_mixins' && (!newClass.hasOwnProperty(classProp) || options.override)) {
|
||||
if (classProp !== 'super_' && classProp !== '_mixins'
|
||||
&& (!newClass.hasOwnProperty(classProp) || options.override)) {
|
||||
var pd = Object.getOwnPropertyDescriptor(mixinClass, classProp);
|
||||
if(options.proxyFunctions && pd.writable && typeof pd.value === 'function') {
|
||||
if (options.proxyFunctions && pd.writable
|
||||
&& typeof pd.value === 'function') {
|
||||
pd.value = exports.proxy(pd.value, staticProxies);
|
||||
}
|
||||
Object.defineProperty(newClass, classProp, pd);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
module.exports = List;
|
||||
|
||||
/**
|
||||
|
|
|
@ -109,7 +109,8 @@ ModelBuilder.prototype.getModelDefinition = function(name) {
|
|||
ModelBuilder.prototype.define = function defineClass(className, properties, settings, parent) {
|
||||
var modelBuilder = this;
|
||||
var args = slice.call(arguments);
|
||||
var pluralName = settings && settings.plural;
|
||||
var pluralName = (settings && settings.plural) ||
|
||||
inflection.pluralize(className);
|
||||
|
||||
if (!className) {
|
||||
throw new Error('Class name required');
|
||||
|
@ -186,8 +187,9 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
|
|||
// Add metadata to the ModelClass
|
||||
hiddenProperty(ModelClass, 'modelBuilder', modelBuilder);
|
||||
hiddenProperty(ModelClass, 'dataSource', modelBuilder); // Keep for back-compatibility
|
||||
hiddenProperty(ModelClass, 'pluralModelName', pluralName || inflection.pluralize(className));
|
||||
hiddenProperty(ModelClass, 'pluralModelName', pluralName);
|
||||
hiddenProperty(ModelClass, 'relations', {});
|
||||
hiddenProperty(ModelClass, 'http', { path: '/' + pluralName });
|
||||
|
||||
// inherit ModelBaseClass static methods
|
||||
for (var i in ModelBaseClass) {
|
||||
|
@ -461,7 +463,6 @@ ModelBuilder.prototype.extendModel = function (model, props) {
|
|||
});
|
||||
};
|
||||
|
||||
|
||||
ModelBuilder.prototype.copyModel = function copyModel(Master) {
|
||||
var modelBuilder = this;
|
||||
var className = Master.modelName;
|
||||
|
@ -491,7 +492,6 @@ ModelBuilder.prototype.copyModel = function copyModel(Master) {
|
|||
return Slave;
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
* Define hidden property
|
||||
*/
|
||||
|
|
|
@ -49,7 +49,6 @@ util.inherits(ModelDefinition, EventEmitter);
|
|||
// Set up types
|
||||
require('./types')(ModelDefinition);
|
||||
|
||||
|
||||
/**
|
||||
* Return table name for specified `modelName`
|
||||
* @param {String} connectorType The connector type, such as 'oracle' or 'mongodb'
|
||||
|
@ -165,7 +164,8 @@ ModelDefinition.prototype.idName = function() {
|
|||
var id = this.ids()[0];
|
||||
if (this.properties.id && this.properties.id.id) {
|
||||
return 'id';
|
||||
} else {}
|
||||
} else {
|
||||
}
|
||||
return id && id.name;
|
||||
};
|
||||
|
||||
|
@ -253,7 +253,6 @@ ModelDefinition.prototype.defineProperty = function (propertyName, propertyDefin
|
|||
this.build(true);
|
||||
};
|
||||
|
||||
|
||||
function isModelClass(cls) {
|
||||
if (!cls) {
|
||||
return false;
|
||||
|
|
|
@ -68,7 +68,8 @@ Relation.hasMany = function hasMany(anotherClass, params) {
|
|||
data = {};
|
||||
}
|
||||
if ('function' !== typeof done) {
|
||||
done = function() {};
|
||||
done = function () {
|
||||
};
|
||||
}
|
||||
var self = this;
|
||||
anotherClass.create(data, function (err, ac) {
|
||||
|
|
|
@ -34,7 +34,6 @@ BaseSQL.prototype.queryOne = function (sql, callback) {
|
|||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the table name for a given model
|
||||
* @param {String} model The model name
|
||||
|
@ -96,7 +95,8 @@ BaseSQL.prototype.propertyName = function (model, column) {
|
|||
* @returns {String} The column name
|
||||
*/
|
||||
BaseSQL.prototype.idColumn = function (model) {
|
||||
var name = this.getDataSource(model).idColumnName(model);;
|
||||
var name = this.getDataSource(model).idColumnName(model);
|
||||
;
|
||||
var dbName = this.dbName;
|
||||
if (typeof dbName === 'function') {
|
||||
name = dbName(name);
|
||||
|
@ -155,7 +155,6 @@ BaseSQL.prototype.save = function (model, data, callback) {
|
|||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Check if a model instance exists for the given id value
|
||||
* @param {String} model The model name
|
||||
|
|
|
@ -58,4 +58,4 @@ module.exports = function (Types) {
|
|||
Types.registerType(Array);
|
||||
Types.registerType(GeoPoint);
|
||||
Types.registerType(Object);
|
||||
}
|
||||
};
|
|
@ -11,7 +11,9 @@ function safeRequire(module) {
|
|||
try {
|
||||
return require(module);
|
||||
} catch (e) {
|
||||
console.log('Run "npm install loopback-datasource-juggler ' + module + '" command to use loopback-datasource-juggler using ' + module + ' database engine');
|
||||
console.log('Run "npm install loopback-datasource-juggler ' + module
|
||||
+ '" command to use loopback-datasource-juggler using ' + module
|
||||
+ ' database engine');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +91,8 @@ function removeUndefined(query) {
|
|||
this.remove();
|
||||
}
|
||||
|
||||
if (!Array.isArray(x) && (typeof x === 'object' && x !== null && x.constructor !== Object)) {
|
||||
if (!Array.isArray(x) && (typeof x === 'object' && x !== null
|
||||
&& x.constructor !== Object)) {
|
||||
// This object is not a plain object
|
||||
this.update(x, true); // Stop navigating into this object
|
||||
return x;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "loopback-datasource-juggler",
|
||||
"version": "1.2.12",
|
||||
"version": "1.2.13",
|
||||
"description": "LoopBack DataSoure Juggler",
|
||||
"keywords": [
|
||||
"StrongLoop",
|
||||
|
|
|
@ -18,7 +18,6 @@ describe('basic-querying', function() {
|
|||
|
||||
});
|
||||
|
||||
|
||||
describe('findById', function () {
|
||||
|
||||
before(function (done) {
|
||||
|
@ -311,8 +310,6 @@ describe('basic-querying', function() {
|
|||
|
||||
});
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
function seed(done) {
|
||||
|
@ -323,7 +320,8 @@ function seed(done) {
|
|||
email: 'john@b3atl3s.co.uk',
|
||||
role: 'lead',
|
||||
order: 2
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'Paul McCartney',
|
||||
email: 'paul@b3atl3s.co.uk',
|
||||
role: 'lead',
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
var Schema = require('../index').Schema;
|
||||
var Text = Schema.Text;
|
||||
|
||||
|
@ -72,6 +71,7 @@ function clearAndCreate(model, data, callback) {
|
|||
});
|
||||
|
||||
var itemIndex = 0;
|
||||
|
||||
function nextItem(err, lastItem) {
|
||||
if (lastItem !== null) {
|
||||
createdItems.push(lastItem);
|
||||
|
@ -125,13 +125,17 @@ function testOrm(dataSource) {
|
|||
title: { type: String, length: 255, index: true },
|
||||
subject: { type: String },
|
||||
content: { type: Text },
|
||||
date: { type: Date, default: function () { return new Date }, index: true },
|
||||
date: { type: Date, default: function () {
|
||||
return new Date
|
||||
}, index: true },
|
||||
published: { type: Boolean, default: false, index: true },
|
||||
likes: [],
|
||||
related: [RelatedPost]
|
||||
}, {table: 'posts'});
|
||||
|
||||
function RelatedPost() { }
|
||||
function RelatedPost() {
|
||||
}
|
||||
|
||||
RelatedPost.prototype.someMethod = function () {
|
||||
return this.parent;
|
||||
};
|
||||
|
@ -417,7 +421,6 @@ function testOrm(dataSource) {
|
|||
test.done();
|
||||
});
|
||||
|
||||
|
||||
it('should handle hasMany relationship', function (test) {
|
||||
User.create(function (err, u) {
|
||||
if (err) return console.log(err);
|
||||
|
@ -588,12 +591,14 @@ function testOrm(dataSource) {
|
|||
});
|
||||
|
||||
it('should handle ORDER clause', function (test) {
|
||||
var titles = [ { title: 'Title A', subject: "B" },
|
||||
var titles = [
|
||||
{ title: 'Title A', subject: "B" },
|
||||
{ title: 'Title Z', subject: "A" },
|
||||
{ title: 'Title M', subject: "C" },
|
||||
{ title: 'Title A', subject: "A" },
|
||||
{ title: 'Title B', subject: "A" },
|
||||
{ title: 'Title C', subject: "D" }];
|
||||
{ title: 'Title C', subject: "D" }
|
||||
];
|
||||
var isRedis = Post.dataSource.name === 'redis';
|
||||
var dates = isRedis ? [ 5, 9, 0, 17, 10, 9 ] : [
|
||||
new Date(1000 * 5),
|
||||
|
@ -608,6 +613,7 @@ function testOrm(dataSource) {
|
|||
});
|
||||
|
||||
var i = 0, tests = 0;
|
||||
|
||||
function done(err, obj) {
|
||||
if (++i === titles.length) {
|
||||
doFilterAndSortTest();
|
||||
|
@ -713,6 +719,7 @@ function testOrm(dataSource) {
|
|||
}
|
||||
|
||||
var fin = 0;
|
||||
|
||||
function finished() {
|
||||
if (++fin === tests) {
|
||||
test.done();
|
||||
|
@ -790,7 +797,6 @@ function testOrm(dataSource) {
|
|||
// }
|
||||
// });
|
||||
|
||||
|
||||
// if (
|
||||
// dataSource.name === 'mysql' ||
|
||||
// dataSource.name === 'postgres'
|
||||
|
@ -884,6 +890,7 @@ function testOrm(dataSource) {
|
|||
});
|
||||
});
|
||||
var tests = 2;
|
||||
|
||||
function done() {
|
||||
process.nextTick(function () {
|
||||
if (--wait === 0) {
|
||||
|
|
|
@ -277,17 +277,49 @@ describe('hooks', function() {
|
|||
describe('lifecycle', function () {
|
||||
var life = [], user;
|
||||
before(function (done) {
|
||||
User.beforeSave = function(d){life.push('beforeSave'); d();};
|
||||
User.beforeCreate = function(d){life.push('beforeCreate'); d();};
|
||||
User.beforeUpdate = function(d){life.push('beforeUpdate'); d();};
|
||||
User.beforeDestroy = function(d){life.push('beforeDestroy');d();};
|
||||
User.beforeValidate = function(d){life.push('beforeValidate');d();};
|
||||
User.afterInitialize= function( ){life.push('afterInitialize'); };
|
||||
User.afterSave = function(d){life.push('afterSave'); d();};
|
||||
User.afterCreate = function(d){life.push('afterCreate'); d();};
|
||||
User.afterUpdate = function(d){life.push('afterUpdate'); d();};
|
||||
User.afterDestroy = function(d){life.push('afterDestroy'); d();};
|
||||
User.afterValidate = function(d){life.push('afterValidate');d();};
|
||||
User.beforeSave = function (d) {
|
||||
life.push('beforeSave');
|
||||
d();
|
||||
};
|
||||
User.beforeCreate = function (d) {
|
||||
life.push('beforeCreate');
|
||||
d();
|
||||
};
|
||||
User.beforeUpdate = function (d) {
|
||||
life.push('beforeUpdate');
|
||||
d();
|
||||
};
|
||||
User.beforeDestroy = function (d) {
|
||||
life.push('beforeDestroy');
|
||||
d();
|
||||
};
|
||||
User.beforeValidate = function (d) {
|
||||
life.push('beforeValidate');
|
||||
d();
|
||||
};
|
||||
User.afterInitialize = function () {
|
||||
life.push('afterInitialize');
|
||||
};
|
||||
User.afterSave = function (d) {
|
||||
life.push('afterSave');
|
||||
d();
|
||||
};
|
||||
User.afterCreate = function (d) {
|
||||
life.push('afterCreate');
|
||||
d();
|
||||
};
|
||||
User.afterUpdate = function (d) {
|
||||
life.push('afterUpdate');
|
||||
d();
|
||||
};
|
||||
User.afterDestroy = function (d) {
|
||||
life.push('afterDestroy');
|
||||
d();
|
||||
};
|
||||
User.afterValidate = function (d) {
|
||||
life.push('afterValidate');
|
||||
d();
|
||||
};
|
||||
User.create(function (e, u) {
|
||||
user = u;
|
||||
life = [];
|
||||
|
|
|
@ -197,6 +197,7 @@ function clearAndCreate(model, data, callback) {
|
|||
});
|
||||
|
||||
var itemIndex = 0;
|
||||
|
||||
function nextItem(err, lastItem) {
|
||||
if (lastItem !== null) {
|
||||
createdItems.push(lastItem);
|
||||
|
|
|
@ -98,7 +98,6 @@ describe('ModelBuilder define model', function () {
|
|||
done(null, User);
|
||||
});
|
||||
|
||||
|
||||
it('should be able to define nesting models', function (done) {
|
||||
var modelBuilder = new ModelBuilder();
|
||||
|
||||
|
@ -116,10 +115,12 @@ describe('ModelBuilder define model', function () {
|
|||
zipCode: String,
|
||||
country: String
|
||||
},
|
||||
emails: [{
|
||||
emails: [
|
||||
{
|
||||
label: String,
|
||||
email: String
|
||||
}],
|
||||
}
|
||||
],
|
||||
friends: [String]
|
||||
});
|
||||
|
||||
|
@ -134,7 +135,9 @@ describe('ModelBuilder define model', function () {
|
|||
var user = new User({
|
||||
name: 'Joe', age: 20,
|
||||
address: {street: '123 Main St', 'city': 'San Jose', state: 'CA'},
|
||||
emails: [{label: 'work', email: 'xyz@sample.com'}],
|
||||
emails: [
|
||||
{label: 'work', email: 'xyz@sample.com'}
|
||||
],
|
||||
friends: ['Mary', 'John']
|
||||
});
|
||||
|
||||
|
@ -189,10 +192,8 @@ describe('ModelBuilder define model', function () {
|
|||
done(null, User);
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('DataSource define model', function () {
|
||||
it('should be able to define plain models', function () {
|
||||
var ds = new DataSource('memory');
|
||||
|
@ -401,7 +402,6 @@ describe('DataSource define model', function () {
|
|||
done(null, User);
|
||||
});
|
||||
|
||||
|
||||
it('should change the property value for save if strict=false', function (done) {
|
||||
var ds = new DataSource('memory');// define models
|
||||
var Post = ds.define('Post');
|
||||
|
@ -424,8 +424,10 @@ describe('Load models with base', function () {
|
|||
|
||||
var User = ds.define('User', {name: String});
|
||||
|
||||
User.staticMethod = function staticMethod() {};
|
||||
User.prototype.instanceMethod = function instanceMethod() {};
|
||||
User.staticMethod = function staticMethod() {
|
||||
};
|
||||
User.prototype.instanceMethod = function instanceMethod() {
|
||||
};
|
||||
|
||||
var Customer = ds.define('Customer', {vip: Boolean}, {base: 'User'});
|
||||
|
||||
|
@ -433,7 +435,6 @@ describe('Load models with base', function () {
|
|||
assert(Customer.staticMethod === User.staticMethod);
|
||||
assert(Customer.prototype.instanceMethod === User.prototype.instanceMethod);
|
||||
|
||||
|
||||
try {
|
||||
var Customer1 = ds.define('Customer1', {vip: Boolean}, {base: 'User1'});
|
||||
} catch (e) {
|
||||
|
@ -510,6 +511,19 @@ describe('Load models with relations', function () {
|
|||
done();
|
||||
});
|
||||
|
||||
it('should set up foreign key with the correct type', function (done) {
|
||||
var ds = new DataSource('memory');
|
||||
|
||||
var User = ds.define('User', {name: String, id: {type: String, id: true}});
|
||||
var Post = ds.define('Post', {content: String}, {relations: {user: {type: 'belongsTo', model: 'User'}}});
|
||||
|
||||
var fk = Post.definition.properties['userId'];
|
||||
assert(fk, 'The foreign key should be added');
|
||||
assert(fk.type === String, 'The foreign key should be the same type as primary key');
|
||||
assert(Post.relations['user'], 'User relation should be set');
|
||||
done();
|
||||
});
|
||||
|
||||
it('should set up hasMany and belongsTo relations', function (done) {
|
||||
var ds = new DataSource('memory');
|
||||
|
||||
|
@ -614,7 +628,6 @@ describe('Load models with relations', function () {
|
|||
done();
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
describe('DataAccessObject', function () {
|
||||
|
@ -728,7 +741,6 @@ describe('Load models from json', function () {
|
|||
var path = require('path'),
|
||||
fs = require('fs');
|
||||
|
||||
|
||||
/**
|
||||
* Load LDL schemas from a json doc
|
||||
* @param schemaFile The dataSource json file
|
||||
|
@ -914,7 +926,6 @@ describe('DataSource constructor', function(){
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
describe('Injected methods from connectors', function () {
|
||||
it('are not shared across models for remote methods', function () {
|
||||
var ds = new DataSource('memory');
|
||||
|
@ -952,7 +963,6 @@ describe('Injected methods from connectors', function(){
|
|||
|
||||
});
|
||||
|
||||
|
||||
describe('ModelBuilder options.models', function () {
|
||||
it('should inject model classes from models', function () {
|
||||
var builder = new ModelBuilder();
|
||||
|
|
|
@ -89,7 +89,11 @@ describe('manipulation', function() {
|
|||
});
|
||||
|
||||
it('should create batch of objects', function (done) {
|
||||
var batch = [{name: 'Shaltay'}, {name: 'Boltay'}, {}];
|
||||
var batch = [
|
||||
{name: 'Shaltay'},
|
||||
{name: 'Boltay'},
|
||||
{}
|
||||
];
|
||||
Person.create(batch,function (e, ps) {
|
||||
should.not.exist(e);
|
||||
should.exist(ps);
|
||||
|
|
|
@ -29,7 +29,6 @@ describe('ModelDefinition class', function () {
|
|||
assert.equal(User.properties.joinedAt.type, Date);
|
||||
assert.equal(User.properties.age.type, Number);
|
||||
|
||||
|
||||
var json = User.toJSON();
|
||||
assert.equal(json.name, "User");
|
||||
assert.equal(json.properties.name.type, "String");
|
||||
|
@ -40,7 +39,6 @@ describe('ModelDefinition class', function () {
|
|||
|
||||
done();
|
||||
|
||||
|
||||
});
|
||||
|
||||
it('should be able to define additional properties', function (done) {
|
||||
|
@ -66,10 +64,8 @@ describe('ModelDefinition class', function () {
|
|||
assert.equal(User.properties.id.type, Number);
|
||||
done();
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
it('should be able to define nesting models', function (done) {
|
||||
var modelBuilder = new ModelBuilder();
|
||||
|
||||
|
@ -112,7 +108,6 @@ describe('ModelDefinition class', function () {
|
|||
|
||||
});
|
||||
|
||||
|
||||
it('should be able to define referencing models', function (done) {
|
||||
var modelBuilder = new ModelBuilder();
|
||||
|
||||
|
@ -140,7 +135,6 @@ describe('ModelDefinition class', function () {
|
|||
assert.equal(User.properties.age.type, Number);
|
||||
assert.equal(User.properties.address.type, Address);
|
||||
|
||||
|
||||
var json = User.toJSON();
|
||||
assert.equal(json.name, "User");
|
||||
assert.equal(json.properties.name.type, "String");
|
||||
|
@ -182,7 +176,6 @@ describe('ModelDefinition class', function () {
|
|||
assert.equal(User.properties.age.type, Number);
|
||||
assert.equal(User.properties.address.type, Address);
|
||||
|
||||
|
||||
var json = User.toJSON();
|
||||
assert.equal(json.name, "User");
|
||||
assert.equal(json.properties.name.type, "String");
|
||||
|
|
|
@ -15,14 +15,12 @@ schemas =
|
|||
url: 'http://localhost:5984/nano-test'
|
||||
|
||||
testOrm = (dataSource) ->
|
||||
|
||||
User = Post = 'unknown'
|
||||
maxUsers = 100
|
||||
maxPosts = 50000
|
||||
users = []
|
||||
|
||||
it 'should define simple', (test) ->
|
||||
|
||||
User = dataSource.define 'User', {
|
||||
name: String,
|
||||
bio: Text,
|
||||
|
@ -51,7 +49,8 @@ testOrm = (dataSource) ->
|
|||
|
||||
it 'should create bunch of data', (test) ->
|
||||
wait = maxPosts
|
||||
done = -> test.done() if --wait == 0
|
||||
done = ->
|
||||
test.done() if --wait == 0
|
||||
rnd = (title) ->
|
||||
{
|
||||
userId: users[Math.floor(Math.random() * maxUsers)].id
|
||||
|
@ -61,11 +60,13 @@ testOrm = (dataSource) ->
|
|||
|
||||
it 'do some queries using foreign keys', (test) ->
|
||||
wait = 4
|
||||
done = -> test.done() if --wait == 0
|
||||
done = ->
|
||||
test.done() if --wait == 0
|
||||
ts = Date.now()
|
||||
query = (num) ->
|
||||
users[num].posts { title: 'Post number 3' }, (err, collection) ->
|
||||
console.log('User ' + num + ':', collection.length, 'posts in', Date.now() - ts,'ms')
|
||||
console.log('User ' + num + ':', collection.length, 'posts in',
|
||||
Date.now() - ts, 'ms')
|
||||
done()
|
||||
query num for num in [0..4]
|
||||
|
||||
|
|
|
@ -4,11 +4,9 @@ var fieldsToArray = utils.fieldsToArray;
|
|||
var removeUndefined = utils.removeUndefined;
|
||||
var mergeSettings = utils.mergeSettings;
|
||||
|
||||
|
||||
describe('util.fieldsToArray', function () {
|
||||
it('Turn objects and strings into an array of fields to include when finding models', function () {
|
||||
|
||||
|
||||
function sample(fields) {
|
||||
var properties = ['foo', 'bar', 'bat', 'baz'];
|
||||
return {
|
||||
|
|
Loading…
Reference in New Issue