<commit_before>var Ipc = require('ipc');
var Async = require('async');

Ipc.on('scene:ipc-messages', function ( ipcList ) {
    for ( var i = 0; i < ipcList.length; ++i ) {
        Ipc.emit.apply( Ipc, ipcList[i] );
    }
});

Ipc.on('scene:new-scene', function () {
    window.sceneView.newScene();
});

Ipc.on('scene:save-scene-from-page', function ( url ) {
    var sceneAsset = new Fire.Scene();
    sceneAsset.scene = Fire.engine.getCurrentScene();

    // NOTE: we stash scene because we want to save and reload the connected browser
    Editor.stashScene(function () {
        // reload connected browser
        Editor.sendToCore('app:reload-on-device');

        //
        Editor.sendToCore( 'scene:save-scene', url, Editor.serialize(sceneAsset) );
    });
});

Ipc.on('scene:open-scene-by-uuid', function ( uuid ) {
    window.sceneView.loadScene(uuid);
});

Ipc.on('scene:play-on-device', function () {
    Editor.stashScene( function () {
        Editor.sendToCore( 'app:play-on-device' );
    });
});

Ipc.on('scene:reload-on-device', function () {
    Editor.stashScene( function () {
        Editor.sendToCore( 'app:reload-on-device' );
    });
});

Ipc.on('scene:drop', function ( uuids, type, x, y ) {
    Editor.Selection.clear('node');
    Async.each( uuids, function ( uuid, done ) {
        Async.waterfall([
            function ( next ) {
                Editor.createNode(uuid, next);
            },

            function ( node, next ) {
                var nodeID;
                if ( node ) {
                    var wrapper = Fire(node);
                    nodeID = wrapper.uuid;

                    wrapper.position = window.sceneView.pixelToScene( Fire.v2(x,y) );
                    wrapper.parent = Fire.engine.getCurrentScene();
                }

                next ( null, nodeID );
            },

        ], function ( err, nodeID ) {
            if ( err ) {
                Editor.failed( 'Failed to drop asset %s, message: %s', uuid, err.stack );
                return;
            }

            if ( nodeID ) {
                Editor.Selection.select('node', nodeID, false, true );
            }
            Fire.engine.repaintInEditMode();
            done();
        });
    });
});

Ipc.on('scene:create-nodes-by-uuids', function ( uuids, parentID ) {
    var parentNode;
    if ( parentID ) {
        parentNode = Fire.engine.getInstanceByIdN(parentID);
    }
    if ( !parentNode ) {
        parentNode = Fire.engine.getCurrentSceneN();
    }

    Editor.Selection.clear('node');

    //
    Async.each( uuids, function ( uuid, done ) {
        Async.waterfall([
            function ( next ) {
                Editor.createNode(uuid, next);
            },

            function ( node, next ) {
                var nodeID;
                if ( node ) {
                    var wrapper = Fire(node);
                    nodeID = wrapper.uuid;

                    if ( parentNode ) {
                        wrapper.parent = Fire(parentNode);
                    }
                    var center_x = Fire.engine.canvasSize.x/2;
                    var center_y = Fire.engine.canvasSize.y/2;
                    wrapper.scenePosition = window.sceneView.pixelToScene( Fire.v2(center_x, center_y) );
                }

                next ( null, nodeID );
            },

        ], function ( err, nodeID ) {
            if ( err ) {
                Editor.failed( 'Failed to drop asset %s, message: %s', uuid, err.stack );
                return;
            }

            if ( nodeID ) {
                Editor.Selection.select('node', nodeID, false, true );
            }
            Fire.engine.repaintInEditMode();
            done();
        });
    });
});

Ipc.on('scene:create-node-by-classid', function ( name, classID, referenceID, position ) {
    var parentNode;

    if ( referenceID ) {
        parentNode = Fire.engine.getInstanceByIdN(referenceID);
        if ( position === 'sibling' ) {
            parentNode = Fire(parentNode).parentN;
        }
    }

    if ( !parentNode ) {
        parentNode = Fire.engine.getCurrentSceneN();
    }
    var Wrapper = Fire.JS._getClassById(classID);
    if (Wrapper) {
        var wrapper = new Wrapper();
        wrapper.createAndAttachNode();
        wrapper.parent = Fire(parentNode);
        wrapper.name = name;

        var center_x = Fire.engine.canvasSize.x/2;
        var center_y = Fire.engine.canvasSize.y/2;
        wrapper.scenePosition = window.sceneView.pixelToScene( Fire.v2(center_x, center_y) );

        Fire.engine.repaintInEditMode();
        Editor.Selection.select('node', wrapper.uuid, true, true );
    }
    else {
        Editor.error('Unknown node to create:', classID);
    }
});

Ipc.on('scene:query-hierarchy', function ( queryID ) {
    var nodes = Editor.getHierarchyDump();
    var sceneUuid = Fire.engine.getCurrentScene().uuid;
    Editor.sendToWindows( 'scene:reply-query-hierarchy', queryID, sceneUuid, nodes );
});

Ipc.on('scene:query-node', function ( queryID, nodeID ) {
    var node = Fire.engine.getInstanceByIdN(nodeID);
    var dump = Editor.getNodeDump(node);
    Editor.sendToWindows( 'scene:reply-query-node', queryID, dump );
});

Ipc.on('scene:query-node-info', function ( sessionID, nodeID ) {
    var nodeWrapper = Fire.engine.getInstanceById(nodeID);

    Editor.sendToWindows( 'scene:query-node-info:reply', sessionID, {
        name: nodeWrapper ? nodeWrapper.name : '',
        type: Fire.JS.getClassName(nodeWrapper),
        missed: nodeWrapper ? false : true,
    });
});

Ipc.on('scene:node-new-property', function ( info ) {
    var node = Fire.engine.getInstanceByIdN(info.id);
    if (node) {
        var objToSet = info.mixinType ? node : Fire(node);
        try {
            var id = info.type;
            var ctor;
            if (Fire.JS._isTempClassId(id)) {
                ctor = Fire.JS._getClassById(id);
            }
            else {
                ctor = Fire.JS.getClassByName(id);
            }
            if ( ctor ) {
                var obj;
                try {
                    obj = new ctor();
                }
                catch (e) {
                    Editor.error('Can not create new info.type directly.\nInner message: ' + e.stack);
                    return;
                }
                Editor.setDeepPropertyByPath(objToSet, info.path, obj, info.type);
                Fire.engine.repaintInEditMode();
            }
        }
        catch (e) {
            Editor.warn('Failed to new property %s of %s to %s, ' + e.message,
                info.path, Fire(node).name, info.value);
        }
    }
});

Ipc.on('scene:node-set-property', function ( info ) {
    var node = Fire.engine.getInstanceByIdN(info.id);
    if (node) {
        var objToSet = info.mixinType ? node : Fire(node);
        try {
            Editor.setDeepPropertyByPath(objToSet, info.path, info.value, info.type);
            Fire.engine.repaintInEditMode();
        }
        catch (e) {
            Editor.warn('Failed to set property %s of %s to %s, ' + e.message,
                info.path, Fire(node).name, info.value);
        }
    }
});

Ipc.on('scene:node-mixin', function ( id, uuid ) {
    if (uuid && Editor.isUuid(uuid)) {
        // check script
        var className = Editor.compressUuid(uuid);
        var classToMix = Fire.JS._getClassById(className);
        if (!classToMix) {
            return Editor.error('Can not find Behavior in the script "%s".', uuid);
        }
        //
        var node = Fire.engine.getInstanceByIdN(id);
        if (node) {
            Fire.mixin(node, classToMix);
        }
        else {
            Editor.error('Can not find node to mixin: %s', id);
        }
    }
    else {
        Editor.error('invalid script to mixin');
    }
});

Ipc.on('scene:node-unmixin', function ( id, className ) {
    var node = Fire.engine.getInstanceByIdN(id);
    if (node) {
        Fire.unMixin( node, className);
    }
});

Ipc.on('scene:move-nodes', function ( ids, parentID, nextSiblingId ) {
    var parent;

    if (parentID)
        parent = Fire.engine.getInstanceById(parentID);
    else
        parent = Fire.engine.getCurrentScene();

    var next = nextSiblingId ? Fire.engine.getInstanceById(nextSiblingId) : null;
    var nextIndex = next ? next.getSiblingIndex() : -1;

    for (var i = 0; i < ids.length; i++) {
        var id = ids[i];
        var wrapper = Fire.engine.getInstanceById(id);
        if (wrapper && (!parent || !parent.isChildOf(wrapper))) {
            if (wrapper.parent !== parent) {
                // keep world transform not changed
                var worldPos = wrapper.worldPosition;
                var worldRotation = wrapper.worldRotation;
                var lossyScale = wrapper.worldScale;

                wrapper.parent = parent;

                // restore world transform
                wrapper.worldPosition = worldPos;
                wrapper.worldRotation = worldRotation;
                if (parent) {
                    wrapper.scale = lossyScale.divSelf(parent.worldScale);
                }
                else {
                    wrapper.scale = lossyScale;
                }

                if (next) {
                    wrapper.setSiblingIndex(nextIndex);
                    ++nextIndex;
                }
            }
            else if (next) {
                var lastIndex = wrapper.getSiblingIndex();
                var newIndex = nextIndex;
                if (newIndex > lastIndex) {
                    --newIndex;
                }
                if (newIndex !== lastIndex) {
                    wrapper.setSiblingIndex(newIndex);
                    if (lastIndex > newIndex) {
                        ++nextIndex;
                    }
                    else {
                        --nextIndex;
                    }
                }
            }
            else {
                wrapper.setAsLastSibling();
            }
        }
    }
});

Ipc.on('scene:delete-nodes', function ( ids ) {
    window.sceneView.delete(ids);
});

Ipc.on('scene:duplicate-nodes', function ( ids ) {
    var wrappers = [];
    for ( var i = 0; i < ids.length; ++i ) {
         var wrapper = Fire.engine.getInstanceById(ids[i]);
        if (wrapper) {
            wrappers.push(wrapper);
        }
    }

    // get top-level wrappers
    var results = Editor.Utils.arrayCmpFilter ( wrappers, function ( a, b ) {
        var parent;

        // a contains b
        parent = b.parent;
        while ( parent ) {
            if ( a === parent ) {
                return 1;
            }
            parent = parent.parent;
        }

        // b contains a
        parent = a.parent;
        while ( parent ) {
            if ( b === parent ) {
                return -1;
            }
            parent = parent.parent;
        }

        return 0;
    });

    // duplicate results
    var clones = [];
    results.forEach(function ( wrapper ) {
        var clone = Fire.instantiate(wrapper);
        clone.parent = wrapper.parent;

        clones.push(clone.uuid);
    });

    // select the last one
    Editor.Selection.select('node', clones);
});

Ipc.on('scene:stash-and-reload', function () {
    Editor.stashScene(function () {
        Ipc.sendToHost('scene:ask-for-reload');
    });
});

Ipc.on('scene:soft-reload', function (compiled) {
    Editor.softReload(compiled);
});

Ipc.on('selection:activated', function ( type, id ) {
    if ( type !== 'node' || !id ) {
        return;
    }

    window.sceneView.activate(id);
});

Ipc.on('selection:deactivated', function ( type, id ) {
    if ( type !== 'node' ) {
        return;
    }

    window.sceneView.deactivate(id);
});

Ipc.on('selection:selected', function ( type, ids ) {
    if ( type !== 'node' ) {
        return;
    }
    window.sceneView.select(ids);
});

Ipc.on('selection:unselected', function ( type, ids ) {
    if ( type !== 'node' ) {
        return;
    }
    window.sceneView.unselect(ids);
});

Ipc.on('selection:hoverin', function ( type, id ) {
    if ( type !== 'node' ) {
        return;
    }
    window.sceneView.hoverin(id);
});

Ipc.on('selection:hoverout', function ( type, id ) {
    if ( type !== 'node' ) {
        return;
    }
    window.sceneView.hoverout(id);
});

