<commit_before>"use strict";

var htmlparser = require("htmlparser2");
var domutils = require('domutils');
var visitor = require('./visitor.js');
var evaluator = require('./evaluator.js');
var nextTag = require('./utilities.js').nextTag;
var replaceNode = require('./utilities.js').replaceNode;

function pearl() {
}

function getModel(state) {
    var obj = {};
    for (var i = 0; i < state.modelStack.length; i++) {
        obj = Object.assign(obj, state.modelStack[i]);
    }
    return obj;
}

function popBlock(id, state) {
    for (var j = state.blockStack.length - 1; j >= 0; j--) {
        if (id in state.blockStack[j]) {
            var block = state.blockStack[j][id];
            delete state.blockStack[j][id];
            return htmlparser.parseDOM(block)[0];
        }
    }
    return null;
}

pearl.process = function (dom, model, config) {
    dom = { type: "tag", name: "pearl", children: dom };
    for (var c = 0; c < dom.children.length; c++) {
        dom.children[c].parent = dom;
    }

    var defaults = {};
    defaults.resource = {};
    if (process.env.NODE_ENV === "development") {
        defaults.resource.format = "{path}.{type}";
    } else {
        defaults.resource.format = "{path}.min.{type}";
    }

    //TODO: Extend defaults
    config = Object.assign({}, defaults, config);

    var state = {
        regions: {},
        templates: {},
        exports: {},
        blockStack: [],
        modelStack: [model],
        dom: dom,
        config: config
    };

    var els = domutils.getElementsByTagName("region", dom);
    for (var j = 0; j < els.length; j++) {
        state.regions[els[j].attribs.id] = els[j];
    }

    els = domutils.getElementsByTagName("component", dom);
    for (var i = 0; i < els.length; i++) {
        domutils.removeElement(els[i]);
        els[i].parent = null;
        els[i].next = null;
        els[i].prev = null;
        state.templates[els[i].attribs.id] = domutils.getOuterHTML(els[i]);
    }

    pearl.visitor.walk(dom.children, state);

    for (var k in state.regions) {
        domutils.removeElement(state.regions[k]);
    }

    return dom.children;
};

pearl.tags = {
    text: function (node, state) {
        //Simply rewrite the text node
        node.data = evaluator.rewrite(node.data, getModel(state));
    },
    include: function (node, state) {
        var $ = {};

        //Create a new DOM object from the template object and visit it
        var template = htmlparser.parseDOM(state.templates[node.attribs.name])[0];
        for (var def in template.attribs) {
            if (def[0] === '$') {
                $[def.substr(1)] = evaluator.rewrite(template.attribs[def], getModel(state));
            }
        }

        //Generate arguments object
        for (var attr in node.attribs) {
            if (attr[0] === '$') {
                $[attr.substr(1)] = evaluator.rewrite(node.attribs[attr], getModel(state));
            }
        }

        //Find and store all blocks that are being overridden and then remove them
        var overrideBlocks = domutils.getElementsByTagName("block", node);
        var blocks = {};
        for (var i = 0; i < overrideBlocks.length; i++) {
            blocks[overrideBlocks[i].attribs.id] = domutils.getOuterHTML(overrideBlocks[i]);
            domutils.removeElement(overrideBlocks[i]);
        }

        //Push new scope
        state.blockStack.push(blocks);
        state.modelStack.push({ $: $ });

        pearl.visitor.walk(template.children, state);

        //Pop scope
        state.modelStack.pop();
        state.blockStack.pop();

        //Replace this include with the children of the template
        replaceNode(node, template.children);

        //Dont update the children, we already have
        return false;
    },
    export: function (node, state) {
        //Check to see if this export is marked as unique indicating that it should only be exported once
        if ("unique" in node.attribs) {
            var uid = evaluator.rewrite(node.attribs.unique, getModel(state));
            //If we've already exported this just remove it
            if (uid in state.exports) {
                domutils.removeElement(node);
                return;
            } else {
                state.exports[uid] = true;
            }
        }

        //Ensure its children are processed and then copy it into the target region
        pearl.visitor.walk(node.children, state);

        var into = evaluator.rewrite(node.attribs.into, getModel(state));
        if (into in state.regions) {
            var region = state.regions[into];

            for (var i = 0; i < node.children.length; i++) {
                domutils.prepend(region, node.children[i]);
            }

            domutils.removeElement(node);

            //Dont update the children, we already have
            return false;
        } else {
            this.error(node, "region not found: " + into);
        }
    },
    resource: function (node, state) {
        var type = evaluator.rewrite(node.attribs.type, getModel(state));
        var path = evaluator.rewrite(node.attribs.path, getModel(state));

        path = state.config.resource.format.replace("{path}", path).replace("{type}", type);

        var newNode;

        //Create a new link or script tag depending on the type
        switch (type) {
            case "css":
                newNode = {
                    type: "tag",
                    name: "link",
                    attribs: {
                        href: path,
                        rel: "stylesheet"
                    }
                };
                break;
            case "js":
                newNode = {
                    type: "tag",
                    name: "script",
                    attribs: {
                        src: path,
                        type: "text/javascript"
                    }
                };
                break;
        }

        //Replace the resource node
        domutils.prepend(node, newNode);
        domutils.removeElement(node);
    },
    if: function (node, state) {
        var nodes = [];
        nodes.push(node);

        //Process all elseif/else nodes following
        while (true) {
            node = nextTag(node);
            if (node === null) {
                break;
            } else if (node.name === "elseif") {
                nodes.push(node);
            } else if (node.name === "else") {
                nodes.push(node);
                break;
            } else {
                break;
            }
        }

        //Iterate over each condition and check it for success
        for (var i = 0; i < nodes.length; i++) {
            var cond = false;
            var n = nodes[i];
            if (n.name === "else") {
                cond = true;
            } else {
                var condition = evaluator.evaluate(n.attribs.condition, getModel(state));
                if (condition && condition !== "undefined") {
                    cond = true;
                }
            }
            //If the condition evaluated to true then append its children
            if (cond) {
                pearl.visitor.walk(n.children, state);

                for (var j = 0; j < n.children.length; j++) {
                    domutils.prepend(n, n.children[j]);
                }
                break;
            }
        }

        //Remove all if/elseif/else nodes
        for (var k = 0; k < nodes.length; k++) {
            domutils.removeElement(nodes[k]);
        }
    },
    for: function (node, state) {
        var variable = node.attribs.var;
        var target = evaluator.rewrite(node.attribs.in, getModel(state));

        //Get the HTML of the node se we can duplicate it
        var html = domutils.getOuterHTML(node);

        //Iterate over each target
        for (var i = 0; i < target.length; i++) {
            var block = htmlparser.parseDOM(html)[0];

            //Create a new scope with the key and process children
            var k = {};
            k[variable] = i;
            state.modelStack.push(k);
            pearl.visitor.walk(block.children, state);
            //Pop the model off the stack
            state.modelStack.pop();

            //Append the children after the node
            for (var x = 0; x < block.children.length; x++) {
                domutils.prepend(node, block.children[x]);
            }
        }

        //Remove the node
        domutils.removeElement(node);
        return false;
    },
    foreach: function (node, state) {
        var variable = node.attribs.var;
        var target = evaluator.rewrite(node.attribs.in, getModel(state));

        //Get the HTML of the node se we can duplicate it
        var html = domutils.getOuterHTML(node);

        //Iterate over each target
        for (var key in target) {
            var block = htmlparser.parseDOM(html)[0];

            //Create a new scope with the key and process children
            var k = {};
            k[variable] = key;
            state.modelStack.push(k);
            pearl.visitor.walk(block.children, state);

            //Pop the model off the stack
            state.modelStack.pop();

            //Append the children after the node
            for (var i = 0; i < block.children.length; i++) {
                domutils.prepend(node, block.children[i]);
            }
        }

        //Remove the node
        domutils.removeElement(node);
        return false;
    },
    block: function (node, state) {
        //Try and find the block that we are overriding
        var block = popBlock(node.attribs.id, state);
        if (block === null) {
            replaceNode(node, node.children);
            return;
        }

        //Visit the children of the node and add then to the dom
        pearl.visitor.walk(block.children, state);

        replaceNode(node, block.children);
        return false;
    },
    script: function (node, state) {
        if (node.attribs.type === "text/pearl") {
            Function.apply({}, ['_', 'with(_) { ' + domutils.getText(node) + ' }'])(getModel(state));
            domutils.replaceElement(node, { type: "text", data: "" });
        }
    }
};

pearl.visitor = new visitor(function (node, state) {
    if (node.type in pearl.tags) {
        if (pearl.tags[node.type](node, state) === false) return visitor.Skip;
    }

    if (node.type == "tag") {
        if (node.name in pearl.tags) {
            if (pearl.tags[node.name](node, state) === false) return visitor.Skip;
        }

        if (node.attribs) {
            for (var attr in node.attribs) {
                node.attribs[attr] = evaluator.rewrite(node.attribs[attr], getModel(state));
            }
        }
    }

}, function (node) {
    return node.children;
});

module.exports = pearl;<commit_msg>Implemented displaying parent content in overridden block<commit_after>"use strict";

var htmlparser = require("htmlparser2");
var domutils = require('domutils');
var visitor = require('./visitor.js');
var evaluator = require('./evaluator.js');
var nextTag = require('./utilities.js').nextTag;
var replaceNode = require('./utilities.js').replaceNode;

function pearl() {
}

function getModel(state) {
    var obj = {};
    for (var i = 0; i < state.modelStack.length; i++) {
        obj = Object.assign(obj, state.modelStack[i]);
    }
    return obj;
}

function popBlock(id, state) {
    for (var j = state.blockStack.length - 1; j >= 0; j--) {
        if (id in state.blockStack[j]) {
            var block = state.blockStack[j][id];
            delete state.blockStack[j][id];
            return {
                el: htmlparser.parseDOM(block.html)[0],
                orig: block.orig
            };
        }
    }
    return null;
}

