[Pkg-javascript-commits] [node-class-utils] 01/07: Import Upstream version 0.3.4

Sruthi Chandran srud-guest at moszumanska.debian.org
Fri Oct 28 07:45:21 UTC 2016


This is an automated email from the git hooks/post-receive script.

srud-guest pushed a commit to branch master
in repository node-class-utils.

commit 5c354fde2e4527b8f4cfd6079253ae6b7441449b
Author: Sruthi <srud at disroot.org>
Date:   Fri Oct 28 12:52:50 2016 +0530

    Import Upstream version 0.3.4
---
 .editorconfig    |  22 +++
 .eslintrc        | 125 +++++++++++++++
 .gitattributes   |  10 ++
 .gitignore       |  15 ++
 .travis.yml      |  10 ++
 .verb.md         |   8 +
 LICENSE          |  21 +++
 README.md        | 285 ++++++++++++++++++++++++++++++++++
 example.js       |   9 ++
 examples/a.js    |  34 ++++
 examples/app.js  |  33 ++++
 examples/b.js    |  39 +++++
 examples/c.js    |  34 ++++
 examples/meta.js |   6 +
 fixtures/app.js  |  22 +++
 gulpfile.js      |  63 ++++++++
 index.js         | 365 +++++++++++++++++++++++++++++++++++++++++++
 package.json     |  87 +++++++++++
 test.js          | 465 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 utils.js         |  21 +++
 20 files changed, 1674 insertions(+)

diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..991900b
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,22 @@
+# http://editorconfig.org
+root = true
+
+[*]
+indent_style = space
+end_of_line = lf
+charset = utf-8
+indent_size = 2
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
+insert_final_newline = false
+
+[test/**]
+trim_trailing_whitespace = false
+insert_final_newline = false
+
+[templates/**]
+trim_trailing_whitespace = false
+insert_final_newline = false
diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000..7b5d047
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,125 @@
+{
+  "ecmaFeatures": {
+    "modules": true,
+    "experimentalObjectRestSpread": true
+  },
+
+  "env": {
+    "browser": false,
+    "es6": true,
+    "node": true,
+    "mocha": true
+  },
+
+  "globals": {
+    "document": false,
+    "navigator": false,
+    "window": false
+  },
+
+  "rules": {
+    "accessor-pairs": 2,
+    "arrow-spacing": [2, { "before": true, "after": true }],
+    "block-spacing": [2, "always"],
+    "brace-style": [2, "1tbs", { "allowSingleLine": true }],
+    "comma-dangle": [2, "never"],
+    "comma-spacing": [2, { "before": false, "after": true }],
+    "comma-style": [2, "last"],
+    "constructor-super": 2,
+    "curly": [2, "multi-line"],
+    "dot-location": [2, "property"],
+    "eol-last": 2,
+    "eqeqeq": [2, "allow-null"],
+    "generator-star-spacing": [2, { "before": true, "after": true }],
+    "handle-callback-err": [2, "^(err|error)$" ],
+    "indent": [2, 2, { "SwitchCase": 1 }],
+    "key-spacing": [2, { "beforeColon": false, "afterColon": true }],
+    "new-cap": [2, { "newIsCap": true, "capIsNew": false }],
+    "new-parens": 2,
+    "no-array-constructor": 2,
+    "no-caller": 2,
+    "no-class-assign": 2,
+    "no-cond-assign": 2,
+    "no-const-assign": 2,
+    "no-control-regex": 2,
+    "no-debugger": 2,
+    "no-delete-var": 2,
+    "no-dupe-args": 2,
+    "no-dupe-class-members": 2,
+    "no-dupe-keys": 2,
+    "no-duplicate-case": 2,
+    "no-empty-character-class": 2,
+    "no-empty-label": 2,
+    "no-eval": 2,
+    "no-ex-assign": 2,
+    "no-extend-native": 2,
+    "no-extra-bind": 2,
+    "no-extra-boolean-cast": 2,
+    "no-extra-parens": [2, "functions"],
+    "no-fallthrough": 2,
+    "no-floating-decimal": 2,
+    "no-func-assign": 2,
+    "no-implied-eval": 2,
+    "no-inner-declarations": [2, "functions"],
+    "no-invalid-regexp": 2,
+    "no-irregular-whitespace": 2,
+    "no-iterator": 2,
+    "no-label-var": 2,
+    "no-labels": 2,
+    "no-lone-blocks": 2,
+    "no-mixed-spaces-and-tabs": 2,
+    "no-multi-spaces": 2,
+    "no-multi-str": 2,
+    "no-multiple-empty-lines": [2, { "max": 1 }],
+    "no-native-reassign": 2,
+    "no-negated-in-lhs": 2,
+    "no-new": 2,
+    "no-new-func": 2,
+    "no-new-object": 2,
+    "no-new-require": 2,
+    "no-new-wrappers": 2,
+    "no-obj-calls": 2,
+    "no-octal": 2,
+    "no-octal-escape": 2,
+    "no-proto": 0,
+    "no-redeclare": 2,
+    "no-regex-spaces": 2,
+    "no-return-assign": 2,
+    "no-self-compare": 2,
+    "no-sequences": 2,
+    "no-shadow-restricted-names": 2,
+    "no-spaced-func": 2,
+    "no-sparse-arrays": 2,
+    "no-this-before-super": 2,
+    "no-throw-literal": 2,
+    "no-trailing-spaces": 0,
+    "no-undef": 2,
+    "no-undef-init": 2,
+    "no-unexpected-multiline": 2,
+    "no-unneeded-ternary": [2, { "defaultAssignment": false }],
+    "no-unreachable": 2,
+    "no-unused-vars": [2, { "vars": "all", "args": "none" }],
+    "no-useless-call": 0,
+    "no-with": 2,
+    "one-var": [0, { "initialized": "never" }],
+    "operator-linebreak": [0, "after", { "overrides": { "?": "before", ":": "before" } }],
+    "padded-blocks": [0, "never"],
+    "quotes": [2, "single", "avoid-escape"],
+    "radix": 2,
+    "semi": [2, "always"],
+    "semi-spacing": [2, { "before": false, "after": true }],
+    "space-after-keywords": [2, "always"],
+    "space-before-blocks": [2, "always"],
+    "space-before-function-paren": [2, "never"],
+    "space-before-keywords": [2, "always"],
+    "space-in-parens": [2, "never"],
+    "space-infix-ops": 2,
+    "space-return-throw-case": 2,
+    "space-unary-ops": [2, { "words": true, "nonwords": false }],
+    "spaced-comment": [0, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!", ","] }],
+    "use-isnan": 2,
+    "valid-typeof": 2,
+    "wrap-iife": [2, "any"],
+    "yoda": [2, "never"]
+  }
+}
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..660957e
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,10 @@
+# Enforce Unix newlines
+* text eol=lf
+
+# binaries
+*.ai binary
+*.psd binary
+*.jpg binary
+*.gif binary
+*.png binary
+*.jpeg binary
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..80a228c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,15 @@
+*.DS_Store
+*.sublime-*
+_gh_pages
+bower_components
+node_modules
+npm-debug.log
+actual
+test/actual
+temp
+tmp
+TODO.md
+vendor
+.idea
+benchmark
+coverage
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..d6e658e
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,10 @@
+sudo: false
+language: node_js
+node_js:
+  - "stable"
+  - "0.12"
+  - "0.10"
+matrix:
+  fast_finish: true
+  allow_failures:
+    - node_js: "0.10"
diff --git a/.verb.md b/.verb.md
new file mode 100644
index 0000000..0018001
--- /dev/null
+++ b/.verb.md
@@ -0,0 +1,8 @@
+## Usage
+
+```js
+var cu = require('{%= name %}');
+```
+
+## API
+{%= apidocs('index.js') %}
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..65f90ac
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015, Jon Schlinkert.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..41b72f6
--- /dev/null
+++ b/README.md
@@ -0,0 +1,285 @@
+# class-utils [![NPM version](https://img.shields.io/npm/v/class-utils.svg?style=flat)](https://www.npmjs.com/package/class-utils) [![NPM downloads](https://img.shields.io/npm/dm/class-utils.svg?style=flat)](https://npmjs.org/package/class-utils) [![Build Status](https://img.shields.io/travis/jonschlinkert/class-utils.svg?style=flat)](https://travis-ci.org/jonschlinkert/class-utils)
+
+> Utils for working with JavaScript classes and prototype methods.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install class-utils --save
+```
+
+## Usage
+
+```js
+var cu = require('class-utils');
+```
+
+## API
+
+### [.has](index.js#L40)
+
+Returns true if an array has any of the given elements, or an object has any of the give keys.
+
+**Params**
+
+* `obj` **{Object}**
+* `val` **{String|Array}**
+* `returns` **{Boolean}**
+
+**Example**
+
+```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
+```
+
+### [.hasAll](index.js#L87)
+
+Returns true if an array or object has all of the given values.
+
+**Params**
+
+* `val` **{Object|Array}**
+* `values` **{String|Array}**
+* `returns` **{Boolean}**
+
+**Example**
+
+```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
+```
+
+### [.arrayify](index.js#L114)
+
+Cast the given value to an array.
+
+**Params**
+
+* `val` **{String|Array}**
+* `returns` **{Array}**
+
+**Example**
+
+```js
+cu.arrayify('foo');
+//=> ['foo']
+
+cu.arrayify(['foo']);
+//=> ['foo']
+```
+
+### [.hasConstructor](index.js#L149)
+
+Returns true if a value has a `contructor`
+
+**Params**
+
+* `value` **{Object}**
+* `returns` **{Boolean}**
+
+**Example**
+
+```js
+cu.hasConstructor({});
+//=> true
+
+cu.hasConstructor(Object.create(null));
+//=> false
+```
+
+### [.nativeKeys](index.js#L171)
+
+Get the native `ownPropertyNames` from the constructor of the given `object`. An empty array is returned if the object does not have a constructor.
+
+**Params**
+
+* `obj` **{Object}**: Object that has a `constructor`.
+* `returns` **{Array}**: Array of keys.
+
+**Example**
+
+```js
+cu.nativeKeys({a: 'b', b: 'c', c: 'd'})
+//=> ['a', 'b', 'c']
+
+cu.nativeKeys(function(){})
+//=> ['length', 'caller']
+```
+
+### [.getDescriptor](index.js#L203)
+
+Returns property descriptor `key` if it's an "own" property of the given object.
+
+**Params**
+
+* `obj` **{Object}**
+* `key` **{String}**
+* `returns` **{Object}**: Returns descriptor `key`
+
+**Example**
+
+```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
+// }
+```
+
+### [.copyDescriptor](index.js#L233)
+
+Copy a descriptor from one object to another.
+
+**Params**
+
+* `receiver` **{Object}**
+* `provider` **{Object}**
+* `name` **{String}**
+* `returns` **{Object}**
+
+**Example**
+
+```js
+function App() {}
+Object.defineProperty(App.prototype, 'count', {
+  get: function() {
+    return Object.keys(this).length;
+  }
+});
+var obj = {};
+cu.copyDescriptor(obj, App.prototype, 'count');
+```
+
+### [.copy](index.js#L259)
+
+Copy static properties, prototype properties, and descriptors
+from one object to another.
+
+**Params**
+
+* `receiver` **{Object}**
+* `provider` **{Object}**
+* `omit` **{String|Array}**: One or more properties to omit
+* `returns` **{Object}**
+
+### [.inherit](index.js#L294)
+
+Inherit the static properties, prototype properties, and descriptors
+from of an object.
+
+**Params**
+
+* `receiver` **{Object}**
+* `provider` **{Object}**
+* `omit` **{String|Array}**: One or more properties to omit
+* `returns` **{Object}**
+
+### [.extend](index.js#L338)
+
+Returns a function for extending the static properties, prototype properties, and descriptors from the `Parent` constructor onto `Child` constructors.
+
+**Params**
+
+* `Parent` **{Function}**: Parent ctor
+* `extend` **{Function}**: Optional extend function to handle custom extensions. Useful when updating methods that require a specific prototype.
+* `Child` **{Function}**: Child ctor
+* `proto` **{Object}**: Optionally pass additional prototype properties to inherit.
+* `returns` **{Object}**
+
+**Example**
+
+```js
+var extend = cu.extend(Parent);
+Parent.extend(Child);
+
+// optional methods
+Parent.extend(Child, {
+  foo: function() {},
+  bar: function() {}
+});
+```
+
+### [.bubble](index.js#L351)
+
+Bubble up events emitted from static methods on the Parent ctor.
+
+**Params**
+
+* `Parent` **{Object}**
+* `events` **{Array}**: Event names to bubble up
+
+## Related projects
+
+You might also be interested in these projects:
+
+* [define-property](https://www.npmjs.com/package/define-property): Define a non-enumerable property on an object. | [homepage](https://github.com/jonschlinkert/define-property)
+* [delegate-properties](https://www.npmjs.com/package/delegate-properties): Deep-clone properties from one object to another and make them non-enumerable, or make existing properties… [more](https://www.npmjs.com/package/delegate-properties) | [homepage](https://github.com/jonschlinkert/delegate-properties)
+* [is-descriptor](https://www.npmjs.com/package/is-descriptor): Returns true if a value has the characteristics of a valid JavaScript descriptor. Works for… [more](https://www.npmjs.com/package/is-descriptor) | [homepage](https://github.com/jonschlinkert/is-descriptor)
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/class-utils/issues/new).
+
+## Building docs
+
+Generate readme and API documentation with [verb](https://github.com/verbose/verb):
+
+```sh
+$ npm install verb && npm run docs
+```
+
+Or, if [verb](https://github.com/verbose/verb) is installed globally:
+
+```sh
+$ verb
+```
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm install -d && npm test
+```
+
+## Author
+
+**Jon Schlinkert**
+
+Follow me on GitHub or Twitter for updates about class-utils and my other libraries:
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT license](https://github.com/jonschlinkert/class-utils/blob/master/LICENSE).
+
+***
+
+_This file was generated by [verb](https://github.com/verbose/verb), v, on April 05, 2016._
\ No newline at end of file
diff --git a/example.js b/example.js
new file mode 100644
index 0000000..654dd00
--- /dev/null
+++ b/example.js
@@ -0,0 +1,9 @@
+var cu = require('./');
+
+function App() {}
+Object.defineProperty(App.prototype, 'count', {
+  get: function () {
+    return Object.keys(this).length;
+  }
+});
+console.log(cu.getDescriptor(App.prototype, 'count'));
diff --git a/examples/a.js b/examples/a.js
new file mode 100644
index 0000000..67d3c58
--- /dev/null
+++ b/examples/a.js
@@ -0,0 +1,34 @@
+'use strict';
+
+var App = require('./app');
+var define = require('define-property');
+
+function A(options) {
+  App.call(this);
+  this.options = options || {};
+}
+
+define(A, 'metadata', {
+  name: 'A',
+  repository: 'foo/a'
+});
+App.extend(A);
+
+A.prototype.set = function(key, value) {
+  this[key] = value;
+  return this;
+};
+A.prototype.get = function(key) {
+  return this[key];
+};
+A.prototype.del = function(key) {
+  delete this[key];
+};
+Object.defineProperty(A.prototype, 'count', {
+  get: function () {
+    return Object.keys(this).length;
+  },
+  set: function () {
+  }
+});
+module.exports = A;
diff --git a/examples/app.js b/examples/app.js
new file mode 100644
index 0000000..5eeb45c
--- /dev/null
+++ b/examples/app.js
@@ -0,0 +1,33 @@
+var define = require('define-property');
+var cu = require('..');
+
+function App(options) {
+  this.options = options || {};
+}
+App.prototype.set = function(key, value) {
+  this[key] = value;
+  return this;
+};
+App.prototype.get = function(key) {
+  return this[key];
+};
+App.prototype.del = function(key) {
+  delete this[key];
+};
+Object.defineProperty(App.prototype, 'count', {
+  get: function () {
+    return Object.keys(this).length;
+  },
+  set: function () {
+  }
+});
+
+define(App, 'metadata', {
+  name: 'App',
+  repository: 'app/app'
+});
+
+App.extend = cu.extend(App);
+App.inherit = cu.inherit;
+
+module.exports = App;
diff --git a/examples/b.js b/examples/b.js
new file mode 100644
index 0000000..26f5842
--- /dev/null
+++ b/examples/b.js
@@ -0,0 +1,39 @@
+'use strict';
+
+var A = require('./a');
+var define = require('define-property');
+
+function B(options) {
+  A.call(this);
+  this.options = options || {};
+}
+
+define(B, 'metadata', {
+  name: 'B',
+  repository: 'foo/b'
+});
+A.extend(B);
+
+B.prototype.set = function(key, value) {
+  this[key] = value;
+  return this;
+};
+B.prototype.get = function(key) {
+  return this[key];
+};
+B.prototype.del = function(key) {
+  delete this[key];
+};
+Object.defineProperty(B.prototype, 'count', {
+  get: function () {
+    return Object.keys(this).length;
+  },
+  set: function () {
+  }
+});
+
+define(B, 'metadata', {
+  name: 'B',
+  repository: 'foo/b'
+});
+module.exports = B;
diff --git a/examples/c.js b/examples/c.js
new file mode 100644
index 0000000..6219ad6
--- /dev/null
+++ b/examples/c.js
@@ -0,0 +1,34 @@
+'use strict';
+
+var B = require('./b');
+var define = require('define-property');
+
+function C(options) {
+  B.call(this);
+  this.options = options || {};
+}
+B.extend(C);
+define(C, 'metadata', {
+  name: 'C',
+  repository: 'foo/c'
+});
+
+C.prototype.set = function(key, value) {
+  this[key] = value;
+  return this;
+};
+C.prototype.get = function(key) {
+  return this[key];
+};
+C.prototype.del = function(key) {
+  delete this[key];
+};
+Object.defineProperty(C.prototype, 'count', {
+  get: function () {
+    return Object.keys(this).length;
+  },
+  set: function () {
+  }
+});
+
+module.exports = C;
diff --git a/examples/meta.js b/examples/meta.js
new file mode 100644
index 0000000..3c793bc
--- /dev/null
+++ b/examples/meta.js
@@ -0,0 +1,6 @@
+
+var B = require('./b');
+var App = require('./c');
+
+// console.log(App.metadata)
+var app = new App();
diff --git a/fixtures/app.js b/fixtures/app.js
new file mode 100644
index 0000000..4f9c66b
--- /dev/null
+++ b/fixtures/app.js
@@ -0,0 +1,22 @@
+function App(options) {
+  this.options = options || {};
+}
+App.prototype.set = function(key, value) {
+  this[key] = value;
+  return this;
+};
+App.prototype.get = function(key) {
+  return this[key];
+};
+App.prototype.del = function(key) {
+  delete this[key];
+};
+Object.defineProperty(App.prototype, 'count', {
+  get: function () {
+    return Object.keys(this).length;
+  },
+  set: function () {
+  }
+});
+
+module.exports = App;
\ No newline at end of file
diff --git a/gulpfile.js b/gulpfile.js
new file mode 100644
index 0000000..cd32374
--- /dev/null
+++ b/gulpfile.js
@@ -0,0 +1,63 @@
+'use strict';
+
+var gulp = require('gulp');
+var mocha = require('gulp-mocha');
+var istanbul = require('gulp-istanbul');
+var eslint = require('gulp-eslint');
+var through = require('through2');
+
+gulp.task('coverage', function() {
+  return gulp.src(['index.js', 'utils.js'])
+    .pipe(istanbul({includeUntested: true}))
+    .pipe(istanbul.hookRequire());
+});
+
+gulp.task('mocha', ['coverage'], function() {
+  return gulp.src('test.js')
+    .pipe(mocha())
+    .pipe(istanbul.writeReports());
+});
+
+gulp.task('eslint', function() {
+  return gulp.src('*.js')
+    .pipe(eslint())
+    .pipe(eslint.format());
+});
+
+gulp.task('vars', function() {
+  var utils = require('./utils');
+  var keys = Object.keys(utils);
+  var report = {};
+  var cache = {};
+
+  return gulp.src(['index.js', 'utils.js'])
+    .pipe(through.obj(function(file, enc, next) {
+      var str = file.contents.toString();
+      keys.forEach(function(key) {
+        report[key] = report[key] || 0;
+        var re = cache[key] || (cache[key] = new RegExp('\\.' + key, 'g'));
+        var m = str.match(re);
+        if (!m) return;
+        report[key]++;
+      });
+
+      next(null, file);
+    }, function(next) {
+      var keys = Object.keys(report);
+      var res = {};
+
+      keys.sort(function(a, b) {
+        return report[a] > report[b] ? -1 : 1;
+      });
+
+      keys.forEach(function(key) {
+        res[key] = report[key];
+      });
+
+      console.log(res);
+      console.log(keys.length, 'modules');
+      next();
+    }))
+});
+
+gulp.task('default', ['mocha', 'eslint']);
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..f14ea04
--- /dev/null
+++ b/index.js
@@ -0,0 +1,365 @@
+'use strict';
+
+var util = require('util');
+var utils = require('./utils');
+
+/**
+ * Expose class utils
+ */
+
+var cu = module.exports;
+
+/**
+ * Expose class utils: `cu`
+ */
+
+cu.isObject = function isObject(val) {
+  return utils.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 [];
+  return Object.getOwnPropertyNames(val);
+};
+
+/**
+ * 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)) {
+      utils.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 utils.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 = utils.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);
+  };
+};
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..4dd995f
--- /dev/null
+++ b/package.json
@@ -0,0 +1,87 @@
+{
+  "name": "class-utils",
+  "description": "Utils for working with JavaScript classes and prototype methods.",
+  "version": "0.3.4",
+  "homepage": "https://github.com/jonschlinkert/class-utils",
+  "author": "Jon Schlinkert (https://github.com/jonschlinkert)",
+  "repository": "jonschlinkert/class-utils",
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/class-utils/issues"
+  },
+  "license": "MIT",
+  "files": [
+    "index.js",
+    "utils.js"
+  ],
+  "main": "index.js",
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "dependencies": {
+    "arr-union": "^3.1.0",
+    "define-property": "^0.2.5",
+    "isobject": "^2.0.0",
+    "lazy-cache": "^1.0.3",
+    "static-extend": "^0.1.1"
+  },
+  "devDependencies": {
+    "gulp": "^3.9.1",
+    "gulp-eslint": "^2.0.0",
+    "gulp-format-md": "^0.1.7",
+    "gulp-istanbul": "^0.10.3",
+    "gulp-mocha": "^2.2.0",
+    "mocha": "^2.4.5",
+    "should": "^8.2.2",
+    "through2": "^2.0.1"
+  },
+  "keywords": [
+    "array",
+    "assign",
+    "class",
+    "copy",
+    "ctor",
+    "define",
+    "delegate",
+    "descriptor",
+    "extend",
+    "extends",
+    "inherit",
+    "inheritance",
+    "merge",
+    "method",
+    "object",
+    "prop",
+    "properties",
+    "property",
+    "prototype",
+    "util",
+    "utils"
+  ],
+  "verb": {
+    "run": true,
+    "toc": false,
+    "layout": "default",
+    "tasks": [
+      "readme"
+    ],
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "define-property",
+        "delegate-properties",
+        "is-descriptor"
+      ]
+    },
+    "reflinks": [
+      "verb"
+    ],
+    "lint": {
+      "reflinks": true
+    }
+  }
+}
diff --git a/test.js b/test.js
new file mode 100644
index 0000000..4c4e7a4
--- /dev/null
+++ b/test.js
@@ -0,0 +1,465 @@
+'use strict';
+require('mocha');
+require('should');
+var assert = require('assert');
+var App = require('./fixtures/app');
+var cu = require('./');
+
+assert.hasAll = function(a, b) {
+  assert(cu.hasAll(a, b));
+};
+assert.contains = function(a, b) {
+  assert(cu.has(a, b));
+};
+
+
+describe('noop', function() {
+  it('should return undefined:', function() {
+    assert(typeof cu.noop({}) === 'undefined');
+    assert(typeof cu.noop('foo') === 'undefined');
+  });
+});
+
+describe('isObject', function() {
+  it('should be true if the value is an object:', function() {
+    assert(cu.isObject({}));
+  });
+  it('should be true if the value is a function:', function() {
+    assert(cu.isObject(function() {}));
+  });
+  it('should be false if the value is an object:', function() {
+    assert(!cu.isObject('foo'));
+  });
+});
+
+describe('identity', function() {
+  it('should return the given value:', function() {
+    assert.deepEqual(cu.identity({}), {});
+    assert.deepEqual(cu.identity('foo'), 'foo');
+    assert.deepEqual(cu.identity(['foo']), ['foo']);
+    assert.deepEqual(cu.identity([]), []);
+  });
+});
+
+describe('hasAll', function() {
+  describe('object', function() {
+    it('should be true if an object has all given value:', function() {
+      assert(cu.hasAll({
+        a: 'b',
+        b: 'c',
+        c: 'd'
+      }, 'c'));
+      assert(cu.hasAll({
+        a: 'b',
+        b: 'c',
+        c: 'd'
+      }, ['c', 'b']));
+      assert(cu.hasAll({
+        a: 'b',
+        b: 'c',
+        c: 'd'
+      }, ['a', 'b', 'c']));
+    });
+
+    it('should be false if an object does not have all given value:', function() {
+      assert(!cu.hasAll({
+        a: 'b',
+        b: 'c',
+        c: 'd'
+      }, 'd'));
+      assert(!cu.hasAll({
+        a: 'b',
+        b: 'c',
+        c: 'd'
+      }, ['c', 'b', 'z']));
+    });
+  });
+
+  describe('arrays', function() {
+    it('should be true if an array has all given value:', function() {
+      assert(cu.hasAll(['a', 'b', 'c'], 'c'));
+      assert(cu.hasAll(['a', 'b', 'c'], ['c', 'b']));
+      assert(cu.hasAll(['a', 'b', 'c'], ['a', 'b', 'c']));
+    });
+
+    it('should be false if an array does not have all given value:', function() {
+      assert(!cu.hasAll(['a', 'b', 'c'], 'd'));
+      assert(!cu.hasAll(['a', 'b', 'c'], ['c', 'b', 'z']));
+    });
+  });
+});
+
+describe('has', function() {
+  describe('objects', function() {
+    it('should return true if an array has the given value:', function() {
+      assert(cu.has({
+        a: 'b',
+        b: 'c',
+        c: 'd'
+      }, 'c'));
+      assert(cu.has({
+        a: 'b',
+        b: 'c',
+        c: 'd'
+      }, 'b'));
+    });
+    it('should return false if an array does not have the given value:', function() {
+      assert(!cu.has({
+        a: 'b',
+        b: 'c',
+        c: 'd'
+      }, 'd'));
+      assert(!cu.has({
+        a: 'b',
+        b: 'c',
+        c: 'd'
+      }, 'e'));
+    });
+    it('should return true if an array has any given values:', function() {
+      assert(cu.has({
+        a: 'b',
+        b: 'c',
+        c: 'd'
+      }, ['c', 'z']));
+      assert(cu.has({
+        a: 'b',
+        b: 'c',
+        c: 'd'
+      }, ['a', 'z']));
+    });
+    it('should return false if an array does not have any given values:', function() {
+      assert(!cu.has({
+        a: 'b',
+        b: 'c',
+        c: 'd'
+      }, ['x', 'z']));
+      assert(!cu.has({
+        a: 'b',
+        b: 'c',
+        c: 'd'
+      }, ['y', 'z']));
+    });
+  });
+
+  describe('arrays', function() {
+    it('should return true if an array has the given value:', function() {
+      assert(cu.has(['a', 'b', 'c'], 'c'));
+      assert(cu.has(['a', 'b', 'c'], 'b'));
+    });
+    it('should return false if an array does not have the given value:', function() {
+      assert(!cu.has(['a', 'b', 'c'], 'd'));
+      assert(!cu.has(['a', 'b', 'c'], 'e'));
+    });
+    it('should return true if an array has any given values:', function() {
+      assert(cu.has(['a', 'b', 'c'], ['c', 'z']));
+      assert(cu.has(['a', 'b', 'c'], ['a', 'z']));
+    });
+    it('should return false if an array does not have any given values:', function() {
+      assert(!cu.has(['a', 'b', 'c'], ['x', 'z']));
+      assert(!cu.has(['a', 'b', 'c'], ['y', 'z']));
+    });
+  });
+
+  it('should throw an error when the value is not an array or object:', function() {
+    (function() {
+      cu.has('foo');
+    }).should.throw('expected an array or object.');
+  });
+});
+
+describe('hasConstructor', function() {
+  it('should return true if a value is an object and has a constructor:', function() {
+    assert(cu.hasConstructor({
+      a: 'b',
+      b: 'c',
+      c: 'd'
+    }));
+    assert(cu.hasConstructor(function() {}));
+    assert(cu.hasConstructor(App));
+    assert(cu.hasConstructor(new App()));
+    assert(cu.hasConstructor(Object.create(new App())));
+  });
+
+  it('should return false if a value is not object:', function() {
+    assert(!cu.hasConstructor('foo'));
+    assert(!cu.hasConstructor(5));
+  });
+
+  it('should return false if an object does not have a constructor:', function() {
+    assert(!cu.hasConstructor(Object.create(null)));
+    assert(!cu.hasConstructor(null));
+  });
+});
+
+describe('nativeKeys', function() {
+  it('should get the native keys of an object:', function() {
+    assert.hasAll(cu.nativeKeys({
+      a: 'b',
+      b: 'c',
+      c: 'd'
+    }), ['a', 'b', 'c']);
+    assert.hasAll(cu.nativeKeys(function() {}), ['length', 'name', 'prototype']);
+    assert.hasAll(cu.nativeKeys(App), ['length', 'name', 'prototype']);
+    assert.hasAll(cu.nativeKeys(App.prototype), ['constructor', 'set', 'get', 'del']);
+    assert.hasAll(cu.nativeKeys(App.constructor), ['length', 'name', 'caller']);
+    assert.hasAll(cu.nativeKeys(App.prototype.constructor), ['length', 'caller']);
+    assert.hasAll(cu.nativeKeys(new App()), ['options']);
+    assert.hasAll(cu.nativeKeys(Object.create(new App())), []);
+  });
+
+  it('should return empty array if a value does not have native keys:', function() {
+    assert.deepEqual(cu.nativeKeys(Object.create(null)), []);
+    assert.deepEqual(cu.nativeKeys(null), []);
+  });
+});
+
+describe('getDescriptor', function() {
+  it('should get the native keys of an object:', function() {
+    assert.contains(cu.getDescriptor(App.prototype, 'count'), ['get',
+      'set'
+    ]);
+    assert(typeof cu.getDescriptor(App.prototype, 'foo') ===
+      'undefined');
+  });
+
+  it('should throw an error when key is not a string:', function() {
+    (function() {
+      cu.getDescriptor({}, {}, null);
+    }).should.throw('expected key to be a string.');
+  });
+
+  it('should throw an error when receiver is not an object:', function() {
+    (function() {
+      cu.getDescriptor('foo');
+    }).should.throw('expected an object.');
+  });
+});
+
+describe('copyDescriptor', function() {
+  it('should copy a descriptor from the provider to receiver:', function() {
+    var proto = App.prototype;
+    var obj = {};
+    cu.copyDescriptor(obj, proto, 'count');
+    assert.contains(cu.getDescriptor(obj, 'count'), ['get', 'set']);
+  });
+
+  it('should do nothing when the descriptor does not exist:', function() {
+    var proto = App.prototype;
+    var obj = {};
+    cu.copyDescriptor(obj, proto, 'foo');
+    assert.deepEqual(obj, {});
+  });
+
+  it('should throw an error when name is not a string:', function() {
+    (function() {
+      cu.copyDescriptor({}, {}, null);
+    }).should.throw('expected name to be a string.');
+  });
+
+  it('should throw an error when receiver is not an object:', function() {
+    (function() {
+      cu.copyDescriptor('foo');
+    }).should.throw('expected receiving object to be an object.');
+  });
+
+  it('should throw an error when provider is not an object:', function() {
+    (function() {
+      cu.copyDescriptor({}, 'foo');
+    }).should.throw('expected providing object to be an object.');
+  });
+});
+
+describe('copy', function() {
+  it('should copy descriptors from the provider to receiver:', function() {
+    var proto = App.prototype;
+    var obj = {};
+    cu.copy(obj, proto);
+    assert.contains(cu.getDescriptor(obj, 'count'), ['get', 'set']);
+  });
+
+  it('should copy properties from the provider to receiver:', function() {
+    var proto = App.prototype;
+    var obj = {};
+    cu.copy(obj, proto);
+    obj.set('a', 'b');
+    assert(obj.a === 'b');
+    assert.contains(obj, ['get', 'set']);
+  });
+
+  it('should do nothing when the property does not exist:', function() {
+    var proto = App.prototype;
+    var obj = {};
+    cu.copy(obj, proto, 'foo');
+    assert.deepEqual(obj, {});
+  });
+
+  it('should throw an error when receiver is not an object:', function() {
+    (function() {
+      cu.copy('foo');
+    }).should.throw('expected receiving object to be an object.');
+  });
+
+  it('should throw an error when provider is not an object:', function() {
+    (function() {
+      cu.copy({}, 'foo');
+    }).should.throw('expected providing object to be an object.');
+  });
+});
+
+describe('inherit', function() {
+  it('should inherit descriptors from provider:', function() {
+    var proto = App.prototype;
+    var obj = {};
+    cu.inherit(obj, proto);
+    assert.contains(cu.getDescriptor(obj, 'count'), ['get', 'set']);
+  });
+
+  it('should inherit properties from provider:', function() {
+    var proto = App.prototype;
+    var obj = {};
+    cu.inherit(obj, proto);
+    obj.set('a', 'b');
+    assert(obj.a === 'b');
+    assert.contains(obj, ['get', 'set', 'del']);
+  });
+
+  it('should do nothing when the property does not exist:', function() {
+    var proto = App.prototype;
+    var obj = {};
+    cu.inherit(obj, proto, 'foo');
+    assert.deepEqual(obj, {});
+  });
+
+  it('should throw an error when receiver is not an object:', function() {
+    (function() {
+      cu.inherit('foo');
+    }).should.throw('expected receiving object to be an object.');
+  });
+
+  it('should throw an error when provider is not an object:', function() {
+    (function() {
+      cu.inherit({}, 'foo');
+    }).should.throw('expected providing object to be an object.');
+  });
+});
+
+describe('extend', function() {
+  var Parent;
+  var Ctor;
+  var proto;
+
+  beforeEach(function() {
+    Parent = function() {}
+    Parent.foo = 'bar';
+    Parent.prototype.a = function() {};
+    Parent.prototype.b = function() {};
+    Parent.prototype.c = function() {};
+    Object.defineProperty(Parent.prototype, 'count', {
+      get: function() {
+        return Object.keys(this).length;
+      },
+      set: function() {}
+    });
+    Ctor = function() {
+      Parent.call(this);
+    };
+    proto = App.prototype;
+  });
+
+  it('should add `Parent.prototype` to `Ctor` instances as `_parent_`', function() {
+    var extend = cu.extend(Parent);
+    var instance1 = new Ctor();
+    assert.equal(typeof instance1._parent_, 'undefined');
+    extend(Ctor);
+    var instance2 = new Ctor();
+    assert.equal(typeof instance2._parent_, 'object');
+    assert.deepEqual(instance2._parent_, Parent.prototype);
+  });
+
+  it('should access `Parent` methods through `_parent_`', function() {
+    Parent.prototype.upper = function(str) {
+      return str.toUpperCase();
+    };
+
+    var extend = cu.extend(Parent);
+    extend(Ctor);
+
+    var instance = new Ctor();
+    assert.equal(instance.upper('foo'), 'FOO');
+
+    instance.upper = function(str) {
+      return str;
+    };
+    assert.equal(instance.upper('foo'), 'foo');
+
+    instance.upper = function(str) {
+      return this._parent_.upper(str) + ' ' + str;
+    };
+    assert.equal(instance.upper('foo'), 'FOO foo');
+  });
+
+  it('should add static methods to Ctor:', function() {
+    var extend = cu.extend(Parent);
+    extend(Ctor);
+    assert(typeof Ctor.extend === 'function');
+    assert(Ctor.foo === 'bar');
+  });
+
+  it('should add prototype methods to Ctor:', function() {
+    var extend = cu.extend(Parent);
+    extend(Ctor);
+    assert(typeof Ctor.prototype.a === 'function');
+    assert(typeof Ctor.prototype.b === 'function');
+    assert(typeof Ctor.prototype.c === 'function');
+  });
+
+  it('should add descriptors to Ctor:', function() {
+    var extend = cu.extend(Parent);
+    extend(Ctor);
+  });
+
+  it('should copy prototype properties to Ctor:', function() {
+    var extend = cu.extend(Parent);
+    extend(Ctor, App.prototype);
+    assert(typeof Ctor.prototype.get === 'function');
+    assert(typeof Ctor.prototype.set === 'function');
+    assert(typeof Ctor.prototype.del === 'function');
+  });
+
+  it('should add a mixin method to the prototype of Ctor using `extend` function:', function() {
+    var extend = cu.extend(Parent, function(Child) {
+      Child.prototype.mixin = function(key, val) {
+        Child.prototype[key] = val;
+      };
+    });
+    extend(Ctor, App.prototype);
+    assert(typeof Ctor.prototype.mixin === 'function');
+    assert(typeof Ctor.prototype.get === 'function');
+    assert(typeof Ctor.prototype.set === 'function');
+    assert(typeof Ctor.prototype.del === 'function');
+  });
+
+  it('should mixin methods to the Ctor.prototype using `extend` function:', function() {
+    var extend = cu.extend(Parent, function(Child) {
+      Child.prototype.mixin = function(key, val) {
+        Child.prototype[key] = val;
+      };
+    });
+    extend(Ctor, App.prototype);
+    var app = new Ctor();
+    app.mixin('foo', function() {});
+    assert.equal(typeof Ctor.prototype.foo, 'function');
+  });
+
+  it('should throw an error when Parent is not a function:', function() {
+    (function() {
+      cu.extend('foo');
+    }).should.throw('expected Parent to be a function.');
+  });
+
+  it('should throw an error when Ctor is not a function:', function() {
+    (function() {
+      cu.extend(function Foo() {})('bar')
+    }).should.throw('expected Ctor to be a function.');
+  });
+});
diff --git a/utils.js b/utils.js
new file mode 100644
index 0000000..0cf143e
--- /dev/null
+++ b/utils.js
@@ -0,0 +1,21 @@
+'use strict';
+
+var utils = require('lazy-cache')(require);
+var fn = require;
+require = utils;
+
+/**
+ * Lazily required module dependencies
+ */
+
+require('arr-union', 'union');
+require('define-property', 'define');
+require('isobject', 'isObj');
+require('static-extend');
+require = fn;
+
+/**
+ * Expose `utils`
+ */
+
+module.exports = utils;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-class-utils.git



More information about the Pkg-javascript-commits mailing list