// Copyright IBM Corp. 2011,2019. 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 'use strict'; const util = require('util'); /** * * @param newClass * @param baseClass */ exports.inherits = function(newClass, baseClass, options) { util.inherits(newClass, baseClass); options = options || { staticProperties: true, override: false, }; if (options.staticProperties) { Object.keys(baseClass).forEach(function(classProp) { if (classProp !== 'super_' && (!newClass.hasOwnProperty(classProp) || options.override)) { const pd = Object.getOwnPropertyDescriptor(baseClass, classProp); Object.defineProperty(newClass, classProp, pd); } }); } }; /** * 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 * @param options */ exports.mixin = function(newClass, mixinClass, options) { if (Array.isArray(newClass._mixins)) { if (newClass._mixins.indexOf(mixinClass) !== -1) { return; } newClass._mixins.push(mixinClass); } else { newClass._mixins = [mixinClass]; } options = options || { staticProperties: true, instanceProperties: true, override: false, proxyFunctions: false, }; if (options.staticProperties === undefined) { options.staticProperties = true; } if (options.instanceProperties === undefined) { options.instanceProperties = true; } if (options.staticProperties) { mixInto(mixinClass, newClass, options); } if (options.instanceProperties && mixinClass.prototype) { mixInto(mixinClass.prototype, newClass.prototype, options); } return newClass; }; function mixInto(sourceScope, targetScope, options) { Object.keys(sourceScope).forEach(function(propertyName) { 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() for (const ix in source) { const mx = source[ix]; if (target.indexOf(mx) === -1) target.push(mx); } }