pearl.process = function (dom, model, config) {
    dom = { type: "tag", name: "pearl", children: dom };
    for (var c = 0; c < dom.children.length; c++) {
        dom.children[c].parent = dom;
    }

    var defaults = {};
    defaults.resource = {};
    if (process.env.NODE_ENV === "development") {
        defaults.resource.format = "{path}.{type}";
    } else {
        defaults.resource.format = "{path}.min.{type}";
    }

    //TODO: Extend defaults
    config = Object.assign({}, defaults, config);

    var state = {
        regions: {},
        templates: {},
        exports: {},
        blockStack: [],
        parentBlock: [],
        modelStack: [model],
        dom: dom,
        config: config
    };

    var els = domutils.getElementsByTagName("region", dom);
    for (var j = 0; j < els.length; j++) {
        state.regions[els[j].attribs.id] = els[j];
    }

    els = domutils.getElementsByTagName("component", dom);
    for (var i = 0; i < els.length; i++) {
        domutils.removeElement(els[i]);
        els[i].parent = null;
        els[i].next = null;
        els[i].prev = null;
        state.templates[els[i].attribs.id] = domutils.getOuterHTML(els[i]);
    }

    pearl.visitor.walk(dom.children, state);

    for (var k in state.regions) {
        domutils.removeElement(state.regions[k]);
    }

    return dom.children;
};

pearl.tags = {
    text: function (node, state) {
        //Simply rewrite the text node
        node.data = evaluator.rewrite(node.data, getModel(state));
    },
    include: function (node, state) {
        var $ = {};

        //Create a new DOM object from the template object and visit it
        var template = htmlparser.parseDOM(state.templates[node.attribs.name])[0];
        for (var def in template.attribs) {
            if (def[0] === '$') {
                $[def.substr(1)] = evaluator.rewrite(template.attribs[def], getModel(state));
            }
        }

        //Generate arguments object
        for (var attr in node.attribs) {
            if (attr[0] === '$') {
                $[attr.substr(1)] = evaluator.rewrite(node.attribs[attr], getModel(state));
            }
        }

        //Find and store all blocks that are being overridden and then remove them
        var overrideBlocks = domutils.getElementsByTagName("block", node);
        var blocks = {};

        var findBlock = function (id) {
            return function (el) {
                return el.type === "tag" && el.name === "block" && el.attribs && el.attribs.id === id;
            };
        };

        for (var i = 0; i < overrideBlocks.length; i++) {
            blocks[overrideBlocks[i].attribs.id] = {
                html: domutils.getOuterHTML(overrideBlocks[i]),
                orig: domutils.findOne(findBlock(overrideBlocks[i].attribs.id), template.children)
            };
            domutils.removeElement(overrideBlocks[i]);
        }

        //Push new scope
        state.blockStack.push(blocks);
        state.modelStack.push({ $: $ });

        pearl.visitor.walk(template.children, state);

        //Pop scope
        state.modelStack.pop();
        state.blockStack.pop();

        //Replace this include with the children of the template
        replaceNode(node, template.children);

        //Dont update the children, we already have
        return false;
    },
    export: function (node, state) {
        //Check to see if this export is marked as unique indicating that it should only be exported once
        if ("unique" in node.attribs) {
            var uid = evaluator.rewrite(node.attribs.unique, getModel(state));
            //If we've already exported this just remove it
            if (uid in state.exports) {
                domutils.removeElement(node);
                return;
            } else {
                state.exports[uid] = true;
            }
        }

        //Ensure its children are processed and then copy it into the target region
        pearl.visitor.walk(node.children, state);

        var into = evaluator.rewrite(node.attribs.into, getModel(state));
        if (into in state.regions) {
            var region = state.regions[into];

            for (var i = 0; i < node.children.length; i++) {
                domutils.prepend(region, node.children[i]);
            }

            domutils.removeElement(node);

            //Dont update the children, we already have
            return false;
        } else {
            this.error(node, "region not found: " + into);
        }
    },
    resource: function (node, state) {
        var type = evaluator.rewrite(node.attribs.type, getModel(state));
        var path = evaluator.rewrite(node.attribs.path, getModel(state));

        path = state.config.resource.format.replace("{path}", path).replace("{type}", type);

        var newNode;

        //Create a new link or script tag depending on the type
        switch (type) {
            case "css":
                newNode = {
                    type: "tag",
                    name: "link",
                    attribs: {
                        href: path,
                        rel: "stylesheet"
                    }
                };
                break;
            case "js":
                newNode = {
                    type: "tag",
                    name: "script",
                    attribs: {
                        src: path,
                        type: "text/javascript"
                    }
                };
                break;
        }

        //Replace the resource node
        domutils.prepend(node, newNode);
        domutils.removeElement(node);
    },
    if: function (node, state) {
        var nodes = [];
        nodes.push(node);

        //Process all elseif/else nodes following
        while (true) {
            node = nextTag(node);
            if (node === null) {
                break;
            } else if (node.name === "elseif") {
                nodes.push(node);
            } else if (node.name === "else") {
                nodes.push(node);
                break;
            } else {
                break;
            }
        }

        //Iterate over each condition and check it for success
        for (var i = 0; i < nodes.length; i++) {
            var cond = false;
            var n = nodes[i];
            if (n.name === "else") {
                cond = true;
            } else {
                var condition = evaluator.evaluate(n.attribs.condition, getModel(state));
                if (condition && condition !== "undefined") {
                    cond = true;
                }
            }
            //If the condition evaluated to true then append its children
            if (cond) {
                pearl.visitor.walk(n.children, state);

                for (var j = 0; j < n.children.length; j++) {
                    domutils.prepend(n, n.children[j]);
                }
                break;
            }
        }

        //Remove all if/elseif/else nodes
        for (var k = 0; k < nodes.length; k++) {
            domutils.removeElement(nodes[k]);
        }
    },
    for: function (node, state) {
        var variable = node.attribs.var;
        var target = evaluator.rewrite(node.attribs.in, getModel(state));

        //Get the HTML of the node se we can duplicate it
        var html = domutils.getOuterHTML(node);

        //Iterate over each target
        for (var i = 0; i < target.length; i++) {
            var block = htmlparser.parseDOM(html)[0];

            //Create a new scope with the key and process children
            var k = {};
            k[variable] = i;
            state.modelStack.push(k);
            pearl.visitor.walk(block.children, state);
            //Pop the model off the stack
            state.modelStack.pop();

            //Append the children after the node
            for (var x = 0; x < block.children.length; x++) {
                domutils.prepend(node, block.children[x]);
            }
        }

        //Remove the node
        domutils.removeElement(node);
        return false;
    },
    foreach: function (node, state) {
        var variable = node.attribs.var;
        var target = evaluator.rewrite(node.attribs.in, getModel(state));

        //Get the HTML of the node se we can duplicate it
        var html = domutils.getOuterHTML(node);

        //Iterate over each target
        for (var key in target) {
            var block = htmlparser.parseDOM(html)[0];

            //Create a new scope with the key and process children
            var k = {};
            k[variable] = key;
            state.modelStack.push(k);
            pearl.visitor.walk(block.children, state);

            //Pop the model off the stack
            state.modelStack.pop();

            //Append the children after the node
            for (var i = 0; i < block.children.length; i++) {
                domutils.prepend(node, block.children[i]);
            }
        }

        //Remove the node
        domutils.removeElement(node);
        return false;
    },
    block: function (node, state) {
        //Try and find the block that we are overriding
        var block = popBlock(node.attribs.id, state);
        if (block === null) {
            replaceNode(node, node.children);
            return;
        }
        state.parentBlock.push(block);

        //Visit the children of the node and add then to the dom
        pearl.visitor.walk(block.el.children, state);

        state.parentBlock.pop();

        replaceNode(node, block.el.children);
        return false;
    },
    script: function (node, state) {
        if (node.attribs.type === "text/pearl") {
            Function.apply({}, ['_', 'with(_) { ' + domutils.getText(node) + ' }'])(getModel(state));
            domutils.replaceElement(node, { type: "text", data: "" });
        }
    },
    parent: function (node, state){
        var block = state.parentBlock[state.parentBlock.length - 1].orig;
        pearl.visitor.walk(block.children, state);
        replaceNode(node, block.children);
        return false;
    }
};

pearl.visitor = new visitor(function (node, state) {
    if (node.type in pearl.tags) {
        if (pearl.tags[node.type](node, state) === false) return visitor.Skip;
    }

    if (node.type == "tag") {
        if (node.name in pearl.tags) {
            if (pearl.tags[node.name](node, state) === false) return visitor.Skip;
        }

        if (node.attribs) {
            for (var attr in node.attribs) {
                node.attribs[attr] = evaluator.rewrite(node.attribs[attr], getModel(state));
            }
        }
    }

}, function (node) {
    return node.children;
});

module.exports = pearl;<|endoftext|>


<commit_before>import assert from 'assert';
import makeDebug from 'debug';
import { cloneDeep, compact, defaults, find, flatten, get, set, map } from 'lodash';
import fp from 'mostly-func';
import { plural } from 'pluralize';

const debug = makeDebug('mostly:feathers-mongoose:helpers');

// get field by path, supporting `array.field`
export function getField (item, field) {
  let parts = field.split('.');
  let value = item, part;
  while (parts.length) {
    part = parts.shift();
    if (Array.isArray(value)) {
      value = fp.pipe(
        fp.map(fp.prop(part)),
        fp.reject(fp.isNil),
        fp.flatten
      )(value);
    } else {
      value = value? value[part] : null;
    }
  }

  return Array.isArray(value) ? fp.filter(fp.identity, value) : value;
}

export function setFieldByKey (item, field, data) {
  let parts = field.split('.');
  let key = parts.pop();
  let value = item, part;
  while (parts.length) {
    part = parts.shift();
    value = value[part];
  }
  if (!value) return; // nothing to setField

  if (Array.isArray(value) && !value[key]) {
    value.forEach(function (v) {
      let id = v[key];
      if (Array.isArray(id)) {
        set(v, key, map(id, it => data[it] || it));
      } else {
        set(v, key, data[id] || id);
      }
    });
  } else {
    if (value && value[key]) {
      let id = value[key];
      if (Array.isArray(id)) {
        set(item, field, map(id, it => data[it] || it));
      } else {
        set(item, field, data[id] || id);
      }
    }
  }

  return cloneDeep(item);
}

