UNPKG

2.96 kBJavaScriptView Raw
1// Copyright IBM Corp. 2011,2019. All Rights Reserved.
2// Node module: loopback-datasource-juggler
3// This file is licensed under the MIT License.
4// License text available at https://opensource.org/licenses/MIT
5
6'use strict';
7
8const util = require('util');
9
10/**
11 *
12 * @param newClass
13 * @param baseClass
14 */
15exports.inherits = function(newClass, baseClass, options) {
16 util.inherits(newClass, baseClass);
17
18 options = options || {
19 staticProperties: true,
20 override: false,
21 };
22
23 if (options.staticProperties) {
24 Object.keys(baseClass).forEach(function(classProp) {
25 if (classProp !== 'super_' && (!newClass.hasOwnProperty(classProp) ||
26 options.override)) {
27 const pd = Object.getOwnPropertyDescriptor(baseClass, classProp);
28 Object.defineProperty(newClass, classProp, pd);
29 }
30 });
31 }
32};
33
34/**
35 * Mix in the a class into the new class
36 * @param newClass The target class to receive the mixin
37 * @param mixinClass The class to be mixed in
38 * @param options
39 */
40exports.mixin = function(newClass, mixinClass, options) {
41 if (Array.isArray(newClass._mixins)) {
42 if (newClass._mixins.indexOf(mixinClass) !== -1) {
43 return;
44 }
45 newClass._mixins.push(mixinClass);
46 } else {
47 newClass._mixins = [mixinClass];
48 }
49
50 options = options || {
51 staticProperties: true,
52 instanceProperties: true,
53 override: false,
54 proxyFunctions: false,
55 };
56
57 if (options.staticProperties === undefined) {
58 options.staticProperties = true;
59 }
60
61 if (options.instanceProperties === undefined) {
62 options.instanceProperties = true;
63 }
64
65 if (options.staticProperties) {
66 mixInto(mixinClass, newClass, options);
67 }
68
69 if (options.instanceProperties && mixinClass.prototype) {
70 mixInto(mixinClass.prototype, newClass.prototype, options);
71 }
72
73 return newClass;
74};
75
76function mixInto(sourceScope, targetScope, options) {
77 Object.keys(sourceScope).forEach(function(propertyName) {
78 const targetPropertyExists = targetScope.hasOwnProperty(propertyName);
79 const sourceProperty = Object.getOwnPropertyDescriptor(sourceScope, propertyName);
80 const targetProperty = targetPropertyExists && Object.getOwnPropertyDescriptor(targetScope, propertyName);
81 const sourceIsFunc = typeof sourceProperty.value === 'function';
82 const isFunc = targetPropertyExists && typeof targetProperty.value === 'function';
83 const isDelegate = isFunc && targetProperty.value._delegate;
84 const shouldOverride = options.override || !targetPropertyExists || isDelegate;
85
86 if (propertyName == '_mixins') {
87 mergeMixins(sourceScope._mixins, targetScope._mixins);
88 return;
89 }
90
91 if (shouldOverride) {
92 Object.defineProperty(targetScope, propertyName, sourceProperty);
93 }
94 });
95}
96
97function mergeMixins(source, target) {
98 // hand-written equivalent of lodash.union()
99 for (const ix in source) {
100 const mx = source[ix];
101 if (target.indexOf(mx) === -1)
102 target.push(mx);
103 }
104}