loopback-datasource-juggler/lib/jutil.js

105 lines
2.9 KiB
JavaScript
Raw Normal View History

2016-04-01 22:25:16 +00:00
// Copyright IBM Corp. 2011,2016. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
2016-08-22 19:55:22 +00:00
'use strict';
2018-12-07 14:54:29 +00:00
const util = require('util');
2013-05-28 05:20:30 +00:00
/**
*
* @param newClass
* @param baseClass
*/
2016-04-01 11:48:17 +00:00
exports.inherits = function(newClass, baseClass, options) {
2014-01-24 17:09:53 +00:00
util.inherits(newClass, baseClass);
2013-05-29 17:03:01 +00:00
2014-01-24 17:09:53 +00:00
options = options || {
staticProperties: true,
2016-04-01 11:48:17 +00:00
override: false,
2014-01-24 17:09:53 +00:00
};
2013-05-29 17:03:01 +00:00
2014-01-24 17:09:53 +00:00
if (options.staticProperties) {
2016-04-01 11:48:17 +00:00
Object.keys(baseClass).forEach(function(classProp) {
2016-04-01 13:23:42 +00:00
if (classProp !== 'super_' && (!newClass.hasOwnProperty(classProp) ||
options.override)) {
2018-12-07 14:54:29 +00:00
const pd = Object.getOwnPropertyDescriptor(baseClass, classProp);
2014-01-24 17:09:53 +00:00
Object.defineProperty(newClass, classProp, pd);
}
});
}
2011-10-10 13:22:51 +00:00
};
2013-05-28 05:20:30 +00:00
/**
* Mix in the a class into the new class
* @param newClass The target class to receive the mixin
* @param mixinClass The class to be mixed in
2013-05-28 05:20:30 +00:00
* @param options
*/
2016-04-01 11:48:17 +00:00
exports.mixin = function(newClass, mixinClass, options) {
2014-01-24 17:09:53 +00:00
if (Array.isArray(newClass._mixins)) {
if (newClass._mixins.indexOf(mixinClass) !== -1) {
return;
}
2014-01-24 17:09:53 +00:00
newClass._mixins.push(mixinClass);
} else {
newClass._mixins = [mixinClass];
}
2014-01-24 17:09:53 +00:00
options = options || {
staticProperties: true,
instanceProperties: true,
override: false,
2016-04-01 11:48:17 +00:00
proxyFunctions: false,
2014-01-24 17:09:53 +00:00
};
2013-05-28 05:20:30 +00:00
2014-01-24 17:09:53 +00:00
if (options.staticProperties === undefined) {
options.staticProperties = true;
}
2013-12-04 21:44:25 +00:00
2014-01-24 17:09:53 +00:00
if (options.instanceProperties === undefined) {
options.instanceProperties = true;
}
2013-12-04 21:44:25 +00:00
2014-01-24 17:09:53 +00:00
if (options.staticProperties) {
mixInto(mixinClass, newClass, options);
2014-01-24 17:09:53 +00:00
}
2013-05-28 05:20:30 +00:00
if (options.instanceProperties && mixinClass.prototype) {
mixInto(mixinClass.prototype, newClass.prototype, options);
2014-01-24 17:09:53 +00:00
}
2014-01-24 17:09:53 +00:00
return newClass;
2013-05-28 05:20:30 +00:00
};
function mixInto(sourceScope, targetScope, options) {
2016-04-01 11:48:17 +00:00
Object.keys(sourceScope).forEach(function(propertyName) {
2018-12-07 14:54:29 +00:00
const targetPropertyExists = targetScope.hasOwnProperty(propertyName);
const sourceProperty = Object.getOwnPropertyDescriptor(sourceScope, propertyName);
const targetProperty = targetPropertyExists && Object.getOwnPropertyDescriptor(targetScope, propertyName);
const sourceIsFunc = typeof sourceProperty.value === 'function';
const isFunc = targetPropertyExists && typeof targetProperty.value === 'function';
const isDelegate = isFunc && targetProperty.value._delegate;
const shouldOverride = options.override || !targetPropertyExists || isDelegate;
if (propertyName == '_mixins') {
mergeMixins(sourceScope._mixins, targetScope._mixins);
return;
}
if (shouldOverride) {
Object.defineProperty(targetScope, propertyName, sourceProperty);
}
});
}
function mergeMixins(source, target) {
// hand-written equivalent of lodash.union()
2018-12-07 14:54:29 +00:00
for (const ix in source) {
const mx = source[ix];
if (target.indexOf(mx) === -1)
target.push(mx);
}
}