// set field by path
export function setField (item, target, data, field, options) {
  //debug('setField ==== %s, \n  >>>> %s / %s, \n  >>>> %s ',
  //  util.inspect(item), target, field, util.inspect(data));
  options = options || {};

  field = field || target;
  let parts = field.split('.');
  let key = parts.pop();
  let value = item, part;
  while (parts.length) {
    part = parts.shift();
    if (value[part] !== undefined) value = value[part];
    if (fp.isArray(value) && parts.length > 0) {
      let subValue = fp.map(fp.prop(parts[0]), value);
      if (fp.any(fp.isArray, subValue)) {
        value = [].concat.apply([], subValue); // flatten the array of array
        continue;
      } else {
        key = [...parts, key].join('.');
        break;
      }
    }
  }

  if (!value) {
    warn(0, '<nothing-to-setField>');
    return; // nothing to setField
  }

  function warn (which, id) {
    debug(' >>> WARN %d: setField %s/%s(id=%j) not found with item %s',
      which, target, field, id, item[options.idField]);
  }

  // avoid duplicate setField
  function cloneById (v, k) {
    if (Array.isArray(v)) {
      let match = find(v, it => String(it[options.idField]) === String(k));
      return match ? cloneDeep(match) : (options.keepOrig ? k : null);
    } else {
      return String(v[options.idField]) === String(k)? cloneDeep(v) : (options.keepOrig ? k : null);
    }
  }

  if (Array.isArray(value)) {
    value.forEach(function (v) {
      let entry = get(v, key);
      if(Array.isArray(entry)) {
        set(v, key, compact(entry.map(it => {
          let id = options.path? it[options.idField] : it;
          let clone = id? cloneById(data, id) : (options.keepOrig? entry._value : null);
          return options.retained? defaults(it, clone) : clone;
        })));
        if (!get(v, key)) warn(1, entry);
      } else {
        let id = options.path? entry[options.idField] : entry;
        let clone = id? cloneById(data, id) : (options.keepOrig? entry._value : null);
        set(v, key, options.retained? defaults(entry, clone) : clone);
        if (!get(v, key)) warn(2, entry);
      }
    });
  } else {
    if (value && value[key]) {
      let entry = get(value, key);
      if (Array.isArray(entry)) {
        set(item, target, compact(entry.map(it => {
          let id = options.path? it[options.idField] : it;
          let clone = id? cloneById(data, id) : (options.keepOrig? entry._value : null);
          return options.retained? defaults(it, clone) : clone;
        })));
        if (!get(item, target)) warn(3, entry);
      } else {
        let id = options.path? entry[options.idField] : entry;
        let clone = id? cloneById(data, id) : (options.keepOrig? entry._value : null);
        set(item, target, options.retained? defaults(entry, clone) : clone);
        if (!get(item, target)) warn(4, entry);
      }
    } else {
      //warn(4, 'skip <no-such-field>');
    }
  }
  return item;
}

const unsetIdv = function (obj) {
  if (obj && obj._id) {
    return fp.pipe(
      fp.assoc('id', String(obj.id || obj._id)),
      fp.dissoc('_id'),
      fp.dissoc('__v')
    )(obj);
  } else {
    return obj;
  }
};

const unsetObj = function (obj) {
  if (Array.isArray(obj)) {
    return fp.map(unsetIdv, obj);
  } else {
    return unsetIdv(obj);
  }
};

// transform the results
export const transform = function (results) {
  if (results) {
    if (fp.has('data', results)) {
      results.data = unsetObj(results.data);
    } else {
      results = unsetObj(results);
    }
  }
  return results;
};

export const reorderPosition = async function (Model, item, newPos, options) {
  const items = fp.asArray(item);
  assert(items.length, 'At least one item must be provided');
  const idField = options.idField || '_id';
  const prevPos = fp.reduce((acc, item) => Math.max(acc, item.position), 0, items); // last position
  newPos = parseInt(newPos || 0);

  const whichWay = (newPos > prevPos ? -1 : 1); // down : up
  const start = (newPos > prevPos) ? prevPos + 1 : newPos;
  const end = (newPos > prevPos) ? newPos : prevPos - 1;

  // sort item reverse (desc) for moving down and asc for moving up
  const sortedItems = fp.sort((a, b) => whichWay * (a.position - b.position), items);

  const others = {
    position: { '$gte': start, '$lte': end }
  };
  if (options.classify) {
    others[options.classify] = sortedItems[0][options.classify];
  }
  // update others position one way down
  await Model.update(others, {
    $inc: { position: sortedItems.length * whichWay }
  }, {
    multi: true
  });

  const updatePosition = function (item, index) {
    const cond = {
      [idField]: item._id || item.id
    };
    const update = {
      position: newPos + index * whichWay,
    };
    if (options.classify) {
      assert(item[options.classify], 'item classify is not exists');
      cond[options.classify] = item[options.classify];
      update[options.classify] = item[options.classify]; // must provided with position
    }
    // update position of the item
    return Model.findOneAndUpdate(cond, update, { new : true });
  };

  return Promise.all(fp.mapIndexed(updatePosition, sortedItems));
};

// get mongo id as string (object, mongo id, typed id)
export const pathId = fp.curry((idField, obj) => {
  if (obj) {
    if (fp.is(String, obj)) {
      // whether a typed id
      if (obj.indexOf(':') > 0) {
        return fp.last(fp.split(':', obj));
      } else {
        return obj;
      }
    }
    if (fp.isObjectId(obj.toString())) return obj.toString();
    if (obj[idField]) return pathId(idField, obj[idField]);
  }
  return null;
});
export const getId = pathId('id');

export const typedId = (obj) => {
  return obj && obj.type? obj.type + ':' + obj.id : obj;
};

export const convertMongoId = (id) => {
  if (id && fp.isObjectId(id.toString())) {
    return id.toString();
  } else {
    return Array.isArray(id)? fp.map(convertMongoId, id) : id;
  }
};

export const repeatDoubleStar = fp.map(fp.replace(/(\w*).\*\*/, '$1.$1.**'));

export const normalizeSelect = function (select) {
  if (select) {
    // convert string $select to array
    if (fp.is(String, select)) {
      select = fp.map(fp.trim, fp.split(',', select));
    }
    // repeat ** as recursive fields
    select = repeatDoubleStar(select);
  }
  return select;
};

export const isSelected = (target, select) => {
  if (select) {
    // normalize the $select
    select = normalizeSelect(select);
    // check whether target is in the $select
    return fp.any(fp.startsWith(target), select);
  }
  return false;
};

export const addToSelect = (select, ...args) => {
  select = select? normalizeSelect(select) : [];
  return fp.uniq(select.concat(args));
};

export const prefixSelect = (select, prefix) => {
  const fields = fp.splitOrArray(select);
  return fp.map(fp.concat(prefix + '.'), fields);
};

export const selectNext = (target, select) => {
  if (select) {
    // normalize the $select
    select = normalizeSelect(select);
    // filter and replace current target from the $select
    return fp.pipe(
      fp.filter(fp.startsWith(target)),
      fp.map(fp.replace(new RegExp('^' + target + '\.?'), '')),
      fp.reject(fp.isEmpty),
      fp.unless(fp.isEmpty, fp.append('*')) // add * for non-empty
    )(select);
  }
  return select;
};

export const sortWith = (sort, data) => {
  const descSorts = ['desc', 'descending', '-1', -1];
  var propSort = fp.mapObjIndexed((dir, field) => {
    if (descSorts.indexOf(dir) === -1) {
      return fp.ascend(fp.prop(field));
    } else {
      return fp.descend(fp.prop(field));
    }
  }, sort);
  return fp.sortWith(fp.values(propSort), data);
};

export const getHookData = (context) => {
  const items = context.type === 'before'? context.data : context.result;
  return fp.propOf('data', items);
};

export const getHookDataAsArray = (context) => {
  const items = getHookData(context);
  return items? fp.asArray(items) : [];
};

export const setHookData = (context, items) => {
  if (context.type === 'before') {
    context.data = items;
  } else {
    if (fp.hasProp('data', context.result)) {
      context.result.data = items;
    } else {
      context.result = items;
    }
  }
};

// find with a groupby entries like { 'type1': [{ id: 1 }, { id: 2 }] }
export const findEntriesByType = (app, entriesByType, params = {}, options = {}) => {
  // find by descriminated service
  const findByType = fp.mapObjIndexed((entries, type) => {
    if (options.skipType && type === options.skipType) {
      return Promise.resolve(entries);
    } else {
      let typeParams = fp.assignAll({ query: {} }, params); // copy for change
      typeParams.query.id = {
        $in: fp.map(fp.prop('id'), entries)
      };
      if (!typeParams.query.$sort) {
        typeParams.query.$sort = options.sort; // default sort
      }
      typeParams.paginate = false;
      return app.service(plural(type)).find(typeParams);
    }
  });

  const promises = fp.values(findByType(entriesByType));
  return Promise.all(promises).then(entries => {
    // merge the results
    const data = fp.flatMap(fp.propOf('data'), entries);
    // sort again
    if (entries.length > 1) {
      const sort = fp.dotPath('query.$sort', params) || options.sort;
      return sort? sortWith(sort, data) : data;
    } else {
      return data;
    }
  });
};

// find with typed ids from various descriminated services
export const findWithTypedIds = (app, list, params, options) => {
  if (!fp.isValid(list)) return Promise.resolve(list);

  const typeAndIds = fp.map(typed => {
    const field = fp.split(':', typed);
    return { type: fp.head(field), id: fp.last(field) };
  }, list);
  const entriesByType = fp.groupBy(fp.prop('type'), typeAndIds);

  // find the grouped entries by descriminated service
  return findEntriesByType(app, entriesByType, params, options);
};

// find and merge the results from various descriminated services
export const discriminatedFind = (app, keyType, result, params, options) => {
  if (!result || !fp.isValid(fp.propOf('data', result))) {
    return Promise.resolve(result);
  }

  const entriesByType = fp.groupBy(fp.prop('type'), fp.propOf('data', result));

  // find the grouped entries by descriminated service
  return findEntriesByType(app, entriesByType, params, options).then(data => {
    if (fp.hasProp('data', result)) {
      result.data = data;
    } else {
      result = data;
    }
    return result;
  });
};

// get the result from descriminated service
export const discriminatedGet = (app, keyType, result, params) => {
  if (result && result.type && result.type !== keyType) {
    return app.service(plural(result.type)).get(result.id, params);
  } else {
    return Promise.resolve(result);
  }
};

