Ejegg has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/200090

Change subject: Add node.extend
......................................................................

Add node.extend

Go go gadget arms!

Change-Id: I3bd88e785099b12ba04d2a7fb51e89c3de1757f9
---
A node.extend/.jscs.json
A node.extend/.npmignore
A node.extend/.travis.yml
A node.extend/History.md
A node.extend/Readme.md
A node.extend/index.js
A node.extend/lib/extend.js
A node.extend/node_modules/is/CHANGELOG.md
A node.extend/node_modules/is/LICENSE.md
A node.extend/node_modules/is/Makefile
A node.extend/node_modules/is/README.md
A node.extend/node_modules/is/component.json
A node.extend/node_modules/is/index.js
A node.extend/node_modules/is/package.json
A node.extend/node_modules/is/test/index.js
A node.extend/package.json
16 files changed, 2,043 insertions(+), 0 deletions(-)


  git pull 
ssh://gerrit.wikimedia.org:29418/wikimedia/fundraising/dash/node_modules 
refs/changes/90/200090/1

diff --git a/node.extend/.jscs.json b/node.extend/.jscs.json
new file mode 100644
index 0000000..8bca4f1
--- /dev/null
+++ b/node.extend/.jscs.json
@@ -0,0 +1,66 @@
+{
+       "additionalRules": [],
+
+       "requireCurlyBraces": ["if", "else", "for", "while", "do", "try", 
"catch"],
+
+       "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", 
"switch", "return", "try", "catch", "function"],
+
+       "disallowSpaceAfterKeywords": [],
+
+       "requireSpacesInAnonymousFunctionExpression": { 
"beforeOpeningRoundBrace": true, "beforeOpeningCurlyBrace": true },
+       "requireSpacesInNamedFunctionExpression": { "beforeOpeningCurlyBrace": 
true },
+       "disallowSpacesInNamedFunctionExpression": { "beforeOpeningRoundBrace": 
true },
+       "requireSpacesInFunctionDeclaration": { "beforeOpeningCurlyBrace": true 
},
+       "disallowSpacesInFunctionDeclaration": { "beforeOpeningRoundBrace": 
true },
+
+       "disallowSpacesInsideParentheses": true,
+
+       "disallowSpacesInsideArrayBrackets": true,
+
+       "disallowQuotedKeysInObjects": "allButReserved",
+
+       "disallowSpaceAfterObjectKeys": true,
+
+       "requireCommaBeforeLineBreak": true,
+
+       "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", 
"!"],
+       "requireSpaceAfterPrefixUnaryOperators": [],
+
+       "disallowSpaceBeforePostfixUnaryOperators": ["++", "--"],
+       "requireSpaceBeforePostfixUnaryOperators": [],
+
+       "disallowSpaceBeforeBinaryOperators": [],
+       "requireSpaceBeforeBinaryOperators": ["+", "-", "/", "*", "=", "==", 
"===", "!=", "!=="],
+
+       "requireSpaceAfterBinaryOperators": ["+", "-", "/", "*", "=", "==", 
"===", "!=", "!=="],
+       "disallowSpaceAfterBinaryOperators": [],
+
+       "disallowImplicitTypeConversion": ["binary", "string"],
+
+       "disallowKeywords": ["with", "eval"],
+
+       "requireKeywordsOnNewLine": [],
+       "disallowKeywordsOnNewLine": ["else"],
+
+       "requireLineFeedAtFileEnd": true,
+
+       "disallowTrailingWhitespace": true,
+
+       "disallowTrailingComma": true,
+
+       "excludeFiles": ["node_modules/**", "vendor/**"],
+
+       "disallowMultipleLineStrings": true,
+
+       "requireDotNotation": true,
+
+       "requireParenthesesAroundIIFE": true,
+
+       "validateLineBreaks": "LF",
+
+       "validateQuoteMarks": {
+               "escape": true,
+               "mark": "'"
+       }
+}
+
diff --git a/node.extend/.npmignore b/node.extend/.npmignore
new file mode 100644
index 0000000..f1250e5
--- /dev/null
+++ b/node.extend/.npmignore
@@ -0,0 +1,4 @@
+support
+test
+examples
+*.sock
diff --git a/node.extend/.travis.yml b/node.extend/.travis.yml
new file mode 100644
index 0000000..912080a
--- /dev/null
+++ b/node.extend/.travis.yml
@@ -0,0 +1,18 @@
+language: node_js
+node_js:
+  - "0.11"
+  - "0.10"
+  - "0.9"
+  - "0.8"
+  - "0.6"
+  - "0.4"
+before_install:
+  - '[ "${TRAVIS_NODE_VERSION}" == "0.6" ] || npm install -g npm@~1.4.6'
+matrix:
+  fast_finish: true
+  allow_failures:
+    - node_js: "0.11"
+    - node_js: "0.9"
+    - node_js: "0.6"
+    - node_js: "0.4"
+
diff --git a/node.extend/History.md b/node.extend/History.md
new file mode 100644
index 0000000..633fb93
--- /dev/null
+++ b/node.extend/History.md
@@ -0,0 +1,21 @@
+## 1.0.1 / 2013-04-02
+
+  - Fix tests
+
+
+
+## 1.0.0 / 2012-02-28
+
+  - Add tests for the stable release
+
+
+
+## 0.0.2 / 2012-01-11
+
+  - Add repository to package.json
+
+
+
+## 0.0.1 / 2012-01-10
+
+  - Initial release
diff --git a/node.extend/Readme.md b/node.extend/Readme.md
new file mode 100644
index 0000000..df4bf66
--- /dev/null
+++ b/node.extend/Readme.md
@@ -0,0 +1,77 @@
+# node.extend
+
+A port of jQuery.extend that **actually works** on node.js
+
+[![Build Status][travis-svg]][travis-url]
+[![dependency status][deps-svg]][deps-url]
+[![dev dependency status][dev-deps-svg]][dev-deps-url]
+
+[![browser support][testling-png]][testling-url]
+
+
+## Description
+
+None of the existing ones on npm really work therefore I ported it myself.
+
+
+
+## Usage
+
+To install this module in your current working directory (which should already 
contain a package.json), run
+
+```
+npm install node.extend
+```
+
+You can additionally just list the module in your 
[package.json](https://npmjs.org/doc/json.html) and run npm install.
+
+Then, require this package where you need it:
+
+```
+var extend = require('node.extend');
+```
+
+The syntax for merging two objects is as follows:
+
+```
+var destObject = extend({}, sourceObject);
+// Where sourceObject is the object whose properties will be copied into 
another.
+// NOTE: In this situation, this is not a deep merge. See below on how to 
handle a deep merge.
+```
+
+For information about how the clone works internally, view source in 
lib/extend.js or checkout the doc from [jQuery][]
+
+### A Note About Deep Merge (avoiding pass-by-reference cloning)
+
+In order to force a deep merge, when extending an object, you must pass 
boolean true as the first argument to extend:
+
+```
+var destObject = extend(true, {}, sourceObject);
+// Where sourceObject is the object whose properties will be copied into 
another.
+```
+
+See [this 
article](http://www.jon-carlos.com/2013/is-javascript-call-by-value-or-call-by-reference/)
 for more information about the need for deep merges in JavaScript.
+
+## Credit
+
+- Jordan Harband [@ljharb][]
+
+
+
+## License
+
+Copyright 2011, John Resig
+Dual licensed under the MIT or GPL Version 2 licenses.
+http://jquery.org/license
+
+[testling-png]: https://ci.testling.com/dreamerslab/node.extend.png
+[testling-url]: https://ci.testling.com/dreamerslab/node.extend
+[travis-svg]: https://travis-ci.org/dreamerslab/node.extend.svg
+[travis-url]: https://travis-ci.org/dreamerslab/node.extend
+[deps-svg]: https://david-dm.org/dreamerslab/node.extend.svg
+[deps-url]: https://david-dm.org/dreamerslab/node.extend
+[dev-deps-svg]: https://david-dm.org/dreamerslab/node.extend/dev-status.svg
+[dev-deps-url]: 
https://david-dm.org/dreamerslab/node.extend#info=devDependencies
+[jQuery]: http://api.jquery.com/jQuery.extend/
+[@ljharb]: https://twitter.com/ljharb
+
diff --git a/node.extend/index.js b/node.extend/index.js
new file mode 100644
index 0000000..52ee121
--- /dev/null
+++ b/node.extend/index.js
@@ -0,0 +1,2 @@
+module.exports = require('./lib/extend');
+
diff --git a/node.extend/lib/extend.js b/node.extend/lib/extend.js
new file mode 100644
index 0000000..78e9991
--- /dev/null
+++ b/node.extend/lib/extend.js
@@ -0,0 +1,82 @@
+/*!
+ * node.extend
+ * Copyright 2011, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * @fileoverview
+ * Port of jQuery.extend that actually works on node.js
+ */
+var is = require('is');
+
+function extend() {
+  var target = arguments[0] || {};
+  var i = 1;
+  var length = arguments.length;
+  var deep = false;
+  var options, name, src, copy, copy_is_array, clone;
+
+  // Handle a deep copy situation
+  if (typeof target === 'boolean') {
+    deep = target;
+    target = arguments[1] || {};
+    // skip the boolean and the target
+    i = 2;
+  }
+
+  // Handle case when target is a string or something (possible in deep copy)
+  if (typeof target !== 'object' && !is.fn(target)) {
+    target = {};
+  }
+
+  for (; i < length; i++) {
+    // Only deal with non-null/undefined values
+    options = arguments[i]
+    if (options != null) {
+      if (typeof options === 'string') {
+          options = options.split('');
+      }
+      // Extend the base object
+      for (name in options) {
+        src = target[name];
+        copy = options[name];
+
+        // Prevent never-ending loop
+        if (target === copy) {
+          continue;
+        }
+
+        // Recurse if we're merging plain objects or arrays
+        if (deep && copy && (is.hash(copy) || (copy_is_array = 
is.array(copy)))) {
+          if (copy_is_array) {
+            copy_is_array = false;
+            clone = src && is.array(src) ? src : [];
+          } else {
+            clone = src && is.hash(src) ? src : {};
+          }
+
+          // Never move original objects, clone them
+          target[name] = extend(deep, clone, copy);
+
+        // Don't bring in undefined values
+        } else if (typeof copy !== 'undefined') {
+          target[name] = copy;
+        }
+      }
+    }
+  }
+
+  // Return the modified object
+  return target;
+};
+
+/**
+ * @public
+ */
+extend.version = '1.0.8';
+
+/**
+ * Exports module.
+ */
+module.exports = extend;
+
diff --git a/node.extend/node_modules/is/CHANGELOG.md 
b/node.extend/node_modules/is/CHANGELOG.md
new file mode 100644
index 0000000..764197e
--- /dev/null
+++ b/node.extend/node_modules/is/CHANGELOG.md
@@ -0,0 +1,67 @@
+2.1.0 / 2014-10-21
+==================
+  * Add `CHANGELOG.md`
+  * Add `is.hex` and `is.base64` 
[#12](https://github.com/enricomarino/is/issues/12)
+  * Update `tape`, `jscs`
+  * Lock `covert` to v1.0.0 
[substack/covert#9](https://github.com/substack/covert/issues/9)
+
+2.0.2 / 2014-10-05
+==================
+  * `undefined` can be redefined in ES3 browsers.
+  * Update `jscs.json` and make style consistent
+  * Update `foreach`, `jscs`, `tape`
+  * Naming URLs in README
+
+2.0.1 / 2014-09-02
+==================
+  * Add the license to package.json
+  * Add license and downloads badges
+  * Update `jscs`
+
+2.0.0 / 2014-08-25
+==================
+  * Add `make release`
+  * Update copyright notice.
+  * Fix is.empty(new String())
+
+1.1.0 / 2014-08-22
+==================
+  * Removing redundant license
+  * Add a non-deprecated method for is.null
+  * Use a more reliable valueOf coercion for is.false/is.true
+  * Clean up `README.md`
+  * Running `npm run lint` as part of tests.
+  * Fixing lint errors.
+  * Adding `npm run lint`
+  * Updating `covert`
+
+1.0.0 / 2014-08-07
+==================
+  * Update `tape`, `covert`
+  * Increase code coverage
+  * Update `LICENSE.md`, `README.md`
+
+0.3.0 / 2014-03-02
+==================
+  * Update `tape`, `covert`
+  * Adding `npm run coverage`
+  * is.arguments -> is.args, because reserved words.
+  * "undefined" is a reserved word in ES3 browsers.
+  * Optimizing is.equal to return early if value and other are strictly equal.
+  * Fixing is.equal for objects.
+  * Test improvements
+
+0.2.7 / 2013-12-26
+==================
+  * Update `tape`, `foreach`
+  * is.decimal(Infinity) shouldn't be true 
[#11](https://github.com/enricomarino/is/issues/11)
+
+0.2.6 / 2013-05-06
+==================
+  * Fix lots of tests [#9](https://github.com/enricomarino/is/issues/9)
+  * Update tape [#8](https://github.com/enricomarino/is/issues/8)
+
+0.2.5 / 2013-04-24
+==================
+  * Use `tap` instead of `tape` 
[#7](https://github.com/enricomarino/is/issues/7)
+
diff --git a/node.extend/node_modules/is/LICENSE.md 
b/node.extend/node_modules/is/LICENSE.md
new file mode 100644
index 0000000..9d91b0e
--- /dev/null
+++ b/node.extend/node_modules/is/LICENSE.md
@@ -0,0 +1,23 @@
+(The MIT License)
+
+Copyright (c) 2013 Enrico Marino  
+Copyright (c) 2014 Enrico Marino and Jordan Harband
+
+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/node.extend/node_modules/is/Makefile 
b/node.extend/node_modules/is/Makefile
new file mode 100644
index 0000000..d1e265a
--- /dev/null
+++ b/node.extend/node_modules/is/Makefile
@@ -0,0 +1,17 @@
+
+.PHONY: verify-tag release
+
+default: release
+
+verify-tag:
+ifndef TAG
+       $(error TAG is undefined)
+endif
+
+release: verify-tag
+       @ OLD_TAG=`git describe --abbrev=0 --tags` && \
+               npm run minify && \
+               replace "$${OLD_TAG/v/}" "$(TAG)" -- *.json README.md && \
+               git commit -m "v$(TAG)" *.js *.json README.md && \
+               git tag "v$(TAG)"
+
diff --git a/node.extend/node_modules/is/README.md 
b/node.extend/node_modules/is/README.md
new file mode 100644
index 0000000..8c652b4
--- /dev/null
+++ b/node.extend/node_modules/is/README.md
@@ -0,0 +1,135 @@
+# is <sup>[![Version Badge][npm-version-svg]][npm-url]</sup>
+
+[![Build Status][travis-svg]][travis-url]
+[![dependency status][deps-svg]][deps-url]
+[![dev dependency status][dev-deps-svg]][dev-deps-url]
+[![License][license-image]][license-url]
+[![Downloads][downloads-image]][downloads-url]
+
+[![npm badge][npm-badge-png]][npm-url]
+
+[![browser support][testling-png]][testling-url]
+
+The definitive JavaScript type testing library
+
+To be or not to be? This is the library!
+
+## Installation
+
+As a node.js module
+
+```shell
+$ npm install is
+```
+
+As a component
+```shell
+$ component install enricomarino/is
+```
+
+## API
+
+### general
+
+ - ``is.a`` (value, type) or ``is.type`` (value, type)
+ - ``is.defined`` (value)
+ - ``is.empty`` (value)
+ - ``is.equal`` (value, other)
+ - ``is.hosted`` (value, host)
+ - ``is.instance`` (value, constructor)
+ - ``is.instanceof`` (value, constructor) - deprecated, because in ES3 
browsers, "instanceof" is a reserved word
+ - ``is.nil`` (value)
+ - ``is.null`` (value) - deprecated, because in ES3 browsers, "null" is a 
reserved word
+ - ``is.undef`` (value)
+ - ``is.undefined`` (value) - deprecated, because in ES3 browsers, "undefined" 
is a reserved word
+
+### arguments
+
+ - ``is.args`` (value)
+ - ``is.arguments`` (value) - deprecated, because "arguments" is a reserved 
word
+ - ``is.args.empty`` (value)
+
+### array
+
+ - ``is.array`` (value)
+ - ``is.array.empty`` (value)
+ - ``is.arraylike`` (value)
+
+### boolean
+
+ - ``is.boolean`` (value)
+ - ``is.false`` (value) - deprecated, because in ES3 browsers, "false" is a 
reserved word
+ - ``is.true`` (value) - deprecated, because in ES3 browsers, "true" is a 
reserved word
+
+### date
+
+ - ``is.date`` (value)
+
+### element
+
+ - ``is.element`` (value)
+
+### error
+
+ - is.error (value)
+
+### function
+
+ - ``is.fn`` (value)
+ - ``is.function`` (value) - deprecated, because in ES3 browsers, "function" 
is a reserved word
+
+### number
+
+ - ``is.number`` (value)
+ - ``is.infinite`` (value)
+ - ``is.decimal`` (value)
+ - ``is.divisibleBy`` (value, n)
+ - ``is.int`` (value)
+ - ``is.maximum`` (value, others)
+ - ``is.minimum`` (value, others)
+ - ``is.nan`` (value)
+ - ``is.even`` (value)
+ - ``is.odd`` (value)
+ - ``is.ge`` (value, other)
+ - ``is.gt`` (value, other)
+ - ``is.le`` (value, other)
+ - ``is.lt`` (value, other)
+ - ``is.within`` (value, start, finish)
+
+### object
+
+ - ``is.object`` (value)
+
+### regexp
+
+ - ``is.regexp`` (value)
+
+### string
+
+ - ``is.string`` (value)
+
+### encoded binary
+
+ - ``is.base64`` (value)
+ - ``is.hex`` (value)
+
+
+## Contributors
+
+- [Jordan Harband](https://github.com/ljharb)
+
+[npm-url]: https://npmjs.org/package/is
+[npm-version-svg]: http://vb.teelaun.ch/enricomarino/is.svg
+[travis-svg]: https://travis-ci.org/enricomarino/is.svg
+[travis-url]: https://travis-ci.org/enricomarino/is
+[deps-svg]: https://david-dm.org/enricomarino/is.svg
+[deps-url]: https://david-dm.org/enricomarino/is
+[dev-deps-svg]: https://david-dm.org/enricomarino/is/dev-status.svg
+[dev-deps-url]: https://david-dm.org/enricomarino/is#info=devDependencies
+[testling-png]: https://ci.testling.com/enricomarino/is.png
+[testling-url]: https://ci.testling.com/enricomarino/is
+[npm-badge-png]: https://nodei.co/npm/is.png?downloads=true&stars=true
+[license-image]: http://img.shields.io/npm/l/is.svg
+[license-url]: LICENSE.md
+[downloads-image]: http://img.shields.io/npm/dm/is.svg
+[downloads-url]: http://npm-stat.com/charts.html?package=is
diff --git a/node.extend/node_modules/is/component.json 
b/node.extend/node_modules/is/component.json
new file mode 100644
index 0000000..f8c94a1
--- /dev/null
+++ b/node.extend/node_modules/is/component.json
@@ -0,0 +1,8 @@
+{
+  "name": "is",
+  "repo": "enricomarino/is",
+  "description": "The definitive type testing library",
+  "version": "2.1.0",
+  "dependencies": {},
+  "scripts": ["index.js"]
+}
diff --git a/node.extend/node_modules/is/index.js 
b/node.extend/node_modules/is/index.js
new file mode 100644
index 0000000..a5b08b4
--- /dev/null
+++ b/node.extend/node_modules/is/index.js
@@ -0,0 +1,745 @@
+
+/**!
+ * is
+ * the definitive JavaScript type testing library
+ *
+ * @copyright 2013-2014 Enrico Marino / Jordan Harband
+ * @license MIT
+ */
+
+var objProto = Object.prototype;
+var owns = objProto.hasOwnProperty;
+var toString = objProto.toString;
+var isActualNaN = function (value) {
+  return value !== value;
+};
+var NON_HOST_TYPES = {
+  boolean: 1,
+  number: 1,
+  string: 1,
+  undefined: 1
+};
+
+var base64Regex = 
/^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$/;
+var hexRegex = /^[A-Fa-f0-9]+$/;
+
+/**
+ * Expose `is`
+ */
+
+var is = module.exports = {};
+
+/**
+ * Test general.
+ */
+
+/**
+ * is.type
+ * Test if `value` is a type of `type`.
+ *
+ * @param {Mixed} value value to test
+ * @param {String} type type
+ * @return {Boolean} true if `value` is a type of `type`, false otherwise
+ * @api public
+ */
+
+is.a = is.type = function (value, type) {
+  return typeof value === type;
+};
+
+/**
+ * is.defined
+ * Test if `value` is defined.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if 'value' is defined, false otherwise
+ * @api public
+ */
+
+is.defined = function (value) {
+  return typeof value !== 'undefined';
+};
+
+/**
+ * is.empty
+ * Test if `value` is empty.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is empty, false otherwise
+ * @api public
+ */
+
+is.empty = function (value) {
+  var type = toString.call(value);
+  var key;
+
+  if ('[object Array]' === type || '[object Arguments]' === type || '[object 
String]' === type) {
+    return value.length === 0;
+  }
+
+  if ('[object Object]' === type) {
+    for (key in value) {
+      if (owns.call(value, key)) { return false; }
+    }
+    return true;
+  }
+
+  return false;
+};
+
+/**
+ * is.equal
+ * Test if `value` is equal to `other`.
+ *
+ * @param {Mixed} value value to test
+ * @param {Mixed} other value to compare with
+ * @return {Boolean} true if `value` is equal to `other`, false otherwise
+ */
+
+is.equal = function (value, other) {
+  var strictlyEqual = value === other;
+  if (strictlyEqual) {
+    return true;
+  }
+
+  var type = toString.call(value);
+  var key;
+
+  if (type !== toString.call(other)) {
+    return false;
+  }
+
+  if ('[object Object]' === type) {
+    for (key in value) {
+      if (!is.equal(value[key], other[key]) || !(key in other)) {
+        return false;
+      }
+    }
+    for (key in other) {
+      if (!is.equal(value[key], other[key]) || !(key in value)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  if ('[object Array]' === type) {
+    key = value.length;
+    if (key !== other.length) {
+      return false;
+    }
+    while (--key) {
+      if (!is.equal(value[key], other[key])) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  if ('[object Function]' === type) {
+    return value.prototype === other.prototype;
+  }
+
+  if ('[object Date]' === type) {
+    return value.getTime() === other.getTime();
+  }
+
+  return strictlyEqual;
+};
+
+/**
+ * is.hosted
+ * Test if `value` is hosted by `host`.
+ *
+ * @param {Mixed} value to test
+ * @param {Mixed} host host to test with
+ * @return {Boolean} true if `value` is hosted by `host`, false otherwise
+ * @api public
+ */
+
+is.hosted = function (value, host) {
+  var type = typeof host[value];
+  return type === 'object' ? !!host[value] : !NON_HOST_TYPES[type];
+};
+
+/**
+ * is.instance
+ * Test if `value` is an instance of `constructor`.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is an instance of `constructor`
+ * @api public
+ */
+
+is.instance = is['instanceof'] = function (value, constructor) {
+  return value instanceof constructor;
+};
+
+/**
+ * is.nil / is.null
+ * Test if `value` is null.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is null, false otherwise
+ * @api public
+ */
+
+is.nil = is['null'] = function (value) {
+  return value === null;
+};
+
+/**
+ * is.undef / is.undefined
+ * Test if `value` is undefined.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is undefined, false otherwise
+ * @api public
+ */
+
+is.undef = is['undefined'] = function (value) {
+  return typeof value === 'undefined';
+};
+
+/**
+ * Test arguments.
+ */
+
+/**
+ * is.args
+ * Test if `value` is an arguments object.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is an arguments object, false otherwise
+ * @api public
+ */
+
+is.args = is['arguments'] = function (value) {
+  var isStandardArguments = '[object Arguments]' === toString.call(value);
+  var isOldArguments = !is.array(value) && is.arraylike(value) && 
is.object(value) && is.fn(value.callee);
+  return isStandardArguments || isOldArguments;
+};
+
+/**
+ * Test array.
+ */
+
+/**
+ * is.array
+ * Test if 'value' is an array.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is an array, false otherwise
+ * @api public
+ */
+
+is.array = function (value) {
+  return '[object Array]' === toString.call(value);
+};
+
+/**
+ * is.arguments.empty
+ * Test if `value` is an empty arguments object.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is an empty arguments object, false 
otherwise
+ * @api public
+ */
+is.args.empty = function (value) {
+  return is.args(value) && value.length === 0;
+};
+
+/**
+ * is.array.empty
+ * Test if `value` is an empty array.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is an empty array, false otherwise
+ * @api public
+ */
+is.array.empty = function (value) {
+  return is.array(value) && value.length === 0;
+};
+
+/**
+ * is.arraylike
+ * Test if `value` is an arraylike object.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is an arguments object, false otherwise
+ * @api public
+ */
+
+is.arraylike = function (value) {
+  return !!value && !is.boolean(value)
+    && owns.call(value, 'length')
+    && isFinite(value.length)
+    && is.number(value.length)
+    && value.length >= 0;
+};
+
+/**
+ * Test boolean.
+ */
+
+/**
+ * is.boolean
+ * Test if `value` is a boolean.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is a boolean, false otherwise
+ * @api public
+ */
+
+is.boolean = function (value) {
+  return '[object Boolean]' === toString.call(value);
+};
+
+/**
+ * is.false
+ * Test if `value` is false.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is false, false otherwise
+ * @api public
+ */
+
+is['false'] = function (value) {
+  return is.boolean(value) && Boolean(Number(value)) === false;
+};
+
+/**
+ * is.true
+ * Test if `value` is true.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is true, false otherwise
+ * @api public
+ */
+
+is['true'] = function (value) {
+  return is.boolean(value) && Boolean(Number(value)) === true;
+};
+
+/**
+ * Test date.
+ */
+
+/**
+ * is.date
+ * Test if `value` is a date.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is a date, false otherwise
+ * @api public
+ */
+
+is.date = function (value) {
+  return '[object Date]' === toString.call(value);
+};
+
+/**
+ * Test element.
+ */
+
+/**
+ * is.element
+ * Test if `value` is an html element.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is an HTML Element, false otherwise
+ * @api public
+ */
+
+is.element = function (value) {
+  return value !== undefined
+    && typeof HTMLElement !== 'undefined'
+    && value instanceof HTMLElement
+    && value.nodeType === 1;
+};
+
+/**
+ * Test error.
+ */
+
+/**
+ * is.error
+ * Test if `value` is an error object.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is an error object, false otherwise
+ * @api public
+ */
+
+is.error = function (value) {
+  return '[object Error]' === toString.call(value);
+};
+
+/**
+ * Test function.
+ */
+
+/**
+ * is.fn / is.function (deprecated)
+ * Test if `value` is a function.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is a function, false otherwise
+ * @api public
+ */
+
+is.fn = is['function'] = function (value) {
+  var isAlert = typeof window !== 'undefined' && value === window.alert;
+  return isAlert || '[object Function]' === toString.call(value);
+};
+
+/**
+ * Test number.
+ */
+
+/**
+ * is.number
+ * Test if `value` is a number.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is a number, false otherwise
+ * @api public
+ */
+
+is.number = function (value) {
+  return '[object Number]' === toString.call(value);
+};
+
+/**
+ * is.infinite
+ * Test if `value` is positive or negative infinity.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is positive or negative Infinity, false 
otherwise
+ * @api public
+ */
+is.infinite = function (value) {
+  return value === Infinity || value === -Infinity;
+};
+
+/**
+ * is.decimal
+ * Test if `value` is a decimal number.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is a decimal number, false otherwise
+ * @api public
+ */
+
+is.decimal = function (value) {
+  return is.number(value) && !isActualNaN(value) && !is.infinite(value) && 
value % 1 !== 0;
+};
+
+/**
+ * is.divisibleBy
+ * Test if `value` is divisible by `n`.
+ *
+ * @param {Number} value value to test
+ * @param {Number} n dividend
+ * @return {Boolean} true if `value` is divisible by `n`, false otherwise
+ * @api public
+ */
+
+is.divisibleBy = function (value, n) {
+  var isDividendInfinite = is.infinite(value);
+  var isDivisorInfinite = is.infinite(n);
+  var isNonZeroNumber = is.number(value) && !isActualNaN(value) && 
is.number(n) && !isActualNaN(n) && n !== 0;
+  return isDividendInfinite || isDivisorInfinite || (isNonZeroNumber && value 
% n === 0);
+};
+
+/**
+ * is.int
+ * Test if `value` is an integer.
+ *
+ * @param value to test
+ * @return {Boolean} true if `value` is an integer, false otherwise
+ * @api public
+ */
+
+is.int = function (value) {
+  return is.number(value) && !isActualNaN(value) && value % 1 === 0;
+};
+
+/**
+ * is.maximum
+ * Test if `value` is greater than 'others' values.
+ *
+ * @param {Number} value value to test
+ * @param {Array} others values to compare with
+ * @return {Boolean} true if `value` is greater than `others` values
+ * @api public
+ */
+
+is.maximum = function (value, others) {
+  if (isActualNaN(value)) {
+    throw new TypeError('NaN is not a valid value');
+  } else if (!is.arraylike(others)) {
+    throw new TypeError('second argument must be array-like');
+  }
+  var len = others.length;
+
+  while (--len >= 0) {
+    if (value < others[len]) {
+      return false;
+    }
+  }
+
+  return true;
+};
+
+/**
+ * is.minimum
+ * Test if `value` is less than `others` values.
+ *
+ * @param {Number} value value to test
+ * @param {Array} others values to compare with
+ * @return {Boolean} true if `value` is less than `others` values
+ * @api public
+ */
+
+is.minimum = function (value, others) {
+  if (isActualNaN(value)) {
+    throw new TypeError('NaN is not a valid value');
+  } else if (!is.arraylike(others)) {
+    throw new TypeError('second argument must be array-like');
+  }
+  var len = others.length;
+
+  while (--len >= 0) {
+    if (value > others[len]) {
+      return false;
+    }
+  }
+
+  return true;
+};
+
+/**
+ * is.nan
+ * Test if `value` is not a number.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is not a number, false otherwise
+ * @api public
+ */
+
+is.nan = function (value) {
+  return !is.number(value) || value !== value;
+};
+
+/**
+ * is.even
+ * Test if `value` is an even number.
+ *
+ * @param {Number} value value to test
+ * @return {Boolean} true if `value` is an even number, false otherwise
+ * @api public
+ */
+
+is.even = function (value) {
+  return is.infinite(value) || (is.number(value) && value === value && value % 
2 === 0);
+};
+
+/**
+ * is.odd
+ * Test if `value` is an odd number.
+ *
+ * @param {Number} value value to test
+ * @return {Boolean} true if `value` is an odd number, false otherwise
+ * @api public
+ */
+
+is.odd = function (value) {
+  return is.infinite(value) || (is.number(value) && value === value && value % 
2 !== 0);
+};
+
+/**
+ * is.ge
+ * Test if `value` is greater than or equal to `other`.
+ *
+ * @param {Number} value value to test
+ * @param {Number} other value to compare with
+ * @return {Boolean}
+ * @api public
+ */
+
+is.ge = function (value, other) {
+  if (isActualNaN(value) || isActualNaN(other)) {
+    throw new TypeError('NaN is not a valid value');
+  }
+  return !is.infinite(value) && !is.infinite(other) && value >= other;
+};
+
+/**
+ * is.gt
+ * Test if `value` is greater than `other`.
+ *
+ * @param {Number} value value to test
+ * @param {Number} other value to compare with
+ * @return {Boolean}
+ * @api public
+ */
+
+is.gt = function (value, other) {
+  if (isActualNaN(value) || isActualNaN(other)) {
+    throw new TypeError('NaN is not a valid value');
+  }
+  return !is.infinite(value) && !is.infinite(other) && value > other;
+};
+
+/**
+ * is.le
+ * Test if `value` is less than or equal to `other`.
+ *
+ * @param {Number} value value to test
+ * @param {Number} other value to compare with
+ * @return {Boolean} if 'value' is less than or equal to 'other'
+ * @api public
+ */
+
+is.le = function (value, other) {
+  if (isActualNaN(value) || isActualNaN(other)) {
+    throw new TypeError('NaN is not a valid value');
+  }
+  return !is.infinite(value) && !is.infinite(other) && value <= other;
+};
+
+/**
+ * is.lt
+ * Test if `value` is less than `other`.
+ *
+ * @param {Number} value value to test
+ * @param {Number} other value to compare with
+ * @return {Boolean} if `value` is less than `other`
+ * @api public
+ */
+
+is.lt = function (value, other) {
+  if (isActualNaN(value) || isActualNaN(other)) {
+    throw new TypeError('NaN is not a valid value');
+  }
+  return !is.infinite(value) && !is.infinite(other) && value < other;
+};
+
+/**
+ * is.within
+ * Test if `value` is within `start` and `finish`.
+ *
+ * @param {Number} value value to test
+ * @param {Number} start lower bound
+ * @param {Number} finish upper bound
+ * @return {Boolean} true if 'value' is is within 'start' and 'finish'
+ * @api public
+ */
+is.within = function (value, start, finish) {
+  if (isActualNaN(value) || isActualNaN(start) || isActualNaN(finish)) {
+    throw new TypeError('NaN is not a valid value');
+  } else if (!is.number(value) || !is.number(start) || !is.number(finish)) {
+    throw new TypeError('all arguments must be numbers');
+  }
+  var isAnyInfinite = is.infinite(value) || is.infinite(start) || 
is.infinite(finish);
+  return isAnyInfinite || (value >= start && value <= finish);
+};
+
+/**
+ * Test object.
+ */
+
+/**
+ * is.object
+ * Test if `value` is an object.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is an object, false otherwise
+ * @api public
+ */
+
+is.object = function (value) {
+  return '[object Object]' === toString.call(value);
+};
+
+/**
+ * is.hash
+ * Test if `value` is a hash - a plain object literal.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is a hash, false otherwise
+ * @api public
+ */
+
+is.hash = function (value) {
+  return is.object(value) && value.constructor === Object && !value.nodeType 
&& !value.setInterval;
+};
+
+/**
+ * Test regexp.
+ */
+
+/**
+ * is.regexp
+ * Test if `value` is a regular expression.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is a regexp, false otherwise
+ * @api public
+ */
+
+is.regexp = function (value) {
+  return '[object RegExp]' === toString.call(value);
+};
+
+/**
+ * Test string.
+ */
+
+/**
+ * is.string
+ * Test if `value` is a string.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if 'value' is a string, false otherwise
+ * @api public
+ */
+
+is.string = function (value) {
+  return '[object String]' === toString.call(value);
+};
+
+/**
+ * Test base64 string.
+ */
+
+/**
+ * is.base64
+ * Test if `value` is a valid base64 encoded string.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if 'value' is a base64 encoded string, false 
otherwise
+ * @api public
+ */
+
+is.base64 = function (value) {
+  return is.string(value) && (!value.length || base64Regex.test(value));
+};
+
+/**
+ * Test base64 string.
+ */
+
+/**
+ * is.hex
+ * Test if `value` is a valid hex encoded string.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if 'value' is a hex encoded string, false otherwise
+ * @api public
+ */
+
+is.hex = function (value) {
+  return is.string(value) && (!value.length || hexRegex.test(value));
+};
diff --git a/node.extend/node_modules/is/package.json 
b/node.extend/node_modules/is/package.json
new file mode 100644
index 0000000..1963e89
--- /dev/null
+++ b/node.extend/node_modules/is/package.json
@@ -0,0 +1,88 @@
+{
+  "name": "is",
+  "version": "2.1.0",
+  "main": "index.js",
+  "scripts": {
+    "test": "npm run lint && node test/index.js",
+    "coverage": "covert test/index.js",
+    "coverage-quiet": "covert test/index.js --quiet",
+    "lint": "jscs *.js */*.js"
+  },
+  "author": {
+    "name": "Enrico Marino",
+    "url": "http://onirame.com";
+  },
+  "description": "the definitive JavaScript type testing library",
+  "homepage": "https://github.com/enricomarino/is";,
+  "license": "MIT",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/enricomarino/is.git"
+  },
+  "keywords": [
+    "util",
+    "type",
+    "test"
+  ],
+  "contributors": [
+    {
+      "name": "Jordan Harband",
+      "url": "https://github.com/ljharb";
+    }
+  ],
+  "dependencies": {},
+  "devDependencies": {
+    "tape": "~3.0.1",
+    "foreach": "~2.0.5",
+    "covert": "1.0.0",
+    "jscs": "~1.7.3"
+  },
+  "testling": {
+    "files": "test/index.js",
+    "browsers": [
+      "iexplore/6.0..latest",
+      "firefox/3.0",
+      "firefox/15.0..latest",
+      "firefox/nightly",
+      "chrome/4.0",
+      "chrome/22.0..latest",
+      "chrome/canary",
+      "opera/10.0..latest",
+      "opera/next",
+      "safari/5.0.5..latest",
+      "ipad/6.0..latest",
+      "iphone/6.0..latest"
+    ]
+  },
+  "engines": {
+    "node": "*"
+  },
+  "gitHead": "a9e13b16c35adf35cbc920a8aae0ffc9a92fe5ed",
+  "bugs": {
+    "url": "https://github.com/enricomarino/is/issues";
+  },
+  "_id": "[email protected]",
+  "_shasum": "cf3dc3a5e1dd21c72e3838d8170e5f746127be8b",
+  "_from": "is@~2.1.0",
+  "_npmVersion": "1.4.28",
+  "_npmUser": {
+    "name": "ljharb",
+    "email": "[email protected]"
+  },
+  "maintainers": [
+    {
+      "name": "ljharb",
+      "email": "[email protected]"
+    },
+    {
+      "name": "enricomarino",
+      "email": "[email protected]"
+    }
+  ],
+  "dist": {
+    "shasum": "cf3dc3a5e1dd21c72e3838d8170e5f746127be8b",
+    "tarball": "http://registry.npmjs.org/is/-/is-2.1.0.tgz";
+  },
+  "directories": {},
+  "_resolved": "https://registry.npmjs.org/is/-/is-2.1.0.tgz";
+}
diff --git a/node.extend/node_modules/is/test/index.js 
b/node.extend/node_modules/is/test/index.js
new file mode 100644
index 0000000..f5c2190
--- /dev/null
+++ b/node.extend/node_modules/is/test/index.js
@@ -0,0 +1,590 @@
+var test = require('tape');
+var is = require('../index.js');
+
+var forEach = require('foreach');
+var toStr = Object.prototype.toString;
+
+test('is.type', function (t) {
+  var booleans = [true, false];
+  forEach(booleans, function (boolean) {
+    t.ok(is.type(boolean, 'boolean'), '"' + boolean + '" is a boolean');
+  });
+
+  var numbers = [1, 0 / 1, 0 / -1, NaN, Infinity, -Infinity];
+  forEach(numbers, function (number) {
+    t.ok(is.type(number, 'number'), '"' + number + '" is a number');
+  });
+
+  var objects = [{}, null, new Date()];
+  forEach(objects, function (object) {
+    t.ok(is.type(object, 'object'), '"' + object + '" is an object');
+  });
+
+  var strings = ['', 'abc'];
+  forEach(strings, function (string) {
+    t.ok(is.type(string, 'string'), '"' + string + '" is a string');
+  });
+
+  t.ok(is.type(undefined, 'undefined'), 'undefined is undefined');
+
+  t.end();
+});
+
+test('is.undef', function (t) {
+  t.ok(is.undef(), 'absent undefined is undefined');
+  t.ok(is.undef(undefined), 'literal undefined is undefined');
+  t.notOk(is.undef(null), 'null is not undefined');
+  t.notOk(is.undef({}), 'object is not undefined');
+  t.end();
+});
+
+test('is.defined', function (t) {
+  t.notOk(is.defined(), 'undefined is not defined');
+  t.ok(is.defined(null), 'null is defined');
+  t.ok(is.defined({}), 'object is undefined');
+  t.end();
+});
+
+test('is.empty', function (t) {
+  t.ok(is.empty(''), 'empty string is empty');
+  t.ok(is.empty(new String()), 'empty String object is empty');
+  t.ok(is.empty([]), 'empty array is empty');
+  t.ok(is.empty({}), 'empty object is empty');
+  (function () { t.ok(is.empty(arguments), 'empty arguments is empty'); }());
+  t.notOk(is.empty({ a: 1 }), 'nonempty object is not empty');
+  t.notOk(is.empty(true), 'true is not empty');
+  t.notOk(is.empty(false), 'false is not empty');
+  t.notOk(is.empty(/a/g), 'regex is not empty');
+  t.notOk(is.empty(new Date()), 'date is not empty');
+  t.end();
+});
+
+test('is.equal', function (t) {
+  t.test('primitives', function (pt) {
+    var primitives = [true, false, undefined, null, '', 'foo', 0, Infinity, 
-Infinity];
+    pt.plan(primitives.length);
+    for (var i = 0; i < primitives.length; ++i) {
+      pt.ok(is.equal(primitives[i], primitives[i]), 'primitives are equal to 
themselves: ' + primitives[i]);
+    }
+    pt.end();
+  });
+
+  t.test('arrays', function (at) {
+    at.ok(is.equal([1, 2, 3], [1, 2, 3]), 'arrays are shallowly equal');
+    at.ok(is.equal([1, 2, [3, 4]], [1, 2, [3, 4]]), 'arrays are deep equal');
+    at.notOk(is.equal([1, 2], [2, 3]), 'inequal arrays are not equal');
+    at.notOk(is.equal([1, 2, 3], [2, 3]), 'inequal length arrays are not 
equal');
+
+    var arr = [1, 2];
+    at.ok(is.equal(arr, arr), 'array is equal to itself');
+
+    at.end();
+  });
+
+  t.test('dates', function (dt) {
+    dt.plan(2);
+    var now = new Date();
+    dt.ok(is.equal(now, new Date(now.getTime())), 'two equal date objects are 
equal');
+    setTimeout(function () {
+      dt.notOk(is.equal(now, new Date()), 'two inequal date objects are not 
equal');
+      dt.end();
+    }, 1);
+  });
+
+  t.test('plain objects', function (ot) {
+    ot.ok(is.equal({ a: 1, b: 2, c: 3 }, { a: 1, b: 2, c: 3 }), 'objects are 
shallowly equal');
+    ot.ok(is.equal({ a: { b: 1 } }, { a: { b: 1 } }), 'objects are deep 
equal');
+    ot.notOk(is.equal({ a: 1 }, { a: 2 }), 'inequal objects are not equal');
+    ot.end();
+  });
+
+  t.test('object instances', function (ot) {
+    var F = function F() {
+      this.foo = 'bar';
+    };
+    F.prototype = {};
+    var G = function G() {
+      this.foo = 'bar';
+    };
+    var f = new F();
+    var g = new G();
+
+    ot.ok(is.equal(f, f), 'the same object instances are equal');
+    ot.ok(is.equal(f, new F()), 'two object instances are equal when the 
prototype and props are the same');
+    ot.ok(is.equal(f, new G()), 'two object instances are equal when the 
prototype is not the same, but props are');
+
+    g.bar = 'baz';
+    ot.notOk(is.equal(f, g), 'object instances are not equal when the 
prototype and props are not the same');
+    ot.notOk(is.equal(g, f), 'object instances are not equal when the 
prototype and props are not the same');
+    ot.end();
+  });
+
+  t.test('functions', function (ft) {
+    var F = function () {};
+    F.prototype = {};
+    var G = function () {};
+    G.prototype = new Date();
+
+    ft.notEqual(F.prototype, G.prototype, 'F and G have different prototypes');
+    ft.notOk(is.equal(F, G), 'two functions are not equal when the prototype 
is not the same');
+
+    var H = function () {};
+    H.prototype = F.prototype;
+
+    ft.equal(F.prototype, H.prototype, 'F and H have the same prototype');
+    ft.ok(is.equal(F, H), 'two functions are equal when the prototype is the 
same');
+    ft.end();
+  });
+
+  t.end();
+});
+
+test('is.hosted', function (t) {
+  t.ok(is.hosted('a', { a: {} }), 'object is hosted');
+  t.ok(is.hosted('a', { a: [] }), 'array is hosted');
+  t.ok(is.hosted('a', { a: function () {} }), 'function is hosted');
+  t.notOk(is.hosted('a', { a: true }), 'boolean value is not hosted');
+  t.notOk(is.hosted('a', { a: false }), 'boolean value is not hosted');
+  t.notOk(is.hosted('a', { a: 3 }), 'number value is not hosted');
+  t.notOk(is.hosted('a', { a: undefined }), 'undefined value is not hosted');
+  t.notOk(is.hosted('a', { a: 'abc' }), 'string value is not hosted');
+  t.notOk(is.hosted('a', { a: null }), 'null value is not hosted');
+  t.end();
+});
+
+test('is.instance', function (t) {
+  t.ok(is.instance(new Date(), Date), 'new Date is instanceof Date');
+  var F = function () {};
+  t.ok(is.instance(new F(), F), 'new constructor is instanceof constructor');
+  t.end();
+});
+
+test('is.nil', function (t) {
+  var isNull = is.nil;
+  t.equal(isNull, is['null'], 'is.nil is the same as is.null');
+  t.ok(isNull(null), 'null is null');
+  t.notOk(isNull(undefined), 'undefined is not null');
+  t.notOk(isNull({}), 'object is not null');
+  t.end();
+});
+
+test('is.args', function (t) {
+  t.notOk(is.args([]), 'array is not arguments');
+  (function () { t.ok(is.args(arguments), 'arguments is arguments'); }());
+  (function () { t.notOk(is.args(Array.prototype.slice.call(arguments)), 
'sliced arguments is not arguments'); }());
+  var fakeOldArguments = {
+    length: 3,
+    callee: function () {}
+  };
+  t.ok(is.args(fakeOldArguments), 'old-style arguments object is arguments');
+  t.end();
+});
+
+test('is.args.empty', function (t) {
+  t.notOk(is.args.empty([]), 'empty array is not empty arguments');
+  (function () { t.ok(is.args.empty(arguments), 'empty arguments is empty 
arguments'); }());
+  (function () { t.notOk(is.args.empty(Array.prototype.slice.call(arguments)), 
'empty sliced arguments is not empty arguments'); }());
+  t.end();
+});
+
+
+test('is.array', function (t) {
+  t.ok(is.array([]), 'array is array');
+  (function () { t.ok(is.array(Array.prototype.slice.call(arguments)), 'sliced 
arguments is array'); }());
+  t.end();
+});
+
+test('is.array.empty', function (t) {
+  t.ok(is.array.empty([]), 'empty array is empty array');
+  (function () { t.notOk(is.array.empty(arguments), 'empty arguments is not 
empty array'); }());
+  (function () { t.ok(is.array.empty(Array.prototype.slice.call(arguments)), 
'empty sliced arguments is empty array'); }());
+  t.end();
+});
+
+test('is.isarraylike', function (t) {
+  t.notOk(is.arraylike(), 'undefined is not array-like');
+  t.notOk(is.arraylike(null), 'null is not array-like');
+  t.notOk(is.arraylike(false), 'false is not array-like');
+  t.notOk(is.arraylike(true), 'true is not array-like');
+  t.ok(is.arraylike({ length: 0 }), 'object with zero length is array-like');
+  t.ok(is.arraylike({ length: 1 }), 'object with positive length is 
array-like');
+  t.notOk(is.arraylike({ length: -1 }), 'object with negative length is not 
array-like');
+  t.notOk(is.arraylike({ length: NaN }), 'object with NaN length is not 
array-like');
+  t.notOk(is.arraylike({ length: 'foo' }), 'object with string length is not 
array-like');
+  t.notOk(is.arraylike({ length: '' }), 'object with empty string length is 
not array-like');
+  t.ok(is.arraylike([]), 'array is array-like');
+  (function () { t.ok(is.arraylike(arguments), 'empty arguments is 
array-like'); }());
+  (function () { t.ok(is.arraylike(arguments), 'nonempty arguments is 
array-like'); }(1, 2, 3));
+  t.end();
+});
+
+test('is.boolean', function (t) {
+  t.ok(is.boolean(true), 'literal true is a boolean');
+  t.ok(is.boolean(false), 'literal false is a boolean');
+  t.ok(is.boolean(new Boolean(true)), 'object true is a boolean');
+  t.ok(is.boolean(new Boolean(false)), 'object false is a boolean');
+  t.notOk(is.boolean(), 'undefined is not a boolean');
+  t.notOk(is.boolean(null), 'null is not a boolean');
+  t.end();
+});
+
+test('is.false', function (t) {
+  var isFalse = is['false'];
+  t.ok(isFalse(false), 'false is false');
+  t.ok(isFalse(new Boolean(false)), 'object false is false');
+  t.notOk(isFalse(true), 'true is not false');
+  t.notOk(isFalse(), 'undefined is not false');
+  t.notOk(isFalse(null), 'null is not false');
+  t.notOk(isFalse(''), 'empty string is not false');
+  t.end();
+});
+
+test('is.true', function (t) {
+  var isTrue = is['true'];
+  t.ok(isTrue(true), 'true is true');
+  t.ok(isTrue(new Boolean(true)), 'object true is true');
+  t.notOk(isTrue(false), 'false is not true');
+  t.notOk(isTrue(), 'undefined is not true');
+  t.notOk(isTrue(null), 'null is not true');
+  t.notOk(isTrue(''), 'empty string is not true');
+  t.end();
+});
+
+test('is.date', function (t) {
+  t.ok(is.date(new Date()), 'new Date is date');
+  t.notOk(is.date(), 'undefined is not date');
+  t.notOk(is.date(null), 'null is not date');
+  t.notOk(is.date(''), 'empty string is not date');
+  var nowTS = (new Date()).getTime();
+  t.notOk(is.date(nowTS), 'timestamp is not date');
+  var F = function () {};
+  F.prototype = new Date();
+  t.notOk(is.date(new F()), 'Date subtype is not date');
+  t.end();
+});
+
+test('is.element', function (t) {
+  t.notOk(is.element(), 'undefined is not element');
+  if (typeof HTMLElement !== 'undefined') {
+    var element = document.createElement('div');
+    t.ok(is.element(element), 'HTMLElement is element');
+    t.notOk(is.element({ nodeType: 1 }), 'object with nodeType is not 
element');
+  } else {
+    t.ok(true, 'Skipping is.element test in a non-browser environment');
+  }
+  t.end();
+});
+
+test('is.error', function (t) {
+  var err = new Error('foo');
+  t.ok(is.error(err), 'Error is error');
+  t.notOk(is.error({}), 'object is not error');
+  var objWithErrorToString = { toString: function () { return '[object 
Error]'; } };
+  t.equal(String(objWithErrorToString), toStr.call(new Error()), 'obj has 
Error\'s toString');
+  t.notOk(is.error(objWithErrorToString), 'object with Error\'s toString is 
not error');
+  t.end();
+});
+
+test('is.fn', function (t) {
+  t.equal(is['function'], is.fn, 'alias works');
+  t.ok(is.fn(function () {}), 'function is function');
+  t.ok(is.fn(console.log), 'console.log is function');
+  if (typeof window !== 'undefined') {
+    // in IE7/8, typeof alert === 'object'
+    t.ok(is.fn(window.alert), 'window.alert is function');
+  }
+  t.notOk(is.fn({}), 'object is not function');
+  t.notOk(is.fn(null), 'null is not function');
+  t.end();
+});
+
+test('is.number', function (t) {
+  t.ok(is.number(0), 'positive zero is number');
+  t.ok(is.number(0 / -1), 'negative zero is number');
+  t.ok(is.number(3), 'three is number');
+  t.ok(is.number(NaN), 'NaN is number');
+  t.ok(is.number(Infinity), 'infinity is number');
+  t.ok(is.number(-Infinity), 'negative infinity is number');
+  t.ok(is.number(new Number(42)), 'object number is number');
+  t.notOk(is.number(), 'undefined is not number');
+  t.notOk(is.number(null), 'null is not number');
+  t.notOk(is.number(true), 'true is not number');
+  t.end();
+});
+
+test('is.infinite', function (t) {
+  t.ok(is.infinite(Infinity), 'positive infinity is infinite');
+  t.ok(is.infinite(-Infinity), 'negative infinity is infinite');
+  t.notOk(is.infinite(NaN), 'NaN is not infinite');
+  t.notOk(is.infinite(0), 'a number is not infinite');
+  t.end();
+});
+
+test('is.decimal', function (t) {
+  t.ok(is.decimal(1.1), 'decimal is decimal');
+  t.notOk(is.decimal(0), 'zero is not decimal');
+  t.notOk(is.decimal(1), 'integer is not decimal');
+  t.notOk(is.decimal(NaN), 'NaN is not decimal');
+  t.notOk(is.decimal(Infinity), 'Infinity is not decimal');
+  t.end();
+});
+
+test('is.divisibleBy', function (t) {
+  t.ok(is.divisibleBy(4, 2), '4 is divisible by 2');
+  t.ok(is.divisibleBy(4, 2), '4 is divisible by 2');
+  t.ok(is.divisibleBy(0, 1), '0 is divisible by 1');
+  t.ok(is.divisibleBy(Infinity, 1), 'infinity is divisible by anything');
+  t.ok(is.divisibleBy(1, Infinity), 'anything is divisible by infinity');
+  t.ok(is.divisibleBy(Infinity, Infinity), 'infinity is divisible by 
infinity');
+  t.notOk(is.divisibleBy(1, 0), '1 is not divisible by 0');
+  t.notOk(is.divisibleBy(NaN, 1), 'NaN is not divisible by 1');
+  t.notOk(is.divisibleBy(1, NaN), '1 is not divisible by NaN');
+  t.notOk(is.divisibleBy(NaN, NaN), 'NaN is not divisible by NaN');
+  t.notOk(is.divisibleBy(1, 3), '1 is not divisible by 3');
+  t.end();
+});
+
+test('is.int', function (t) {
+  t.ok(is.int(0), '0 is integer');
+  t.ok(is.int(3), '3 is integer');
+  t.notOk(is.int(1.1), '1.1 is not integer');
+  t.notOk(is.int(NaN), 'NaN is not integer');
+  t.notOk(is.int(Infinity), 'infinity is not integer');
+  t.notOk(is.int(null), 'null is not integer');
+  t.notOk(is.int(), 'undefined is not integer');
+  t.end();
+});
+
+test('is.maximum', function (t) {
+  t.ok(is.maximum(3, [3, 2, 1]), '3 is maximum of [3,2,1]');
+  t.ok(is.maximum(3, [1, 2, 3]), '3 is maximum of [1,2,3]');
+  t.ok(is.maximum(4, [1, 2, 3]), '4 is maximum of [1,2,3]');
+  t.ok(is.maximum('c', ['a', 'b', 'c']), 'c is maximum of [a,b,c]');
+  t.notOk(is.maximum(2, [1, 2, 3]), '2 is not maximum of [1,2,3]');
+
+  var nanError = new TypeError('NaN is not a valid value');
+  t.throws(function () { return is.maximum(NaN); }, nanError, 'throws when 
first value is NaN');
+
+  var error = new TypeError('second argument must be array-like');
+  t.throws(function () { return is.maximum(2, null); }, error, 'throws when 
second value is not array-like');
+  t.throws(function () { return is.maximum(2, {}); }, error, 'throws when 
second value is not array-like');
+  t.end();
+});
+
+test('is.minimum', function (t) {
+  t.ok(is.minimum(1, [1, 2, 3]), '1 is minimum of [1,2,3]');
+  t.ok(is.minimum(0, [1, 2, 3]), '0 is minimum of [1,2,3]');
+  t.ok(is.minimum('a', ['a', 'b', 'c']), 'a is minimum of [a,b,c]');
+  t.notOk(is.minimum(2, [1, 2, 3]), '2 is not minimum of [1,2,3]');
+
+  var nanError = new TypeError('NaN is not a valid value');
+  t.throws(function () { return is.minimum(NaN); }, nanError, 'throws when 
first value is NaN');
+
+  var error = new TypeError('second argument must be array-like');
+  t.throws(function () { return is.minimum(2, null); }, error, 'throws when 
second value is not array-like');
+  t.throws(function () { return is.minimum(2, {}); }, error, 'throws when 
second value is not array-like');
+  t.end();
+});
+
+test('is.nan', function (t) {
+  t.ok(is.nan(NaN), 'NaN is not a number');
+  t.ok(is.nan('abc'), 'string is not a number');
+  t.ok(is.nan(true), 'boolean is not a number');
+  t.ok(is.nan({}), 'object is not a number');
+  t.ok(is.nan([]), 'array is not a number');
+  t.ok(is.nan(function () {}), 'function is not a number');
+  t.notOk(is.nan(0), 'zero is a number');
+  t.notOk(is.nan(3), 'three is a number');
+  t.notOk(is.nan(1.1), '1.1 is a number');
+  t.notOk(is.nan(Infinity), 'infinity is a number');
+  t.end();
+});
+
+test('is.even', function (t) {
+  t.ok(is.even(0), 'zero is even');
+  t.ok(is.even(2), 'two is even');
+  t.ok(is.even(Infinity), 'infinity is even');
+  t.notOk(is.even(1), '1 is not even');
+  t.notOk(is.even(), 'undefined is not even');
+  t.notOk(is.even(null), 'null is not even');
+  t.notOk(is.even(NaN), 'NaN is not even');
+  t.end();
+});
+
+test('is.odd', function (t) {
+  t.ok(is.odd(1), 'zero is odd');
+  t.ok(is.odd(3), 'two is odd');
+  t.ok(is.odd(Infinity), 'infinity is odd');
+  t.notOk(is.odd(0), '0 is not odd');
+  t.notOk(is.odd(2), '2 is not odd');
+  t.notOk(is.odd(), 'undefined is not odd');
+  t.notOk(is.odd(null), 'null is not odd');
+  t.notOk(is.odd(NaN), 'NaN is not odd');
+  t.end();
+});
+
+test('is.ge', function (t) {
+  t.ok(is.ge(3, 2), '3 is greater than 2');
+  t.notOk(is.ge(2, 3), '2 is not greater than 3');
+  t.ok(is.ge(3, 3), '3 is greater than or equal to 3');
+  t.ok(is.ge('abc', 'a'), 'abc is greater than a');
+  t.ok(is.ge('abc', 'abc'), 'abc is greater than or equal to abc');
+  t.notOk(is.ge('a', 'abc'), 'a is not greater than abc');
+  t.notOk(is.ge(Infinity, 0), 'infinity is not greater than anything');
+  t.notOk(is.ge(0, Infinity), 'anything is not greater than infinity');
+  var error = new TypeError('NaN is not a valid value');
+  t.throws(function () { return is.ge(NaN, 2); }, error, 'throws when first 
value is NaN');
+  t.throws(function () { return is.ge(2, NaN); }, error, 'throws when second 
value is NaN');
+  t.end();
+});
+
+test('is.gt', function (t) {
+  t.ok(is.gt(3, 2), '3 is greater than 2');
+  t.notOk(is.gt(2, 3), '2 is not greater than 3');
+  t.notOk(is.gt(3, 3), '3 is not greater than 3');
+  t.ok(is.gt('abc', 'a'), 'abc is greater than a');
+  t.notOk(is.gt('abc', 'abc'), 'abc is not greater than abc');
+  t.notOk(is.gt('a', 'abc'), 'a is not greater than abc');
+  t.notOk(is.gt(Infinity, 0), 'infinity is not greater than anything');
+  t.notOk(is.gt(0, Infinity), 'anything is not greater than infinity');
+  var error = new TypeError('NaN is not a valid value');
+  t.throws(function () { return is.gt(NaN, 2); }, error, 'throws when first 
value is NaN');
+  t.throws(function () { return is.gt(2, NaN); }, error, 'throws when second 
value is NaN');
+  t.end();
+});
+
+test('is.le', function (t) {
+  t.ok(is.le(2, 3), '2 is lesser than or equal to 3');
+  t.notOk(is.le(3, 2), '3 is not lesser than or equal to 2');
+  t.ok(is.le(3, 3), '3 is lesser than or equal to 3');
+  t.ok(is.le('a', 'abc'), 'a is lesser than or equal to abc');
+  t.ok(is.le('abc', 'abc'), 'abc is lesser than or equal to abc');
+  t.notOk(is.le('abc', 'a'), 'abc is not lesser than or equal to a');
+  t.notOk(is.le(Infinity, 0), 'infinity is not lesser than or equal to 
anything');
+  t.notOk(is.le(0, Infinity), 'anything is not lesser than or equal to 
infinity');
+  var error = new TypeError('NaN is not a valid value');
+  t.throws(function () { return is.le(NaN, 2); }, error, 'throws when first 
value is NaN');
+  t.throws(function () { return is.le(2, NaN); }, error, 'throws when second 
value is NaN');
+  t.end();
+});
+
+test('is.lt', function (t) {
+  t.ok(is.lt(2, 3), '2 is lesser than 3');
+  t.notOk(is.lt(3, 2), '3 is not lesser than 2');
+  t.notOk(is.lt(3, 3), '3 is not lesser than 3');
+  t.ok(is.lt('a', 'abc'), 'a is lesser than abc');
+  t.notOk(is.lt('abc', 'abc'), 'abc is not lesser than abc');
+  t.notOk(is.lt('abc', 'a'), 'abc is not lesser than a');
+  t.notOk(is.lt(Infinity, 0), 'infinity is not lesser than anything');
+  t.notOk(is.lt(0, Infinity), 'anything is not lesser than infinity');
+  var error = new TypeError('NaN is not a valid value');
+  t.throws(function () { return is.lt(NaN, 2); }, error, 'throws when first 
value is NaN');
+  t.throws(function () { return is.lt(2, NaN); }, error, 'throws when second 
value is NaN');
+  t.end();
+});
+
+test('is.within', function (t) {
+  var nanError = new TypeError('NaN is not a valid value');
+  t.throws(function () { return is.within(NaN, 0, 0); }, nanError, 'throws 
when first value is NaN');
+  t.throws(function () { return is.within(0, NaN, 0); }, nanError, 'throws 
when second value is NaN');
+  t.throws(function () { return is.within(0, 0, NaN); }, nanError, 'throws 
when third value is NaN');
+
+  var error = new TypeError('all arguments must be numbers');
+  t.throws(function () { return is.within('', 0, 0); }, error, 'throws when 
first value is string');
+  t.throws(function () { return is.within(0, '', 0); }, error, 'throws when 
second value is string');
+  t.throws(function () { return is.within(0, 0, ''); }, error, 'throws when 
third value is string');
+  t.throws(function () { return is.within({}, 0, 0); }, error, 'throws when 
first value is object');
+  t.throws(function () { return is.within(0, {}, 0); }, error, 'throws when 
second value is object');
+  t.throws(function () { return is.within(0, 0, {}); }, error, 'throws when 
third value is object');
+  t.throws(function () { return is.within(null, 0, 0); }, error, 'throws when 
first value is null');
+  t.throws(function () { return is.within(0, null, 0); }, error, 'throws when 
second value is null');
+  t.throws(function () { return is.within(0, 0, null); }, error, 'throws when 
third value is null');
+  t.throws(function () { return is.within(undefined, 0, 0); }, error, 'throws 
when first value is undefined');
+  t.throws(function () { return is.within(0, undefined, 0); }, error, 'throws 
when second value is undefined');
+  t.throws(function () { return is.within(0, 0, undefined); }, error, 'throws 
when third value is undefined');
+
+  t.ok(is.within(2, 1, 3), '2 is between 1 and 3');
+  t.ok(is.within(0, -1, 1), '0 is between -1 and 1');
+  t.ok(is.within(2, 0, Infinity), 'infinity always returns true');
+  t.ok(is.within(2, Infinity, 2), 'infinity always returns true');
+  t.ok(is.within(Infinity, 0, 1), 'infinity always returns true');
+  t.notOk(is.within(2, -1, -1), '2 is not between -1 and 1');
+  t.end();
+});
+
+test('is.object', function (t) {
+  t.ok(is.object({}), 'object literal is object');
+  t.notOk(is.object(), 'undefined is not an object');
+  t.notOk(is.object(null), 'null is not an object');
+  t.notOk(is.object(true), 'true is not an object');
+  t.notOk(is.object(''), 'string is not an object');
+  t.notOk(is.object(NaN), 'NaN is not an object');
+  t.notOk(is.object(Object), 'object constructor is not an object');
+  t.notOk(is.object(function () {}), 'function is not an object');
+  t.end();
+});
+
+test('is.hash', function (t) {
+  t.ok(is.hash({}), 'empty object literal is hash');
+  t.ok(is.hash({ 1: 2, a: 'b' }), 'object literal is hash');
+  t.notOk(is.hash(), 'undefined is not a hash');
+  t.notOk(is.hash(null), 'null is not a hash');
+  t.notOk(is.hash(new Date()), 'date is not a hash');
+  t.notOk(is.hash(new String()), 'string object is not a hash');
+  t.notOk(is.hash(''), 'string literal is not a hash');
+  t.notOk(is.hash(new Number()), 'number object is not a hash');
+  t.notOk(is.hash(1), 'number literal is not a hash');
+  t.notOk(is.hash(true), 'true is not a hash');
+  t.notOk(is.hash(false), 'false is not a hash');
+  t.notOk(is.hash(new Boolean()), 'boolean obj is not hash');
+  t.notOk(is.hash(false), 'literal false is not hash');
+  t.notOk(is.hash(true), 'literal true is not hash');
+  if (typeof module !== 'undefined') {
+    t.ok(is.hash(module.exports), 'module.exports is a hash');
+  }
+  if (typeof window !== 'undefined') {
+    t.notOk(is.hash(window), 'window is not a hash');
+    t.notOk(is.hash(document.createElement('div')), 'element is not a hash');
+  } else if (typeof process !== 'undefined') {
+    t.notOk(is.hash(global), 'global is not a hash');
+    t.notOk(is.hash(process), 'process is not a hash');
+  }
+  t.end();
+});
+
+test('is.regexp', function (t) {
+  t.ok(is.regexp(/a/g), 'regex literal is regex');
+  t.ok(is.regexp(new RegExp('a', 'g')), 'regex object is regex');
+  t.notOk(is.regexp(), 'undefined is not regex');
+  t.notOk(is.regexp(function () {}), 'function is not regex');
+  t.notOk(is.regexp('/a/g'), 'string regex is not regex');
+  t.end();
+});
+
+test('is.string', function (t) {
+  t.ok(is.string('foo'), 'string literal is string');
+  t.ok(is.string(new String('foo')), 'string literal is string');
+  t.notOk(is.string(), 'undefined is not string');
+  t.notOk(is.string(String), 'string constructor is not string');
+  var F = function () {};
+  F.prototype = new String();
+  t.notOk(is.string(F), 'string subtype is not string');
+  t.end();
+});
+
+test('is.base64', function (t) {
+  t.ok(is.base64('wxyzWXYZ/+=='), 'string is base64 encoded');
+  t.ok(is.base64(''), 'zero length string is base64 encoded');
+  t.notOk(is.base64('wxyzWXYZ123/+=='), 'string length not a multiple of four 
is not base64 encoded');
+  t.notOk(is.base64('wxyzWXYZ1234|]=='), 'string with invalid characters is 
not base64 encoded');
+  t.notOk(is.base64('wxyzWXYZ1234==/+'), 'string with = not at end is not 
base64 encoded');
+  t.notOk(is.base64('wxyzWXYZ1234/==='), 'string ending with === is not base64 
encoded');
+  t.end();
+});
+
+test('is.hex', function (t) {
+  t.ok(is.hex('abcdABCD1234'), 'string is hex encoded');
+  t.ok(is.hex(''), 'zero length string is hex encoded');
+  t.notOk(is.hex('wxyzWXYZ1234/+=='), 'string with invalid characters is not 
hex encoded');
+  t.end();
+});
diff --git a/node.extend/package.json b/node.extend/package.json
new file mode 100644
index 0000000..3672849
--- /dev/null
+++ b/node.extend/package.json
@@ -0,0 +1,100 @@
+{
+  "name": "node.extend",
+  "version": "1.1.3",
+  "description": "A port of jQuery.extend that actually works on node.js",
+  "keywords": [
+    "extend",
+    "jQuery",
+    "jQuery extend",
+    "clone",
+    "copy",
+    "inherit"
+  ],
+  "author": {
+    "name": "dreamerslab",
+    "email": "[email protected]"
+  },
+  "dependencies": {
+    "is": "~2.1.0"
+  },
+  "devDependencies": {
+    "tape": "~3.0.1",
+    "covert": "1.0.0",
+    "jscs": "~1.7.3"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/dreamerslab/node.extend.git";
+  },
+  "contributors": [
+    {
+      "name": "Jordan Harband"
+    }
+  ],
+  "main": "index",
+  "scripts": {
+    "test": "npm run lint && node test/index.js && npm run coverage-quiet",
+    "coverage": "covert test/index.js",
+    "coverage-quiet": "covert test/index.js --quiet",
+    "lint": "jscs *.js */*.js"
+  },
+  "engines": [
+    "node >= 0.4"
+  ],
+  "testling": {
+    "files": "test/index.js",
+    "browsers": [
+      "iexplore/6.0..latest",
+      "firefox/3.0..6.0",
+      "firefox/15.0..latest",
+      "firefox/nightly",
+      "chrome/4.0..10.0",
+      "chrome/20.0..latest",
+      "chrome/canary",
+      "opera/10.0..latest",
+      "opera/next",
+      "safari/4.0..latest",
+      "ipad/6.0..latest",
+      "iphone/6.0..latest"
+    ]
+  },
+  "licenses": [
+    {
+      "type": "MIT",
+      "url": "http://en.wikipedia.org/wiki/MIT_License";
+    },
+    {
+      "type": "GPL",
+      "url": "http://en.wikipedia.org/wiki/GNU_General_Public_License";
+    }
+  ],
+  "gitHead": "9392ba7672392e5d1b84a53475cff8289e4ff2be",
+  "bugs": {
+    "url": "https://github.com/dreamerslab/node.extend/issues";
+  },
+  "homepage": "https://github.com/dreamerslab/node.extend";,
+  "_id": "[email protected]",
+  "_shasum": "9cd06d6b05a19ca9daf8f7ba574a8d1ced280d9f",
+  "_from": "node.extend@",
+  "_npmVersion": "1.4.28",
+  "_npmUser": {
+    "name": "ljharb",
+    "email": "[email protected]"
+  },
+  "maintainers": [
+    {
+      "name": "dreamerslab",
+      "email": "[email protected]"
+    },
+    {
+      "name": "ljharb",
+      "email": "[email protected]"
+    }
+  ],
+  "dist": {
+    "shasum": "9cd06d6b05a19ca9daf8f7ba574a8d1ced280d9f",
+    "tarball": "http://registry.npmjs.org/node.extend/-/node.extend-1.1.3.tgz";
+  },
+  "directories": {},
+  "_resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.3.tgz";
+}

-- 
To view, visit https://gerrit.wikimedia.org/r/200090
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I3bd88e785099b12ba04d2a7fb51e89c3de1757f9
Gerrit-PatchSet: 1
Gerrit-Project: wikimedia/fundraising/dash/node_modules
Gerrit-Branch: master
Gerrit-Owner: Ejegg <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to