<commit_before>(function () {
    "use strict";

    function defineIsa(extended) {

        var undef, pSlice = Array.prototype.slice;

        var hasOwnProperty = Object.prototype.hasOwnProperty;
        var toStr = Object.prototype.toString;

        function argsToArray(args, slice) {
            slice = slice || 0;
            return pSlice.call(args, slice);
        }

        function keys(obj) {
            var ret = [];
            for (var i in obj) {
                if (obj.hasOwnProperty(i)) {
                    ret.push(i);
                }
            }
            return ret;
        }

        //taken from node js assert.js
        //https://github.com/joyent/node/blob/master/lib/assert.js
        function deepEqual(actual, expected) {
            // 7.1. All identical values are equivalent, as determined by ===.
            if (actual === expected) {
                return true;

            } else if (typeof Buffer !== "undefined" && Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
                if (actual.length !== expected.length) {
                    return false;
                }

                for (var i = 0; i < actual.length; i++) {
                    if (actual[i] !== expected[i]) {
                        return false;
                    }
                }

                return true;

                // 7.2. If the expected value is a Date object, the actual value is
                // equivalent if it is also a Date object that refers to the same time.
            } else if (isDate(actual) && isDate(expected)) {
                return actual.getTime() === expected.getTime();

                // 7.3 If the expected value is a RegExp object, the actual value is
                // equivalent if it is also a RegExp object with the same source and
                // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
            } else if (isRegExp(actual) && isRegExp(expected)) {
                return actual.source === expected.source &&
                    actual.global === expected.global &&
                    actual.multiline === expected.multiline &&
                    actual.lastIndex === expected.lastIndex &&
                    actual.ignoreCase === expected.ignoreCase;

                // 7.4. Other pairs that do not both pass typeof value == 'object',
                // equivalence is determined by ==.
            } else if (isString(actual) && isString(expected) && actual !== expected) {
                return false;
            } else if (typeof actual !== 'object' && typeof expected !== 'object') {
                return actual === expected;

                // 7.5 For all other Object pairs, including Array objects, equivalence is
                // determined by having the same number of owned properties (as verified
                // with Object.prototype.hasOwnProperty.call), the same set of keys
                // (although not necessarily the same order), equivalent values for every
                // corresponding key, and an identical 'prototype' property. Note: this
                // accounts for both named and indexed properties on Arrays.
            } else {
                return objEquiv(actual, expected);
            }
        }

        function objEquiv(a, b) {
            var key;
            if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) {
                return false;
            }
            // an identical 'prototype' property.
            if (a.prototype !== b.prototype) {
                return false;
            }
            //~~~I've managed to break Object.keys through screwy arguments passing.
            //   Converting to array solves the problem.
            if (isArguments(a)) {
                if (!isArguments(b)) {
                    return false;
                }
                a = pSlice.call(a);
                b = pSlice.call(b);
                return deepEqual(a, b);
            }
            try {
                var ka = keys(a),
                    kb = keys(b),
                    i;
                // having the same number of owned properties (keys incorporates
                // hasOwnProperty)
                if (ka.length !== kb.length) {
                    return false;
                }
                //the same set of keys (although not necessarily the same order),
                ka.sort();
                kb.sort();
                //~~~cheap key test
                for (i = ka.length - 1; i >= 0; i--) {
                    if (ka[i] !== kb[i]) {
                        return false;
                    }
                }
                //equivalent values for every corresponding key, and
                //~~~possibly expensive deep test
                for (i = ka.length - 1; i >= 0; i--) {
                    key = ka[i];
                    if (!deepEqual(a[key], b[key])) {
                        return false;
                    }
                }
            } catch (e) {//happens when one is a string literal and the other isn't
                return false;
            }
            return true;
        }

        var isFunction = function (obj) {
            return toStr.call(obj) === '[object Function]';
        };

        //ie hack
        if ("undefined" !== typeof window && !isFunction(window.alert)) {
            (function (alert) {
                isFunction = function (obj) {
                    return toStr.call(obj) === '[object Function]' || obj === alert;
                };
            }(window.alert));
        }

        function isObject(obj) {
            var undef;
            return obj !== null && obj !== undef && typeof obj === "object";
        }

        function isHash(obj) {
            var ret = isObject(obj);
            return ret && obj.constructor === Object && !obj.nodeType && !obj.setInterval;
        }

        function isEmpty(object) {
            if (isArguments(object)) {
                return object.length === 0;
            } else if (isObject(object)) {
                return keys(object).length === 0;
            } else if (isString(object) || isArray(object)) {
                return object.length === 0;
            }
            return true;
        }

        function isBoolean(obj) {
            return obj === true || obj === false || toStr.call(obj) === "[object Boolean]";
        }

        function isUndefined(obj) {
            return typeof obj === 'undefined';
        }

        function isDefined(obj) {
            return !isUndefined(obj);
        }

        function isUndefinedOrNull(obj) {
            return isUndefined(obj) || isNull(obj);
        }

        function isNull(obj) {
            return obj !== undef && obj === null;
        }

        var isArguments = function _isArguments(object) {
            return toStr.call(object) === '[object Arguments]';
        };

        if (!isArguments(arguments)) {
            isArguments = function _isArguments(obj) {
                return !!(obj && obj.hasOwnProperty("callee"));
            };
        }

        function isInstanceOf(obj, clazz) {
            if (isFunction(clazz)) {
                return obj instanceof clazz;
            } else {
                return false;
            }
        }

        function isRegExp(obj) {
            return toStr.call(obj) === '[object RegExp]';
        }

        var isArray = Array.isArray || function isArray(obj) {
            return toStr.call(obj) === "[object Array]";
        };

        function isDate(obj) {
            return toStr.call(obj) === '[object Date]';
        }

        function isString(obj) {
            return toStr.call(obj) === '[object String]';
        }

        function isNumber(obj) {
            return toStr.call(obj) === '[object Number]';
        }

        function isTrue(obj) {
            return obj === true;
        }

        function isFalse(obj) {
            return obj === false;
        }

        function isNotNull(obj) {
            return !isNull(obj);
        }

        function isEq(obj, obj2) {
            /*jshint eqeqeq:false*/
            return obj == obj2;
        }

        function isNeq(obj, obj2) {
            /*jshint eqeqeq:false*/
            return obj != obj2;
        }

        function isSeq(obj, obj2) {
            return obj === obj2;
        }

        function isSneq(obj, obj2) {
            return obj !== obj2;
        }

        function isIn(obj, arr) {
            if (isArray(arr)) {
                for (var i = 0, l = arr.length; i < l; i++) {
                    if (isEq(obj, arr[i])) {
                        return true;
                    }
                }
            }
            return false;
        }

        function isNotIn(obj, arr) {
            return !isIn(obj, arr);
        }

        function isLt(obj, obj2) {
            return obj < obj2;
        }

        function isLte(obj, obj2) {
            return obj <= obj2;
        }

        function isGt(obj, obj2) {
            return obj > obj2;
        }

        function isGte(obj, obj2) {
            return obj >= obj2;
        }

        function isLike(obj, reg) {
            if (isString(reg)) {
                reg = new RegExp(reg);
            }
            if (isRegExp(reg)) {
                return reg.test("" + obj);
            }
            return false;
        }

        function isNotLike(obj, reg) {
            return !isLike(obj, reg);
        }

        function contains(arr, obj) {
            return isIn(obj, arr);
        }

        function notContains(arr, obj) {
            return !isIn(obj, arr);
        }

        function containsAt(arr, obj, index) {
            if (isArray(arr) && arr.length > index) {
                return isEq(arr[index], obj);
            }
            return false;
        }

        function notContainsAt(arr, obj, index) {
            if (isArray(arr)) {
                return !isEq(arr[index], obj);
            }
            return false;
        }

        function has(obj, prop) {
            return hasOwnProperty.call(obj, prop);
        }

        function notHas(obj, prop) {
            return !has(obj, prop);
        }

        function length(obj, l) {
            if (has(obj, "length")) {
                return obj.length === l;
            }
            return false;
        }

        function notLength(obj, l) {
            if (has(obj, "length")) {
                return obj.length !== l;
            }
            return false;
        }

        var isa = {
            isFunction: isFunction,
            isObject: isObject,
            isEmpty: isEmpty,
            isHash: isHash,
            isNumber: isNumber,
            isString: isString,
            isDate: isDate,
            isArray: isArray,
            isBoolean: isBoolean,
            isUndefined: isUndefined,
            isDefined: isDefined,
            isUndefinedOrNull: isUndefinedOrNull,
            isNull: isNull,
            isArguments: isArguments,
            instanceOf: isInstanceOf,
            isRegExp: isRegExp,
            deepEqual: deepEqual,
            isTrue: isTrue,
            isFalse: isFalse,
            isNotNull: isNotNull,
            isEq: isEq,
            isNeq: isNeq,
            isSeq: isSeq,
            isSneq: isSneq,
            isIn: isIn,
            isNotIn: isNotIn,
            isLt: isLt,
            isLte: isLte,
            isGt: isGt,
            isGte: isGte,
            isLike: isLike,
            isNotLike: isNotLike,
            contains: contains,
            notContains: notContains,
            has: has,
            notHas: notHas,
            isLength: length,
            isNotLength: notLength,
            containsAt: containsAt,
            notContainsAt: notContainsAt
        };

        var tester = {
            constructor: function () {
                this._testers = [];
            },

            noWrap: {
                tester: function () {
                    var testers = this._testers;
                    return function tester(value) {
                        var isa = false;
                        for (var i = 0, l = testers.length; i < l && !isa; i++) {
                            isa = testers[i](value);
                        }
                        return isa;
                    };
                }
            }
        };

        var switcher = {
            constructor: function () {
                this._cases = [];
                this.__default = null;
            },

            def: function (val, fn) {
                this.__default = fn;
            },

            noWrap: {
                switcher: function () {
                    var testers = this._cases, __default = this.__default;
                    return function tester() {
                        var handled = false, args = argsToArray(arguments), caseRet;
                        for (var i = 0, l = testers.length; i < l && !handled; i++) {
                            caseRet = testers[i](args);
                            if (caseRet.length > 1) {
                                if (caseRet[1] || caseRet[0]) {
                                    return caseRet[1];
                                }
                            }
                        }
                        if (!handled && __default) {
                            return  __default.apply(this, args);
                        }
                    };
                }
            }
        };

        function addToTester(func) {
            tester[func] = function isaTester() {
                this._testers.push(isa[func]);
            };
        }

        function addToSwitcher(func) {
            switcher[func] = function isaTester() {
                var args = argsToArray(arguments, 1), isFunc = isa[func], handler, doBreak = true;
                if (args.length <= isFunc.length - 1) {
                    throw new TypeError("A handler must be defined when calling using switch");
                } else {
                    handler = args.pop();
                    if (isBoolean(handler)) {
                        doBreak = handler;
                        handler = args.pop();
                    }
                }
                if (!isFunction(handler)) {
                    throw new TypeError("handler must be defined");
                }
                this._cases.push(function (testArgs) {
                    if (isFunc.apply(isa, testArgs.concat(args))) {
                        return [doBreak, handler.apply(this, testArgs)];
                    }
                    return [false];
                });
            };
        }

        for (var i in isa) {
            if (isa.hasOwnProperty(i)) {
                addToSwitcher(i);
                addToTester(i);
            }
        }

        var is = extended.define(isa).expose(isa);
        is.tester = extended.define(tester);
        is.switcher = extended.define(switcher);
        return is;

    }

    if ("undefined" !== typeof exports) {
        if ("undefined" !== typeof module && module.exports) {
            module.exports = defineIsa(require("extended"));

        }
    } else if ("function" === typeof define) {
        define(["require"], function (require) {
            return defineIsa((require("extended")));
        });
    } else {
        this.isExtended = defineIsa(this.extended);
    }

}).call(this);