const populateList = (list, idField, options = {}) => (data) => {
  return fp.map((obj) => {
    let item = data.find((item) => {
      return String(obj[idField]) === String(item.id);
    });
    if (options.merge) {
      // retain _id for original id
      const retained = fp.reduce((acc, field) => {
        acc['_' + field] = obj[field];
        return acc;
      }, {});
      return item && fp.mergeAll([retained(options.retained || []), obj, item]);
    } else {
      obj[idField] = item;
      return obj;
    }
  })(list);
};

export function populateByService (app, idField, typeField, options = {}) {
  return (list) => {
    let types = fp.groupBy(fp.prop(typeField), list);
    return Promise.all(
      fp.map(type => {
        let entries = types[type];
        return app.service(plural(type)).find(Object.assign({
          query: {
            _id: { $in: fp.uniq(fp.map(fp.prop(idField), entries)) },
          },
          paginate: false
        }, options));
      }, Object.keys(types))
    ).then(results => {
      const data = fp.flatten(results);
      const populated = populateList(list, idField, options)(data);
      return fp.reject(fp.isNil, populated);
    });
  };
}
<commit_msg>add findEntries/findUserEntries helpers<commit_after>import assert from 'assert';
import makeDebug from 'debug';
import { cloneDeep, compact, defaults, find, flatten, get, set, map } from 'lodash';
import fp from 'mostly-func';
import { plural } from 'pluralize';

const debug = makeDebug('mostly:feathers-mongoose:helpers');

// get field by path, supporting `array.field`
export function getField (item, field) {
  let parts = field.split('.');
  let value = item, part;
  while (parts.length) {
    part = parts.shift();
    if (Array.isArray(value)) {
      value = fp.pipe(
        fp.map(fp.prop(part)),
        fp.reject(fp.isNil),
        fp.flatten
      )(value);
    } else {
      value = value? value[part] : null;
    }
  }

  return Array.isArray(value) ? fp.filter(fp.identity, value) : value;
}

export function setFieldByKey (item, field, data) {
  let parts = field.split('.');
  let key = parts.pop();
  let value = item, part;
  while (parts.length) {
    part = parts.shift();
    value = value[part];
  }
  if (!value) return; // nothing to setField

  if (Array.isArray(value) && !value[key]) {
    value.forEach(function (v) {
      let id = v[key];
      if (Array.isArray(id)) {
        set(v, key, map(id, it => data[it] || it));
      } else {
        set(v, key, data[id] || id);
      }
    });
  } else {
    if (value && value[key]) {
      let id = value[key];
      if (Array.isArray(id)) {
        set(item, field, map(id, it => data[it] || it));
      } else {
        set(item, field, data[id] || id);
      }
    }
  }

  return cloneDeep(item);
}

// set field by path
export function setField (item, target, data, field, options) {
  //debug('setField ==== %s, \n  >>>> %s / %s, \n  >>>> %s ',
  //  util.inspect(item), target, field, util.inspect(data));
  options = options || {};

  field = field || target;
  let parts = field.split('.');
  let key = parts.pop();
  let value = item, part;
  while (parts.length) {
    part = parts.shift();
    if (value[part] !== undefined) value = value[part];
    if (fp.isArray(value) && parts.length > 0) {
      let subValue = fp.map(fp.prop(parts[0]), value);
      if (fp.any(fp.isArray, subValue)) {
        value = [].concat.apply([], subValue); // flatten the array of array
        continue;
      } else {
        key = [...parts, key].join('.');
        break;
      }
    }
  }

  if (!value) {
    warn(0, '<nothing-to-setField>');
    return; // nothing to setField
  }

  function warn (which, id) {
    debug(' >>> WARN %d: setField %s/%s(id=%j) not found with item %s',
      which, target, field, id, item[options.idField]);
  }

  // avoid duplicate setField
  function cloneById (v, k) {
    if (Array.isArray(v)) {
      let match = find(v, it => String(it[options.idField]) === String(k));
      return match ? cloneDeep(match) : (options.keepOrig ? k : null);
    } else {
      return String(v[options.idField]) === String(k)? cloneDeep(v) : (options.keepOrig ? k : null);
    }
  }

  if (Array.isArray(value)) {
    value.forEach(function (v) {
      let entry = get(v, key);
      if(Array.isArray(entry)) {
        set(v, key, compact(entry.map(it => {
          let id = options.path? it[options.idField] : it;
          let clone = id? cloneById(data, id) : (options.keepOrig? entry._value : null);
          return options.retained? defaults(it, clone) : clone;
        })));
        if (!get(v, key)) warn(1, entry);
      } else {
        let id = options.path? entry[options.idField] : entry;
        let clone = id? cloneById(data, id) : (options.keepOrig? entry._value : null);
        set(v, key, options.retained? defaults(entry, clone) : clone);
        if (!get(v, key)) warn(2, entry);
      }
    });
  } else {
    if (value && value[key]) {
      let entry = get(value, key);
      if (Array.isArray(entry)) {
        set(item, target, compact(entry.map(it => {
          let id = options.path? it[options.idField] : it;
          let clone = id? cloneById(data, id) : (options.keepOrig? entry._value : null);
          return options.retained? defaults(it, clone) : clone;
        })));
        if (!get(item, target)) warn(3, entry);
      } else {
        let id = options.path? entry[options.idField] : entry;
        let clone = id? cloneById(data, id) : (options.keepOrig? entry._value : null);
        set(item, target, options.retained? defaults(entry, clone) : clone);
        if (!get(item, target)) warn(4, entry);
      }
    } else {
      //warn(4, 'skip <no-such-field>');
    }
  }
  return item;
}

const unsetIdv = function (obj) {
  if (obj && obj._id) {
    return fp.pipe(
      fp.assoc('id', String(obj.id || obj._id)),
      fp.dissoc('_id'),
      fp.dissoc('__v')
    )(obj);
  } else {
    return obj;
  }
};

const unsetObj = function (obj) {
  if (Array.isArray(obj)) {
    return fp.map(unsetIdv, obj);
  } else {
    return unsetIdv(obj);
  }
};

// transform the results
export const transform = function (results) {
  if (results) {
    if (fp.has('data', results)) {
      results.data = unsetObj(results.data);
    } else {
      results = unsetObj(results);
    }
  }
  return results;
};

export const reorderPosition = async function (Model, item, newPos, options) {
  const items = fp.asArray(item);
  assert(items.length, 'At least one item must be provided');
  const idField = options.idField || '_id';
  const prevPos = fp.reduce((acc, item) => Math.max(acc, item.position), 0, items); // last position
  newPos = parseInt(newPos || 0);

  const whichWay = (newPos > prevPos ? -1 : 1); // down : up
  const start = (newPos > prevPos) ? prevPos + 1 : newPos;
  const end = (newPos > prevPos) ? newPos : prevPos - 1;

  // sort item reverse (desc) for moving down and asc for moving up
  const sortedItems = fp.sort((a, b) => whichWay * (a.position - b.position), items);

  const others = {
    position: { '$gte': start, '$lte': end }
  };
  if (options.classify) {
    others[options.classify] = sortedItems[0][options.classify];
  }
  // update others position one way down
  await Model.update(others, {
    $inc: { position: sortedItems.length * whichWay }
  }, {
    multi: true
  });

  const updatePosition = function (item, index) {
    const cond = {
      [idField]: item._id || item.id
    };
    const update = {
      position: newPos + index * whichWay,
    };
    if (options.classify) {
      assert(item[options.classify], 'item classify is not exists');
      cond[options.classify] = item[options.classify];
      update[options.classify] = item[options.classify]; // must provided with position
    }
    // update position of the item
    return Model.findOneAndUpdate(cond, update, { new : true });
  };

  return Promise.all(fp.mapIndexed(updatePosition, sortedItems));
};

// get mongo id as string (object, mongo id, typed id)
export const pathId = fp.curry((idField, obj) => {
  if (obj) {
    if (fp.is(String, obj)) {
      // whether a typed id
      if (obj.indexOf(':') > 0) {
        return fp.last(fp.split(':', obj));
      } else {
        return obj;
      }
    }
    if (fp.isObjectId(obj.toString())) return obj.toString();
    if (obj[idField]) return pathId(idField, obj[idField]);
  }
  return null;
});
export const getId = pathId('id');

export const typedId = (obj) => {
  return obj && obj.type? obj.type + ':' + obj.id : obj;
};

export const convertMongoId = (id) => {
  if (id && fp.isObjectId(id.toString())) {
    return id.toString();
  } else {
    return Array.isArray(id)? fp.map(convertMongoId, id) : id;
  }
};

export const repeatDoubleStar = fp.map(fp.replace(/(\w*).\*\*/, '$1.$1.**'));

export const normalizeSelect = function (select) {
  if (select) {
    // convert string $select to array
    if (fp.is(String, select)) {
      select = fp.map(fp.trim, fp.split(',', select));
    }
    // repeat ** as recursive fields
    select = repeatDoubleStar(select);
  }
  return select;
};

export const isSelected = (target, select) => {
  if (select) {
    // normalize the $select
    select = normalizeSelect(select);
    // check whether target is in the $select
    return fp.any(fp.startsWith(target), select);
  }
  return false;
};

export const addToSelect = (select, ...args) => {
  select = select? normalizeSelect(select) : [];
  return fp.uniq(select.concat(args));
};

export const prefixSelect = (select, prefix) => {
  const fields = fp.splitOrArray(select);
  return fp.map(fp.concat(prefix + '.'), fields);
};

export const selectNext = (target, select) => {
  if (select) {
    // normalize the $select
    select = normalizeSelect(select);
    // filter and replace current target from the $select
    return fp.pipe(
      fp.filter(fp.startsWith(target)),
      fp.map(fp.replace(new RegExp('^' + target + '\.?'), '')),
      fp.reject(fp.isEmpty),
      fp.unless(fp.isEmpty, fp.append('*')) // add * for non-empty
    )(select);
  }
  return select;
};

export const sortWith = (sort, data) => {
  const descSorts = ['desc', 'descending', '-1', -1];
  var propSort = fp.mapObjIndexed((dir, field) => {
    if (descSorts.indexOf(dir) === -1) {
      return fp.ascend(fp.prop(field));
    } else {
      return fp.descend(fp.prop(field));
    }
  }, sort);
  return fp.sortWith(fp.values(propSort), data);
};

