Merge branch 'release/1.2.6' into production
This commit is contained in:
commit
aeb1a7cce2
|
@ -90,14 +90,14 @@ function DataSource(name, settings, modelBuilder) {
|
||||||
var connector = this.connector;
|
var connector = this.connector;
|
||||||
|
|
||||||
// DataAccessObject - connector defined or supply the default
|
// DataAccessObject - connector defined or supply the default
|
||||||
this.DataAccessObject = (connector && connector.DataAccessObject) ? connector.DataAccessObject : this.constructor.DataAccessObject;
|
var dao = (connector && connector.DataAccessObject) || this.constructor.DataAccessObject;
|
||||||
this.DataAccessObject.apply(this, arguments);
|
this.DataAccessObject = function() {};
|
||||||
|
|
||||||
|
|
||||||
// define DataAccessObject methods
|
// define DataAccessObject methods
|
||||||
Object.keys(this.DataAccessObject).forEach(function (name) {
|
Object.keys(dao).forEach(function (name) {
|
||||||
var fn = this.DataAccessObject[name];
|
var fn = dao[name];
|
||||||
|
this.DataAccessObject[name] = fn;
|
||||||
|
|
||||||
if(typeof fn === 'function') {
|
if(typeof fn === 'function') {
|
||||||
this.defineOperation(name, {
|
this.defineOperation(name, {
|
||||||
accepts: fn.accepts,
|
accepts: fn.accepts,
|
||||||
|
@ -111,11 +111,10 @@ function DataSource(name, settings, modelBuilder) {
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
// define DataAccessObject.prototype methods
|
// define DataAccessObject.prototype methods
|
||||||
Object.keys(this.DataAccessObject.prototype).forEach(function (name) {
|
Object.keys(dao.prototype).forEach(function (name) {
|
||||||
var fn = this.DataAccessObject.prototype[name];
|
var fn = dao.prototype[name];
|
||||||
|
this.DataAccessObject.prototype[name] = fn;
|
||||||
if(typeof fn === 'function') {
|
if(typeof fn === 'function') {
|
||||||
|
|
||||||
this.defineOperation(name, {
|
this.defineOperation(name, {
|
||||||
prototype: true,
|
prototype: true,
|
||||||
accepts: fn.accepts,
|
accepts: fn.accepts,
|
||||||
|
@ -127,8 +126,11 @@ function DataSource(name, settings, modelBuilder) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
util.inherits(DataSource, EventEmitter);
|
util.inherits(DataSource, EventEmitter);
|
||||||
|
|
||||||
// allow child classes to supply a data access object
|
// allow child classes to supply a data access object
|
||||||
|
@ -232,7 +234,7 @@ DataSource.prototype.setup = function(name, settings) {
|
||||||
}
|
}
|
||||||
connector = require(name);
|
connector = require(name);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return console.log('\nWARNING: LoopbackData connector "' + name + '" is not installed,\nso your models would not work, to fix run:\n\n npm install ' + name, '\n');
|
return console.log('\nWARNING: LoopBack connector "' + name + '" is not installed,\nso your models would not work, to fix run:\n\n npm install ' + name, '\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -501,7 +503,7 @@ DataSource.prototype.mixin = function (ModelCtor) {
|
||||||
var DAO = this.DataAccessObject;
|
var DAO = this.DataAccessObject;
|
||||||
|
|
||||||
// mixin DAO
|
// mixin DAO
|
||||||
jutil.mixin(ModelCtor, DAO);
|
jutil.mixin(ModelCtor, DAO, {proxyFunctions : true});
|
||||||
|
|
||||||
// decorate operations as alias functions
|
// decorate operations as alias functions
|
||||||
Object.keys(ops).forEach(function (name) {
|
Object.keys(ops).forEach(function (name) {
|
||||||
|
@ -920,7 +922,7 @@ DataSource.prototype.discoverSchemas = function (modelName, options, cb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
var schemaName = this.name || this.connector.name;
|
var schemaName = this.connector.name || this.name;
|
||||||
|
|
||||||
var tasks = [
|
var tasks = [
|
||||||
this.discoverModelProperties.bind(this, modelName, options),
|
this.discoverModelProperties.bind(this, modelName, options),
|
||||||
|
@ -1027,14 +1029,13 @@ DataSource.prototype.discoverSchemas = function (modelName, options, cb) {
|
||||||
console.log('Foreign keys: ', fks);
|
console.log('Foreign keys: ', fks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
schema.options.relations = {};
|
||||||
foreignKeys.forEach(function (fk) {
|
foreignKeys.forEach(function (fk) {
|
||||||
var propName = fromDBName(fk.pkTableName, true);
|
var propName = fromDBName(fk.pkTableName, true);
|
||||||
schema.properties[propName] = {
|
schema.options.relations[propName] = {
|
||||||
type: fromDBName(fk.pkTableName, false),
|
model: fromDBName(fk.pkTableName, false),
|
||||||
relation: {
|
type: 'belongsTo',
|
||||||
type: 'belongsTo',
|
foreignKey: fromDBName(fk.fkColumnName, true)
|
||||||
foreignKey: fromDBName(fk.pkColumnName, true)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var key = fk.pkOwner + '.' + fk.pkTableName;
|
var key = fk.pkOwner + '.' + fk.pkTableName;
|
||||||
|
@ -1175,14 +1176,13 @@ DataSource.prototype.discoverSchemasSync = function (modelName, options) {
|
||||||
console.log('Foreign keys: ', fks);
|
console.log('Foreign keys: ', fks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
schema.options.relations = {};
|
||||||
foreignKeys.forEach(function (fk) {
|
foreignKeys.forEach(function (fk) {
|
||||||
var propName = fromDBName(fk.pkTableName, true);
|
var propName = fromDBName(fk.pkTableName, true);
|
||||||
schema.properties[propName] = {
|
schema.options.relations[propName] = {
|
||||||
type: fromDBName(fk.pkTableName, false),
|
model: fromDBName(fk.pkTableName, false),
|
||||||
relation: {
|
type: 'belongsTo',
|
||||||
type: 'belongsTo',
|
foreignKey: fromDBName(fk.fkColumnName, true)
|
||||||
foreignKey: fromDBName(fk.pkColumnName, true)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var key = fk.pkOwner + '.' + fk.pkTableName;
|
var key = fk.pkOwner + '.' + fk.pkTableName;
|
||||||
|
@ -1241,6 +1241,10 @@ DataSource.prototype.discoverAndBuildModels = function (modelName, options, cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
var models = self.modelBuilder.buildModels(schemaList);
|
var models = self.modelBuilder.buildModels(schemaList);
|
||||||
|
// Now attach the models to the data source
|
||||||
|
for(var m in models) {
|
||||||
|
models[m].attachTo(self);
|
||||||
|
}
|
||||||
cb && cb(err, models);
|
cb && cb(err, models);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
27
lib/jutil.js
27
lib/jutil.js
|
@ -42,13 +42,25 @@ exports.mixin = function (newClass, mixinClass, options) {
|
||||||
options = options || {
|
options = options || {
|
||||||
staticProperties: true,
|
staticProperties: true,
|
||||||
instanceProperties: true,
|
instanceProperties: true,
|
||||||
override: false
|
override: false,
|
||||||
|
proxyFunctions: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if(options.staticProperties === undefined) {
|
||||||
|
options.staticProperties = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(options.instanceProperties === undefined) {
|
||||||
|
options.instanceProperties = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (options.staticProperties) {
|
if (options.staticProperties) {
|
||||||
Object.keys(mixinClass).forEach(function (classProp) {
|
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);
|
var pd = Object.getOwnPropertyDescriptor(mixinClass, classProp);
|
||||||
|
if(options.proxyFunctions && pd.writable && typeof pd.value === 'function') {
|
||||||
|
pd.value = exports.proxy(pd.value);
|
||||||
|
}
|
||||||
Object.defineProperty(newClass, classProp, pd);
|
Object.defineProperty(newClass, classProp, pd);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -59,6 +71,9 @@ exports.mixin = function (newClass, mixinClass, options) {
|
||||||
Object.keys(mixinClass.prototype).forEach(function (instanceProp) {
|
Object.keys(mixinClass.prototype).forEach(function (instanceProp) {
|
||||||
if (!newClass.prototype.hasOwnProperty(instanceProp) || options.override) {
|
if (!newClass.prototype.hasOwnProperty(instanceProp) || options.override) {
|
||||||
var pd = Object.getOwnPropertyDescriptor(mixinClass.prototype, instanceProp);
|
var pd = Object.getOwnPropertyDescriptor(mixinClass.prototype, instanceProp);
|
||||||
|
if(options.proxyFunctions && pd.writable && typeof pd.value === 'function') {
|
||||||
|
pd.value = exports.proxy(pd.value);
|
||||||
|
}
|
||||||
Object.defineProperty(newClass.prototype, instanceProp, pd);
|
Object.defineProperty(newClass.prototype, instanceProp, pd);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -68,3 +83,13 @@ exports.mixin = function (newClass, mixinClass, options) {
|
||||||
return newClass;
|
return newClass;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.proxy = function(fn) {
|
||||||
|
var f = function() {
|
||||||
|
return fn.apply(this, arguments);
|
||||||
|
};
|
||||||
|
Object.keys(fn).forEach(function(x) {
|
||||||
|
f[x] = fn[x];
|
||||||
|
});
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
|
@ -195,7 +195,7 @@ Relation.belongsTo = function (anotherClass, params) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var idName = this.dataSource.idName(this.modelName) || 'id';
|
var idName = this.dataSource.idName(anotherClass.modelName) || 'id';
|
||||||
var methodName = params.as || i8n.camelize(anotherClass.modelName, true);
|
var methodName = params.as || i8n.camelize(anotherClass.modelName, true);
|
||||||
var fk = params.foreignKey || methodName + 'Id';
|
var fk = params.foreignKey || methodName + 'Id';
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "loopback-datasource-juggler",
|
"name": "loopback-datasource-juggler",
|
||||||
"version": "1.2.5",
|
"version": "1.2.6",
|
||||||
"description": "LoopBack DataSoure Juggler",
|
"description": "LoopBack DataSoure Juggler",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"StrongLoop",
|
"StrongLoop",
|
||||||
|
|
|
@ -673,3 +673,34 @@ 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');
|
||||||
|
var M1 = ds.createModel('M1');
|
||||||
|
var M2 = ds.createModel('M2');
|
||||||
|
// Remotable methods are not shared across models
|
||||||
|
assert.notEqual(M1.create, M2.create, 'Remotable methods are not shared');
|
||||||
|
assert.equal(M1.create.shared, true, 'M1.create is remotable');
|
||||||
|
assert.equal(M2.create.shared, true, 'M2.create is remotable');
|
||||||
|
M1.create.shared = false;
|
||||||
|
assert.equal(M1.create.shared, false, 'M1.create should be local now');
|
||||||
|
assert.equal(M2.create.shared, true, 'M2.create should stay remotable');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('are not shared across models for non-remote methods', function() {
|
||||||
|
var ds = new DataSource('memory');
|
||||||
|
var M1 = ds.createModel('M1');
|
||||||
|
var M2 = ds.createModel('M2');
|
||||||
|
var m1 = M1.prototype.save;
|
||||||
|
var m2 = M2.prototype.save;
|
||||||
|
assert.notEqual(m1, m2, 'non-remote methods are not shared');
|
||||||
|
assert.equal(!!m1.shared, false, 'M1.save is not remotable');
|
||||||
|
assert.equal(!!m2.shared, false, 'M2.save is not remotable');
|
||||||
|
m1.shared = true;
|
||||||
|
assert.equal(m1.shared, true, 'M1.save is now remotable');
|
||||||
|
assert.equal(!!m2.shared, false, 'M2.save is not remotable');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in New Issue