<commit_msg>Undefined checks aren't helpful in isNull.<commit_after>(function () {
    "use strict";

    function defineIsa(extended) {

        var undef, pSlice = Array.prototype.slice;

        var hasOwnProperty = Object.prototype.hasOwnProperty;
        var toStr = Object.prototype.toString;

        function argsToArray(args, slice) {
            slice = slice || 0;
            return pSlice.call(args, slice);
        }

        function keys(obj) {
            var ret = [];
            for (var i in obj) {
                if (obj.hasOwnProperty(i)) {
                    ret.push(i);
                }
            }
            return ret;
        }

        //taken from node js assert.js
        //https://github.com/joyent/node/blob/master/lib/assert.js
        function deepEqual(actual, expected) {
            // 7.1. All identical values are equivalent, as determined by ===.
            if (actual === expected) {
                return true;

            } else if (typeof Buffer !== "undefined" && Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
                if (actual.length !== expected.length) {
                    return false;
                }

                for (var i = 0; i < actual.length; i++) {
                    if (actual[i] !== expected[i]) {
                        return false;
                    }
                }

                return true;

                // 7.2. If the expected value is a Date object, the actual value is
                // equivalent if it is also a Date object that refers to the same time.
            } else if (isDate(actual) && isDate(expected)) {
                return actual.getTime() === expected.getTime();

                // 7.3 If the expected value is a RegExp object, the actual value is
                // equivalent if it is also a RegExp object with the same source and
                // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
            } else if (isRegExp(actual) && isRegExp(expected)) {
                return actual.source === expected.source &&
                    actual.global === expected.global &&
                    actual.multiline === expected.multiline &&
                    actual.lastIndex === expected.lastIndex &&
                    actual.ignoreCase === expected.ignoreCase;

                // 7.4. Other pairs that do not both pass typeof value == 'object',
                // equivalence is determined by ==.
            } else if (isString(actual) && isString(expected) && actual !== expected) {
                return false;
            } else if (typeof actual !== 'object' && typeof expected !== 'object') {
                return actual === expected;

                // 7.5 For all other Object pairs, including Array objects, equivalence is
                // determined by having the same number of owned properties (as verified
                // with Object.prototype.hasOwnProperty.call), the same set of keys
                // (although not necessarily the same order), equivalent values for every
                // corresponding key, and an identical 'prototype' property. Note: this
                // accounts for both named and indexed properties on Arrays.
            } else {
                return objEquiv(actual, expected);
            }
        }

        function objEquiv(a, b) {
            var key;
            if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) {
                return false;
            }
            // an identical 'prototype' property.
            if (a.prototype !== b.prototype) {
                return false;
            }
            //~~~I've managed to break Object.keys through screwy arguments passing.
            //   Converting to array solves the problem.
            if (isArguments(a)) {
                if (!isArguments(b)) {
                    return false;
                }
                a = pSlice.call(a);
                b = pSlice.call(b);
                return deepEqual(a, b);
            }
            try {
                var ka = keys(a),
                    kb = keys(b),
                    i;
                // having the same number of owned properties (keys incorporates
                // hasOwnProperty)
                if (ka.length !== kb.length) {
                    return false;
                }
                //the same set of keys (although not necessarily the same order),
                ka.sort();
                kb.sort();
                //~~~cheap key test
                for (i = ka.length - 1; i >= 0; i--) {
                    if (ka[i] !== kb[i]) {
                        return false;
                    }
                }
                //equivalent values for every corresponding key, and
                //~~~possibly expensive deep test
                for (i = ka.length - 1; i >= 0; i--) {
                    key = ka[i];
                    if (!deepEqual(a[key], b[key])) {
                        return false;
                    }
                }
            } catch (e) {//happens when one is a string literal and the other isn't
                return false;
            }
            return true;
        }

        var isFunction = function (obj) {
            return toStr.call(obj) === '[object Function]';
        };

        //ie hack
        if ("undefined" !== typeof window && !isFunction(window.alert)) {
            (function (alert) {
                isFunction = function (obj) {
                    return toStr.call(obj) === '[object Function]' || obj === alert;
                };
            }(window.alert));
        }

        function isObject(obj) {
            var undef;
            return obj !== null && obj !== undef && typeof obj === "object";
        }

        function isHash(obj) {
            var ret = isObject(obj);
            return ret && obj.constructor === Object && !obj.nodeType && !obj.setInterval;
        }

        function isEmpty(object) {
            if (isArguments(object)) {
                return object.length === 0;
            } else if (isObject(object)) {
                return keys(object).length === 0;
            } else if (isString(object) || isArray(object)) {
                return object.length === 0;
            }
            return true;
        }

        function isBoolean(obj) {
            return obj === true || obj === false || toStr.call(obj) === "[object Boolean]";
        }

        function isUndefined(obj) {
            return typeof obj === 'undefined';
        }

        function isDefined(obj) {
            return !isUndefined(obj);
        }

        function isUndefinedOrNull(obj) {
            return isUndefined(obj) || isNull(obj);
        }

        function isNull(obj) {
            return obj === null;
        }

        var isArguments = function _isArguments(object) {
            return toStr.call(object) === '[object Arguments]';
        };

        if (!isArguments(arguments)) {
            isArguments = function _isArguments(obj) {
                return !!(obj && obj.hasOwnProperty("callee"));
            };
        }

        function isInstanceOf(obj, clazz) {
            if (isFunction(clazz)) {
                return obj instanceof clazz;
            } else {
                return false;
            }
        }

        function isRegExp(obj) {
            return toStr.call(obj) === '[object RegExp]';
        }

        var isArray = Array.isArray || function isArray(obj) {
            return toStr.call(obj) === "[object Array]";
        };

        function isDate(obj) {
            return toStr.call(obj) === '[object Date]';
        }

        function isString(obj) {
            return toStr.call(obj) === '[object String]';
        }

        function isNumber(obj) {
            return toStr.call(obj) === '[object Number]';
        }

        function isTrue(obj) {
            return obj === true;
        }

        function isFalse(obj) {
            return obj === false;
        }

        function isNotNull(obj) {
            return !isNull(obj);
        }

        function isEq(obj, obj2) {
            /*jshint eqeqeq:false*/
            return obj == obj2;
        }

        function isNeq(obj, obj2) {
            /*jshint eqeqeq:false*/
            return obj != obj2;
        }

        function isSeq(obj, obj2) {
            return obj === obj2;
        }

        function isSneq(obj, obj2) {
            return obj !== obj2;
        }

        function isIn(obj, arr) {
            if (isArray(arr)) {
                for (var i = 0, l = arr.length; i < l; i++) {
                    if (isEq(obj, arr[i])) {
                        return true;
                    }
                }
            }
            return false;
        }

        function isNotIn(obj, arr) {
            return !isIn(obj, arr);
        }

        function isLt(obj, obj2) {
            return obj < obj2;
        }

        function isLte(obj, obj2) {
            return obj <= obj2;
        }

        function isGt(obj, obj2) {
            return obj > obj2;
        }

        function isGte(obj, obj2) {
            return obj >= obj2;
        }

        function isLike(obj, reg) {
            if (isString(reg)) {
                reg = new RegExp(reg);
            }
            if (isRegExp(reg)) {
                return reg.test("" + obj);
            }
            return false;
        }

        function isNotLike(obj, reg) {
            return !isLike(obj, reg);
        }

        function contains(arr, obj) {
            return isIn(obj, arr);
        }

        function notContains(arr, obj) {
            return !isIn(obj, arr);
        }

        function containsAt(arr, obj, index) {
            if (isArray(arr) && arr.length > index) {
                return isEq(arr[index], obj);
            }
            return false;
        }

        function notContainsAt(arr, obj, index) {
            if (isArray(arr)) {
                return !isEq(arr[index], obj);
            }
            return false;
        }

        function has(obj, prop) {
            return hasOwnProperty.call(obj, prop);
        }

        function notHas(obj, prop) {
            return !has(obj, prop);
        }

        function length(obj, l) {
            if (has(obj, "length")) {
                return obj.length === l;
            }
            return false;
        }

        function notLength(obj, l) {
            if (has(obj, "length")) {
                return obj.length !== l;
            }
            return false;
        }

        var isa = {
            isFunction: isFunction,
            isObject: isObject,
            isEmpty: isEmpty,
            isHash: isHash,
            isNumber: isNumber,
            isString: isString,
            isDate: isDate,
            isArray: isArray,
            isBoolean: isBoolean,
            isUndefined: isUndefined,
            isDefined: isDefined,
            isUndefinedOrNull: isUndefinedOrNull,
            isNull: isNull,
            isArguments: isArguments,
            instanceOf: isInstanceOf,
            isRegExp: isRegExp,
            deepEqual: deepEqual,
            isTrue: isTrue,
            isFalse: isFalse,
            isNotNull: isNotNull,
            isEq: isEq,
            isNeq: isNeq,
            isSeq: isSeq,
            isSneq: isSneq,
            isIn: isIn,
            isNotIn: isNotIn,
            isLt: isLt,
            isLte: isLte,
            isGt: isGt,
            isGte: isGte,
            isLike: isLike,
            isNotLike: isNotLike,
            contains: contains,
            notContains: notContains,
            has: has,
            notHas: notHas,
            isLength: length,
            isNotLength: notLength,
            containsAt: containsAt,
            notContainsAt: notContainsAt
        };

        var tester = {
            constructor: function () {
                this._testers = [];
            },

            noWrap: {
                tester: function () {
                    var testers = this._testers;
                    return function tester(value) {
                        var isa = false;
                        for (var i = 0, l = testers.length; i < l && !isa; i++) {
                            isa = testers[i](value);
                        }
                        return isa;
                    };
                }
            }
        };

        var switcher = {
            constructor: function () {
                this._cases = [];
                this.__default = null;
            },

            def: function (val, fn) {
                this.__default = fn;
            },

            noWrap: {
                switcher: function () {
                    var testers = this._cases, __default = this.__default;
                    return function tester() {
                        var handled = false, args = argsToArray(arguments), caseRet;
                        for (var i = 0, l = testers.length; i < l && !handled; i++) {
                            caseRet = testers[i](args);
                            if (caseRet.length > 1) {
                                if (caseRet[1] || caseRet[0]) {
                                    return caseRet[1];
                                }
                            }
                        }
                        if (!handled && __default) {
                            return  __default.apply(this, args);
                        }
                    };
                }
            }
        };

        function addToTester(func) {
            tester[func] = function isaTester() {
                this._testers.push(isa[func]);
            };
        }

        function addToSwitcher(func) {
            switcher[func] = function isaTester() {
                var args = argsToArray(arguments, 1), isFunc = isa[func], handler, doBreak = true;
                if (args.length <= isFunc.length - 1) {
                    throw new TypeError("A handler must be defined when calling using switch");
                } else {
                    handler = args.pop();
                    if (isBoolean(handler)) {
                        doBreak = handler;
                        handler = args.pop();
                    }
                }
                if (!isFunction(handler)) {
                    throw new TypeError("handler must be defined");
                }
                this._cases.push(function (testArgs) {
                    if (isFunc.apply(isa, testArgs.concat(args))) {
                        return [doBreak, handler.apply(this, testArgs)];
                    }
                    return [false];
                });
            };
        }

        for (var i in isa) {
            if (isa.hasOwnProperty(i)) {
                addToSwitcher(i);
                addToTester(i);
            }
        }

        var is = extended.define(isa).expose(isa);
        is.tester = extended.define(tester);
        is.switcher = extended.define(switcher);
        return is;

    }

    if ("undefined" !== typeof exports) {
        if ("undefined" !== typeof module && module.exports) {
            module.exports = defineIsa(require("extended"));

        }
    } else if ("function" === typeof define) {
        define(["require"], function (require) {
            return defineIsa((require("extended")));
        });
    } else {
        this.isExtended = defineIsa(this.extended);
    }

}).call(this);