export const getHookData = (context) => {
  const items = context.type === 'before'? context.data : context.result;
  return fp.propOf('data', items);
};

export const getHookDataAsArray = (context) => {
  const items = getHookData(context);
  return items? fp.asArray(items) : [];
};

export const setHookData = (context, items) => {
  if (context.type === 'before') {
    context.data = items;
  } else {
    if (fp.hasProp('data', context.result)) {
      context.result.data = items;
    } else {
      context.result = items;
    }
  }
};

export const findEntries = (service, ids, select = '*') => {
  return service.find({
    query: {
      _id: { $in: ids },
      $select: select
    },
    paginate: false
  });
};

export const findUserEntries = (service, ids, user, select = '*') => {
  return service.find({
    query: {
      _id: { $in: ids },
      user: user,
      $select: select
    },
    paginate: false
  });
};

// find with a groupby entries like { 'type1': [{ id: 1 }, { id: 2 }] }
export const findEntriesByType = (app, entriesByType, params = {}, options = {}) => {
  // find by descriminated service
  const findByType = fp.mapObjIndexed((entries, type) => {
    if (options.skipType && type === options.skipType) {
      return Promise.resolve(entries);
    } else {
      let typeParams = fp.assignAll({ query: {} }, params); // copy for change
      typeParams.query.id = {
        $in: fp.map(fp.prop('id'), entries)
      };
      if (!typeParams.query.$sort) {
        typeParams.query.$sort = options.sort; // default sort
      }
      typeParams.paginate = false;
      return app.service(plural(type)).find(typeParams);
    }
  });

  const promises = fp.values(findByType(entriesByType));
  return Promise.all(promises).then(entries => {
    // merge the results
    const data = fp.flatMap(fp.propOf('data'), entries);
    // sort again
    if (entries.length > 1) {
      const sort = fp.dotPath('query.$sort', params) || options.sort;
      return sort? sortWith(sort, data) : data;
    } else {
      return data;
    }
  });
};

// find with typed ids from various descriminated services
export const findWithTypedIds = (app, list, params, options) => {
  if (!fp.isValid(list)) return Promise.resolve(list);

  const typeAndIds = fp.map(typed => {
    const field = fp.split(':', typed);
    return { type: fp.head(field), id: fp.last(field) };
  }, list);
  const entriesByType = fp.groupBy(fp.prop('type'), typeAndIds);

  // find the grouped entries by descriminated service
  return findEntriesByType(app, entriesByType, params, options);
};

// find and merge the results from various descriminated services
export const discriminatedFind = (app, keyType, result, params, options) => {
  if (!result || !fp.isValid(fp.propOf('data', result))) {
    return Promise.resolve(result);
  }

  const entriesByType = fp.groupBy(fp.prop('type'), fp.propOf('data', result));

  // find the grouped entries by descriminated service
  return findEntriesByType(app, entriesByType, params, options).then(data => {
    if (fp.hasProp('data', result)) {
      result.data = data;
    } else {
      result = data;
    }
    return result;
  });
};

// get the result from descriminated service
export const discriminatedGet = (app, keyType, result, params) => {
  if (result && result.type && result.type !== keyType) {
    return app.service(plural(result.type)).get(result.id, params);
  } else {
    return Promise.resolve(result);
  }
};

const populateList = (list, idField, options = {}) => (data) => {
  return fp.map((obj) => {
    let item = data.find((item) => {
      return String(obj[idField]) === String(item.id);
    });
    if (options.merge) {
      // retain _id for original id
      const retained = fp.reduce((acc, field) => {
        acc['_' + field] = obj[field];
        return acc;
      }, {});
      return item && fp.mergeAll([retained(options.retained || []), obj, item]);
    } else {
      obj[idField] = item;
      return obj;
    }
  })(list);
};

export function populateByService (app, idField, typeField, options = {}) {
  return (list) => {
    let types = fp.groupBy(fp.prop(typeField), list);
    return Promise.all(
      fp.map(type => {
        let entries = types[type];
        return app.service(plural(type)).find(Object.assign({
          query: {
            _id: { $in: fp.uniq(fp.map(fp.prop(idField), entries)) },
          },
          paginate: false
        }, options));
      }, Object.keys(types))
    ).then(results => {
      const data = fp.flatten(results);
      const populated = populateList(list, idField, options)(data);
      return fp.reject(fp.isNil, populated);
    });
  };
}
<|endoftext|>


<commit_before>import express from 'express';
import path from 'path';
import ffmpeg from 'fluent-ffmpeg';
import mdns from 'mdns-js';
import os from 'os';
import net from 'net';
import async from 'async';
import util from 'util';
import EventEmitter from 'events';

try {
    var wincmd wincmd = require('node-windows');
} catch (ex) {
    var wincmd = null;
}

import {
    Client as castv2Client,
    DefaultMediaReceiver as castv2DefaultMediaReceiver
}
from 'castv2-client';

const app = express();

app.get('/', (req, res) => {
    req.connection.setTimeout(Number.MAX_SAFE_INTEGER);
    console.log("Device requested: /");
    let command = ffmpeg();

    command.setFfmpegPath(path.join(process.cwd(), 'ffmpeg'));
    command.input('audio=virtual-audio-capturer')
    command.inputFormat('dshow')
    command.audioCodec("libmp3lame")
    command.outputFormat("mp3")
        .on('start', commandLine => {
            console.log('Spawned Ffmpeg with command: ' + commandLine);
        })
        .on('error', (err, one, two) => {
            console.log('An error occurred: ' + err.message);
            console.log(two);
        })
        .on('end', () => {
            console.log("end");
            res.end();
        })

    let ffstream = command.pipe();
    ffstream.on('data', res.write.bind(res));
});

const App = () => {
    EventEmitter.call(this);
    this.portRange = 3000;
    this.devices = [];
    async.parallel([
        done => {
            this.getFreePort(port => {
                this.onFreePortFound(port);
                done();
            });
        },
        // this.detectVirtualAudioDevice.bind(this)
    ], err => {
        if (err) {
            // something went wrong
        } else {

        }
    });
};
util.inherits(App, EventEmitter);

App.prototype.getFreePort = cb => {
    var port = this.portRange
    this.portRange++;

    let server = net.createServer();

    server.listen(port, err => {
        server.once('close', () => {
            cb(port);
        });
        server.close();
    });
    server.on('error', this.getFreePort.bind(this, cb));
};

App.prototype.onFreePortFound = port => {
    this._port = port;
    console.info("onFreePortFound::", port);
    this._server = app.listen(port, () => {
        console.info('Example app listening at http://%s:%s', this.getIp(), port);
    });
};

App.prototype.detectVirtualAudioDevice = (cb, redetection) => {
    var command = ffmpeg("dummy");
    command.setFfmpegPath(path.join(process.cwd(), 'ffmpeg'));
    command.inputOptions([
        "-list_devices true",
        "-f dshow",
    ])
    command.outputOptions([])
        .on('start', commandLine => {
            console.log('Spawned Ffmpeg with command: ' + commandLine);
        })
        .on('error', (err, one, two) => {
            console.log('An error occurred: ' + err.message);
            if (one, two) {
                if (two.indexOf("virtual-audio-capturer") > -1) {
                    console.log("VIRTUAL DEVICE FOUND");
                    cb();
                } else if (redetection) {
                    let err = "Please re-run application and temporarily allow Administrator to install Virtual Audio Driver.";
                    console.log(err);
                    cb(err);
                } else {
                    wincmd.elevate("register_run_as_admin.bat", setTimeout.bind(this, this.detectVirtualAudioDevice.bind(this, cb, true), 2000));
                }
            }
        })
        .on('end', console.log.bind(this, 'end'))

    let ffstream = command.pipe();
};

App.prototype.ondeviceup = (host, name) => {
    if (this.devices.indexOf(host) == -1) {
        this.devices.push(host);
        console.info("ondeviceup", host, this.devices);
        this.emit("deviceFound", host, name);
    }
};

App.prototype.getIp = () => {
    var ip, alias = 0;
    var ifaces = os.networkInterfaces();

    for (var dev in ifaces) {
        ifaces[dev].forEach(details => {
            if (details.family === 'IPv4') {
                if (!/(loopback|vmware|internal|hamachi|vboxnet)/gi.test(dev + (alias ? ':' + alias : ''))) {
                    if (details.address.substring(0, 8) === '192.168.' ||
                        details.address.substring(0, 7) === '172.16.' ||
                        details.address.substring(0, 5) === '10.0.'
                    ) {
                        ip = details.address;
                        ++alias;
                    }
                }
            }
        });
    }

    return ip;
};

App.prototype.searchForDevices = () => {
    let browser = mdns.createBrowser(mdns.tcp('googlecast'));
    browser.on('ready', browser.discover);

    browser.on('update', service => {
        console.log('data:', service);
        console.log('found device "%s" at %s:%d', service.fullname.substring(0, service.fullname.indexOf("._googlecast")), service.addresses[0], service.port);
        this.ondeviceup(service.addresses[0], service.fullname.indexOf("._googlecast"));
        browser.stop();
    });
};

App.prototype.stream = host => {
    let client = new castv2Client();

    client.connect(host, () => {
        console.log('connected, launching app ...');

        client.launch(castv2DefaultMediaReceiver, (err, player) => {
            let media = {

                // Here you can plug an URL to any mp4, webm, mp3 or jpg file with the proper contentType.
                contentId: 'http://' + this.getIp() + ':' + this._server.address().port + '/',
                contentType: 'audio/mp3',
                streamType: 'BUFFERED', // or LIVE

                // Title and cover displayed while buffering
                metadata: {
                    type: 0,
                    metadataType: 0,
                    title: "Audio Caster",
                }
            };

            player.on('status', status => {
                console.log('status broadcast playerState=%s', status);
            });

            console.log('app "%s" launched, loading media %s ...', player, media);

            player.load(media, {
                autoplay: true
            }, (err, status) => {
                console.log('media loaded playerState=%s', status);
            });

        });

    });

    client.on('error', err => {
        console.log('Error: %s', err.message);
        client.close();
    });
};

var instance = new App;
instance.searchForDevices();

