| // Each of these is a string that will be require()'d in the couchapp |
| |
| exports.deep = |
| [ "exports.deepEquals = deepEquals" |
| , "exports.extend = deepExtend" |
| , function deepExtend(o1, o2) { |
| // extend o1 with o2 (in-place) |
| for (var prop in o2) { |
| if (hOP(o2, prop)) { |
| if (hOP(o1, prop)) { |
| if (typeof o1[prop] === "object") { |
| deepExtend(o1[prop], o2[prop]) |
| } |
| } else { |
| o1[prop] = o2[prop] |
| } |
| } |
| } |
| return o1 |
| } |
| , function fullPath(pathPrefix, p){ |
| return pathPrefix.concat([p]) |
| } |
| , function isObject(v){ |
| return typeof v === 'object' |
| } |
| , function arrayInArray(v, arr) { |
| // Check whether `arr` contains an array that's shallowly equal to `v`. |
| return arr.some(function(e) { |
| if (e.length !== v.length) return false |
| for (var i=0; i<e.length; i++) { |
| if (e[i] !== v[i]) { |
| return false |
| } |
| } |
| return true |
| }) |
| } |
| , function deepEquals(o1, o2, ignoreKeys, pathPrefix){ |
| pathPrefix = pathPrefix || [] |
| ignoreKeys = ignoreKeys || [] |
| function hOP (obj, prop) { |
| return Object.prototype.hasOwnProperty.call(obj, prop) |
| } |
| if (typeof o1 !== typeof o2) { |
| return false |
| } else if (!isObject(o1)) { |
| return o1 === o2 |
| } |
| for (var prop in o1) { |
| if (hOP(o1, prop) && |
| !arrayInArray(fullPath(pathPrefix, prop), ignoreKeys)) { |
| if (!hOP(o2, prop) || |
| !deepEquals(o1[prop], |
| o2[prop], |
| ignoreKeys, |
| fullPath(pathPrefix, prop))) { |
| return false |
| } |
| } |
| } |
| for (var prop in o2) { |
| if (hOP(o2, prop) && |
| !hOP(o1, prop) && |
| !arrayInArray(fullPath(pathPrefix, prop), ignoreKeys)) { |
| return false |
| } |
| } |
| return true |
| } |
| ].map(function (s) { return s.toString() }).join("\n") |
| |
| exports.semver = require('fs').readFileSync(require.resolve('semver'), 'utf8') |
| |
| exports.valid = |
| [ 'var semver = require("semver")' |
| , 'exports.name = validName' |
| , 'exports.package = validPackage' |
| , function validName (name) { |
| if (!name) return false |
| var n = name.trim() |
| if (!n || n.charAt(0) === "." |
| || !n.match(/^[a-zA-Z0-9]/) |
| || n.match(/[\/\(\)&\?#\|<>@:%\s\\\*'"!~`]/) |
| || n.toLowerCase() === "node_modules" |
| || n !== encodeURIComponent(n) |
| || n.toLowerCase() === "favicon.ico") { |
| return false |
| } |
| return n |
| } |
| , function validPackage (pkg) { |
| return validName(pkg.name) && semver.valid(pkg.version) |
| } |
| ].map(function (s) { return s.toString() }).join("\n") |
| |
| |
| // monkey patchers |
| exports.Date = |
| [ "exports.parse = parse" |
| , "exports.toISOString = toISOString" |
| , "exports.now = now" |
| , function now () { |
| return new Date().getTime() |
| } |
| , function parse (s) { |
| // s is something like "2010-12-29T07:31:06Z" |
| s = s.split("T") |
| var ds = s[0] |
| , ts = s[1] |
| , d = new Date() |
| ds = ds.split("-") |
| ts = ts.split(":") |
| var tz = ts[2].substr(2) |
| ts[2] = ts[2].substr(0, 2) |
| d.setUTCFullYear(+ds[0]) |
| d.setUTCMonth(+ds[1]-1) |
| d.setUTCDate(+ds[2]) |
| d.setUTCHours(+ts[0]) |
| d.setUTCMinutes(+ts[1]) |
| d.setUTCSeconds(+ts[2]) |
| d.setUTCMilliseconds(0) |
| return d.getTime() |
| } |
| , "exports.toISOString = toISOString" |
| , function toISOString () { return ISODateString(this) } |
| , function pad(n){return n<10 ? '0'+n : n} |
| , function ISODateString(d){ |
| return d.getUTCFullYear()+'-' |
| + pad(d.getUTCMonth()+1)+'-' |
| + pad(d.getUTCDate())+'T' |
| + pad(d.getUTCHours())+':' |
| + pad(d.getUTCMinutes())+':' |
| + pad(d.getUTCSeconds())+'Z'} |
| ].map(function (s) { return s.toString() }).join("\n") |
| |
| exports.Object = |
| [ "exports.keys = keys" |
| , function keys (o) { |
| var a = [] |
| for (var i in o) a.push(i) |
| return a } |
| ].map(function (s) { return s.toString() }).join("\n") |
| |
| exports.Array = |
| [ "exports.isArray = isArray" |
| , "exports.forEach = forEach", |
| , "exports.reduce = reduce", |
| , function forEach (fn) { |
| for (var i = 0, l = this.length; i < l; i ++) { |
| if (this.hasOwnProperty(i)) { |
| fn(this[i], i, this) |
| } |
| } |
| } |
| , function reduce (callback, initialValue) { |
| var previousValue = initialValue || this[0]; |
| for (var i = initialValue ? 0 : 1; i < this.length; i++) { |
| previousValue = callback(previousValue, this[i], i, this); |
| } |
| return previousValue; |
| } |
| , function isArray (a) { |
| return a instanceof Array |
| || Object.prototype.toString.call(a) === "[object Array]" |
| || (typeof a === "object" && typeof a.length === "number") } |
| ].map(function (s) { return s.toString() }).join("\n") |
| |
| exports.String = |
| [ "exports.trim = trim" |
| , function trim () { |
| return this.replace(/^\s+|\s+$/g, "") |
| } |
| ].map(function (s) { return s.toString() }).join("\n") |
| |
| exports.monkeypatch = |
| [ "exports.patch = patch" |
| , function patch (Object, Date, Array, String) { |
| if (!Date.parse || isNaN(Date.parse("2010-12-29T07:31:06Z"))) { |
| Date.parse = require("Date").parse |
| } |
| |
| Date.prototype.toISOString = Date.prototype.toISOString |
| || require("Date").toISOString |
| |
| Date.now = Date.now |
| || require("Date").now |
| |
| Object.keys = Object.keys |
| || require("Object").keys |
| |
| Array.prototype.forEach = Array.prototype.forEach |
| || require("Array").forEach |
| |
| Array.prototype.reduce = Array.prototype.reduce |
| || require("Array").reduce |
| |
| Array.isArray = Array.isArray |
| || require("Array").isArray |
| |
| String.prototype.trim = String.prototype.trim |
| || require("String").trim |
| } |
| ].map(function (s) { return s.toString() }).join("\n") |
| |