<|endoftext|>


<commit_before>/*jslint node:true*/

// using own "yui" dependencies for modown-yui
var YUI = require(__dirname + '/../node_modules/yui').YUI,
    Y = YUI().use('loader-base');

module.exports = {

    /**
     * Specify a list of modules to use as seed.
     *
     * E.g. seed(['yui-base', 'loader-base'];
     *
     * @param {Array} modules list of modules to use
     */
    seed: function (modules) {

        var config = this.config({
            seed: modules
        });

        return false;

    },

    /**
     * Expand the list of seed modules and expose the seeds to the client.
     */
    exposeSeed: function () {

        // getting static config
        var config = this.config(),
            seedCache = '',
            modules = [].concat(config.seed || ['yui-base']),
            mod,
            i,
            loader;

        // TODO: add config so that module expansion can be disabled if needed
        // expand modules
        loader = new Y.Loader({
            base: config.base,
            ignoreRegistered: true,
            require : modules
        });
        loader.calculate();
        modules = [].concat(loader.sorted);
        /*
        for (mod in modules) {
            if (modules.hasOwnProperty(mod)) {
                // TBD: more processing required ?
            }
        }
        */

        // producing blob with the html fragment
        for (i = 0; i < modules.length; i += 1) {
            seedCache += '<script src="' +
                config.base + modules[i] + '/' + modules[i] +
                (config.filter === 'debug' ? '-debug' : '-min') +
                '.js' + '"></script>';
        }

        return seedCache ? function (req, res, next) {

            // TODO: maybe using lang to replace a token

            // if express-expose is available, we surface some entries
            if (res.expose) {
                res.expose(seedCache, 'yui_seed');
            }

            next();

        } : false;

    }

};
<commit_msg>Fixes based on feedback: 1. uing YUI from yui.YUI 2. creating Y on demand; 3. pass app modules to Y.use; 4. clean up Y and loader;<commit_after>/*jslint node:true*/

module.exports = {

    /**
     * Specify a list of modules to use as seed.
     *
     * E.g. seed(['yui-base', 'loader-base'];
     *
     * @param {Array} modules list of modules to use
     */
    seed: function (modules) {

        var config = this.config({
            seed: modules
        });

        return false;

    },

    /**
     * Expand the list of seed modules and expose the seeds to the client.
     */
    exposeSeed: function () {

        // getting static config
        var config = this.config(),
            seedCache = '',
            modules = [].concat(config.seed || ['yui-base']),
            appModules = [].concat((config.groups && config.groups.app && config.groups.app.modules) || []),
            mod,
            i,
            Y,
            loader;

        Y = this.YUI({sync: true}).use(['loader-base'].concat(appModules));

        // TODO: add config so that module expansion can be disabled if needed
        // expand modules
        loader = new Y.Loader({
            base: config.base,
            ignoreRegistered: true,
            require : modules
        });
        loader.calculate();
        modules = [].concat(loader.sorted);
        loader = null;
        Y = null;

        // producing blob with the html fragment
        for (i = 0; i < modules.length; i += 1) {
            seedCache += '<script src="' +
                config.base + modules[i] + '/' + modules[i] +
                (config.filter === 'debug' ? '-debug' : '-min') +
                '.js' + '"></script>';
        }

        return seedCache ? function (req, res, next) {

            // TODO: maybe using lang to replace a token

            // if express-expose is available, we surface some entries
            if (res.expose) {
                res.expose(seedCache, 'yui_seed');
            }

            next();

        } : false;

    }

};
<|endoftext|>


<commit_before>var express = require('express');
var bodyParser = require('body-parser');
var gpio = require('ms-gpio');
var app = new express();

startUp();

//Listen for all the request
var server = app.listen(app.get('port'), function () {
    var port = server.address().port;
    console.log('Server running on port ' + port);
});

//Register all the startup related stuffs in this function
function startUp() {
    gpio.GPIO_Path = "test"; //Comment it out if used in Raspberry device
    configureExternalModule();
    setUpHttpHandler();
    app.set('port', 9000);
}

//Configure external modules here
function configureExternalModule() {
    app.use(bodyParser.urlencoded({
        extended: true
    }));

    app.use(bodyParser.json());

    var options = {
        index: "index.htm"
    };

    app.use('/', express.static('public', options));
}

//Configure http request handler
function setUpHttpHandler() {
    app.use('/getDevices', function (req, res) {
        var devices = getRegisteredDevices();
        for (var i = 0; i < devices.length; i++) {
            var status = gpio.read(devices[i].deviceId);
            devices[i].status = status;
        }
        res.json(devices);
    });

    app.post("/", function (req, res) {
        var deviceId = req.body.deviceId;
        gpio.setUp(deviceId, gpio.OUTPUT_MODE);
        var currentLEDStatus = gpio.read(deviceId);
        if (currentLEDStatus == 0 || currentLEDStatus == -1) {
            setApplianceState(deviceId, true, res);
        }
        else {
            setApplianceState(deviceId, false, res);
        }
    });
}

//Set appliance state
function setApplianceState(pinNo, setState, response) {
    gpio.write(pinNo, setState);
    var jsonResult = { "status": setState, "deviceId": pinNo };
    response.json(jsonResult);
}

//Hard coded list of devices, ideally it should come from API/Database
function getRegisteredDevices() {
    var devices = [
        {
            deviceId: 15, status: false, device: "fan"
        },
        {
            deviceId: 16, status: false, device: "bulb"
        },
        {
            deviceId: 18, status: false, device: "washer"
        },
        {
            deviceId: 19, status: false, device: "tv"
        }
    ];
    return devices;
}
<commit_msg>Updated code to be in sync with ms-gpio<commit_after>var express = require('express');
var bodyParser = require('body-parser');
var gpio = require('ms-gpio');
var app = new express();

startUp();

//Listen for all the request
var server = app.listen(app.get('port'), function () {
    var port = server.address().port;
    console.log('Server running on port ' + port);
});

//Register all the startup related stuffs in this function
function startUp() {
    gpio.GPIO_Path = "test"; //Comment it out if used in Raspberry device
    configureExternalModule();
    setUpHttpHandler();
    app.set('port', 9000);
}

//Configure external modules here
function configureExternalModule() {
    app.use(bodyParser.urlencoded({
        extended: true
    }));

    app.use(bodyParser.json());

    var options = {
        index: "index.htm"
    };

    app.use('/', express.static('public', options));
}

//Configure http request handler
function setUpHttpHandler() {
    app.use('/getDevices', function (req, res) {
        var devices = getRegisteredDevices();
        for (var i = 0; i < devices.length; i++) {
            gpio.setup(devices[i].deviceId);
            devices[i].status =  gpio.read(devices[i].deviceId);
        }
        res.json(devices);
    });

    app.post("/", function (req, res) {
        var deviceId = req.body.deviceId;
        //gpio.setup(deviceId, gpio.OUTPUT_MODE);
        setApplianceState(deviceId, !gpio.read(deviceId), res);
    });
}

//Set appliance state
function setApplianceState(pinNo, setState, response) {
    gpio.write(pinNo, setState);
    var jsonResult = { "status": setState, "deviceId": pinNo };
    response.json(jsonResult);
}