Ipc.on('scene:init-scene-view', function ( settings ) {
    window.sceneView.$.gizmosView.transformTool = settings.transformTool;
    window.sceneView.$.gizmosView.coordinate = settings.coordinate;
    window.sceneView.$.gizmosView.pivot = settings.pivot;
    window.sceneView.$.gizmosView.designSize = [settings.designWidth, settings.designHeight];
});

Ipc.on('scene:transform-tool-changed', function ( value ) {
    window.sceneView.$.gizmosView.transformTool = value;
    Fire.engine.repaintInEditMode();
});

Ipc.on('scene:coordinate-changed', function ( value ) {
    window.sceneView.$.gizmosView.coordinate = value;
    Fire.engine.repaintInEditMode();
});

Ipc.on('scene:pivot-changed', function ( value ) {
    window.sceneView.$.gizmosView.pivot = value;
    Fire.engine.repaintInEditMode();
});

Ipc.on('scene:design-size-changed', function ( w, h ) {
    window.sceneView.$.gizmosView.designSize = [w, h];
    Fire.engine.repaintInEditMode();
});
<commit_msg>fix the sequence of the dumped properties (fireball-x/fireball#267)<commit_after>var Ipc = require('ipc');
var Async = require('async');

Ipc.on('scene:ipc-messages', function ( ipcList ) {
    for ( var i = 0; i < ipcList.length; ++i ) {
        Ipc.emit.apply( Ipc, ipcList[i] );
    }
});

Ipc.on('scene:new-scene', function () {
    window.sceneView.newScene();
});

Ipc.on('scene:save-scene-from-page', function ( url ) {
    var sceneAsset = new Fire.Scene();
    sceneAsset.scene = Fire.engine.getCurrentScene();

    // NOTE: we stash scene because we want to save and reload the connected browser
    Editor.stashScene(function () {
        // reload connected browser
        Editor.sendToCore('app:reload-on-device');

        //
        Editor.sendToCore( 'scene:save-scene', url, Editor.serialize(sceneAsset) );
    });
});

Ipc.on('scene:open-scene-by-uuid', function ( uuid ) {
    window.sceneView.loadScene(uuid);
});

Ipc.on('scene:play-on-device', function () {
    Editor.stashScene( function () {
        Editor.sendToCore( 'app:play-on-device' );
    });
});

Ipc.on('scene:reload-on-device', function () {
    Editor.stashScene( function () {
        Editor.sendToCore( 'app:reload-on-device' );
    });
});

Ipc.on('scene:drop', function ( uuids, type, x, y ) {
    Editor.Selection.clear('node');
    Async.each( uuids, function ( uuid, done ) {
        Async.waterfall([
            function ( next ) {
                Editor.createNode(uuid, next);
            },

            function ( node, next ) {
                var nodeID;
                if ( node ) {
                    var wrapper = Fire(node);
                    nodeID = wrapper.uuid;

                    wrapper.position = window.sceneView.pixelToScene( Fire.v2(x,y) );
                    wrapper.parent = Fire.engine.getCurrentScene();
                }

                next ( null, nodeID );
            },

        ], function ( err, nodeID ) {
            if ( err ) {
                Editor.failed( 'Failed to drop asset %s, message: %s', uuid, err.stack );
                return;
            }

            if ( nodeID ) {
                Editor.Selection.select('node', nodeID, false, true );
            }
            Fire.engine.repaintInEditMode();
            done();
        });
    });
});

Ipc.on('scene:create-nodes-by-uuids', function ( uuids, parentID ) {
    var parentNode;
    if ( parentID ) {
        parentNode = Fire.engine.getInstanceByIdN(parentID);
    }
    if ( !parentNode ) {
        parentNode = Fire.engine.getCurrentSceneN();
    }

    Editor.Selection.clear('node');

    //
    Async.each( uuids, function ( uuid, done ) {
        Async.waterfall([
            function ( next ) {
                Editor.createNode(uuid, next);
            },

            function ( node, next ) {
                var nodeID;
                if ( node ) {
                    var wrapper = Fire(node);
                    nodeID = wrapper.uuid;

                    if ( parentNode ) {
                        wrapper.parent = Fire(parentNode);
                    }
                    var center_x = Fire.engine.canvasSize.x/2;
                    var center_y = Fire.engine.canvasSize.y/2;
                    wrapper.scenePosition = window.sceneView.pixelToScene( Fire.v2(center_x, center_y) );
                }

                next ( null, nodeID );
            },

        ], function ( err, nodeID ) {
            if ( err ) {
                Editor.failed( 'Failed to drop asset %s, message: %s', uuid, err.stack );
                return;
            }

            if ( nodeID ) {
                Editor.Selection.select('node', nodeID, false, true );
            }
            Fire.engine.repaintInEditMode();
            done();
        });
    });
});

Ipc.on('scene:create-node-by-classid', function ( name, classID, referenceID, position ) {
    var parentNode;

    if ( referenceID ) {
        parentNode = Fire.engine.getInstanceByIdN(referenceID);
        if ( position === 'sibling' ) {
            parentNode = Fire(parentNode).parentN;
        }
    }

    if ( !parentNode ) {
        parentNode = Fire.engine.getCurrentSceneN();
    }
    var Wrapper = Fire.JS._getClassById(classID);
    if (Wrapper) {
        var wrapper = new Wrapper();
        wrapper.createAndAttachNode();
        wrapper.parent = Fire(parentNode);
        wrapper.name = name;

        var center_x = Fire.engine.canvasSize.x/2;
        var center_y = Fire.engine.canvasSize.y/2;
        wrapper.scenePosition = window.sceneView.pixelToScene( Fire.v2(center_x, center_y) );

        Fire.engine.repaintInEditMode();
        Editor.Selection.select('node', wrapper.uuid, true, true );
    }
    else {
        Editor.error('Unknown node to create:', classID);
    }
});

Ipc.on('scene:query-hierarchy', function ( queryID ) {
    var nodes = Editor.getHierarchyDump();
    var sceneUuid = Fire.engine.getCurrentScene().uuid;
    Editor.sendToWindows( 'scene:reply-query-hierarchy', queryID, sceneUuid, nodes );
});

Ipc.on('scene:query-node', function ( queryID, nodeID ) {
    var node = Fire.engine.getInstanceByIdN(nodeID);
    var dump = Editor.getNodeDump(node);
    dump = JSON.stringify(dump);    // 改成发送字符串，以免字典的顺序发生改变
    Editor.sendToWindows( 'scene:reply-query-node', queryID, dump );
});

Ipc.on('scene:query-node-info', function ( sessionID, nodeID ) {
    var nodeWrapper = Fire.engine.getInstanceById(nodeID);

    Editor.sendToWindows( 'scene:query-node-info:reply', sessionID, {
        name: nodeWrapper ? nodeWrapper.name : '',
        type: Fire.JS.getClassName(nodeWrapper),
        missed: nodeWrapper ? false : true,
    });
});

Ipc.on('scene:node-new-property', function ( info ) {
    var node = Fire.engine.getInstanceByIdN(info.id);
    if (node) {
        var objToSet = info.mixinType ? node : Fire(node);
        try {
            var id = info.type;
            var ctor;
            if (Fire.JS._isTempClassId(id)) {
                ctor = Fire.JS._getClassById(id);
            }
            else {
                ctor = Fire.JS.getClassByName(id);
            }
            if ( ctor ) {
                var obj;
                try {
                    obj = new ctor();
                }
                catch (e) {
                    Editor.error('Can not create new info.type directly.\nInner message: ' + e.stack);
                    return;
                }
                Editor.setDeepPropertyByPath(objToSet, info.path, obj, info.type);
                Fire.engine.repaintInEditMode();
            }
        }
        catch (e) {
            Editor.warn('Failed to new property %s of %s to %s, ' + e.message,
                info.path, Fire(node).name, info.value);
        }
    }
});

Ipc.on('scene:node-set-property', function ( info ) {
    var node = Fire.engine.getInstanceByIdN(info.id);
    if (node) {
        var objToSet = info.mixinType ? node : Fire(node);
        try {
            Editor.setDeepPropertyByPath(objToSet, info.path, info.value, info.type);
            Fire.engine.repaintInEditMode();
        }
        catch (e) {
            Editor.warn('Failed to set property %s of %s to %s, ' + e.message,
                info.path, Fire(node).name, info.value);
        }
    }
});

Ipc.on('scene:node-mixin', function ( id, uuid ) {
    if (uuid && Editor.isUuid(uuid)) {
        // check script
        var className = Editor.compressUuid(uuid);
        var classToMix = Fire.JS._getClassById(className);
        if (!classToMix) {
            return Editor.error('Can not find Behavior in the script "%s".', uuid);
        }
        //
        var node = Fire.engine.getInstanceByIdN(id);
        if (node) {
            Fire.mixin(node, classToMix);
        }
        else {
            Editor.error('Can not find node to mixin: %s', id);
        }
    }
    else {
        Editor.error('invalid script to mixin');
    }
});

Ipc.on('scene:node-unmixin', function ( id, className ) {
    var node = Fire.engine.getInstanceByIdN(id);
    if (node) {
        Fire.unMixin( node, className);
    }
});

Ipc.on('scene:move-nodes', function ( ids, parentID, nextSiblingId ) {
    var parent;

    if (parentID)
        parent = Fire.engine.getInstanceById(parentID);
    else
        parent = Fire.engine.getCurrentScene();

    var next = nextSiblingId ? Fire.engine.getInstanceById(nextSiblingId) : null;
    var nextIndex = next ? next.getSiblingIndex() : -1;

    for (var i = 0; i < ids.length; i++) {
        var id = ids[i];
        var wrapper = Fire.engine.getInstanceById(id);
        if (wrapper && (!parent || !parent.isChildOf(wrapper))) {
            if (wrapper.parent !== parent) {
                // keep world transform not changed
                var worldPos = wrapper.worldPosition;
                var worldRotation = wrapper.worldRotation;
                var lossyScale = wrapper.worldScale;

                wrapper.parent = parent;

                // restore world transform
                wrapper.worldPosition = worldPos;
                wrapper.worldRotation = worldRotation;
                if (parent) {
                    wrapper.scale = lossyScale.divSelf(parent.worldScale);
                }
                else {
                    wrapper.scale = lossyScale;
                }

                if (next) {
                    wrapper.setSiblingIndex(nextIndex);
                    ++nextIndex;
                }
            }
            else if (next) {
                var lastIndex = wrapper.getSiblingIndex();
                var newIndex = nextIndex;
                if (newIndex > lastIndex) {
                    --newIndex;
                }
                if (newIndex !== lastIndex) {
                    wrapper.setSiblingIndex(newIndex);
                    if (lastIndex > newIndex) {
                        ++nextIndex;
                    }
                    else {
                        --nextIndex;
                    }
                }
            }
            else {
                wrapper.setAsLastSibling();
            }
        }
    }
});

Ipc.on('scene:delete-nodes', function ( ids ) {
    window.sceneView.delete(ids);
});

Ipc.on('scene:duplicate-nodes', function ( ids ) {
    var wrappers = [];
    for ( var i = 0; i < ids.length; ++i ) {
         var wrapper = Fire.engine.getInstanceById(ids[i]);
        if (wrapper) {
            wrappers.push(wrapper);
        }
    }

    // get top-level wrappers
    var results = Editor.Utils.arrayCmpFilter ( wrappers, function ( a, b ) {
        var parent;

        // a contains b
        parent = b.parent;
        while ( parent ) {
            if ( a === parent ) {
                return 1;
            }
            parent = parent.parent;
        }

        // b contains a
        parent = a.parent;
        while ( parent ) {
            if ( b === parent ) {
                return -1;
            }
            parent = parent.parent;
        }

        return 0;
    });

    // duplicate results
    var clones = [];
    results.forEach(function ( wrapper ) {
        var clone = Fire.instantiate(wrapper);
        clone.parent = wrapper.parent;

        clones.push(clone.uuid);
    });

    // select the last one
    Editor.Selection.select('node', clones);
});

Ipc.on('scene:stash-and-reload', function () {
    Editor.stashScene(function () {
        Ipc.sendToHost('scene:ask-for-reload');
    });
});

Ipc.on('scene:soft-reload', function (compiled) {
    Editor.softReload(compiled);
});

Ipc.on('selection:activated', function ( type, id ) {
    if ( type !== 'node' || !id ) {
        return;
    }

    window.sceneView.activate(id);
});

Ipc.on('selection:deactivated', function ( type, id ) {
    if ( type !== 'node' ) {
        return;
    }

    window.sceneView.deactivate(id);
});

Ipc.on('selection:selected', function ( type, ids ) {
    if ( type !== 'node' ) {
        return;
    }
    window.sceneView.select(ids);
});

Ipc.on('selection:unselected', function ( type, ids ) {
    if ( type !== 'node' ) {
        return;
    }
    window.sceneView.unselect(ids);
});

Ipc.on('selection:hoverin', function ( type, id ) {
    if ( type !== 'node' ) {
        return;
    }
    window.sceneView.hoverin(id);
});

Ipc.on('selection:hoverout', function ( type, id ) {
    if ( type !== 'node' ) {
        return;
    }
    window.sceneView.hoverout(id);
});

Ipc.on('scene:init-scene-view', function ( settings ) {
    window.sceneView.$.gizmosView.transformTool = settings.transformTool;
    window.sceneView.$.gizmosView.coordinate = settings.coordinate;
    window.sceneView.$.gizmosView.pivot = settings.pivot;
    window.sceneView.$.gizmosView.designSize = [settings.designWidth, settings.designHeight];
});

Ipc.on('scene:transform-tool-changed', function ( value ) {
    window.sceneView.$.gizmosView.transformTool = value;
    Fire.engine.repaintInEditMode();
});

Ipc.on('scene:coordinate-changed', function ( value ) {
    window.sceneView.$.gizmosView.coordinate = value;
    Fire.engine.repaintInEditMode();
});

Ipc.on('scene:pivot-changed', function ( value ) {
    window.sceneView.$.gizmosView.pivot = value;
    Fire.engine.repaintInEditMode();
});

Ipc.on('scene:design-size-changed', function ( w, h ) {
    window.sceneView.$.gizmosView.designSize = [w, h];
    Fire.engine.repaintInEditMode();
});
<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */

var mouth = require('mouth');
var Store = require('datastore');

/**
 * Create tree of dom nodes.
 *
 * @param {String} tag
 * @param {String | Object} attrs (optional)
 * @param {String | Object} nodes (optional)
 * @return {Function} factory
 * @api public
 */

module.exports = function(tag, attrs, nodes) {
  var dom = typeof tag === 'string' ? create(tag) : tag;
  var bool = !(attrs instanceof Array) && typeof attrs === 'object';
  var store;
  return function(data) {
    if(store) {
      // todo: we should be able to reset a datastore with an other datastore
      store.reset(data);
    } else {
      store = new Store(data);
      if(bool) {
        attributes(dom, attrs, store);
        attrs = nodes;
      }
      if(attrs) children(dom, [].concat(attrs), store);
    }
    return dom;
  };
};

/**
 * Create dom element from
 * query string.
 *
 * Examples:
 *
 *   create(button.btn);
 *   // => <button class='btn'></button>
 *
 *   create('.item#uniq');
 *   // =>

 *
 * @param  {String} tag
 * @return {Element}
 * @api private
 */

function create(tag) {
  var dom, id, classes = '';
  tag = tag.replace(/([#|.])(\w*)/g, function(_, type, attr) {
    if(type === '#') id = attr;
    else classes += attr + ' ';
    return '';
  });
  // note it is dirty! it would be better to merge attrs (to test)
  dom = document.createElement(tag || 'div');
  if(classes) dom.className = classes;
  if(id) dom.id = id;
  return dom;
}

/**
 * Set attributes.
 *
 * @param  {Element} dom
 * @param  {Object} obj
 * @param  {Object} data
 * @api private
 */

function attributes(dom, obj, store) {
  for(var key in obj) {
    var value = obj[key];
    // note: tests if faster than setAttribute
    var attr = document.createAttribute(key);
    if(typeof value === 'function') {
        if(key.substring(0,2) === 'on') {
          dom[key] = value;
          break;
        }
        // todo: we don't want to parse for identifiers it function
        // text handler should have a static option
        value = value.call(store.data);
    }
    if(key === 'style' && typeof value === 'object') {
      value = styles(value);
    }
    text(attr, value, store);
    dom.attributes.setNamedItem(attr);
  }
}

/**
 * Create style attribute from
 * object.
 *
 * Examples:
 *
 *   styles({
 *     background: 'red',
 *     width: '100px'
 *   });
 *   // => 'background:red;width:100px'
 *
 * @param  {Object} obj
 * @return {String}
 * @api privte
 */

function styles(obj) {
  var result = '';
  for(var style in obj) {
    result += style + ':' + obj[style] + ';';
  }
  return result;
}

/**
 * Create and append text node.
 *
 * @param  {Element} dom
 * @param  {String} str
 * @api private
 */

function text(dom, str, store) {
  // todo: we should cache function and props
  var tmpl = mouth(str);
  var props = tmpl.props;
  var render = tmpl.text;
  var node = document.createTextNode(render(store.data));
  dom.appendChild(node);
  // todo: we should have option static
  for(var l = props.length; l--;) {
    store.on('change ' + props[l], function() {
      node.nodeValue = render(store.data);
    });
  }
}

/**
 * Set node children elements.
 *
 * @param  {Element} dom
 * @param  {Array} nodes
 * @api private
 */

function children(dom, nodes, data) {
  for(var i = 0, l = nodes.length; i < l; i++) {
    var node = nodes[i];
    if(typeof node === 'string') text(dom, node, data);
    else dom.appendChild(node());
  }
}

<commit_msg>set version 0.1.0 and dry<commit_after>/**
 * Module dependencies.
 */

var mouth = require('mouth');
var Store = require('datastore');

/**
 * Create tree of dom nodes.
 *
 * @param {String} tag
 * @param {String | Object} attrs (optional)
 * @param {String | Object} nodes (optional)
 * @return {Function} factory
 * @api public
 */

module.exports = function(tag, attrs, nodes) {
  var dom = typeof tag === 'string' ? create(tag) : tag;
  var bool = !(attrs instanceof Array) && typeof attrs === 'object';
  var store;
  return function(data) {
    // todo: we should be able to reset a datastore with an other datastore
    if(store) store.reset(data);
    else {
      store = new Store(data);
      if(bool) {
        attributes(dom, attrs, store);
        attrs = nodes;
      }
      if(attrs) children(dom, [].concat(attrs), store);
    }
    return dom;
  };
};

/**
 * Create dom element from
 * query string.
 *
 * Examples:
 *
 *   create(button.btn);
 *   // => <button class='btn'></button>
 *
 *   create('.item#uniq');
 *   // =>

 *
 * @param  {String} tag
 * @return {Element}
 * @api private
 */

function create(tag) {
  var dom, id, classes = '';
  tag = tag.replace(/([#|.])(\w*)/g, function(_, type, attr) {
    if(type === '#') id = attr;
    else classes += attr + ' ';
    return '';
  });
  // note it is dirty! it would be better to merge attrs (to test)
  dom = document.createElement(tag || 'div');
  if(classes) dom.className = classes;
  if(id) dom.id = id;
  return dom;
}

/**
 * Set attributes.
 *
 * @param  {Element} dom
 * @param  {Object} obj
 * @param  {Object} data
 * @api private
 */

function attributes(dom, obj, store) {
  for(var key in obj) {
    var value = obj[key];
    var type = typeof value;
    // note: tests if faster than setAttribute
    var attr = document.createAttribute(key);
    if(type === 'function') {
        if(key.substring(0,2) === 'on') {
          dom[key] = value;
          break;
        }
        // todo: we don't want to parse for identifiers it function
        // text handler should have a static option
        value = value.call(store.data);
    }
    if(key === 'style' && type === 'object') {
      value = styles(value);
    }
    text(attr, value, store);
    dom.attributes.setNamedItem(attr);
  }
}

/**
 * Create style attribute from
 * object.
 *
 * Examples:
 *
 *   styles({
 *     background: 'red',
 *     width: '100px'
 *   });
 *   // => 'background:red;width:100px'
 *
 * @param  {Object} obj
 * @return {String}
 * @api privte
 */

function styles(obj) {
  var result = '';
  for(var style in obj) {
    result += style + ':' + obj[style] + ';';
  }
  return result;
}

/**
 * Create and append text node.
 *
 * @param  {Element} dom
 * @param  {String} str
 * @api private
 */

function text(dom, str, store) {
  // todo: we should cache function and props
  var tmpl = mouth(str);
  var props = tmpl.props;
  var render = tmpl.text;
  var node = document.createTextNode(render(store.data));
  dom.appendChild(node);
  // todo: we should have option static
  for(var l = props.length; l--;) {
    store.on('change ' + props[l], function() {
      node.nodeValue = render(store.data);
    });
  }
}

/**
 * Set node children elements.
 *
 * @param  {Element} dom
 * @param  {Array} nodes
 * @api private
 */

function children(dom, nodes, data) {
  for(var i = 0, l = nodes.length; i < l; i++) {
    var node = nodes[i];
    if(typeof node === 'string') text(dom, node, data);
    else dom.appendChild(node());
  }
}

<|endoftext|>


<commit_before>module.exports = require('sails-generate-entities')({
  module: 'sails-auth',
  id: 'auth-api',
  statics: [
    'api/models/Passport.js',
    'api/models/User.js',
    'api/controllers/AuthController.js',
    'api/controllers/UserController.js',
    'api/services/protocols/index.js',
    'config/passport.js',
    'config/locales/en.json'
  ],
  classes: [
    'api/services/passport.js',
    'api/services/protocols/local.js',
    'api/services/protocols/oauth.js',
    'api/services/protocols/oauth2.js',
    'api/services/protocols/openid.js'
  ],
  functions: [
    'api/policies/passport.js',
    'api/hooks/auth-api/index.js'
  ]
});
<commit_msg>use nonexistent-yet i18n property<commit_after>module.exports = require('sails-generate-entities')({
  module: 'sails-auth',
  id: 'auth-api',
  i18n: [
    'config/locales/en.json'
  ],
  statics: [
    'api/models/Passport.js',
    'api/models/User.js',
    'api/controllers/AuthController.js',
    'api/controllers/UserController.js',
    'api/services/protocols/index.js',
    'config/passport.js',
  ],
  classes: [
    'api/services/passport.js',
    'api/services/protocols/local.js',
    'api/services/protocols/oauth.js',
    'api/services/protocols/oauth2.js',
    'api/services/protocols/openid.js'
  ],
  functions: [
    'api/policies/passport.js',
    'api/hooks/auth-api/index.js'
  ]
});
<|endoftext|>


<commit_before>'use strict'

// setup
const http = require('http')
const Pg = require('pg').Pool
const jsonwebtoken = require('jsonwebtoken')
const tinyParams = require('tiny-params')
const port = process.env.PORT || process.env.port || 8091
const handlers = {
  search: resourceSearch,
  create: resourceCreate,
  read: resourceRead,
  update: resourceUpdate,
  delete: resourceDelete
}
const scrud = {
  GET: 'search',
  'GET?': 'search',
  POST: 'create',
  'POST/': 'create',
  'GET/': 'read',
  'PUT/': 'update',
  'DELETE/': 'delete'
}
const hasBody = ['create', 'update']
const wlSign = [
  'algorithm',
  'expiresIn',
  'notBefore',
  'audience',
  'issuer',
  'jwtid',
  'subject',
  'noTimestamp',
  'header'
]

// globals
let logger
let pgPool
let jwtOpts
let pgPrefix = ''
let base = ''
let baseRgx = new RegExp(`^/?${base}/`)
let maxBodyBytes = 1e6
let resources = {}

// local helpers
const logIt = (e) => typeof logger === 'function' ? logger(e) : console.log(e)

const cleanPath = (url) => {
  return decodeURIComponent(url).replace(baseRgx, '').replace(/\/$/, '')
}

const parseId = (url) => {
  let id = (url.match(/\/(.+?)(\/|\?|$)/) || [])[1]
  return (id || '').match(/^\d+$/) ? parseInt(id, 10) : id || null
}

const callPgFunc = (name, params) => {
  let q = `SELECT * FROM ${name}($1);`
  if (!pgPool) return Promise.reject(new Error('no database configured'))
  return new Promise((resolve, reject) => {
    pgPool.connect((err, client, done) => {
      if (err) return reject(err)
      client.query(q, [params], (err, result) => {
        done(err)
        if (err) return reject(err)
        resolve((result.rows[0] || {})[name] ? result.rows[0][name] : [])
      })
    })
  })
}

const bodyParse = (req) => new Promise((resolve, reject) => {
  let body = ''
  req.on('data', (d) => {
    body += d.toString()
    if (body.length > maxBodyBytes) return reject(new Error('body too large'))
  })
  req.on('end', () => resolve(body ? JSON.parse(body) : {}))
})

const noIdErr = () => JSON.stringify(new Error('no id passed'))

const filterObj = (obj, ary) => {
  let base = {}
  ary.forEach((o) => { base[o] = obj[o] })
  return base
}

// exports
module.exports = {
  register,
  start,
  sendData,
  sendErr,
  fourOhOne,
  fourOhFour,
  genToken,
  authenticate,
  find,
  findAll,
  create,
  save,
  destroy
}

// register resource
function register (name, opts = {}) {
  if (!name) return Promise.reject(new Error(`no name specified in register`))
  return new Promise((resolve, reject) => {
    let r = resources[name] = Object.assign(opts, {name})
    return resolve(r)
  })
}

// start server
function start (opts = {}) {
  if (opts.namespace) pgPrefix = `${opts.namespace.toLowerCase()}_`
  if (opts.maxBodyBytes) maxBodyBytes = opts.maxBodyBytes
  if (opts.jsonwebtoken) jwtOpts = opts.jsonwebtoken
  if (opts.logger) base = opts.logger
  if (opts.base) base = opts.base
  baseRgx = new RegExp(`^/?${base}/`)
  return new Promise((resolve, reject) => {
    let server = http.createServer(handleRequest)
    server.listen(opts.port || port)
    if (opts.postgres) pgPool = new Pg(opts.postgres)
    return resolve(server)
  })
}

// request handler
function handleRequest (req, res) {
  if (!baseRgx.test(req.url)) return fourOhFour(res)
  let url = cleanPath(req.url)
  let matches = url.match(/^\/?(.+?)(\/|\?|$)/) || []
  let resource = resources[matches[1] || '']
  let modifier = matches[2]
  let action = scrud[`${req.method}${modifier}`]
  if (!resource || !action) return fourOhFour(res)
  res.setHeader('Content-Type', 'application/json')
  res.setHeader('SCRUD', `${resource.name}:${action}`)
  req.id = parseId(url)
  req.params = tinyParams(url)
  let headers = req.headers || {}
  let connection = req.connection || {}
  req.params.ip = headers['x-forwarded-for'] || connection.remoteAddress
  req.once('error', (err) => sendErr(res, err))
  let handler = (resource[action] || handlers[action])
  let jwt = (headers.authorization || '').replace(/^Bearer\s/, '')
  authenticate(jwt).then((authData) => {
    req.auth = req.params.auth = authData
    if (hasBody.indexOf(action) === -1) return handler(req, res, resource.name)
    bodyParse(req).then((body) => {
      req.params = Object.assign(body, req.params)
      return handler(req, res, resource.name)
    })
  }).catch((err) => fourOhOne(res, err))
}

function sendData (res, data = null) {
  return res.end(`{"data": ${JSON.stringify(data)}, "error": null}`)
}

function sendErr (res, err = new Error(), code = 500) {
  res.code = code
  logIt(err, 'fatal')
  err = err instanceof Error ? (err.message || err.name) : err.toString()
  return res.end(`{"data": null, "error": "${err}"}`)
}

function fourOhOne (res, err = new Error(`unable to auhenticate request`)) {
  return sendErr(res, err, 401)
}

function fourOhFour (res, err = new Error(`no match for requested route`)) {
  return sendErr(res, err, 404)
}

function genToken (payload = {}) {
  let key = jwtOpts.secret || jwtOpts.privateKey
  let noOpts = () => new Error('missing required jsonwebtoken opts')
  if (!jwtOpts || !key) return Promise.reject(noOpts())
  let opts = filterObj(jwtOpts, wlSign)
  return new Promise((resolve, reject) => {
    jsonwebtoken.sign(payload, key, opts, (err, token) => {
      return err ? reject(err) : resolve(token)
    })
  })
}

function authenticate (jwt) {
  let key = jwtOpts.secret || jwtOpts.publicKey
  if (!jwtOpts || !key) return Promise.resolve()
  return new Promise((resolve, reject) => {
    jsonwebtoken.verify(jwt, key, jwtOpts, (err, d) => {
      if (err) reject(err)
      let reducer = (o, k) => { o[k.toLowerCase()] = true; return o }
      d.is = (d.roles || []).reduce(reducer, {})
      d.can = (d.permit || []).reduce(reducer, {})
      delete d.roles
      delete d.permit
      return err ? reject(err) : resolve(d)
    })
  })
}

// helper: find resource
function find (resource, id, params) {
  if (!id && id !== 0) return Promise.reject(noIdErr())
  params.id_array = [id]
  let firstRecord = (d) => Promise.resolve(d[0])
  return callPgFunc(`${pgPrefix}${resource}_read`, params).then(firstRecord)
}

// helper: find set of resources
function findAll (resource, params) {
  Object.keys(params).forEach((k) => {
    if (!Array.isArray(params[k])) return
    params[`${k}_array`] = params[k]
    delete params[k]
  })
  return callPgFunc(`${pgPrefix}${resource}_search`, params)
}

// helper: create resource
function create (resource, params) {
  let firstRecord = (d) => Promise.resolve(d[0])
  return callPgFunc(`${pgPrefix}${resource}_create`, params).then(firstRecord)
}

// helper: update resource
function save (resource, id, params) {
  if (!id && id !== 0) return Promise.reject(noIdErr())
  params.id = id
  let firstRecord = (d) => Promise.resolve(d[0])
  return callPgFunc(`${pgPrefix}${resource}_update`, params).then(firstRecord)
}

// helper: delete resource
function destroy (resource, id, params) {
  if (!id && id !== 0) return Promise.reject(noIdErr())
  params.id = id
  return callPgFunc(`${pgPrefix}${resource}_delete`, params)
}

// resource method: search
function resourceSearch (req, res, name) {
  findAll(name, req.params).then((d) => {
    return sendData(res, d)
  }).catch((e) => sendErr(res, e))
}

// resource method: create
function resourceCreate (req, res, name) {
  create(name, req.params).then((d) => {
    return sendData(res, d)
  }).catch((err) => sendErr(res, err))
}

// resource method: read
function resourceRead (req, res, name) {
  find(name, req.id, req.params).then((d) => {
    return sendData(res, d)
  }).catch((err) => sendErr(res, err))
}

// resource method: update
function resourceUpdate (req, res, name) {
  save(name, req.id, req.params).then((d) => {
    return sendData(res, d)
  }).catch((err) => sendErr(res, err))
}

// resource method: delete
function resourceDelete (req, res, name) {
  destroy(name, req.id, req.params).then((d) => {
    return sendData(res, 'success')
  }).catch((err) => sendErr(res, err))
}
<commit_msg>Set status code correctly<commit_after>'use strict'

// setup
const http = require('http')
const Pg = require('pg').Pool
const jsonwebtoken = require('jsonwebtoken')
const tinyParams = require('tiny-params')
const port = process.env.PORT || process.env.port || 8091
const handlers = {
  search: resourceSearch,
  create: resourceCreate,
  read: resourceRead,
  update: resourceUpdate,
  delete: resourceDelete
}
const scrud = {
  GET: 'search',
  'GET?': 'search',
  POST: 'create',
  'POST/': 'create',
  'GET/': 'read',
  'PUT/': 'update',
  'DELETE/': 'delete'
}
const hasBody = ['create', 'update']
const wlSign = [
  'algorithm',
  'expiresIn',
  'notBefore',
  'audience',
  'issuer',
  'jwtid',
  'subject',
  'noTimestamp',
  'header'
]

// globals
let logger
let pgPool
let jwtOpts
let pgPrefix = ''
let base = ''
let baseRgx = new RegExp(`^/?${base}/`)
let maxBodyBytes = 1e6
let resources = {}

// local helpers
const logIt = (e) => typeof logger === 'function' ? logger(e) : console.log(e)

const cleanPath = (url) => {
  return decodeURIComponent(url).replace(baseRgx, '').replace(/\/$/, '')
}

const parseId = (url) => {
  let id = (url.match(/\/(.+?)(\/|\?|$)/) || [])[1]
  return (id || '').match(/^\d+$/) ? parseInt(id, 10) : id || null
}

const callPgFunc = (name, params) => {
  let q = `SELECT * FROM ${name}($1);`
  if (!pgPool) return Promise.reject(new Error('no database configured'))
  return new Promise((resolve, reject) => {
    pgPool.connect((err, client, done) => {
      if (err) return reject(err)
      client.query(q, [params], (err, result) => {
        done(err)
        if (err) return reject(err)
        resolve((result.rows[0] || {})[name] ? result.rows[0][name] : [])
      })
    })
  })
}

const bodyParse = (req) => new Promise((resolve, reject) => {
  let body = ''
  req.on('data', (d) => {
    body += d.toString()
    if (body.length > maxBodyBytes) return reject(new Error('body too large'))
  })
  req.on('end', () => resolve(body ? JSON.parse(body) : {}))
})

const noIdErr = () => JSON.stringify(new Error('no id passed'))

const filterObj = (obj, ary) => {
  let base = {}
  ary.forEach((o) => { base[o] = obj[o] })
  return base
}

// exports
module.exports = {
  register,
  start,
  sendData,
  sendErr,
  fourOhOne,
  fourOhFour,
  genToken,
  authenticate,
  find,
  findAll,
  create,
  save,
  destroy
}

// register resource
function register (name, opts = {}) {
  if (!name) return Promise.reject(new Error(`no name specified in register`))
  return new Promise((resolve, reject) => {
    let r = resources[name] = Object.assign(opts, {name})
    return resolve(r)
  })
}

// start server
function start (opts = {}) {
  if (opts.namespace) pgPrefix = `${opts.namespace.toLowerCase()}_`
  if (opts.maxBodyBytes) maxBodyBytes = opts.maxBodyBytes
  if (opts.jsonwebtoken) jwtOpts = opts.jsonwebtoken
  if (opts.logger) base = opts.logger
  if (opts.base) base = opts.base
  baseRgx = new RegExp(`^/?${base}/`)
  return new Promise((resolve, reject) => {
    let server = http.createServer(handleRequest)
    server.listen(opts.port || port)
    if (opts.postgres) pgPool = new Pg(opts.postgres)
    return resolve(server)
  })
}

// request handler
function handleRequest (req, res) {
  if (!baseRgx.test(req.url)) return fourOhFour(res)
  let url = cleanPath(req.url)
  let matches = url.match(/^\/?(.+?)(\/|\?|$)/) || []
  let resource = resources[matches[1] || '']
  let modifier = matches[2]
  let action = scrud[`${req.method}${modifier}`]
  if (!resource || !action) return fourOhFour(res)
  res.setHeader('Content-Type', 'application/json')
  res.setHeader('SCRUD', `${resource.name}:${action}`)
  req.id = parseId(url)
  req.params = tinyParams(url)
  let headers = req.headers || {}
  let connection = req.connection || {}
  req.params.ip = headers['x-forwarded-for'] || connection.remoteAddress
  req.once('error', (err) => sendErr(res, err))
  let handler = (resource[action] || handlers[action])
  let jwt = (headers.authorization || '').replace(/^Bearer\s/, '')
  authenticate(jwt).then((authData) => {
    req.auth = req.params.auth = authData
    if (hasBody.indexOf(action) === -1) return handler(req, res, resource.name)
    bodyParse(req).then((body) => {
      req.params = Object.assign(body, req.params)
      return handler(req, res, resource.name)
    })
  }).catch((err) => fourOhOne(res, err))
}

function sendData (res, data = null) {
  return res.end(`{"data": ${JSON.stringify(data)}, "error": null}`)
}

function sendErr (res, err = new Error(), code = 500) {
  res.statusCode = code
  logIt(err, 'fatal')
  err = err instanceof Error ? (err.message || err.name) : err.toString()
  return res.end(`{"data": null, "error": "${err}"}`)
}

function fourOhOne (res, err = new Error(`unable to auhenticate request`)) {
  return sendErr(res, err, 401)
}

function fourOhFour (res, err = new Error(`no match for requested route`)) {
  return sendErr(res, err, 404)
}

function genToken (payload = {}) {
  let key = jwtOpts.secret || jwtOpts.privateKey
  let noOpts = () => new Error('missing required jsonwebtoken opts')
  if (!jwtOpts || !key) return Promise.reject(noOpts())
  let opts = filterObj(jwtOpts, wlSign)
  return new Promise((resolve, reject) => {
    jsonwebtoken.sign(payload, key, opts, (err, token) => {
      return err ? reject(err) : resolve(token)
    })
  })
}

function authenticate (jwt) {
  let key = jwtOpts.secret || jwtOpts.publicKey
  if (!jwtOpts || !key) return Promise.resolve()
  return new Promise((resolve, reject) => {
    jsonwebtoken.verify(jwt, key, jwtOpts, (err, d) => {
      if (err) reject(err)
      let reducer = (o, k) => { o[k.toLowerCase()] = true; return o }
      d.is = (d.roles || []).reduce(reducer, {})
      d.can = (d.permit || []).reduce(reducer, {})
      delete d.roles
      delete d.permit
      return err ? reject(err) : resolve(d)
    })
  })
}

// helper: find resource
function find (resource, id, params) {
  if (!id && id !== 0) return Promise.reject(noIdErr())
  params.id_array = [id]
  let firstRecord = (d) => Promise.resolve(d[0])
  return callPgFunc(`${pgPrefix}${resource}_read`, params).then(firstRecord)
}

// helper: find set of resources
function findAll (resource, params) {
  Object.keys(params).forEach((k) => {
    if (!Array.isArray(params[k])) return
    params[`${k}_array`] = params[k]
    delete params[k]
  })
  return callPgFunc(`${pgPrefix}${resource}_search`, params)
}

// helper: create resource
function create (resource, params) {
  let firstRecord = (d) => Promise.resolve(d[0])
  return callPgFunc(`${pgPrefix}${resource}_create`, params).then(firstRecord)
}

// helper: update resource
function save (resource, id, params) {
  if (!id && id !== 0) return Promise.reject(noIdErr())
  params.id = id
  let firstRecord = (d) => Promise.resolve(d[0])
  return callPgFunc(`${pgPrefix}${resource}_update`, params).then(firstRecord)
}

// helper: delete resource
function destroy (resource, id, params) {
  if (!id && id !== 0) return Promise.reject(noIdErr())
  params.id = id
  return callPgFunc(`${pgPrefix}${resource}_delete`, params)
}

// resource method: search
function resourceSearch (req, res, name) {
  findAll(name, req.params).then((d) => {
    return sendData(res, d)
  }).catch((e) => sendErr(res, e))
}

// resource method: create
function resourceCreate (req, res, name) {
  create(name, req.params).then((d) => {
    return sendData(res, d)
  }).catch((err) => sendErr(res, err))
}

// resource method: read
function resourceRead (req, res, name) {
  find(name, req.id, req.params).then((d) => {
    return sendData(res, d)
  }).catch((err) => sendErr(res, err))
}

// resource method: update
function resourceUpdate (req, res, name) {
  save(name, req.id, req.params).then((d) => {
    return sendData(res, d)
  }).catch((err) => sendErr(res, err))
}

// resource method: delete
function resourceDelete (req, res, name) {
  destroy(name, req.id, req.params).then((d) => {
    return sendData(res, 'success')
  }).catch((err) => sendErr(res, err))
}
<|endoftext|>


<commit_before>#!/usr/bin/env node

const _ = require('lodash');
const fs = require('mz/fs');
const path = require('path');
const colors = require('colors');
const globby = require('globby');
const {parse} = require('scss-parser');
const minimist = require('minimist');
const paramCase = require('param-case');
const createQueryAst = require('query-ast');

let status = 0;

// Utils
const each = (wrapper, fn) => {
  for (let n of wrapper.nodes) { fn(n) }
};

// Output
function getContextualMessage(message, filePath, node) {
  const contextualMessage = [];
  if (filePath) {
    contextualMessage.push(`[${path.basename(filePath)}`);
    if (node) {
      contextualMessage.push(`:${node.start.line}`);
    }
    contextualMessage.push('] ');
  }
  contextualMessage.push(message);

  return contextualMessage.join('');
}

function outputWarning(message, filePath, node) {
  console.warn(getContextualMessage(`Warning: ${message}`, filePath, node));
}

function outputError(message, filePath, node) {
  console.error(getContextualMessage(`Error: ${message}`, filePath, node));
  status = 1;
}

function outputStatus(blockName, fileStatus) {
  console.log(colors[fileStatus ? 'green' : 'red'](`  ${fileStatus ? '✓' : '✗'} ${blockName}`));
}

// BemLinter core
function getBlockName(filePath) {
  const fileName = path.basename(filePath);
  return paramCase(fileName.slice(0, fileName.length - 4));
}

function isBlockWithAPseudoClass($wrapper) {
  return $wrapper.parent().next().get(0).type === 'pseudo_class';
}

function isBlockName(className, blockName) {
  return (
    className === blockName ||
    _.startsWith(className, `${blockName}--`) ||
    _.startsWith(className, `${blockName}__`)
  );
}

function isBlockNameOneOf(className, blockList, authorizedBlockName) {
  return _.some(blockList, blockName => blockName !== authorizedBlockName && isBlockName(className, blockName));
}

function checkInternalClassName($, filePath, blockName) {
  return $('class').find('identifier').reduce((fileStatus, wrapper) => {
    const className = wrapper.node.value;
    if (!isBlockName(className, blockName)) {
      outputError(`".${className}" is incoherent with the file name.`, filePath, wrapper.node);
      return false;
    }

    return fileStatus;
  }, true);
}

function checkExternalClassName($, filePath, blockList, blockName) {
  return $('class').find('identifier').reduce((fileStatus, wrapper) => {
    const className = wrapper.node.value;
    if (isBlockNameOneOf(className, blockList, blockName)) {
      if (isBlockWithAPseudoClass($(wrapper))) {
        outputWarning(`".${className}" is tolerated in this stylesheet.`, filePath, wrapper.node);
      } else {
        outputError(`".${className}" should not be style outside of his own stylesheet.`, filePath, wrapper.node);
        return false;
      }
    }

    return fileStatus;
  }, true);
}

function bemLintFile(filePath, blockList) {
  return fs.readFile(filePath, {encoding:'utf8'})
    .then(data => {
      const ast = parse(data);
      const $ = createQueryAst(ast);
      const blockName = getBlockName(filePath);
      let fileStatus;

      if (blockList.indexOf(blockName) !== -1) {
        fileStatus = checkInternalClassName($, filePath, blockName);
      } else {
        fileStatus = checkExternalClassName($, filePath, blockList, blockName);
      }

      outputStatus(blockName, fileStatus);
    })
    .catch(message => outputError(message, filePath))
  ;
}

function bemLint(config) {
  blockList = globby.sync(config.sources, {ignore: _.map(config.ignore, path => `**/${path}`)}).map(getBlockName);
  filePathList = globby.sync(config.sources);
  return Promise.all(_.map(filePathList, filePath => bemLintFile(filePath, blockList)))
    .then(() => {
      console.log({status});
      process.exit(status);
    })
  ;
}

// Main
const argv = minimist(process.argv.slice(2));
const defaultConfig = {
  sources: argv._,
  ignore: []
};

new Promise(resolve => {
  if (!argv.config) {
    resolve(defaultConfig);
  }
  fs.readFile(argv.config, {encoding:'utf8'})
    .then(data => JSON.parse(data))
    .then(resolve)
  ;
})
.then(config => {
  if (config.sources.length < 1) {
    console.log('Usage: ./index.js <scss-file> [<scss-file> ...]');
    process.exit(1);
  }

  bemLint(config);
})
.catch(console.error);
<commit_msg>Remove the .scss extension from configuration file<commit_after>#!/usr/bin/env node

const _ = require('lodash');
const fs = require('mz/fs');
const path = require('path');
const colors = require('colors');
const globby = require('globby');
const {parse} = require('scss-parser');
const minimist = require('minimist');
const paramCase = require('param-case');
const createQueryAst = require('query-ast');

let status = 0;

// Utils
const each = (wrapper, fn) => {
  for (let n of wrapper.nodes) { fn(n) }
};

// Output
function getContextualMessage(message, filePath, node) {
  const contextualMessage = [];
  if (filePath) {
    contextualMessage.push(`[${path.basename(filePath)}`);
    if (node) {
      contextualMessage.push(`:${node.start.line}`);
    }
    contextualMessage.push('] ');
  }
  contextualMessage.push(message);

  return contextualMessage.join('');
}

function outputWarning(message, filePath, node) {
  console.warn(getContextualMessage(`Warning: ${message}`, filePath, node));
}

function outputError(message, filePath, node) {
  console.error(getContextualMessage(`Error: ${message}`, filePath, node));
  status = 1;
}

function outputStatus(blockName, fileStatus) {
  console.log(colors[fileStatus ? 'green' : 'red'](`  ${fileStatus ? '✓' : '✗'} ${blockName}`));
}

// BemLinter core
function getBlockName(filePath) {
  const fileName = path.basename(filePath);
  return paramCase(fileName.slice(0, fileName.length - 4));
}

function isBlockWithAPseudoClass($wrapper) {
  return $wrapper.parent().next().get(0).type === 'pseudo_class';
}

function isBlockName(className, blockName) {
  return (
    className === blockName ||
    _.startsWith(className, `${blockName}--`) ||
    _.startsWith(className, `${blockName}__`)
  );
}

function isBlockNameOneOf(className, blockList, authorizedBlockName) {
  return _.some(blockList, blockName => blockName !== authorizedBlockName && isBlockName(className, blockName));
}

function checkInternalClassName($, filePath, blockName) {
  return $('class').find('identifier').reduce((fileStatus, wrapper) => {
    const className = wrapper.node.value;
    if (!isBlockName(className, blockName)) {
      outputError(`".${className}" is incoherent with the file name.`, filePath, wrapper.node);
      return false;
    }

    return fileStatus;
  }, true);
}

function checkExternalClassName($, filePath, blockList, blockName) {
  return $('class').find('identifier').reduce((fileStatus, wrapper) => {
    const className = wrapper.node.value;
    if (isBlockNameOneOf(className, blockList, blockName)) {
      if (isBlockWithAPseudoClass($(wrapper))) {
        outputWarning(`".${className}" is tolerated in this stylesheet.`, filePath, wrapper.node);
      } else {
        outputError(`".${className}" should not be style outside of his own stylesheet.`, filePath, wrapper.node);
        return false;
      }
    }

    return fileStatus;
  }, true);
}

function bemLintFile(filePath, blockList) {
  return fs.readFile(filePath, {encoding:'utf8'})
    .then(data => {
      const ast = parse(data);
      const $ = createQueryAst(ast);
      const blockName = getBlockName(filePath);
      let fileStatus;

      if (blockList.indexOf(blockName) !== -1) {
        fileStatus = checkInternalClassName($, filePath, blockName);
      } else {
        fileStatus = checkExternalClassName($, filePath, blockList, blockName);
      }

      outputStatus(blockName, fileStatus);
    })
    .catch(message => outputError(message, filePath))
  ;
}

function bemLint(config) {
  blockList = globby.sync(config.sources, {
    ignore: config.ignore
  }).map(getBlockName);
  filePathList = globby.sync(config.sources);
  return Promise.all(filePathList.map(filePath => bemLintFile(filePath, blockList)))
    .then(() => {
      process.exit(status);
    })
  ;
}

// Main
const argv = minimist(process.argv.slice(2));
const defaultConfig = {
  sources: argv._,
  ignore: []
};

new Promise(resolve => {
  if (!argv.config) {
    resolve(defaultConfig);
  }
  fs.readFile(argv.config, {encoding:'utf8'})
    .then(data => JSON.parse(data))
    .then(config => {
      config.sources = config.sources.map(source => source.concat('.scss'));
      config.ignore = config.ignore.map(path => `**/${path}.scss`);
      resolve(config);
    })
  ;
})
.then(config => {
  if (config.sources.length < 1) {
    console.log('Usage: ./index.js <scss-file> [<scss-file> ...]');
    process.exit(1);
  }

  bemLint(config);
})
.catch(console.error);
<|endoftext|>


<commit_before>const app = require('koa')()
const open = require('open')

const handlebars = require('koa-handlebars')
const session = require('koa-generic-session')
const mongoStore = require('koa-session-mongoose')
const bodyParser = require('koa-body')

const compress = require('koa-compress')
const router = require('koa-router')()
const serve = require('koa-static')
const mount = require('koa-mount')

const db = require('./lib/db')

app.use(compress())

if (module.parent) {
  require('dotenv').config({
    path: process.cwd() + '/.env'
  })

  app.use(require('koa-livereload')({
    port: 35729
  }))
} else {
  // This is fine since it's only being used in the development env
  process.env.SESSION_SECRET = 'random'
}

const rope = db.rope

process.on('SIGINT', function () {
  rope.close(function () {
    process.exit(0)
  })
})

app.keys = [process.env.SESSION_SECRET]

app.use(session({
  key: 'muffin.sess',
  prefix: 'muffin:sess:',
  store: mongoStore.create(),
  connection: rope
}))

router.use(bodyParser({
  multipart: true
}))

var globals = {}

globals.menuItems = [
  {
    url: '.',
    title: 'Dashboard'
  },
  {
    url: 'pages',
    title: 'Pages'
  },
  {
    url: 'users',
    title: 'Users'
  },
  {
    url: 'media',
    title: 'Media'
  },
  {
    url: 'settings',
    title: 'Settings'
  }
]

globals.appVersion = require('./package.json').version

app.use(handlebars({
  defaultLayout: 'main',
  cache: false,
  helpers: require('./lib/helpers'),
  root: __dirname + '/views',
  viewsDir: '/',
  data: globals
}))

router.all('/admin*', function *(next) {
  if (this.session.loggedIn || this.request.method === 'GET') {
    yield next
  } else {
    this.response.body('Sorry, but I can\'t let you in.')
  }
})

router.get('/admin*', function *(next) {
  const url = this.request.url
  var to

  // Check if request wants a file. If so, let it through.
  if (url.match(/[^\\/]+\.[^\\/]+$/)) {
    yield next
  }

  if (this.session.loggedIn) {
    yield next
  } else {
    const original = this.request.originalUrl

    switch (original) {
      case '/admin':
      case '/admin/':
        to = ''
        break

      default:
        to = '/?to=' + encodeURIComponent(original.replace('/admin/', ''))
    }

    this.response.redirect('/login' + to)
  }
})

app.use(mount('/admin/assets', serve(__dirname + '/dist')))

function getRoutes (path) {
  return require('./lib/routes/' + path).routes()
}

router.use('/login', getRoutes('login'))
router.use('/uploads*', getRoutes('uploads'))

router.use('/admin', getRoutes('dashboard'))
router.use('/admin/pages', getRoutes('pages'))
router.use('/admin/users', getRoutes('users'))
router.use('/admin/media', getRoutes('media'))

// Tell kit where to find router for outer routes
app.router = require('./lib/routes/front')

function listening() {
  const port = this.address().port
  const url = 'http://localhost:' + port

  console.log('Muffin is running at ' + url)

  if (!process.env.restarted) {
    open(url)
    process.env.restarted = false
  }
}

var hbsConfig = {
  cache: false,
  root: process.cwd() + '/views',
  layoutsDir: '../layouts',
  viewsDir: '/',
  defaultLayout: 'default'
}

app.run = (front, config) => {
  // Allow kit to overwrite template options
  if (config && config.render) {
    Object.assign(hbsConfig, config.render)
  }

  // Require outer routes if run from kit
  if (front) {
    router.use(handlebars(hbsConfig))
    router.use('/', front.routes())
  }

  app.use(router.routes())
  app.use(router.allowedMethods())

  app.listen(2000, listening)
}

if (!module.parent) app.run()
module.exports = app
<commit_msg>Make backend work accessible again<commit_after>const app = require('koa')()
const open = require('open')

const handlebars = require('koa-handlebars')
const session = require('koa-generic-session')
const mongoStore = require('koa-session-mongoose')
const bodyParser = require('koa-body')

const compress = require('koa-compress')
const router = require('koa-router')()
const serve = require('koa-static')
const mount = require('koa-mount')

const db = require('./lib/db')

app.use(compress())

if (module.parent) {
  require('dotenv').config({
    path: process.cwd() + '/.env'
  })

  app.use(require('koa-livereload')({
    port: 35729
  }))
} else {
  // This is fine since it's only being used in the development env
  process.env.SESSION_SECRET = 'random'
}

const rope = db.rope

process.on('SIGINT', function () {
  rope.close(function () {
    process.exit(0)
  })
})

app.keys = [process.env.SESSION_SECRET]

app.use(session({
  key: 'muffin.sess',
  prefix: 'muffin:sess:',
  store: mongoStore.create(),
  connection: rope
}))

router.use(bodyParser({
  multipart: true
}))

var globals = {}

globals.menuItems = [
  {
    url: '.',
    title: 'Dashboard'
  },
  {
    url: 'pages',
    title: 'Pages'
  },
  {
    url: 'users',
    title: 'Users'
  },
  {
    url: 'media',
    title: 'Media'
  },
  {
    url: 'settings',
    title: 'Settings'
  }
]

globals.appVersion = require('./package.json').version

app.use(handlebars({
  defaultLayout: 'main',
  cache: false,
  helpers: require('./lib/helpers'),
  root: __dirname + '/views',
  viewsDir: '/',
  data: globals
}))

router.all('/admin*', function *(next) {
  if (this.session.loggedIn || this.request.method === 'GET') {
    yield next
  } else {
    this.response.body('Sorry, but I can\'t let you in.')
  }
})

router.get('/admin*', function *(next) {
  const url = this.request.url
  var to

  // Check if request wants a file. If so, let it through.
  if (url.match(/[^\\/]+\.[^\\/]+$/)) {
    yield next
  }

  if (this.session.loggedIn) {
    yield next
  } else {
    const original = this.request.originalUrl

    switch (original) {
      case '/admin':
      case '/admin/':
        to = ''
        break

      default:
        to = '/?to=' + encodeURIComponent(original.replace('/admin/', ''))
    }

    this.response.redirect('/login' + to)
  }
})

app.use(mount('/admin/assets', serve(__dirname + '/dist')))

function getRoutes (path) {
  return require('./lib/routes/' + path).routes()
}

router.use('/login', getRoutes('login'))
router.use('/uploads*', getRoutes('uploads'))

router.use('/admin', getRoutes('dashboard'))
router.use('/admin/pages', getRoutes('pages'))
router.use('/admin/users', getRoutes('users'))
router.use('/admin/media', getRoutes('media'))

// Tell kit where to find router for outer routes
app.router = require('./lib/routes/front')

function listening() {
  const port = this.address().port
  const url = 'http://localhost:' + port

  console.log('Muffin is running at ' + url)

  if (!process.env.restarted) {
    open(url)
    process.env.restarted = false
  }
}

var hbsConfig = {
  cache: false,
  root: process.cwd() + '/views',
  layoutsDir: '../layouts',
  viewsDir: '/',
  defaultLayout: 'default'
}

app.run = (front, config) => {
  // Allow kit to overwrite template options
  if (config && config.render) {
    Object.assign(hbsConfig, config.render)
  }

  // Require outer routes if run from kit
  if (front) {
    front.use(handlebars(hbsConfig))
    router.use('/', front.routes())
  }

  app.use(router.routes())
  app.use(router.allowedMethods())

  app.listen(2000, listening)
}

if (!module.parent) app.run()
module.exports = app
<|endoftext|>


<commit_before>'use strict';

var through        = require('through2');
var stylus         = require('accord').load('stylus');
var gutil          = require('gulp-util');
var rext           = require('replace-ext');
var extname        = require('path').extname;
var assign         = require('lodash.assign');
var applySourceMap = require('vinyl-sourcemaps-apply');

function guErr(err) {
  return new gutil.PluginError('gulp-stylus', err);
}

module.exports = function (options) {
  var opts = assign({}, options);

  return through.obj(function (file, enc, cb) {

    if (file.isStream()) {
      return cb(guErr('Streaming not supported'));
    }
    if (file.isNull()) {
      return cb(null, file);
    }
    if (extname(file.path) === '.css') {
      return cb(null, file);
    }
    if (file.sourceMap || opts.sourcemap) {
      opts.sourcemap = assign({basePath: file.base}, opts.sourcemap);
    }
    if (file.data) {
      opts.define = file.data;
    }
    opts.filename = file.path;

    stylus.render(file.contents.toString(enc || 'utf-8'), opts)
      .catch(function(err) {
        delete err.input;
        return cb(guErr(err));
      })
      .done(function(res) {
        if (res == null) {
          return;
        }
        if (res.result !== undefined) {
          file.path = rext(file.path, '.css');
          if (res.sourcemap) {
            res.result = res.result.replace(/^\s*\/\*[@#][\s\t]+sourceMappingURL=.*$/mg, '');
            res.sourcemap.file = file.relative;
            applySourceMap(file, res.sourcemap);
          }
          file.contents = new Buffer(res.result);
          return cb(null, file);
        }
      });
  });

};

module.exports.stylus = require('stylus');
<commit_msg>Remove sourceMappingURL comment even if it is not on its own line. (#178)<commit_after>'use strict';

var through        = require('through2');
var stylus         = require('accord').load('stylus');
var gutil          = require('gulp-util');
var rext           = require('replace-ext');
var extname        = require('path').extname;
var assign         = require('lodash.assign');
var applySourceMap = require('vinyl-sourcemaps-apply');

function guErr(err) {
  return new gutil.PluginError('gulp-stylus', err);
}

module.exports = function (options) {
  var opts = assign({}, options);

  return through.obj(function (file, enc, cb) {

    if (file.isStream()) {
      return cb(guErr('Streaming not supported'));
    }
    if (file.isNull()) {
      return cb(null, file);
    }
    if (extname(file.path) === '.css') {
      return cb(null, file);
    }
    if (file.sourceMap || opts.sourcemap) {
      opts.sourcemap = assign({basePath: file.base}, opts.sourcemap);
    }
    if (file.data) {
      opts.define = file.data;
    }
    opts.filename = file.path;

    stylus.render(file.contents.toString(enc || 'utf-8'), opts)
      .catch(function(err) {
        delete err.input;
        return cb(guErr(err));
      })
      .done(function(res) {
        if (res == null) {
          return;
        }
        if (res.result !== undefined) {
          file.path = rext(file.path, '.css');
          if (res.sourcemap) {
            res.result = res.result.replace(/\/\*[@#][\s\t]+sourceMappingURL=.*?\*\/$/mg, '');
            res.sourcemap.file = file.relative;
            applySourceMap(file, res.sourcemap);
          }
          file.contents = new Buffer(res.result);
          return cb(null, file);
        }
      });
  });

};

module.exports.stylus = require('stylus');
<|endoftext|>


<commit_before>/**
 * Sort an array of objects by any property value, at any depth, in any custom order.
 *
 * @module sort-array
 * @typicalname sortBy
 * @example
 * const sortBy = require('sort-array')
 */
module.exports = sortBy

/**
 * @param {object[]} - Input array of objects
 * @param {string|string[]} - One or more property expressions to sort by,  e.g. `'name'` or `'name.first'`.
 * @param [customOrder] {object} - Custom sort order definitions. An object where each key is the property expression and the value is an array specifying the sort order. Example:

 * `{ importance: [ 'speed', 'strength', 'intelligence' ]}`
 * @returns {Array}
 * @alias module:sort-array
 * @example
 * with this data
 * ```js
 * > DJs = [
 *   { name: 'Trevor', slot: 'twilight' },
 *   { name: 'Chris', slot: 'twilight' },
 *   { name: 'Mike', slot: 'afternoon' },
 *   { name: 'Rodney', slot: 'morning' },
 *   { name: 'Chris', slot: 'morning' },
 *   { name: 'Zane', slot: 'evening' }
 * ]
 * ```
 *
 * sort by `slot` using the default sort order (alphabetical)
 * ```js
 * > sortBy(DJs, 'slot')
 * [ { name: 'Mike', slot: 'afternoon' },
 *   { name: 'Zane', slot: 'evening' },
 *   { name: 'Chris', slot: 'morning' },
 *   { name: 'Rodney', slot: 'morning' },
 *   { name: 'Chris', slot: 'twilight' },
 *   { name: 'Trevor', slot: 'twilight' } ]
 * ```
 *
 * specify a custom sort order for `slot`
 * ```js
 * > const slotOrder = [ 'morning', 'afternoon', 'evening', 'twilight' ]
 * > sortBy(DJs, 'slot', { slot: slotOrder })
 * [ { name: 'Rodney', slot: 'morning' },
 *   { name: 'Chris', slot: 'morning' },
 *   { name: 'Mike', slot: 'afternoon' },
 *   { name: 'Zane', slot: 'evening' },
 *   { name: 'Trevor', slot: 'twilight' },
 *   { name: 'Chris', slot: 'twilight' } ]
 * ```
 *
 * sort by `slot` then `name`
 * ```js
 * > sortBy(DJs, ['slot', 'name'], { slot: slotOrder })
 * [ { name: 'Chris', slot: 'morning' },
 *   { name: 'Rodney', slot: 'morning' },
 *   { name: 'Mike', slot: 'afternoon' },
 *   { name: 'Zane', slot: 'evening' },
 *   { name: 'Chris', slot: 'twilight' },
 *   { name: 'Trevor', slot: 'twilight' } ]
 * ```
 *
 * sort by nested property values (at any depth) using dot notation (e.g. `'inner.number'`)
 * ```js
 * > input = [
 *   { inner: { number: 5 } },
 *   { inner: { number: 2 } },
 *   { inner: { number: 3 } },
 *   { inner: { number: 1 } },
 *   { inner: { number: 4 } }
 * ]
 *
 * > sortBy(input, 'inner.number')
 * [ { inner: { number: 1 } },
 *   { inner: { number: 2 } },
 *   { inner: { number: 3 } },
 *   { inner: { number: 4 } },
 *   { inner: { number: 5 } } ]
 * ```
 *
 * a custom order for a nested property looks like this:
 * ```js
 * const customOrder = {
 *   'inner.number': [ 1, 2, 4, 3, 5 ]
 * }
 * ```
 */
function sortBy (recordset, sortBy, sortTypes, namedConfigs) {
  const arrayify = require('array-back')

  // First stage data preparation
  recordset = arrayify(recordset)
  sortBy = arrayify(sortBy)
  sortTypes = arrayify(sortTypes)

  let namedComputedProps = {}
  let namedCustomOrders = {}
  if (isObject(namedConfigs)) {
    if (isDefined(namedConfigs['namedComputedProps'])) {
      namedComputedProps = namedConfigs['namedComputedProps']
    }
    if (isDefined(namedConfigs['namedCustomOrders'])) {
      namedCustomOrders = namedConfigs['namedCustomOrders']
    }
  }

  // Perform sanity checks.
  let isPrimitiveSort = recordset.some(record => isPrimitive(record))
  if (isPrimitiveSort) {
    // The only applicable 'sortBy' arguments on a primitive array
    // are 'computed property' functions.
    for (let i = 0; i < sortBy.length; i++) {
      if (!isFunction(sortBy[i])) {
        return recordset
      }
    }
  } else {
    // At least one 'sortBy' argument must be provided, so that the recordset
    // can be sorted according to that property.
    if (sortBy.length === 0) {
      return recordset
    }
  }

  // Ensure that if namedComputedProps is provided, that the object keys
  // are referenced in the sortBy array
  let noOfNamedComputedProps = Object.keys(namedComputedProps).length
  if (noOfNamedComputedProps > 0) {
    for (let i = 0; i < noOfNamedComputedProps; i++) {
      if (sortBy.indexOf(Object.keys(namedComputedProps)[i]) < 0) {
        // Missing object key, return the recordset unchanged
        return recordset
      }
    }
  }

  // Ensure that if namedCustomOrders is provided, that the object keys
  // are referenced in the sortTypes array
  let noOfNamedCustomOrders = Object.keys(namedCustomOrders).length
  if (noOfNamedCustomOrders > 0) {
    for (let i = 0; i < noOfNamedCustomOrders; i++) {
      if (sortTypes.indexOf(Object.keys(namedCustomOrders)[i]) < 0) {
        // Missing object key, return the recordset unchanged
        return recordset
      }
    }
  }

  // Second stage data preparation. Ensure that each property in sortBy
  // has a corresponding property in sortTypes. Populate missing and
  // remove excess, as required.
  if ((sortBy.length === 0) && (sortTypes.length === 0)) {
    sortTypes.push('asc')
  } else if (sortBy.length > sortTypes.length) {
    // Not enough sortTypes have been provided. Fully hydrate the sortTypes
    // array, using 'asc' by default.
    let noOfMissingSortTypes = sortBy.length - sortTypes.length
    for (let i = 0; i < noOfMissingSortTypes; i++) {
      sortTypes.push('asc')
    }
  } else if (!isPrimitiveSort && (sortBy.length < sortTypes.length)) {
    // Too many sortTypes have been provided. Prune the redundant ones
    // at the end of the sortType array.
    sortTypes.splice(-1, sortTypes.length - sortBy.length)
  }

  if (isPrimitiveSort) {
    return recordset.sort(comparePrim(sortBy, sortTypes))
  } else {
    return recordset.sort(compare(sortBy, sortTypes, namedComputedProps, namedCustomOrders))
  }
}

function comparePrim (sortBy, sortTypes) {
  // The property should be undefined or a function
  let sorts = sortBy.slice(0)
  let property = sorts.shift()

  // The sort should be 'asc', 'desc', or a custom array
  let sort
  if (sortTypes.length > 1) {
    sort = sortTypes.slice(0)
  } else {
    let types = sortTypes.slice(0)
    sort = types.shift()
  }

  return function sorter (a, b) {
    let x
    let y
    let result

    // Allocate the comparees.
    if (isFunction(property)) {
      x = property(a)
      y = property(b)
    } else {
      x = a
      y = b
    }

    // Perform the sort
    if (isArrayLike(sort)) {
      // Apply custom ordering
      result = sort.indexOf(x) - sort.indexOf(y)
    } else {
      // Perform an asc sort by default, then invert later if a desc has been
      // requested for the current property.
      result = getAscOrder(x, y)
    }

    // Present the result
    if (sort === 'desc') {
      return result * -1
    } else {
      return result
    }
  }
}

function compare (sortBy, sortTypes, namedComputedProps, namedCustomOrders) {
  // Identify the first property on which to sort, and the way it should be sorted.

  // The property may be either a string property name, an anonymous function, or
  // a string key into the namedComputedProps object.
  let sorts = sortBy.slice(0)
  let property = sorts.shift()

  // The sort can be 'asc', 'desc', a custom array or a string key into the
  // namedCustomOrders object.
  let types = sortTypes.slice(0)
  let sort = types.shift()

  return function sorter (a, b) {
    let x
    let y
    let result
    let recurse
    let currentSort = sort

    // Allocate the comparees.
    if (isFunction(property)) {
      x = property(a)
      y = property(b)
    } else if (isDefined(namedComputedProps[property])) {
      x = namedComputedProps[property](a)
      y = namedComputedProps[property](b)
    } else {
      x = a[property]
      y = b[property]
    }

    // Perform the sort
    if (isArrayLike(sort)) {
      // Apply custom ordering
      result = sort.indexOf(x) - sort.indexOf(y)
    } else if (isDefined(namedCustomOrders[sort])) {
      // Apply custom ordering
      result = namedCustomOrders[sort].indexOf(x) - namedCustomOrders[sort].indexOf(y)
    } else {
      // Perform an asc sort by default, then invert later if a desc has been
      // requested for the current property.
      result = getAscOrder(x, y)
    }

    // Reset this sorting function and parent, unless there is an equal
    // result and there are more sorts still to perform, in which case
    // move on to the next one.
    if (result === 0 && sorts.length) {
      recurse = true
    } else {
      recurse = false
      sorts = sortBy.slice(0)
      types = sortTypes.slice(0)
    }
    property = sorts.shift()
    sort = types.shift()

    // Present the result
    if (recurse) {
      return sorter(a, b)
    } else if (currentSort === 'desc') {
      return result * -1
    } else {
      return result
    }
  }
}

function getAscOrder (x, y) {
  let result
  if (x === null && y === null) {
    result = 0
  } else if ((!isDefined(x) || x === null) && isDefined(y)) {
    result = -1
  } else if (isDefined(x) && (!isDefined(y) || y === null)) {
    result = 1
  } else if (!isDefined(x) && !isDefined(y)) {
    result = 0
  } else {
    result = x < y ? -1 : x > y ? 1 : 0
  }
  return result
}

function isObject (input) {
  return typeof input === 'object' && input !== null
}

function isArrayLike (input) {
  return isObject(input) && typeof input.length === 'number'
}

function isDefined (input) {
  return typeof input !== 'undefined'
}

function isFunction (input) {
  return typeof input === 'function'
}

function isPrimitive (input) {
  if (input === null) return true
  switch (typeof input) {
    case 'string':
    case 'number':
    case 'symbol':
    case 'undefined':
    case 'boolean':
      return true
    default:
      return false
  }
}

function arrayify (input) {
  if (Array.isArray(input)) {
    return input
  } else {
    if (input === undefined) {
      return []
    } else if (isArrayLike(input)) {
      return Array.prototype.slice.call(input)
    } else {
      return [ input ]
    }
  }
}
<commit_msg>feat: add support for descending sort<commit_after>/**
 * Sort an array of objects by any property value, at any depth, in any custom order.
 *
 * @module sort-array
 * @typicalname sortBy
 * @example
 * const sortBy = require('sort-array')
 */
module.exports = sortBy

/**
 * @param {object[]} - Input array of objects
 * @param {string|string[]} - One or more property expressions to sort by,  e.g. `'name'` or `'name.first'`.
 * @param [customOrder] {object} - Custom sort order definitions. An object where each key is the property expression and the value is an array specifying the sort order. Example:

 * `{ importance: [ 'speed', 'strength', 'intelligence' ]}`
 * @returns {Array}
 * @alias module:sort-array
 * @example
 * with this data
 * ```js
 * > DJs = [
 *   { name: 'Trevor', slot: 'twilight' },
 *   { name: 'Chris', slot: 'twilight' },
 *   { name: 'Mike', slot: 'afternoon' },
 *   { name: 'Rodney', slot: 'morning' },
 *   { name: 'Chris', slot: 'morning' },
 *   { name: 'Zane', slot: 'evening' }
 * ]
 * ```
 *
 * sort by `slot` using the default sort order (alphabetical)
 * ```js
 * > sortBy(DJs, 'slot')
 * [ { name: 'Mike', slot: 'afternoon' },
 *   { name: 'Zane', slot: 'evening' },
 *   { name: 'Chris', slot: 'morning' },
 *   { name: 'Rodney', slot: 'morning' },
 *   { name: 'Chris', slot: 'twilight' },
 *   { name: 'Trevor', slot: 'twilight' } ]
 * ```
 *
 * specify a custom sort order for `slot`
 * ```js
 * > const slotOrder = [ 'morning', 'afternoon', 'evening', 'twilight' ]
 * > sortBy(DJs, 'slot', { slot: slotOrder })
 * [ { name: 'Rodney', slot: 'morning' },
 *   { name: 'Chris', slot: 'morning' },
 *   { name: 'Mike', slot: 'afternoon' },
 *   { name: 'Zane', slot: 'evening' },
 *   { name: 'Trevor', slot: 'twilight' },
 *   { name: 'Chris', slot: 'twilight' } ]
 * ```
 *
 * sort by `slot` then `name`
 * ```js
 * > sortBy(DJs, ['slot', 'name'], { slot: slotOrder })
 * [ { name: 'Chris', slot: 'morning' },
 *   { name: 'Rodney', slot: 'morning' },
 *   { name: 'Mike', slot: 'afternoon' },
 *   { name: 'Zane', slot: 'evening' },
 *   { name: 'Chris', slot: 'twilight' },
 *   { name: 'Trevor', slot: 'twilight' } ]
 * ```
 *
 * sort by nested property values (at any depth) using dot notation (e.g. `'inner.number'`)
 * ```js
 * > input = [
 *   { inner: { number: 5 } },
 *   { inner: { number: 2 } },
 *   { inner: { number: 3 } },
 *   { inner: { number: 1 } },
 *   { inner: { number: 4 } }
 * ]
 *
 * > sortBy(input, 'inner.number')
 * [ { inner: { number: 1 } },
 *   { inner: { number: 2 } },
 *   { inner: { number: 3 } },
 *   { inner: { number: 4 } },
 *   { inner: { number: 5 } } ]
 * ```
 *
 * a custom order for a nested property looks like this:
 * ```js
 * const customOrder = {
 *   'inner.number': [ 1, 2, 4, 3, 5 ]
 * }
 * ```
 */
function sortBy (recordset, sortBy, sortTypes, namedConfigs) {
  // First stage data preparation
  recordset = arrayify(recordset)
  sortBy = arrayify(sortBy)
  sortTypes = arrayify(sortTypes)

  let namedComputedProps = {}
  let namedCustomOrders = {}
  if (isObject(namedConfigs)) {
    if (isDefined(namedConfigs['namedComputedProps'])) {
      namedComputedProps = namedConfigs['namedComputedProps']
    }
    if (isDefined(namedConfigs['namedCustomOrders'])) {
      namedCustomOrders = namedConfigs['namedCustomOrders']
    }
  }

  // Perform sanity checks.
  let isPrimitiveSort = recordset.some(record => isPrimitive(record))
  if (isPrimitiveSort) {
    // The only applicable 'sortBy' arguments on a primitive array
    // are 'computed property' functions.
    for (let i = 0; i < sortBy.length; i++) {
      if (!isFunction(sortBy[i])) {
        return recordset
      }
    }
  } else {
    // At least one 'sortBy' argument must be provided, so that the recordset
    // can be sorted according to that property.
    if (sortBy.length === 0) {
      return recordset
    }
  }

  // Ensure that if namedComputedProps is provided, that the object keys
  // are referenced in the sortBy array
  let noOfNamedComputedProps = Object.keys(namedComputedProps).length
  if (noOfNamedComputedProps > 0) {
    for (let i = 0; i < noOfNamedComputedProps; i++) {
      if (sortBy.indexOf(Object.keys(namedComputedProps)[i]) < 0) {
        // Missing object key, return the recordset unchanged
        return recordset
      }
    }
  }

  // Ensure that if namedCustomOrders is provided, that the object keys
  // are referenced in the sortTypes array
  let noOfNamedCustomOrders = Object.keys(namedCustomOrders).length
  if (noOfNamedCustomOrders > 0) {
    for (let i = 0; i < noOfNamedCustomOrders; i++) {
      if (sortTypes.indexOf(Object.keys(namedCustomOrders)[i]) < 0) {
        // Missing object key, return the recordset unchanged
        return recordset
      }
    }
  }

  // Second stage data preparation. Ensure that each property in sortBy
  // has a corresponding property in sortTypes. Populate missing and
  // remove excess, as required.
  if ((sortBy.length === 0) && (sortTypes.length === 0)) {
    sortTypes.push('asc')
  } else if (sortBy.length > sortTypes.length) {
    // Not enough sortTypes have been provided. Fully hydrate the sortTypes
    // array, using 'asc' by default.
    let noOfMissingSortTypes = sortBy.length - sortTypes.length
    for (let i = 0; i < noOfMissingSortTypes; i++) {
      sortTypes.push('asc')
    }
  } else if (!isPrimitiveSort && (sortBy.length < sortTypes.length)) {
    // Too many sortTypes have been provided. Prune the redundant ones
    // at the end of the sortType array.
    sortTypes.splice(-1, sortTypes.length - sortBy.length)
  }

  if (isPrimitiveSort) {
    return recordset.sort(comparePrim(sortBy, sortTypes))
  } else {
    return recordset.sort(compare(sortBy, sortTypes, namedComputedProps, namedCustomOrders))
  }
}

function comparePrim (sortBy, sortTypes) {
  // The property should be undefined or a function
  let sorts = sortBy.slice(0)
  let property = sorts.shift()

  // The sort should be 'asc', 'desc', or a custom array
  let sort
  if (sortTypes.length > 1) {
    sort = sortTypes.slice(0)
  } else {
    let types = sortTypes.slice(0)
    sort = types.shift()
  }

  return function sorter (a, b) {
    let x
    let y
    let result

    // Allocate the comparees.
    if (isFunction(property)) {
      x = property(a)
      y = property(b)
    } else {
      x = a
      y = b
    }

    // Perform the sort
    if (isArrayLike(sort)) {
      // Apply custom ordering
      result = sort.indexOf(x) - sort.indexOf(y)
    } else {
      // Perform an asc sort by default, then invert later if a desc has been
      // requested for the current property.
      result = getAscOrder(x, y)
    }

    // Present the result
    if (sort === 'desc') {
      return result * -1
    } else {
      return result
    }
  }
}

function compare (sortBy, sortTypes, namedComputedProps, namedCustomOrders) {
  // Identify the first property on which to sort, and the way it should be sorted.

  // The property may be either a string property name, an anonymous function, or
  // a string key into the namedComputedProps object.
  let sorts = sortBy.slice(0)
  let property = sorts.shift()

  // The sort can be 'asc', 'desc', a custom array or a string key into the
  // namedCustomOrders object.
  let types = sortTypes.slice(0)
  let sort = types.shift()

  return function sorter (a, b) {
    let x
    let y
    let result
    let recurse
    let currentSort = sort

    // Allocate the comparees.
    if (isFunction(property)) {
      x = property(a)
      y = property(b)
    } else if (isDefined(namedComputedProps[property])) {
      x = namedComputedProps[property](a)
      y = namedComputedProps[property](b)
    } else {
      x = a[property]
      y = b[property]
    }

    // Perform the sort
    if (isArrayLike(sort)) {
      // Apply custom ordering
      result = sort.indexOf(x) - sort.indexOf(y)
    } else if (isDefined(namedCustomOrders[sort])) {
      // Apply custom ordering
      result = namedCustomOrders[sort].indexOf(x) - namedCustomOrders[sort].indexOf(y)
    } else {
      // Perform an asc sort by default, then invert later if a desc has been
      // requested for the current property.
      result = getAscOrder(x, y)
    }

    // Reset this sorting function and parent, unless there is an equal
    // result and there are more sorts still to perform, in which case
    // move on to the next one.
    if (result === 0 && sorts.length) {
      recurse = true
    } else {
      recurse = false
      sorts = sortBy.slice(0)
      types = sortTypes.slice(0)
    }
    property = sorts.shift()
    sort = types.shift()

    // Present the result
    if (recurse) {
      return sorter(a, b)
    } else if (currentSort === 'desc') {
      return result * -1
    } else {
      return result
    }
  }
}

function getAscOrder (x, y) {
  let result
  if (x === null && y === null) {
    result = 0
  } else if ((!isDefined(x) || x === null) && isDefined(y)) {
    result = -1
  } else if (isDefined(x) && (!isDefined(y) || y === null)) {
    result = 1
  } else if (!isDefined(x) && !isDefined(y)) {
    result = 0
  } else {
    result = x < y ? -1 : x > y ? 1 : 0
  }
  return result
}

function isObject (input) {
  return typeof input === 'object' && input !== null
}

function isArrayLike (input) {
  return isObject(input) && typeof input.length === 'number'
}

function isDefined (input) {
  return typeof input !== 'undefined'
}

function isFunction (input) {
  return typeof input === 'function'
}

function isPrimitive (input) {
  if (input === null) return true
  switch (typeof input) {
    case 'string':
    case 'number':
    case 'symbol':
    case 'undefined':
    case 'boolean':
      return true
    default:
      return false
  }
}

function arrayify (input) {
  if (Array.isArray(input)) {
    return input
  } else {
    if (input === undefined) {
      return []
    } else if (isArrayLike(input)) {
      return Array.prototype.slice.call(input)
    } else {
      return [ input ]
    }
  }
}
<|endoftext|>


<commit_before>/* global L */
'use strict';
var gju = require('geojson-utils');

var leafletPip = {
  bassackwards: false,
  pointInLayer: function(p, layer, first) {
    if (p instanceof L.LatLng) p = [p.lng, p.lat];
    else if (leafletPip.bassackwards) p = p.concat().reverse();

    var results = [];

    layer.eachLayer(function(l) {
      if (first && results.length) return;

      if (isPoly(l) &&
        gju.pointInPolygon({
          type:        'Point',
          coordinates: p
        }, l.toGeoJSON().geometry)) {
        results.push(l);
      }
    });
    return results;
  }
};

function isPoly(l) {
  if (L.MultiPolygon) {
    return (l instanceof L.MultiPolygon || l instanceof L.Polygon);
  } else {    //leaftletjs >= 1.0
    return (l.feature && l.feature.geometry && l.feature.geometry.type && -1 != ['Polygon', 'MultiPolygon'].indexOf(l.feature.geometry.type));
  }
}

module.exports = leafletPip;
<commit_msg>leaftletjs -> leafletjs<commit_after>/* global L */
'use strict';
var gju = require('geojson-utils');

var leafletPip = {
  bassackwards: false,
  pointInLayer: function(p, layer, first) {
    if (p instanceof L.LatLng) p = [p.lng, p.lat];
    else if (leafletPip.bassackwards) p = p.concat().reverse();

    var results = [];

    layer.eachLayer(function(l) {
      if (first && results.length) return;

      if (isPoly(l) &&
        gju.pointInPolygon({
          type:        'Point',
          coordinates: p
        }, l.toGeoJSON().geometry)) {
        results.push(l);
      }
    });
    return results;
  }
};

function isPoly(l) {
  if (L.MultiPolygon) {
    return (l instanceof L.MultiPolygon || l instanceof L.Polygon);
  } else {    //leafletjs >= 1.0
    return (l.feature && l.feature.geometry && l.feature.geometry.type && -1 != ['Polygon', 'MultiPolygon'].indexOf(l.feature.geometry.type));
  }
}

module.exports = leafletPip;
<|endoftext|>


<commit_before>
<commit_msg>Basic server setup<commit_after>/* eslint-disable new-cap */
/* eslint-disable no-console */

const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const routes = require('./server/routes');

const app = express();
const apiRouter = express.Router();
const port = process.env.PORT || 5000;

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use('/api', routes(apiRouter));

app.use((req, res, next) => {
  res.setHeader('Access-Coontrol-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, content-type');
  next();
});

mongoose.connect('mongodb://localhost/dms', (err) => {
  if (err) {
    console.log('connection error', err);
  } else {
    console.log('connection successful');
  }
});

app.listen(port, (err) => {
  if (err) {
    console.log('Connection error', err);
  } else {
    console.log('Listening on port:', port);
  }
});
<|endoftext|>