| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 | 'use strict';var util = require('util');var union = require('arr-union');var define = require('define-property');var staticExtend = require('static-extend');var isObj = require('isobject');/** * Expose class utils */var cu = module.exports;/** * Expose class utils: `cu` */cu.isObject = function isObject(val) {  return isObj(val) || typeof val === 'function';};/** * Returns true if an array has any of the given elements, or an * object has any of the give keys. * * ```js * cu.has(['a', 'b', 'c'], 'c'); * //=> true * * cu.has(['a', 'b', 'c'], ['c', 'z']); * //=> true * * cu.has({a: 'b', c: 'd'}, ['c', 'z']); * //=> true * ``` * @param {Object} `obj` * @param {String|Array} `val` * @return {Boolean} * @api public */cu.has = function has(obj, val) {  val = cu.arrayify(val);  var len = val.length;  if (cu.isObject(obj)) {    for (var key in obj) {      if (val.indexOf(key) > -1) {        return true;      }    }    var keys = cu.nativeKeys(obj);    return cu.has(keys, val);  }  if (Array.isArray(obj)) {    var arr = obj;    while (len--) {      if (arr.indexOf(val[len]) > -1) {        return true;      }    }    return false;  }  throw new TypeError('expected an array or object.');};/** * Returns true if an array or object has all of the given values. * * ```js * cu.hasAll(['a', 'b', 'c'], 'c'); * //=> true * * cu.hasAll(['a', 'b', 'c'], ['c', 'z']); * //=> false * * cu.hasAll({a: 'b', c: 'd'}, ['c', 'z']); * //=> false * ``` * @param {Object|Array} `val` * @param {String|Array} `values` * @return {Boolean} * @api public */cu.hasAll = function hasAll(val, values) {  values = cu.arrayify(values);  var len = values.length;  while (len--) {    if (!cu.has(val, values[len])) {      return false;    }  }  return true;};/** * Cast the given value to an array. * * ```js * cu.arrayify('foo'); * //=> ['foo'] * * cu.arrayify(['foo']); * //=> ['foo'] * ``` * * @param {String|Array} `val` * @return {Array} * @api public */cu.arrayify = function arrayify(val) {  return val ? (Array.isArray(val) ? val : [val]) : [];};/** * Noop */cu.noop = function noop() {  return;};/** * Returns the first argument passed to the function. */cu.identity = function identity(val) {  return val;};/** * Returns true if a value has a `contructor` * * ```js * cu.hasConstructor({}); * //=> true * * cu.hasConstructor(Object.create(null)); * //=> false * ``` * @param  {Object} `value` * @return {Boolean} * @api public */cu.hasConstructor = function hasConstructor(val) {  return cu.isObject(val) && typeof val.constructor !== 'undefined';};/** * Get the native `ownPropertyNames` from the constructor of the * given `object`. An empty array is returned if the object does * not have a constructor. * * ```js * cu.nativeKeys({a: 'b', b: 'c', c: 'd'}) * //=> ['a', 'b', 'c'] * * cu.nativeKeys(function(){}) * //=> ['length', 'caller'] * ``` * * @param  {Object} `obj` Object that has a `constructor`. * @return {Array} Array of keys. * @api public */cu.nativeKeys = function nativeKeys(val) {  if (!cu.hasConstructor(val)) return [];  var keys = Object.getOwnPropertyNames(val);  if ('caller' in val) keys.push('caller');  return keys;};/** * Returns property descriptor `key` if it's an "own" property * of the given object. * * ```js * function App() {} * Object.defineProperty(App.prototype, 'count', { *   get: function() { *     return Object.keys(this).length; *   } * }); * cu.getDescriptor(App.prototype, 'count'); * // returns: * // { * //   get: [Function], * //   set: undefined, * //   enumerable: false, * //   configurable: false * // } * ``` * * @param {Object} `obj` * @param {String} `key` * @return {Object} Returns descriptor `key` * @api public */cu.getDescriptor = function getDescriptor(obj, key) {  if (!cu.isObject(obj)) {    throw new TypeError('expected an object.');  }  if (typeof key !== 'string') {    throw new TypeError('expected key to be a string.');  }  return Object.getOwnPropertyDescriptor(obj, key);};/** * Copy a descriptor from one object to another. * * ```js * function App() {} * Object.defineProperty(App.prototype, 'count', { *   get: function() { *     return Object.keys(this).length; *   } * }); * var obj = {}; * cu.copyDescriptor(obj, App.prototype, 'count'); * ``` * @param {Object} `receiver` * @param {Object} `provider` * @param {String} `name` * @return {Object} * @api public */cu.copyDescriptor = function copyDescriptor(receiver, provider, name) {  if (!cu.isObject(receiver)) {    throw new TypeError('expected receiving object to be an object.');  }  if (!cu.isObject(provider)) {    throw new TypeError('expected providing object to be an object.');  }  if (typeof name !== 'string') {    throw new TypeError('expected name to be a string.');  }  var val = cu.getDescriptor(provider, name);  if (val) Object.defineProperty(receiver, name, val);};/** * Copy static properties, prototype properties, and descriptors * from one object to another. * * @param {Object} `receiver` * @param {Object} `provider` * @param {String|Array} `omit` One or more properties to omit * @return {Object} * @api public */cu.copy = function copy(receiver, provider, omit) {  if (!cu.isObject(receiver)) {    throw new TypeError('expected receiving object to be an object.');  }  if (!cu.isObject(provider)) {    throw new TypeError('expected providing object to be an object.');  }  var props = Object.getOwnPropertyNames(provider);  var keys = Object.keys(provider);  var len = props.length,    key;  omit = cu.arrayify(omit);  while (len--) {    key = props[len];    if (cu.has(keys, key)) {      define(receiver, key, provider[key]);    } else if (!(key in receiver) && !cu.has(omit, key)) {      cu.copyDescriptor(receiver, provider, key);    }  }};/** * Inherit the static properties, prototype properties, and descriptors * from of an object. * * @param {Object} `receiver` * @param {Object} `provider` * @param {String|Array} `omit` One or more properties to omit * @return {Object} * @api public */cu.inherit = function inherit(receiver, provider, omit) {  if (!cu.isObject(receiver)) {    throw new TypeError('expected receiving object to be an object.');  }  if (!cu.isObject(provider)) {    throw new TypeError('expected providing object to be an object.');  }  var keys = [];  for (var key in provider) {    keys.push(key);    receiver[key] = provider[key];  }  keys = keys.concat(cu.arrayify(omit));  var a = provider.prototype || provider;  var b = receiver.prototype || receiver;  cu.copy(b, a, keys);};/** * Returns a function for extending the static properties, * prototype properties, and descriptors from the `Parent` * constructor onto `Child` constructors. * * ```js * var extend = cu.extend(Parent); * Parent.extend(Child); * * // optional methods * Parent.extend(Child, { *   foo: function() {}, *   bar: function() {} * }); * ``` * @param {Function} `Parent` Parent ctor * @param {Function} `extend` Optional extend function to handle custom extensions. Useful when updating methods that require a specific prototype. *   @param {Function} `Child` Child ctor *   @param {Object} `proto` Optionally pass additional prototype properties to inherit. *   @return {Object} * @api public */cu.extend = function() {  // keep it lazy, instead of assigning to `cu.extend`  return staticExtend.apply(null, arguments);};/** * Bubble up events emitted from static methods on the Parent ctor. * * @param {Object} `Parent` * @param {Array} `events` Event names to bubble up * @api public */cu.bubble = function(Parent, events) {  events = events || [];  Parent.bubble = function(Child, arr) {    if (Array.isArray(arr)) {      events = union([], events, arr);    }    var len = events.length;    var idx = -1;    while (++idx < len) {      var name = events[idx];      Parent.on(name, Child.emit.bind(Child, name));    }    cu.bubble(Child, events);  };};
 |