//Hard coded list of devices, ideally it should come from API/Database
function getRegisteredDevices() {
    var devices = [
        {
            deviceId: 15, status: false, device: "fan"
        },
        {
            deviceId: 16, status: false, device: "bulb"
        },
        {
            deviceId: 18, status: false, device: "washer"
        },
        {
            deviceId: 19, status: false, device: "tv"
        }
    ];
    return devices;
}
<|endoftext|>


<commit_before>/**
  MeDroid - Multimedia Transcoder Service.

  The following input formats are supported:

  images (all image formats supported by imagegraphics)
  videos (all video formats supported by ffmpeg/avconv)
  pdf

  (c) 2013 OptimalBits - MIT Licensed.
*/
"use strict";

var Redis = require('ioredis'),
    Queue = require('bull'),
     util = require('util');

var TranscoderConfig = require('./presets.js');

var JOB_QUEUE_NAME = 'Medroid';

//
//  Returns the channel for informing on job progress.
//
function progressChannel(clientId){
  return 'medroid:'+clientId +':progress:';
}

//------------------------------------------------------------------------------
//
//  Medroid Client
// opts: {
//   redis: {
//     port: 6379,
//     host: localhost
//     opts: {}
//   }
//  }
//------------------------------------------------------------------------------
var Medroid = function Medroid(opts){
  if(!this){
    return new Medroid(opts);
  }
  this.clientId = opts.clientId || 'default';
  this.jobQueue = Queue(JOB_QUEUE_NAME, opts);
  this.resultsQueueName = 'Medroid-client-'+this.clientId;
  this.resultsQueue = Queue(this.resultsQueueName, opts);

  // Open a sub channel with redis for receiving progress events.
  this.subClient = new Redis(opts);

  var channel = progressChannel(this.clientId);
  this.subClient.subscribe(channel);

  var _this = this;
  this.subClient.on('message', function(channel, msg){
    var data = JSON.parse(msg);
    _this.emit('progress', data.args, data.progress);
  });

  this.receiveResult(function(job, done){
    try{
      if(job.data.result.err){
        var err = Error(job.data.result.err.message);
        err.stack = job.data.result.err.stack;
        _this.emit('failed', job.data.jobData, err);
      }else{
        _this.emit('completed', job.data.jobData, job.data.result);
      }
      done();
    }catch(err){
      _this.emit('failed', job.data.jobData, err);
      done(err);
    }
  });
}

util.inherits(Medroid, require('events').EventEmitter);

Medroid.prototype.transcode = function(mimeType, args){
  // TODO: Check if supported mimeType
  var mime = mimeType.split('/');
  switch(mime[0]) {
    case 'video':
      args.outputPath = args.outputPath + '.mp4'; // Hack
      if(args.previewPath){
        args.previewPath += '.mp4';
      }
      return this.transcodeVideo(args);
    case 'image':
      args.outputPath = args.outputPath + '.jpg'; // Hack
      if(args.previewPath){
        args.previewPath += '.jpg';
      }
      return this.transcodeImage(args);
    case 'audio':
      args.outputPath = args.outputPath + '.mp3'; // Hack
      return this.transcodeAudio(args);
    case 'application':
      switch(mime[1]){
        case 'vnd.openxmlformats-officedocument.presentationml.presentation':
        case 'vnd.ms-powerpoint':
          args.outputPath = args.outputPath + '.mp4'; // Hack
          if(args.previewPath){
           args.previewPath += '.mp4';
          }
          return this.transcodePPT(args);
        case 'pdf':
          args.outputPath = args.outputPath + '.mp4'; // Hack
          if(args.previewPath){
            args.previewPath += '.mp4';
          }
          return this.transcodePDF(args);
        case 'zip':
          return this.transcodeZip(args);
      }
  }
}

Medroid.prototype.transcodeZip = function(opts){
  return this._addJob("Zip", undefined, opts);
}

Medroid.prototype.transcodeVideo = function(opts){
  var preset =  opts.presets ? opts.presets.video : opts.account.plan.quota.videoPreset;
  var config = TranscoderConfig.video[preset];
  config.preview = TranscoderConfig.video['320p'];
  return this._addJob("Video", config, opts);
}

Medroid.prototype.transcodeImage = function(opts){
  var preset =  opts.presets ? opts.presets.image : opts.account.plan.quota.imagePreset;
  var config = TranscoderConfig.image[preset];
  config.preview = TranscoderConfig.image['320p'];
  return this._addJob("Image", config, opts);
}

Medroid.prototype.transcodeAudio = function(opts){
  var preset =  opts.presets ? opts.presets.audio : opts.account.plan.quota.audioPreset || 'high';
  return this._addJob("Audio", TranscoderConfig.audio[preset], opts);
}

Medroid.prototype.transcodePPT = function(opts){
  var preset =  opts.presets ? opts.presets.ppt : opts.account.plan.quota.pptPreset;
  var config = TranscoderConfig.video[preset];
  config.preview = TranscoderConfig.video['320p'];
  return this._addJob("Powerpoint", config, opts);
}

Medroid.prototype.transcodePDF = function(opts){
  var preset =  opts.presets ? opts.presets.pdf : opts.account.plan.quota.pdfPreset;
  var config = TranscoderConfig.video[preset];
  config.preview = TranscoderConfig.video['320p'];
  return this._addJob("PDF", config, opts);
}

Medroid.prototype._addJob = function(mediaType, config, args){
  var data = {
    args: args,
    config: config,
    mediaType: mediaType,
    clientId: this.clientId,
    resultsQueueName: this.resultsQueueName
  }
  return this.jobQueue.add(data);
}

Medroid.prototype.receiveResult = function(cb){
  //
  // We may need to ignore certain responses here some massage the results
  // into something suitable for clients.
  //
  this.resultsQueue.process(cb);
}

//------------------------------------------------------------------------------

module.exports = Medroid;

<commit_msg>correctly pass redis options into ioredis construct<commit_after>/**
  MeDroid - Multimedia Transcoder Service.

  The following input formats are supported:

  images (all image formats supported by imagegraphics)
  videos (all video formats supported by ffmpeg/avconv)
  pdf

  (c) 2013 OptimalBits - MIT Licensed.
*/
"use strict";

var Redis = require('ioredis'),
    Queue = require('bull'),
     util = require('util');

var TranscoderConfig = require('./presets.js');

var JOB_QUEUE_NAME = 'Medroid';

//
//  Returns the channel for informing on job progress.
//
function progressChannel(clientId){
  return 'medroid:'+clientId +':progress:';
}

//------------------------------------------------------------------------------
//
//  Medroid Client
// opts: {
//   redis: {
//     port: 6379,
//     host: localhost
//     opts: {}
//   }
//  }
//------------------------------------------------------------------------------
var Medroid = function Medroid(opts){
  if(!this){
    return new Medroid(opts);
  }
  this.clientId = opts.clientId || 'default';
  this.jobQueue = Queue(JOB_QUEUE_NAME, opts);
  this.resultsQueueName = 'Medroid-client-'+this.clientId;
  this.resultsQueue = Queue(this.resultsQueueName, opts);

  // Open a sub channel with redis for receiving progress events.
  this.subClient = new Redis(opts.redis);

  var channel = progressChannel(this.clientId);
  this.subClient.subscribe(channel);

  var _this = this;
  this.subClient.on('message', function(channel, msg){
    var data = JSON.parse(msg);
    _this.emit('progress', data.args, data.progress);
  });

  this.receiveResult(function(job, done){
    try{
      if(job.data.result.err){
        var err = Error(job.data.result.err.message);
        err.stack = job.data.result.err.stack;
        _this.emit('failed', job.data.jobData, err);
      }else{
        _this.emit('completed', job.data.jobData, job.data.result);
      }
      done();
    }catch(err){
      _this.emit('failed', job.data.jobData, err);
      done(err);
    }
  });
}

util.inherits(Medroid, require('events').EventEmitter);

Medroid.prototype.transcode = function(mimeType, args){
  // TODO: Check if supported mimeType
  var mime = mimeType.split('/');
  switch(mime[0]) {
    case 'video':
      args.outputPath = args.outputPath + '.mp4'; // Hack
      if(args.previewPath){
        args.previewPath += '.mp4';
      }
      return this.transcodeVideo(args);
    case 'image':
      args.outputPath = args.outputPath + '.jpg'; // Hack
      if(args.previewPath){
        args.previewPath += '.jpg';
      }
      return this.transcodeImage(args);
    case 'audio':
      args.outputPath = args.outputPath + '.mp3'; // Hack
      return this.transcodeAudio(args);
    case 'application':
      switch(mime[1]){
        case 'vnd.openxmlformats-officedocument.presentationml.presentation':
        case 'vnd.ms-powerpoint':
          args.outputPath = args.outputPath + '.mp4'; // Hack
          if(args.previewPath){
           args.previewPath += '.mp4';
          }
          return this.transcodePPT(args);
        case 'pdf':
          args.outputPath = args.outputPath + '.mp4'; // Hack
          if(args.previewPath){
            args.previewPath += '.mp4';
          }
          return this.transcodePDF(args);
        case 'zip':
          return this.transcodeZip(args);
      }
  }
}

Medroid.prototype.transcodeZip = function(opts){
  return this._addJob("Zip", undefined, opts);
}

Medroid.prototype.transcodeVideo = function(opts){
  var preset =  opts.presets ? opts.presets.video : opts.account.plan.quota.videoPreset;
  var config = TranscoderConfig.video[preset];
  config.preview = TranscoderConfig.video['320p'];
  return this._addJob("Video", config, opts);
}

Medroid.prototype.transcodeImage = function(opts){
  var preset =  opts.presets ? opts.presets.image : opts.account.plan.quota.imagePreset;
  var config = TranscoderConfig.image[preset];
  config.preview = TranscoderConfig.image['320p'];
  return this._addJob("Image", config, opts);
}

Medroid.prototype.transcodeAudio = function(opts){
  var preset =  opts.presets ? opts.presets.audio : opts.account.plan.quota.audioPreset || 'high';
  return this._addJob("Audio", TranscoderConfig.audio[preset], opts);
}

Medroid.prototype.transcodePPT = function(opts){
  var preset =  opts.presets ? opts.presets.ppt : opts.account.plan.quota.pptPreset;
  var config = TranscoderConfig.video[preset];
  config.preview = TranscoderConfig.video['320p'];
  return this._addJob("Powerpoint", config, opts);
}