module.exports = instance;<commit_msg>.' git pu<commit_after>import express from 'express';
import path from 'path';
import ffmpeg from 'fluent-ffmpeg';
import mdns from 'mdns-js';
import os from 'os';
import net from 'net';
import async from 'async';
import util from 'util';
import EventEmitter from 'events';

try {
    var wincmd = require('node-windows');
} catch (ex) {
    var wincmd = null;
}

import {
    Client as castv2Client,
    DefaultMediaReceiver as castv2DefaultMediaReceiver
}
from 'castv2-client';

const app = express();

app.get('/', (req, res) => {
    req.connection.setTimeout(Number.MAX_SAFE_INTEGER);
    console.log("Device requested: /");
    let command = ffmpeg();

    command.setFfmpegPath(path.join(process.cwd(), 'ffmpeg'));
    command.input('audio=virtual-audio-capturer')
    command.inputFormat('dshow')
    command.audioCodec("libmp3lame")
    command.outputFormat("mp3")
        .on('start', commandLine => {
            console.log('Spawned Ffmpeg with command: ' + commandLine);
        })
        .on('error', (err, one, two) => {
            console.log('An error occurred: ' + err.message);
            console.log(two);
        })
        .on('end', () => {
            console.log("end");
            res.end();
        })

    let ffstream = command.pipe();
    ffstream.on('data', res.write.bind(res));
});

const App = () => {
    EventEmitter.call(this);
    this.portRange = 3000;
    this.devices = [];
    async.parallel([
        done => {
            this.getFreePort(port => {
                this.onFreePortFound(port);
                done();
            });
        },
        // this.detectVirtualAudioDevice.bind(this)
    ], err => {
        if (err) {
            // something went wrong
        } else {

        }
    });
};
util.inherits(App, EventEmitter);

App.prototype.getFreePort = cb => {
    var port = this.portRange
    this.portRange++;

    let server = net.createServer();

    server.listen(port, err => {
        server.once('close', () => {
            cb(port);
        });
        server.close();
    });
    server.on('error', this.getFreePort.bind(this, cb));
};

App.prototype.onFreePortFound = port => {
    this._port = port;
    console.info("onFreePortFound::", port);
    this._server = app.listen(port, () => {
        console.info('Example app listening at http://%s:%s', this.getIp(), port);
    });
};

App.prototype.detectVirtualAudioDevice = (cb, redetection) => {
    var command = ffmpeg("dummy");
    command.setFfmpegPath(path.join(process.cwd(), 'ffmpeg'));
    command.inputOptions([
        "-list_devices true",
        "-f dshow",
    ])
    command.outputOptions([])
        .on('start', commandLine => {
            console.log('Spawned Ffmpeg with command: ' + commandLine);
        })
        .on('error', (err, one, two) => {
            console.log('An error occurred: ' + err.message);
            if (one, two) {
                if (two.indexOf("virtual-audio-capturer") > -1) {
                    console.log("VIRTUAL DEVICE FOUND");
                    cb();
                } else if (redetection) {
                    let err = "Please re-run application and temporarily allow Administrator to install Virtual Audio Driver.";
                    console.log(err);
                    cb(err);
                } else {
                    wincmd.elevate("register_run_as_admin.bat", setTimeout.bind(this, this.detectVirtualAudioDevice.bind(this, cb, true), 2000));
                }
            }
        })
        .on('end', console.log.bind(this, 'end'))

    let ffstream = command.pipe();
};

App.prototype.ondeviceup = (host, name) => {
    if (this.devices.indexOf(host) == -1) {
        this.devices.push(host);
        console.info("ondeviceup", host, this.devices);
        this.emit("deviceFound", host, name);
    }
};

App.prototype.getIp = () => {
    var ip, alias = 0;
    var ifaces = os.networkInterfaces();

    for (var dev in ifaces) {
        ifaces[dev].forEach(details => {
            if (details.family === 'IPv4') {
                if (!/(loopback|vmware|internal|hamachi|vboxnet)/gi.test(dev + (alias ? ':' + alias : ''))) {
                    if (details.address.substring(0, 8) === '192.168.' ||
                        details.address.substring(0, 7) === '172.16.' ||
                        details.address.substring(0, 5) === '10.0.'
                    ) {
                        ip = details.address;
                        ++alias;
                    }
                }
            }
        });
    }

    return ip;
};

App.prototype.searchForDevices = () => {
    let browser = mdns.createBrowser(mdns.tcp('googlecast'));
    browser.on('ready', browser.discover);

    browser.on('update', service => {
        console.log('data:', service);
        console.log('found device "%s" at %s:%d', service.fullname.substring(0, service.fullname.indexOf("._googlecast")), service.addresses[0], service.port);
        this.ondeviceup(service.addresses[0], service.fullname.indexOf("._googlecast"));
        browser.stop();
    });
};

App.prototype.stream = host => {
    let client = new castv2Client();

    client.connect(host, () => {
        console.log('connected, launching app ...');

        client.launch(castv2DefaultMediaReceiver, (err, player) => {
            let media = {

                // Here you can plug an URL to any mp4, webm, mp3 or jpg file with the proper contentType.
                contentId: 'http://' + this.getIp() + ':' + this._server.address().port + '/',
                contentType: 'audio/mp3',
                streamType: 'BUFFERED', // or LIVE

                // Title and cover displayed while buffering
                metadata: {
                    type: 0,
                    metadataType: 0,
                    title: "Audio Caster",
                }
            };

            player.on('status', status => {
                console.log('status broadcast playerState=%s', status);
            });

            console.log('app "%s" launched, loading media %s ...', player, media);

            player.load(media, {
                autoplay: true
            }, (err, status) => {
                console.log('media loaded playerState=%s', status);
            });

        });

    });

    client.on('error', err => {
        console.log('Error: %s', err.message);
        client.close();
    });
};

var instance = new App;
instance.searchForDevices();

module.exports = instance;<|endoftext|>


<commit_before>'use strict'

import {BufferedProcess} from 'atom'
const extractionRegex = /Installing (.*?) to .* (.*)/

export function installPackages(dependencies, progressCallback) {
  return new Promise(function(resolve, reject) {
    const errors = []
    new BufferedProcess({
      command: atom.packages.getApmPath(),
      args: ['install'].concat(dependencies).concat(['--production', '--color', 'false']),
      options: {},
      stdout: function(contents) {
        const matches = extractionRegex.exec(contents)
        if (matches[2] === '✓' || matches[2] === 'done') {
          progressCallback(matches[1], true)
          atom.packages.activatePackage(matches[1])
        } else {
          progressCallback(matches[1], false)
          errors.push(contents)
        }
      },
      stderr: function(contents) {
        errors.push(contents)
      },
      exit: function() {
        if (errors.length) {
          const error = new Error('Error installing dependencies')
          error.stack = errors.join('')
          reject(error)
        } else resolve()
      }
    })
  })
}

export function packagesToInstall(name) {
  let packageInfo = atom.packages.getLoadedPackage(name)

  const toInstall = [], toEnable = [];
  (packageInfo ? (packageInfo.metadata['package-deps'] ? packageInfo.metadata['package-deps'] : []) : [])
    .forEach(function(name) {
      if (!window.__steelbrain_package_deps.has(name)) {
        window.__steelbrain_package_deps.add(name)
        if (atom.packages.resolvePackagePath(name)) {
          toEnable.push(name)
        } else {
          toInstall.push(name)
        }
      }
    })

  return {toInstall, toEnable}
}
<commit_msg>:new: Add dependenciesToInstall helper<commit_after>'use strict'

import {BufferedProcess} from 'atom'
const extractionRegex = /Installing (.*?) to .* (.*)/

export function installPackages(dependencies, progressCallback) {
  return new Promise(function(resolve, reject) {
    const errors = []
    new BufferedProcess({
      command: atom.packages.getApmPath(),
      args: ['install'].concat(dependencies).concat(['--production', '--color', 'false']),
      options: {},
      stdout: function(contents) {
        const matches = extractionRegex.exec(contents)
        if (matches[2] === '✓' || matches[2] === 'done') {
          progressCallback(matches[1], true)
          atom.packages.activatePackage(matches[1])
        } else {
          progressCallback(matches[1], false)
          errors.push(contents)
        }
      },
      stderr: function(contents) {
        errors.push(contents)
      },
      exit: function() {
        if (errors.length) {
          const error = new Error('Error installing dependencies')
          error.stack = errors.join('')
          reject(error)
        } else resolve()
      }
    })
  })
}

export function dependenciesToInstall(name) {
  const toReturn = []
  const packageModule = atom.packages.getLoadedPackage(name)
  const packageDependencies = packageModule && packageModule.metadata['package-deps']

  if (packageDependencies) {
    for (const name of packageDependencies) {
      if (!__steelbrain_package_deps.has(name)) {
        __steelbrain_package_deps.add(name)
        if (!atom.packages.resolvePackagePath(name)) {
          toReturn.push(name)
        }
      }
    }
  }

  return toReturn
}
<|endoftext|>


<commit_before>"use strict";

var v86util = v86util || {};

// pad string with spaces on the right
v86util.pads = function(str, len)
{
    str = str ? str + "" : "";

    while(str.length < len)
    {
        str = str + " ";
    }

    return str;
};

// pad string with zeros on the left
v86util.pad0 = function(str, len)
{
    str = str ? str + "" : "";

    while(str.length < len)
    {
        str = "0" + str;
    }

    return str;
};

/**
 * number to hex
 * @param {number} n
 * @param {number=} len
 * @return {string}
 */
function h(n, len)
{
    if(!n)
    {
        var str = "";
    }
    else
    {
        var str = n.toString(16);
    }

    return "0x" + v86util.pad0(str.toUpperCase(), len || 1);
}

if(typeof window !== "undefined" && window.crypto && window.crypto.getRandomValues)
{
    let rand_data = new Int32Array(1);

    v86util.has_rand_int = function()
    {
        return true;
    };

    v86util.get_rand_int = function()
    {
        window.crypto.getRandomValues(rand_data);
        return rand_data[0];
    };
}
else
{
    v86util.has_rand_int = function()
    {
        return false;
    };

    v86util.get_rand_int = function()
    {
        console.assert(false);
    };
}

/**
 * Synchronous access to ArrayBuffer
 * @constructor
 */