Medroid.prototype.transcodePDF = function(opts){
  var preset =  opts.presets ? opts.presets.pdf : opts.account.plan.quota.pdfPreset;
  var config = TranscoderConfig.video[preset];
  config.preview = TranscoderConfig.video['320p'];
  return this._addJob("PDF", config, opts);
}

Medroid.prototype._addJob = function(mediaType, config, args){
  var data = {
    args: args,
    config: config,
    mediaType: mediaType,
    clientId: this.clientId,
    resultsQueueName: this.resultsQueueName
  }
  return this.jobQueue.add(data);
}

Medroid.prototype.receiveResult = function(cb){
  //
  // We may need to ignore certain responses here some massage the results
  // into something suitable for clients.
  //
  this.resultsQueue.process(cb);
}

//------------------------------------------------------------------------------

module.exports = Medroid;

<|endoftext|>


<commit_before>import React, {Component} from 'react';
import {DragDropContext} from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';

import Paper from 'dist/Paper';
import DraggableGrid from 'dist/DraggableGrid';
import Widget from 'dist/Widget';
import WidgetHeader from 'dist/WidgetHeader';

import PropTypeDescTable from '../PropTypeDescTable';
import DraggableGridDoc from 'assets/propTypes/DraggableGrid.json';

import 'sass/containers/app/modules/draggable/DraggableGridExamples.scss';

@DragDropContext(HTML5Backend)
export default class DraggableGridExamples extends Component {

    constructor(props) {

        super(props);

        this.listData = [{
            iconCls: 'fa fa-facebook',
            text: 'Facebook',
            tip: 'Facebook'
        }, {
            iconCls: 'fa fa-twitter',
            text: 'Twitter'
        }, {
            iconCls: 'fa fa-google-plus',
            text: 'Google+'
        }];

        this.groupedListData = [{
            name: 'socialNetwork',
            children: [{
                iconCls: 'fa fa-facebook',
                text: 'Facebook',
                desc: 'Here is a Facebook Desc.'
            }, {
                iconCls: 'fa fa-twitter',
                text: 'Twitter',
                desc: 'Here is a Twitter Desc.'
            }, {
                iconCls: 'fa fa-google-plus',
                text: 'Google+',
                desc: 'Here is a Google+ Desc.'
            }]
        }, {
            name: 'device',
            children: [{
                iconCls: 'fa fa-android',
                text: 'Android',
                desc: 'Here is a Android Desc.'
            }, {
                iconCls: 'fa fa-apple',
                text: 'Apple',
                desc: 'Here is a Apple Desc.'
            }, {
                iconCls: 'fa fa-windows',
                text: 'Windows',
                desc: 'Here is a Windows Desc.'
            }]
        }];

        this.largeListData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];

        this.sequenceChangeHandler = this::this.sequenceChangeHandler;
        this.valueChangeHandler = this::this.valueChangeHandler;

    }

    sequenceChangeHandler(value) {
        console.log('Sequence Changed:', value);
    }

    valueChangeHandler(value) {
        console.log('Value Changed:', value);
    }

    render() {
        return (

DraggableGrid

                    DraggableGrid used to move the draggable object by clicking the mouse and dragging it
                    in the viewport.

Examples

                <Widget>

                    <WidgetHeader className="example-header" title="DraggableGrid"/>

                                    A multiple-choice DraggableGrid example.

                                <DraggableGrid mode={DraggableGrid.Mode.CHECKBOX}
                                               items={this.listData}
                                               onSequenceChange={this.sequenceChangeHandler}
                                               onValueChange={this.valueChangeHandler}/>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header" title="Draggable Group"/>

                                    A group DraggableGrid list example.

                                <DraggableGrid mode={DraggableGrid.Mode.CHECKBOX}
                                               isGrouped={true}
                                               items={this.groupedListData}
                                               isDraggableAnyWhere={true}
                                               onSequenceChange={this.sequenceChangeHandler}
                                               onValueChange={this.valueChangeHandler}/>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header" title="Draggable Group"/>

                                    A DraggableGrid simple example.

                                <DraggableGrid style={{height: 120}}
                                               items={this.largeListData}
                                               col={[5]}
                                               onSequenceChange={this.sequenceChangeHandler}
                                               onValueChange={this.valueChangeHandler}/>

                </Widget>

Properties

                <PropTypeDescTable data={DraggableGridDoc}/>

        );
    }
};<commit_msg>update DraggableGrid examples<commit_after>import React, {Component} from 'react';
import {DragDropContext} from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';

import DraggableGrid from 'dist/DraggableGrid';
import Widget from 'dist/Widget';
import WidgetHeader from 'dist/WidgetHeader';

import PropTypeDescTable from '../PropTypeDescTable';
import DraggableGridDoc from 'assets/propTypes/DraggableGrid.json';

import 'sass/containers/app/modules/draggable/DraggableGridExamples.scss';

@DragDropContext(HTML5Backend)
export default class DraggableGridExamples extends Component {

    constructor(props) {

        super(props);

        this.listData = [{
            iconCls: 'fa fa-facebook',
            text: 'Facebook',
            tip: 'Facebook'
        }, {
            iconCls: 'fa fa-twitter',
            text: 'Twitter'
        }, {
            iconCls: 'fa fa-google-plus',
            text: 'Google+'
        }];

        this.groupedListData = [{
            name: 'socialNetwork',
            children: [{
                iconCls: 'fa fa-facebook',
                text: 'Facebook',
                desc: 'Here is a Facebook Desc.'
            }, {
                iconCls: 'fa fa-twitter',
                text: 'Twitter',
                desc: 'Here is a Twitter Desc.'
            }, {
                iconCls: 'fa fa-google-plus',
                text: 'Google+',
                desc: 'Here is a Google+ Desc.'
            }]
        }, {
            name: 'device',
            children: [{
                iconCls: 'fa fa-android',
                text: 'Android',
                desc: 'Here is a Android Desc.'
            }, {
                iconCls: 'fa fa-apple',
                text: 'Apple',
                desc: 'Here is a Apple Desc.'
            }, {
                iconCls: 'fa fa-windows',
                text: 'Windows',
                desc: 'Here is a Windows Desc.'
            }]
        }];

        this.largeListData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];

        this.sequenceChangeHandler = this::this.sequenceChangeHandler;
        this.valueChangeHandler = this::this.valueChangeHandler;

    }

    sequenceChangeHandler(value) {
        console.log('Sequence Changed:', value);
    }

    valueChangeHandler(value) {
        console.log('Value Changed:', value);
    }

    render() {
        return (

DraggableGrid

                    DraggableGrid used to move the draggable object by clicking the mouse and dragging it
                    in the viewport.

Examples

                <Widget>

                    <WidgetHeader className="example-header" title="DraggableGrid"/>

                                    A multiple-choice DraggableGrid example.

                                <DraggableGrid mode={DraggableGrid.Mode.CHECKBOX}
                                               items={this.listData}
                                               onSequenceChange={this.sequenceChangeHandler}
                                               onValueChange={this.valueChangeHandler}/>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header" title="Draggable Group"/>

                                    A group DraggableGrid list example.

                                <DraggableGrid mode={DraggableGrid.Mode.CHECKBOX}
                                               isGrouped={true}
                                               items={this.groupedListData}
                                               isDraggableAnyWhere={true}
                                               onSequenceChange={this.sequenceChangeHandler}
                                               onValueChange={this.valueChangeHandler}/>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header" title="Draggable Group"/>

                                    A DraggableGrid simple example.

                                <DraggableGrid style={{height: 120}}
                                               items={this.largeListData}
                                               col={[5]}
                                               onSequenceChange={this.sequenceChangeHandler}
                                               onValueChange={this.valueChangeHandler}/>

                </Widget>

Properties

                <PropTypeDescTable data={DraggableGridDoc}/>

        );
    }
};<|endoftext|>


<commit_before>const QueryString = require('querystring');
const formatNumber = require('format-number')();
const Pagination = require('../pagination');
const getValues = require('./get-values');
const getPrimaryValue = require('../get-primary-value');

module.exports = (queryParams, results, config) => {
  config = config || {};
  const rootUrl = config.rootUrl || '';

  const data = {
    title: 'Search Results',
    page: results.data.length ? 'search' : 'noresults',
    q: queryParams.q,
    results: results.data.map(createResult),
    pagination: createPagination(queryParams, results, rootUrl),
    filters: results.meta.filters,
    selectedFilters: createSelectedFilters(queryParams),
    meta: results.meta,
    links: {
      filterAll: createTypeFilterLink(null, queryParams.query, rootUrl),
      filterObjects: createTypeFilterLink('objects', queryParams.query, rootUrl),
      filterPeople: createTypeFilterLink('people', queryParams.query, rootUrl),
      filterDocuments: createTypeFilterLink('documents', queryParams.query, rootUrl),
      clearFilter: createClearFilterLink(queryParams, rootUrl)
    }
  };

  if (queryParams.type === 'objects') {
    data.isFilterObjects = true;
  } else if (queryParams.type === 'people') {
    data.isFilterPeople = true;
  } else if (queryParams.type === 'documents') {
    data.isFilterDocuments = true;
  } else if (queryParams.type === 'all') {
    data.isFilterAll = true;
  }

  console.log(data);
  return data;
};

function createResult (item) {
  return {
    type: item.type,
    title: getValues.getTitle(item),
    category: getCategory(item),
    date: getValues.getDate(item),
    figure: getFigure(item),
    figcaption: getFigCaption(item),
    link: item.links && item.links.self,
    occupation: getOccupation(item),
    isOnDisplay: getValues.getDisplayLocation(item),
    level: getValues.getDocumentLevel(item)
  };
}

function getCategory (item) {
  return getPrimaryValue(item.attributes.categories);
}

function getOccupation (item) {
  return getPrimaryValue(item.attributes.occupation);
}

function getFigure (item) {
  if (item.type === 'documents') return '/assets/img/archive.svg';
  return null; // No images in index yet
}

function getFigCaption (item) {
  if (item.type === 'objects') {
    return getPrimaryValue(item.attributes.description) || getPrimaryValue(item.attributes.title) || item.attributes.summary_title;
  } else if (item.type === 'people') {
    return getBriefBiography(item);
  }
}

function getBriefBiography (item) {
  if (item.attributes.description) {
    const bio = item.attributes.description.find((el) => el.type === 'brief biography');
    return bio ? bio.value : getPrimaryValue(item.attributes.title) || item.attributes.summary_title || null;
  }
}

function createPagination (queryParams, results, rootUrl) {
  const pageNumber = queryParams.pageNumber;
  const pageSize = queryParams.pageSize;

  const pages = Pagination.pages(
    pageNumber,
    results.meta.total_pages,
    {
      createPageLink: (page) => {
        page.pageNumberDisplay = formatNumber(page.pageNumber + 1);
        const pageParams = Object.assign({}, queryParams.query, { 'page[number]': page.pageNumber });
        const type = queryParams.type !== 'all' ? '/' + queryParams.type : '';
        return `${rootUrl}/search${type}?${QueryString.stringify(pageParams)}`;
      }
    }
  );

  return {
    totalPages: results.meta.total_pages,
    pageNumber: pageNumber + 1,
    isFirst: pageNumber === 0,
    isLast: pageNumber === results.meta.total_pages - 1,
    isPageSize50: pageSize === 50,
    isPageSize100: pageSize === 100,
    links: Object.assign({}, results.links, { pages })
  };
}

function createTypeFilterLink (type, params, rootUrl) {
  params = Object.assign({}, params);
  delete params['fields[type]'];
  // resset the page numbers
  delete params['page[number]'];
  type = type ? '/' + type : '';
  return `${rootUrl}/search${type}?${QueryString.stringify(params)}`;
}

function createClearFilterLink (queryParams, rootUrl) {
  const type = queryParams.type !== 'all' ? '/' + queryParams.type : '';
  return `${rootUrl}/search${type}?q=${queryParams.q}`;
}

/**
* create a selectedFilters Object
* {filter[occupation]: {'mathematician': true,...}, filter[date]: '1900'}
*/
function createSelectedFilters (queryParams) {
  var selectedFilters = {};
  const type = queryParams.type === 'all' ? 'objects' : queryParams.type;
  const facets = queryParams.filter[type];
  Object.keys(facets).forEach(filter => {
    if (facets[filter]) {
      selectedFilters[filter] = {};
      if (Object.prototype.toString.call(facets[filter]) === '[object Array]') {
        facets[filter].forEach(value => {
          selectedFilters[filter][value] = true;
        });
      }
      if (Object.prototype.toString.call(facets[filter]) === '[object Date]') {
        selectedFilters[filter] = facets[filter].getFullYear();
      }
    }
  });

  // all
  const facetsAll = queryParams.filter.all;
  Object.keys(facetsAll).forEach(filter => {
    if (facetsAll[filter]) {
      selectedFilters[filter] = {};
      if (Object.prototype.toString.call(facetsAll[filter]) === '[object Array]') {
        facetsAll[filter].forEach(value => {
          selectedFilters[filter][value] = true;
        });
      }
      if (Object.prototype.toString.call(facetsAll[filter]) === '[object Date]') {
        selectedFilters[filter] = facetsAll[filter].getFullYear();
      }
    }
  });

  return selectedFilters;
}
<commit_msg>reset links of the categories, #112<commit_after>const QueryString = require('querystring');
const formatNumber = require('format-number')();
const Pagination = require('../pagination');
const getValues = require('./get-values');
const getPrimaryValue = require('../get-primary-value');

module.exports = (queryParams, results, config) => {
  config = config || {};
  const rootUrl = config.rootUrl || '';

  const data = {
    title: 'Search Results',
    page: results.data.length ? 'search' : 'noresults',
    q: queryParams.q,
    results: results.data.map(createResult),
    pagination: createPagination(queryParams, results, rootUrl),
    filters: results.meta.filters,
    selectedFilters: createSelectedFilters(queryParams),
    meta: results.meta,
    links: {
      filterAll: createTypeFilterLink(null, queryParams, rootUrl),
      filterObjects: createTypeFilterLink('objects', queryParams, rootUrl),
      filterPeople: createTypeFilterLink('people', queryParams, rootUrl),
      filterDocuments: createTypeFilterLink('documents', queryParams, rootUrl),
      clearFilter: createClearFilterLink(queryParams, rootUrl)
    }
  };

  if (queryParams.type === 'objects') {
    data.isFilterObjects = true;
  } else if (queryParams.type === 'people') {
    data.isFilterPeople = true;
  } else if (queryParams.type === 'documents') {
    data.isFilterDocuments = true;
  } else if (queryParams.type === 'all') {
    data.isFilterAll = true;
  }

  return data;
};

function createResult (item) {
  return {
    type: item.type,
    title: getValues.getTitle(item),
    category: getCategory(item),
    date: getValues.getDate(item),
    figure: getFigure(item),
    figcaption: getFigCaption(item),
    link: item.links && item.links.self,
    occupation: getOccupation(item),
    isOnDisplay: getValues.getDisplayLocation(item),
    level: getValues.getDocumentLevel(item)
  };
}

function getCategory (item) {
  return getPrimaryValue(item.attributes.categories);
}

function getOccupation (item) {
  return getPrimaryValue(item.attributes.occupation);
}

function getFigure (item) {
  if (item.type === 'documents') return '/assets/img/archive.svg';
  return null; // No images in index yet
}

function getFigCaption (item) {
  if (item.type === 'objects') {
    return getPrimaryValue(item.attributes.description) || getPrimaryValue(item.attributes.title) || item.attributes.summary_title;
  } else if (item.type === 'people') {
    return getBriefBiography(item);
  }
}

function getBriefBiography (item) {
  if (item.attributes.description) {
    const bio = item.attributes.description.find((el) => el.type === 'brief biography');
    return bio ? bio.value : getPrimaryValue(item.attributes.title) || item.attributes.summary_title || null;
  }
}

function createPagination (queryParams, results, rootUrl) {
  const pageNumber = queryParams.pageNumber;
  const pageSize = queryParams.pageSize;

  const pages = Pagination.pages(
    pageNumber,
    results.meta.total_pages,
    {
      createPageLink: (page) => {
        page.pageNumberDisplay = formatNumber(page.pageNumber + 1);
        const pageParams = Object.assign({}, queryParams.query, { 'page[number]': page.pageNumber });
        const type = queryParams.type !== 'all' ? '/' + queryParams.type : '';
        return `${rootUrl}/search${type}?${QueryString.stringify(pageParams)}`;
      }
    }
  );

  return {
    totalPages: results.meta.total_pages,
    pageNumber: pageNumber + 1,
    isFirst: pageNumber === 0,
    isLast: pageNumber === results.meta.total_pages - 1,
    isPageSize50: pageSize === 50,
    isPageSize100: pageSize === 100,
    links: Object.assign({}, results.links, { pages })
  };
}

function createTypeFilterLink (type, queryParams, rootUrl) {
  const params = {
    q: queryParams.q,
    'page[size]': queryParams.pageSize
  };
  type = type ? '/' + type : '';
  return `${rootUrl}/search${type}?${QueryString.stringify(params)}`;
}

function createClearFilterLink (queryParams, rootUrl) {
  const type = queryParams.type !== 'all' ? '/' + queryParams.type : '';
  const params = {
    q: queryParams.q,
    'page[size]': queryParams.pageSize
  };
  return `${rootUrl}/search${type}?q=${QueryString.stringify(params)}`;
}

/**
* create a selectedFilters Object
* {filter[occupation]: {'mathematician': true,...}, filter[date]: '1900'}
*/
function createSelectedFilters (queryParams) {
  var selectedFilters = {};
  const type = queryParams.type === 'all' ? 'objects' : queryParams.type;
  const facets = queryParams.filter[type];
  Object.keys(facets).forEach(filter => {
    if (facets[filter]) {
      selectedFilters[filter] = {};
      if (Object.prototype.toString.call(facets[filter]) === '[object Array]') {
        facets[filter].forEach(value => {
          selectedFilters[filter][value] = true;
        });
      }
      if (Object.prototype.toString.call(facets[filter]) === '[object Date]') {
        selectedFilters[filter] = facets[filter].getFullYear();
      }
    }
  });

  // all
  const facetsAll = queryParams.filter.all;
  Object.keys(facetsAll).forEach(filter => {
    if (facetsAll[filter]) {
      selectedFilters[filter] = {};
      if (Object.prototype.toString.call(facetsAll[filter]) === '[object Array]') {
        facetsAll[filter].forEach(value => {
          selectedFilters[filter][value] = true;
        });
      }
      if (Object.prototype.toString.call(facetsAll[filter]) === '[object Date]') {
        selectedFilters[filter] = facetsAll[filter].getFullYear();
      }
    }
  });

  return selectedFilters;
}
<|endoftext|>


<commit_before>'use strict';

var contpara  = require('cont').para
var pull      = require('pull-stream')
var pl        = require('pull-level')
var paramap   = require('pull-paramap')
var timestamp = require('monotonic-timestamp')
var Feed      = require('./feed')
var assert    = require('assert')
var ltgt      = require('ltgt')
var mlib      = require('ssb-msgs')
var explain   = require('explain-error')
//this makes msgpack a valid level codec.

//var u         = require('./util')

//53 bit integer
var MAX_INT  = 0x1fffffffffffff

function isString (s) {
  return 'string' === typeof s
}

function isObject (o) {
  return o && 'object' === typeof o && !Array.isArray(o)
}

function all (stream) {
  return function (cb) {
    pull(stream, pull.collect(cb))
  }
}

function compare(a, b) {
  return a < b ? -1 : a > b ? 1 : 0
}