function SyncBuffer(buffer)
{
    this.buffer = buffer;
    this.byteLength = buffer.byteLength;
    this.onload = undefined;
    this.onprogress = undefined;
}

SyncBuffer.prototype.load = function()
{
    this.onload && this.onload({ buffer: this.buffer });
};

/**
 * @param {number} start
 * @param {number} len
 * @param {function(!Uint8Array)} fn
 */
SyncBuffer.prototype.get = function(start, len, fn)
{
    dbg_assert(start + len <= this.byteLength);
    fn(new Uint8Array(this.buffer, start, len));
};

/**
 * @param {number} start
 * @param {!Uint8Array} slice
 * @param {function()} fn
 */
SyncBuffer.prototype.set = function(start, slice, fn)
{
    dbg_assert(start + slice.byteLength <= this.byteLength);

    new Uint8Array(this.buffer, start, slice.byteLength).set(slice);
    fn();
};

/**
 * @param {function(!ArrayBuffer)} fn
 */
SyncBuffer.prototype.get_buffer = function(fn)
{
    fn(this.buffer);
};

(function()
{
    var int_log2_table = new Int8Array(256);

    for(var i = 0, b = -2; i < 256; i++)
    {
        if(!(i & i - 1))
            b++;

        int_log2_table[i] = b;
    }

    /**
     * calculate the integer logarithm base 2 of a byte
     * @param {number} x
     * @return {number}
     */
    v86util.int_log2_byte = function(x)
    {
        dbg_assert(x > 0);
        dbg_assert(x < 0x100);

        return int_log2_table[x];
    };

    /**
     * calculate the integer logarithm base 2
     * @param {number} x
     * @return {number}
     */
    v86util.int_log2 = function(x)
    {
        dbg_assert(x > 0);

        // http://jsperf.com/integer-log2/6
        var tt = x >>> 16;

        if(tt)
        {
            var t = tt >>> 8;
            if(t)
            {
                return 24 + int_log2_table[t];
            }
            else
            {
                return 16 + int_log2_table[tt];
            }
        }
        else
        {
            var t = x >>> 8;
            if(t)
            {
                return 8 + int_log2_table[t];
            }
            else
            {
                return int_log2_table[x];
            }
        }
    };
})();

/**
 * @constructor
 *
 * Queue wrapper around Uint8Array
 * Used by devices such as the PS2 controller
 */
function ByteQueue(size)
{
    var data = new Uint8Array(size),
        start,
        end;

    dbg_assert((size & size - 1) === 0);

    this.length = 0;

    this.push = function(item)
    {
        if(this.length === size)
        {
            // intentional overwrite
        }
        else
        {
            this.length++;
        }

        data[end] = item;
        end = end + 1 & size - 1;
    };

    this.shift = function()
    {
        if(!this.length)
        {
            return -1;
        }
        else
        {
            var item = data[start];

            start = start + 1 & size - 1;
            this.length--;

            return item;
        }
    };

    this.peek = function()
    {
        if(!this.length)
        {
            return -1;
        }
        else
        {
            return data[start];
        }
    };

    this.clear = function()
    {
        start = 0;
        end = 0;
        this.length = 0;
    };

    this.clear();
}

/**
 * Simple circular queue for logs
 *
 * @param {number} size
 * @constructor
 */
function CircularQueue(size)
{
    this.data = [];
    this.index = 0;
    this.size = size;
}

CircularQueue.prototype.add = function(item)
{
    this.data[this.index] = item;
    this.index = (this.index + 1) % this.size;
};

CircularQueue.prototype.toArray = function()
{
    return [].slice.call(this.data, this.index).concat([].slice.call(this.data, 0, this.index));
};

CircularQueue.prototype.clear = function()
{
    this.data = [];
    this.index = 0;
};

/**
 * @param {Array} new_data
 */
CircularQueue.prototype.set = function(new_data)
{
    this.data = new_data;
    this.index = 0;
};
<commit_msg>Protect against call from C<commit_after>"use strict";

var v86util = v86util || {};

// pad string with spaces on the right
v86util.pads = function(str, len)
{
    str = str ? str + "" : "";

    while(str.length < len)
    {
        str = str + " ";
    }

    return str;
};

// pad string with zeros on the left
v86util.pad0 = function(str, len)
{
    str = str ? str + "" : "";

    while(str.length < len)
    {
        str = "0" + str;
    }

    return str;
};

/**
 * number to hex
 * @param {number} n
 * @param {number=} len
 * @return {string}
 */
function h(n, len)
{
    if(!n)
    {
        var str = "";
    }
    else
    {
        var str = n.toString(16);
    }

    return "0x" + v86util.pad0(str.toUpperCase(), len || 1);
}

if(typeof window !== "undefined" && window.crypto && window.crypto.getRandomValues)
{
    let rand_data = new Int32Array(1);

    v86util.has_rand_int = function()
    {
        return true;
    };

    v86util.get_rand_int = function()
    {
        window.crypto.getRandomValues(rand_data);
        return rand_data[0];
    };
}
else
{
    v86util.has_rand_int = function()
    {
        return false;
    };

    v86util.get_rand_int = function()
    {
        console.assert(false);
    };
}

/**
 * Synchronous access to ArrayBuffer
 * @constructor
 */
function SyncBuffer(buffer)
{
    this.buffer = buffer;
    this.byteLength = buffer.byteLength;
    this.onload = undefined;
    this.onprogress = undefined;
}

SyncBuffer.prototype.load = function()
{
    this.onload && this.onload({ buffer: this.buffer });
};

/**
 * @param {number} start
 * @param {number} len
 * @param {function(!Uint8Array)} fn
 */
SyncBuffer.prototype.get = function(start, len, fn)
{
    dbg_assert(start + len <= this.byteLength);
    fn(new Uint8Array(this.buffer, start, len));
};

/**
 * @param {number} start
 * @param {!Uint8Array} slice
 * @param {function()} fn
 */
SyncBuffer.prototype.set = function(start, slice, fn)
{
    dbg_assert(start + slice.byteLength <= this.byteLength);

    new Uint8Array(this.buffer, start, slice.byteLength).set(slice);
    fn();
};

/**
 * @param {function(!ArrayBuffer)} fn
 */
SyncBuffer.prototype.get_buffer = function(fn)
{
    fn(this.buffer);
};

(function()
{
    var int_log2_table = new Int8Array(256);

    for(var i = 0, b = -2; i < 256; i++)
    {
        if(!(i & i - 1))
            b++;

        int_log2_table[i] = b;
    }

    /**
     * calculate the integer logarithm base 2 of a byte
     * @param {number} x
     * @return {number}
     */
    v86util.int_log2_byte = function(x)
    {
        dbg_assert(x > 0);
        dbg_assert(x < 0x100);

        return int_log2_table[x];
    };

    /**
     * calculate the integer logarithm base 2
     * @param {number} x
     * @return {number}
     */
    v86util.int_log2 = function(x)
    {
        x >>>= 0;
        dbg_assert(x > 0);

        // http://jsperf.com/integer-log2/6
        var tt = x >>> 16;

        if(tt)
        {
            var t = tt >>> 8;
            if(t)
            {
                return 24 + int_log2_table[t];
            }
            else
            {
                return 16 + int_log2_table[tt];
            }
        }
        else
        {
            var t = x >>> 8;
            if(t)
            {
                return 8 + int_log2_table[t];
            }
            else
            {
                return int_log2_table[x];
            }
        }
    };
})();

/**
 * @constructor
 *
 * Queue wrapper around Uint8Array
 * Used by devices such as the PS2 controller
 */
function ByteQueue(size)
{
    var data = new Uint8Array(size),
        start,
        end;

    dbg_assert((size & size - 1) === 0);

    this.length = 0;

    this.push = function(item)
    {
        if(this.length === size)
        {
            // intentional overwrite
        }
        else
        {
            this.length++;
        }

        data[end] = item;
        end = end + 1 & size - 1;
    };

    this.shift = function()
    {
        if(!this.length)
        {
            return -1;
        }
        else
        {
            var item = data[start];

            start = start + 1 & size - 1;
            this.length--;

            return item;
        }
    };

    this.peek = function()
    {
        if(!this.length)
        {
            return -1;
        }
        else
        {
            return data[start];
        }
    };

    this.clear = function()
    {
        start = 0;
        end = 0;
        this.length = 0;
    };

    this.clear();
}

/**
 * Simple circular queue for logs
 *
 * @param {number} size
 * @constructor
 */
function CircularQueue(size)
{
    this.data = [];
    this.index = 0;
    this.size = size;
}

CircularQueue.prototype.add = function(item)
{
    this.data[this.index] = item;
    this.index = (this.index + 1) % this.size;
};

CircularQueue.prototype.toArray = function()
{
    return [].slice.call(this.data, this.index).concat([].slice.call(this.data, 0, this.index));
};

CircularQueue.prototype.clear = function()
{
    this.data = [];
    this.index = 0;
};

/**
 * @param {Array} new_data
 */
CircularQueue.prototype.set = function(new_data)
{
    this.data = new_data;
    this.index = 0;
};
<|endoftext|>


<commit_before>import bluebird from 'bluebird'
import fs from 'fs'
import path from 'path'
import structure from './structure'
import mkdirp from 'mkdir-p'

const ROOT_DIR = path.join(__dirname)
const TEMPLATES_DIR = path.join(ROOT_DIR, 'templates')
const FOLDERS = ['controllers', 'models', 'helpers', 'middlewares']
const mkdirAsync = bluebird.promisify(mkdirp)
const readFile = bluebird.promisify(fs.readFile)
const writeFile = bluebird.promisify(fs.writeFile)

const createFiles = (dir) => {
  const fromDest = []
  for (let key in structure) {
    if (key === 'files') {
      fromDest.push(...structure.files.map((file) => ({ _from: `${TEMPLATES_DIR}/${key}/${file}`, to: `${dir}/${file}` })))
    } else {
      if (key === 'src') {
        fromDest.push(...structure.src.map((file) => ({ _from: `${TEMPLATES_DIR}/${key}/${file}`, to: `${dir}/${key}/${file}` })))
      } else {
        fromDest.push(...structure[key].map((file) => ({ _from: `${TEMPLATES_DIR}/${key}/${file}`, to: `${dir}/src/${key}/${file}` })))
      }
    }
  }
  bluebird.all(fromDest.map((file) => readFile(file._from).then((content) => writeFile(`${file.to}`, content).catch((err) => console.log(err)))))
}