module.exports = function (db, opts) {

  var isHash = opts.isHash

  var logDB   = db.sublevel('log')
  var feedDB  = db.sublevel('fd')
  var clockDB = db.sublevel('clk')
  var lastDB  = db.sublevel('lst')
  var indexDB = db.sublevel('idx')
  var appsDB  = db.sublevel('app')

  function get (db, key) {
    return function (cb) { db.get(key, cb) }
  }

  db.opts = opts

  var validation = require('./validation')(db, opts)

  db.pre(function (op, add, _batch) {
    var msg = op.value
    var id = op.key
    // index by sequence number

    add({
      key: [msg.author, msg.sequence], value: id,
      type: 'put', prefix: clockDB
    })

    // index my timestamp, used to generate feed.
    add({
      key: [msg.timestamp, msg.author], value: id,
      type: 'put', prefix: feedDB
    })

    // index the latest message from each author
    add({
      key: msg.author, value: msg.sequence,
      type: 'put', prefix: lastDB
    })

    var localtime = timestamp()

    // index messages in the order _received_
    // this will be used to pass to plugins which
    // must create their indexes asyncly.
    add({
      key: localtime, value: id,
      type: 'put', prefix: logDB
    })

    add({
      key: ['type', msg.content.type.toString().substring(0, 32), localtime],
      value: id, type: 'put', prefix: indexDB
    })

    mlib.indexLinks(msg.content, function (link) {
      if(isHash(link.feed)) {
        add({
          key: ['feed', msg.author, link.rel, link.feed, msg.sequence, id],
          value: link,
          type: 'put', prefix: indexDB
        })
        add({
          key: ['_feed', link.feed, link.rel, msg.author, msg.sequence, id],
          value: link,
          type: 'put', prefix: indexDB
        })
      }

      if(isHash(link.msg)) {
        // do not need forward index here, because
        // it's cheap to just read the message.
        add({
          key: ['_msg', link.msg, link.rel, id], value: link,
          type: 'put', prefix: indexDB
        })
      }

      //TODO, add ext links

      if(isHash(link.ext)) {
        // do not need forward index here, because
        // it's cheap to just read the message.
        add({ //feed to file.
          key: ['ext', id, link.rel, link.ext], value: link,
          type: 'put', prefix: indexDB
        })
        add({ //file from feed.
          key: ['_ext', link.ext, link.rel, id], value: link,
          type: 'put', prefix: indexDB
        })

      }

    })

  })

  db.getPublicKey = function (id, cb) {
    function cont (cb) {
      clockDB.get([id, 1], function (err, hash) {
        if(err) return cb(explain(err, 'do not have first message in feed:' + id))

        db.get(hash, function (err, msg) {
          if(err) return cb(err)
          cb(null, msg.content.public)
        })
      })
    }
    return cb ? cont(cb) : cont
  }

  //msg must be an already valid message, with signature.
  //since creating this involves some state (it must increment
  //the sequence and point to the previous message)
  //it's recommended to append messages via a Feed object
  //which will manage that for you. (see feed.js)

  db.add = function (msg, cb) {
    //check that msg is valid (follows from end of database)
    //then insert into database.
    var n = 1
    validation.validate(msg, function (err, msg, hash) {
      if(--n) throw new Error('called twice')
      cb && cb(err, { key: hash, value: msg })
    })
  }

  // opts standardized to work like levelup api
  function stdopts (opts) {
    opts = opts || {}
    if (opts.keys !== false)
      opts.keys = true
    if (opts.values !== false)
      opts.values = true
    return opts
  }
  function msgFmt (keys, values, obj) {
    if (keys && values)
      return obj
    if (keys)
      return obj.key
    if (values)
      return obj.value
    return null // i guess?
  }

  //TODO: eventually, this should filter out authors you do not follow.
  db.createFeedStream = function (opts) {
    opts = stdopts(opts)
    var _keys = opts.keys
    var _values = opts.values
    opts.keys = false
    opts.values = true
    return pull(
      pl.read(feedDB, opts),
      paramap(function (key, cb) {
        db.get(key, function (err, msg) {
          if (err) cb(err)
          else cb(null, msgFmt(_keys, _values, { key: key, value: msg }))
        })
      })
    )
  }

  db.latest = function (opts) {
    return pull(
      pl.read(lastDB, opts),
      pull.map(function (data) {
        var d = {id: data.key, sequence: data.value}
        return d
      })
    )
  }

  db.createHistoryStream = function (id, seq, live) {
    var _keys = true, _values = true
    if(!isHash(id)) {
      var opts = stdopts(id)
      id       = opts.id
      seq      = opts.sequence || opts.seq || 0
      live     = !!opts.live
      _keys    = opts.keys
      _values  = opts.values
    }
    return pull(
      pl.read(clockDB, {
        gte:  [id, seq],
        lte:  [id, MAX_INT],
        live: live,
        keys: false
      }),
      paramap(function (key, cb) {
        db.get(key, function (err, msg) {
          if (err) cb(err)
          else cb(null, msgFmt(_keys, _values, { key: key, value: msg }))
        })
      })
    )
  }

  //writeStream - used in replication.
  db.createWriteStream = function (cb) {
    return pull(
      paramap(function (data, cb) {
        db.add(data, cb)
      }),
      pull.drain(null, cb)
    )
  }

  db.createFeed = function (keys) {
    if(!keys)
      keys = opts.keys.generate()
    return Feed(db, keys, opts)
  }

  db.createLatestLookupStream = function () {
    return paramap(function (id, cb) {
      return lastDB.get(id, function (err, seq) {
        cb(null, {id: id, sequence: err ? 0 : seq})
      })
    })
  }

  db.getLatest = function (id, cb) {
    lastDB.get(id, function (err, v) {
      if(err) return cb(err)
      clockDB.get([id, v], function (err, hash) {
        if(err) return cb(err)
        db.get(hash, cb)
      })
    })
  }

  db.createLogStream = function (opts) {
    opts = stdopts(opts)
    var live = opts.live || opts.tail
    var _opts = {
      gt : opts.gt || 0, live: live || false
    }
    return pull(
      pl.read(logDB, _opts),
      paramap(function (data, cb) {
        var key = data.value
        var seq = data.key
        db.get(key, function (err, value) {
          if (err) cb(err)
          else cb(null, msgFmt(opts.keys, opts.values, {key: key, value: value, timestamp: seq}))
        })
      })
    )
  }

  var HI = undefined, LO = null

  db.messagesByType = function (opts) {
    if(!opts)
      throw new Error('must provide {type: string} to messagesByType')
    if(isString(opts))
      opts = {type: opts}

    opts = stdopts(opts)
    var _keys   = opts.keys
    var _values = opts.values

    ltgt.toLtgt(opts, opts, function (value) {
      return ['type', opts.type, value]
    }, LO, HI)

    opts.values = true
    return pull(
      pl.read(indexDB, opts),
      paramap(function (data, cb) {
        var id = _keys ? data.value : data
        db.get(id, function (err, msg) {
          var ts = opts.keys ? data.key[2] : undefined
          cb(null, msgFmt(_keys, _values, {key: id, ts: ts, value: msg}))
        })
      }),
      pull.filter()
    )
  }

  function idOpts (fn) {
    return function (hash, rel) {
      //legacy interface.
      if(isHash(hash))
        return fn({id: hash, rel: rel})

      if(!isObject(hash)) throw new Error('must have opts')

      return fn(hash)
    }
  }

  db.messagesLinkedToMessage = idOpts(function (opts) {
    var hash = opts.id || opts.hash
    var rel = opts.rel
    return pull(
      pl.read(indexDB, {
        gte: ['_msg', hash, rel || LO, LO],
        lte: ['_msg', hash, rel || HI, HI],
        live: opts.live,
        reverse: opts.reverse,
        limit: opts.limit
      }),
      paramap(function (op, cb) {
        if(!op.key[3]) return cb()
        db.get(op.key[3], function (err, msg) {
          if (opts.keys && msg)
            cb(null, { key: op.key[3], value: msg })
          else
            cb(null, msg)
        })
      }),
      pull.filter(Boolean)
    )
  })

  function index (type) {
    var back = type[0] === '_'
    return idOpts(function (opts) {
      var id = opts.id || opts.hash
      var rel = opts.rel
      return pull(
        pl.read(indexDB, {
          gte: [type, id || LO, rel || LO, LO],
          lte: [type, id || HI, rel || HI, HI],
          live: opts.live,
          reverse: opts.reverse,
          limit: opts.limit
        }),
        pull.map(function (op) {
          return {
            source: op.key[back ? 3 : 1], dest: op.key[back ? 1 : 3],
            rel: op.key[2], message: op.key[5]
          }
        })
      )
    })
  }

  db.messagesLinkedToFeed =
  db.feedsLinkedToFeed = index('_feed')

  db.messagesLinkedFromFeed =
  db.feedsLinkedFromFeed = index('feed')

  db.feedsLinkedToExternal = index('_ext')

  db.externalsLinkedFromFeed = index('ext')

  //get all messages that link to a given message.
  db.relatedMessages = function (opts, cb) {
    if(isString(opts)) opts = {key: opts}
    if(!opts) throw new Error('opts *must* be object')
    var key = opts.id || opts.key

    var n = 1
    var msgs = {key: key, value: null}
    db.get(key, function (err, msg) {
      msgs.value = msg
      done(err)
    })

    related(msgs)

    function related (msg) {
      n++
      all(db.messagesLinkedToMessage({
        id: msg.key, rel: opts.rel, keys: true
      })) (function (err, ary) {
        if(ary && ary.length) {
          ary.sort(function (a, b) {
            return compare(a.value.timestamp, b.value.timestamp) || compare(a.key, b.key)
          })
          msg.related = ary
          ary.forEach(related)
        }
        done(err)
      })
    }

    function count (msg) {
      if(!opts.count) return msg
      if(!msg.related)
        return msg
      var c = 0
      msg.related.forEach(function (_msg) {
        if(opts.parent) _msg.parent = msg.key
        c += 1 + (count(_msg).count || 0)
      })
      msg.count = c
      return msg
    }

    function done (err) {
      if(err && n > 0) {
        n = -1
        return cb(err)
      }
      if(--n) return
      cb(null, count(msgs))
    }
  }

  return db
}
<commit_msg>fix parent fields for related messages<commit_after>'use strict';

var contpara  = require('cont').para
var pull      = require('pull-stream')
var pl        = require('pull-level')
var paramap   = require('pull-paramap')
var timestamp = require('monotonic-timestamp')
var Feed      = require('./feed')
var assert    = require('assert')
var ltgt      = require('ltgt')
var mlib      = require('ssb-msgs')
var explain   = require('explain-error')
//this makes msgpack a valid level codec.

//var u         = require('./util')

//53 bit integer
var MAX_INT  = 0x1fffffffffffff

function isString (s) {
  return 'string' === typeof s
}

function isObject (o) {
  return o && 'object' === typeof o && !Array.isArray(o)
}

function all (stream) {
  return function (cb) {
    pull(stream, pull.collect(cb))
  }
}