// let fileList = files.map((file) => ({ _from: `${TEMPLATES_DIR}/files/${file}`, to: `${dir}/src/${file}` }))

export const buildFoldersAsync = (base) =>
  bluebird.all(FOLDERS.map((i) => `${base}/src/${i}`).map((folder) => mkdirAsync(folder).then(console.log(`${folder} creado!`))))
  .then(() => createFiles(base))
  .catch((err) => console.log(err))
<commit_msg>clean code<commit_after>import bluebird from 'bluebird'
import fs from 'fs'
import path from 'path'
import structure from './structure'
import mkdirp from 'mkdir-p'

const ROOT_DIR = path.join(__dirname)
const TEMPLATES_DIR = path.join(ROOT_DIR, 'templates')
const FOLDERS = ['controllers', 'models', 'helpers', 'middlewares']
const mkdirAsync = bluebird.promisify(mkdirp)
const readFile = bluebird.promisify(fs.readFile)
const writeFile = bluebird.promisify(fs.writeFile)

const createFiles = (dir) => {
  const fromDest = []
  for (let key in structure) {
    if (key === 'files') {
      fromDest.push(...structure.files.map((file) => ({ _from: `${TEMPLATES_DIR}/${key}/${file}`, to: `${dir}/${file}` })))
    } else {
      if (key === 'src') {
        fromDest.push(...structure.src.map((file) => ({ _from: `${TEMPLATES_DIR}/${key}/${file}`, to: `${dir}/${key}/${file}` })))
      } else {
        fromDest.push(...structure[key].map((file) => ({ _from: `${TEMPLATES_DIR}/${key}/${file}`, to: `${dir}/src/${key}/${file}` })))
      }
    }
  }
  bluebird.all(fromDest.map((file) => readFile(file._from).then((content) => writeFile(`${file.to}`, content).catch((err) => console.log(err)))))
}

export const buildFoldersAsync = (base) =>
  bluebird.all(FOLDERS.map((i) => `${base}/src/${i}`).map((folder) => mkdirAsync(folder).then(console.log(`${folder} creado!`))))
  .then(() => createFiles(base))
  .catch((err) => console.log(err))
<|endoftext|>


<commit_before>// Copyright 2014 Joyent, Inc.  All rights reserved.

var util = require('util');
var RestError = require('restify').RestError;

var sprintf = util.format;

function MahiError(obj) {
    obj.constructorOpt = this.constructor;
    RestError.call(this, obj);
}
util.inherits(MahiError, RestError);
MahiError.prototype.name = 'MahiError';

function AccountBlockedError(account) {
    MahiError.call(this, {
        restCode: 'AccountBlocked',
        statusCode: 403,
        message: 'Account ' + account + ' is blocked.'
    });
    this.account = account;
}
util.inherits(AccountBlockedError, MahiError);
AccountBlockedError.prototype.name = 'AccountBlocked';

function KeyDoesNotExistError(keyId, account, user) {
    var path = user ? sprintf('/%s/%s/keys/%s', account, user, keyId) :
                      sprintf('/%s/keys/%s', account, keyId);
    MahiError.call(this, {
        restCode: 'KeyDoesNotExist',
        statusCode: 404,
        message: path + ' does not exist'
    });
}
util.inherits(KeyDoesNotExistError, MahiError);
KeyDoesNotExistError.prototype.name = 'KeyDoesNotExist';

function InvalidSignatureError() {
    MahiError.call(this, {
        restCode: 'InvalidSignature',
        statusCode: 403,
        message: 'The signature we calculated does not match the one ' +
            'you sent'
    });
}
util.inherits(InvalidSignatureError, MahiError);
InvalidSignatureError.prototype.name = 'InvalidSignature';

function NoMatchingRoleTagError() {
    MahiError.call(this, {
        restCode: 'NoMatchingRoleTag',
        statusCode: 403,
        message: 'None of your active roles are present on the resource.'
    });
}
util.inherits(NoMatchingRoleTagError, MahiError);
NoMatchingRoleTagError.prototype.name = 'NoMatchingRoleTag';

function RulesEvaluationFailedError() {
    MahiError.call(this, {
        restCode: 'RulesEvaluationFailed',
        statusCode: 403,
        message: 'No rules allowed access'
    });
}
util.inherits(RulesEvaluationFailedError, MahiError);
RulesEvaluationFailedError.prototype.name = 'RulesEvaluationFailed';

module.exports = {
    AccountBlockedError: AccountBlockedError,
    InvalidSignatureError: InvalidSignatureError,
    KeyDoesNotExistError: KeyDoesNotExistError,
    MahiError: MahiError,
    NoMatchingRoleTagError: NoMatchingRoleTagError,
    RulesEvaluationFailedError: RulesEvaluationFailedError
};
<commit_msg>MANTA-2307 assuming an invalid role results in an internal error<commit_after>// Copyright 2014 Joyent, Inc.  All rights reserved.

var util = require('util');
var RestError = require('restify').RestError;

var sprintf = util.format;

function MahiError(obj) {
    obj.constructorOpt = this.constructor;
    RestError.call(this, obj);
}
util.inherits(MahiError, RestError);
MahiError.prototype.name = 'MahiError';

function AccountBlockedError(account) {
    MahiError.call(this, {
        restCode: 'AccountBlocked',
        statusCode: 403,
        message: 'Account ' + account + ' is blocked.'
    });
    this.account = account;
}
util.inherits(AccountBlockedError, MahiError);
AccountBlockedError.prototype.name = 'AccountBlocked';

function InvalidRoleError(r) {
    MahiError.call(this, {
        restCode: 'InvalidRole',
        statusCode: 403,
        message: 'Role "' + r + '" is invalid.',
        role: r
    });
}
util.inherits(InvalidRoleError, MahiError);
InvalidRoleError.prototype.name = 'InvalidRole';

function InvalidSignatureError() {
    MahiError.call(this, {
        restCode: 'InvalidSignature',
        statusCode: 403,
        message: 'The signature we calculated does not match the one ' +
            'you sent'
    });
}
util.inherits(InvalidSignatureError, MahiError);
InvalidSignatureError.prototype.name = 'InvalidSignature';

function KeyDoesNotExistError(keyId, account, user) {
    var path = user ? sprintf('/%s/%s/keys/%s', account, user, keyId) :
                      sprintf('/%s/keys/%s', account, keyId);
    MahiError.call(this, {
        restCode: 'KeyDoesNotExist',
        statusCode: 404,
        message: path + ' does not exist'
    });
}
util.inherits(KeyDoesNotExistError, MahiError);
KeyDoesNotExistError.prototype.name = 'KeyDoesNotExist';

function NoMatchingRoleTagError() {
    MahiError.call(this, {
        restCode: 'NoMatchingRoleTag',
        statusCode: 403,
        message: 'None of your active roles are present on the resource.'
    });
}
util.inherits(NoMatchingRoleTagError, MahiError);
NoMatchingRoleTagError.prototype.name = 'NoMatchingRoleTag';

function RulesEvaluationFailedError() {
    MahiError.call(this, {
        restCode: 'RulesEvaluationFailed',
        statusCode: 403,
        message: 'No rules allowed access'
    });
}
util.inherits(RulesEvaluationFailedError, MahiError);
RulesEvaluationFailedError.prototype.name = 'RulesEvaluationFailed';

module.exports = {
    AccountBlockedError: AccountBlockedError,
    InvalidRoleError: InvalidRoleError,
    InvalidSignatureError: InvalidSignatureError,
    KeyDoesNotExistError: KeyDoesNotExistError,
    MahiError: MahiError,
    NoMatchingRoleTagError: NoMatchingRoleTagError,
    RulesEvaluationFailedError: RulesEvaluationFailedError
};
<|endoftext|>


<commit_before>'use strict'

var escapeXMLTable = {
  '&': '&',
  '<': '<',
  '>': '>',
  '"': '"',
  '\'': '''
}

function escapeXMLReplace (match) {
  return escapeXMLTable[match]
}

var unescapeXMLTable = {
  '&': '&',
  '&': '&',
  '<': '<',
  '<': '<',
  '>': '>',
  '>': '>',
  '"': '"',
  '"': '"',
  ''': "'",
  ''': "'"
}

function unescapeXMLReplace (match) {
  return unescapeXMLTable[match]
}

exports.escapeXML = function escapeXML (s) {
  return s.replace(/\&|<|>|"|'/g, escapeXMLReplace)
}

exports.unescapeXML = function unescapeXML (s) {
  return s
        .replace(/\&(amp|#38|lt|#60|gt|#62|quot|#34|apos|#39);/g, unescapeXMLReplace)
}

exports.escapeXMLText = function escapeXMLText (s) {
  return s.replace(/\&|<|>/g, escapeXMLReplace)
}

exports.unescapeXMLText = function unescapeXMLText (s) {
  return s
    .replace(/\&(amp|#38|lt|#60|gt|#62);/g, unescapeXMLReplace)
}
<commit_msg>fix lib/escape indent<commit_after>'use strict'

var escapeXMLTable = {
  '&': '&',
  '<': '<',
  '>': '>',
  '"': '"',
  '\'': '''
}

function escapeXMLReplace (match) {
  return escapeXMLTable[match]
}

var unescapeXMLTable = {
  '&': '&',
  '&': '&',
  '<': '<',
  '<': '<',
  '>': '>',
  '>': '>',
  '"': '"',
  '"': '"',
  ''': "'",
  ''': "'"
}

function unescapeXMLReplace (match) {
  return unescapeXMLTable[match]
}

exports.escapeXML = function escapeXML (s) {
  return s.replace(/\&|<|>|"|'/g, escapeXMLReplace)
}

exports.unescapeXML = function unescapeXML (s) {
  return s.replace(/\&(amp|#38|lt|#60|gt|#62|quot|#34|apos|#39);/g, unescapeXMLReplace)
}

exports.escapeXMLText = function escapeXMLText (s) {
  return s.replace(/\&|<|>/g, escapeXMLReplace)
}

exports.unescapeXMLText = function unescapeXMLText (s) {
  return s.replace(/\&(amp|#38|lt|#60|gt|#62);/g, unescapeXMLReplace)
}
<|endoftext|>