function compare(a, b) {
  return a < b ? -1 : a > b ? 1 : 0
}

module.exports = function (db, opts) {

  var isHash = opts.isHash

  var logDB   = db.sublevel('log')
  var feedDB  = db.sublevel('fd')
  var clockDB = db.sublevel('clk')
  var lastDB  = db.sublevel('lst')
  var indexDB = db.sublevel('idx')
  var appsDB  = db.sublevel('app')

  function get (db, key) {
    return function (cb) { db.get(key, cb) }
  }

  db.opts = opts

  var validation = require('./validation')(db, opts)

  db.pre(function (op, add, _batch) {
    var msg = op.value
    var id = op.key
    // index by sequence number

    add({
      key: [msg.author, msg.sequence], value: id,
      type: 'put', prefix: clockDB
    })

    // index my timestamp, used to generate feed.
    add({
      key: [msg.timestamp, msg.author], value: id,
      type: 'put', prefix: feedDB
    })

    // index the latest message from each author
    add({
      key: msg.author, value: msg.sequence,
      type: 'put', prefix: lastDB
    })

    var localtime = timestamp()

    // index messages in the order _received_
    // this will be used to pass to plugins which
    // must create their indexes asyncly.
    add({
      key: localtime, value: id,
      type: 'put', prefix: logDB
    })

    add({
      key: ['type', msg.content.type.toString().substring(0, 32), localtime],
      value: id, type: 'put', prefix: indexDB
    })

    mlib.indexLinks(msg.content, function (link) {
      if(isHash(link.feed)) {
        add({
          key: ['feed', msg.author, link.rel, link.feed, msg.sequence, id],
          value: link,
          type: 'put', prefix: indexDB
        })
        add({
          key: ['_feed', link.feed, link.rel, msg.author, msg.sequence, id],
          value: link,
          type: 'put', prefix: indexDB
        })
      }

      if(isHash(link.msg)) {
        // do not need forward index here, because
        // it's cheap to just read the message.
        add({
          key: ['_msg', link.msg, link.rel, id], value: link,
          type: 'put', prefix: indexDB
        })
      }

      //TODO, add ext links

      if(isHash(link.ext)) {
        // do not need forward index here, because
        // it's cheap to just read the message.
        add({ //feed to file.
          key: ['ext', id, link.rel, link.ext], value: link,
          type: 'put', prefix: indexDB
        })
        add({ //file from feed.
          key: ['_ext', link.ext, link.rel, id], value: link,
          type: 'put', prefix: indexDB
        })

      }

    })

  })

  db.getPublicKey = function (id, cb) {
    function cont (cb) {
      clockDB.get([id, 1], function (err, hash) {
        if(err) return cb(explain(err, 'do not have first message in feed:' + id))

        db.get(hash, function (err, msg) {
          if(err) return cb(err)
          cb(null, msg.content.public)
        })
      })
    }
    return cb ? cont(cb) : cont
  }

  //msg must be an already valid message, with signature.
  //since creating this involves some state (it must increment
  //the sequence and point to the previous message)
  //it's recommended to append messages via a Feed object
  //which will manage that for you. (see feed.js)

  db.add = function (msg, cb) {
    //check that msg is valid (follows from end of database)
    //then insert into database.
    var n = 1
    validation.validate(msg, function (err, msg, hash) {
      if(--n) throw new Error('called twice')
      cb && cb(err, { key: hash, value: msg })
    })
  }

  // opts standardized to work like levelup api
  function stdopts (opts) {
    opts = opts || {}
    if (opts.keys !== false)
      opts.keys = true
    if (opts.values !== false)
      opts.values = true
    return opts
  }
  function msgFmt (keys, values, obj) {
    if (keys && values)
      return obj
    if (keys)
      return obj.key
    if (values)
      return obj.value
    return null // i guess?
  }

  //TODO: eventually, this should filter out authors you do not follow.
  db.createFeedStream = function (opts) {
    opts = stdopts(opts)
    var _keys = opts.keys
    var _values = opts.values
    opts.keys = false
    opts.values = true
    return pull(
      pl.read(feedDB, opts),
      paramap(function (key, cb) {
        db.get(key, function (err, msg) {
          if (err) cb(err)
          else cb(null, msgFmt(_keys, _values, { key: key, value: msg }))
        })
      })
    )
  }

  db.latest = function (opts) {
    return pull(
      pl.read(lastDB, opts),
      pull.map(function (data) {
        var d = {id: data.key, sequence: data.value}
        return d
      })
    )
  }

  db.createHistoryStream = function (id, seq, live) {
    var _keys = true, _values = true
    if(!isHash(id)) {
      var opts = stdopts(id)
      id       = opts.id
      seq      = opts.sequence || opts.seq || 0
      live     = !!opts.live
      _keys    = opts.keys
      _values  = opts.values
    }
    return pull(
      pl.read(clockDB, {
        gte:  [id, seq],
        lte:  [id, MAX_INT],
        live: live,
        keys: false
      }),
      paramap(function (key, cb) {
        db.get(key, function (err, msg) {
          if (err) cb(err)
          else cb(null, msgFmt(_keys, _values, { key: key, value: msg }))
        })
      })
    )
  }

  //writeStream - used in replication.
  db.createWriteStream = function (cb) {
    return pull(
      paramap(function (data, cb) {
        db.add(data, cb)
      }),
      pull.drain(null, cb)
    )
  }

  db.createFeed = function (keys) {
    if(!keys)
      keys = opts.keys.generate()
    return Feed(db, keys, opts)
  }

  db.createLatestLookupStream = function () {
    return paramap(function (id, cb) {
      return lastDB.get(id, function (err, seq) {
        cb(null, {id: id, sequence: err ? 0 : seq})
      })
    })
  }

  db.getLatest = function (id, cb) {
    lastDB.get(id, function (err, v) {
      if(err) return cb(err)
      clockDB.get([id, v], function (err, hash) {
        if(err) return cb(err)
        db.get(hash, cb)
      })
    })
  }

  db.createLogStream = function (opts) {
    opts = stdopts(opts)
    var live = opts.live || opts.tail
    var _opts = {
      gt : opts.gt || 0, live: live || false
    }
    return pull(
      pl.read(logDB, _opts),
      paramap(function (data, cb) {
        var key = data.value
        var seq = data.key
        db.get(key, function (err, value) {
          if (err) cb(err)
          else cb(null, msgFmt(opts.keys, opts.values, {key: key, value: value, timestamp: seq}))
        })
      })
    )
  }

  var HI = undefined, LO = null

  db.messagesByType = function (opts) {
    if(!opts)
      throw new Error('must provide {type: string} to messagesByType')
    if(isString(opts))
      opts = {type: opts}

    opts = stdopts(opts)
    var _keys   = opts.keys
    var _values = opts.values

    ltgt.toLtgt(opts, opts, function (value) {
      return ['type', opts.type, value]
    }, LO, HI)

    opts.values = true
    return pull(
      pl.read(indexDB, opts),
      paramap(function (data, cb) {
        var id = _keys ? data.value : data
        db.get(id, function (err, msg) {
          var ts = opts.keys ? data.key[2] : undefined
          cb(null, msgFmt(_keys, _values, {key: id, ts: ts, value: msg}))
        })
      }),
      pull.filter()
    )
  }

  function idOpts (fn) {
    return function (hash, rel) {
      //legacy interface.
      if(isHash(hash))
        return fn({id: hash, rel: rel})

      if(!isObject(hash)) throw new Error('must have opts')

      return fn(hash)
    }
  }

  db.messagesLinkedToMessage = idOpts(function (opts) {
    var hash = opts.id || opts.hash
    var rel = opts.rel
    return pull(
      pl.read(indexDB, {
        gte: ['_msg', hash, rel || LO, LO],
        lte: ['_msg', hash, rel || HI, HI],
        live: opts.live,
        reverse: opts.reverse,
        limit: opts.limit
      }),
      paramap(function (op, cb) {
        if(!op.key[3]) return cb()
        db.get(op.key[3], function (err, msg) {
          if (opts.keys && msg)
            cb(null, { key: op.key[3], value: msg })
          else
            cb(null, msg)
        })
      }),
      pull.filter(Boolean)
    )
  })

  function index (type) {
    var back = type[0] === '_'
    return idOpts(function (opts) {
      var id = opts.id || opts.hash
      var rel = opts.rel
      return pull(
        pl.read(indexDB, {
          gte: [type, id || LO, rel || LO, LO],
          lte: [type, id || HI, rel || HI, HI],
          live: opts.live,
          reverse: opts.reverse,
          limit: opts.limit
        }),
        pull.map(function (op) {
          return {
            source: op.key[back ? 3 : 1], dest: op.key[back ? 1 : 3],
            rel: op.key[2], message: op.key[5]
          }
        })
      )
    })
  }

  db.messagesLinkedToFeed =
  db.feedsLinkedToFeed = index('_feed')

  db.messagesLinkedFromFeed =
  db.feedsLinkedFromFeed = index('feed')

  db.feedsLinkedToExternal = index('_ext')

  db.externalsLinkedFromFeed = index('ext')

  //get all messages that link to a given message.
  db.relatedMessages = function (opts, cb) {
    if(isString(opts)) opts = {key: opts}
    if(!opts) throw new Error('opts *must* be object')
    var key = opts.id || opts.key

    var n = 1
    var msgs = {key: key, value: null}
    db.get(key, function (err, msg) {
      msgs.value = msg
      done(err)
    })

    related(msgs)

    function related (msg) {
      n++
      all(db.messagesLinkedToMessage({
        id: msg.key, rel: opts.rel, keys: true
      })) (function (err, ary) {
        if(ary && ary.length) {
          ary.sort(function (a, b) {
            return compare(a.value.timestamp, b.value.timestamp) || compare(a.key, b.key)
          })
          msg.related = ary
          ary.forEach(related)
        }
        done(err)
      })
    }

    function count (msg) {
      if(!msg.related)
        return msg
      var c = 0
      msg.related.forEach(function (_msg) {
        if(opts.parent) _msg.parent = msg.key
        c += 1 + (count(_msg).count || 0)
      })
      if(opts.count) msg.count = c
      return msg
    }

    function done (err) {
      if(err && n > 0) {
        n = -1
        return cb(err)
      }
      if(--n) return
      cb(null, count(msgs))
    }
  }

  return db
}
<|endoftext|>