<commit_before>/*
 * logs.js: Commands related to user resources
 *
 * (C) 2010, Nodejitsu Inc.
 *
 */

var jitsu = require('../../jitsu');

var logs = exports;

logs.usage = [
  'The `jitsu logs` commands allow you to read the logs related to your app.',
  'The default number of lines to show is 10.',
  '',
  'Example usages:',
  'jitsu logs all',
  'jitsu logs all <number of lines to show>',
  'jitsu logs app <app name>',
  'jitsu logs app <app name> <number of lines to show>'
];

//
// ### function all (callback)
// #### @callback {function} Continuation to pass control to when complete.
// Queries the log API and retrieves the logs for all of the user's apps
//
logs.all = function (amount, callback) {
  if (!amount) {
    amount = 10;
  }

  jitsu.logs.byUser(jitsu.config.get('username'), amount, function (err, apps) {
    if (err) {
      return callback(err);
    }

    if (apps.length === 0) {
      jitsu.log.warn('No logs for ' + jitsu.config.get('username').magenta + ' from timespan');
      return callback();
    }

    function sortLength (lname, rname) {
      var llength = apps[lname].data.length,
          rlength = apps[rname].data.length;

      if (llength === rlength) {
        return 0;
      }

      return llength > rlength ? 1 : -1;
    }

    Object.keys(apps).sort(sortLength).forEach(function (app) {
      putLogs(apps[app], app, amount, true);
    });

    callback();
  });
};

logs.all.usage = [
  'Print the logs from all applications. The default number of',
  'lines to show is 10.',
  'jits logs all <number of lines to show>',
  '',
  'Example usage:',
  'jitsu logs all',
  'jitsu logs all 5'
];

//
// ### function app (appName, callback)
// #### @appName {string} the application to get the logs for
// #### @callback {function} Continuation to pass control to when complete.
// Queries the log API and retrieves the logs for the specified application
//
logs.app = function (appName, amount, callback) {
  //
  // This is defined so that it can get called once all the arguments are
  // sorted out.
  //
  function byApp(appName, amount, callback) {
    jitsu.logs.byApp(appName, amount, function (err, results) {
      if (err) {
        return callback(err);
      }
      putLogs(results, appName, amount);
      callback();
    });
  }

  function getAppName(callback) {
    jitsu.package.read(process.cwd(), function (err, pkg) {
      if (!err) {
        return callback(null, pkg.name);
      }

      jitsu.commands.commands.apps.list(function (err) {
        if (err) {
          return callback(err);
        }

        jitsu.log.error('You need to provide an app name');
        jitsu.prompt.get(["app name"], function (err, result) {
          if (err) {
            jitsu.log.error('Prompt error:');
            return callback(err);
          }

          // Plug in the app name and go
          appName = result["app name"];
          callback(null, appName);
        });
      });
    });
  }

  amount = amount || 100;

  if (!appName) {
    return getAppName(function (err, name) {
      return err ? callback(err) : byApp(name, 100, callback);
    });
  }

  byApp(appName, amount, callback);
}

logs.app.usage = [
  'Print the logs from specified application. The default number of',
  'lines to show is 10.',
  'jits logs app <app name> <number of lines to show>',
  '',
  'Example usage:',
  'jitsu logs app test',
  'jitsu logs app test 40'
];

//
// ### function putLogs (results, appName, amount, showApp)
// #### @results {Object} Logs object to output.
// #### @appName {string} App name associated with the log text.
// #### @showApp {boolean} Value indicating if the app name should be output.
// Parses, formats, and outputs the specified `results` to the user.
//
function putLogs (results, appName, amount, showApp) {
  results.data = results.data.filter(function (item) {
    return item.json && item.json.hasOwnProperty('message');
  });

  if (results.data.length === 0) {
    return jitsu.log.warn('No logs for ' + appName.magenta + ' in specified timespan');
  }

  var loglength = jitsu.config.get('loglength'),
      logged = 0;

  results.data.reverse().forEach(function (datum) {
    if (datum.json && datum.json.message != null) {
      datum.json.message.split('\n').forEach(function (line) {
        var prefix = showApp
          ? datum.timestamp.grey + ' ' + datum.json.app.magenta + ': '
          : datum.timestamp.grey + ': '

        if (line.length > 0 && logged < amount) {
          if (line.length > loglength) {
            line = line.substr(0, loglength - 3) + '...';
          }

          jitsu.log.data(prefix + line);
          logged += 1;
        }
      });
    }
  });
}
<commit_msg>[fix] Don't filter log events on the client, let the server do this. Also disabled truncated logging events.<commit_after>/*
 * logs.js: Commands related to user resources
 *
 * (C) 2010, Nodejitsu Inc.
 *
 */

var jitsu = require('../../jitsu');

var logs = exports;

logs.usage = [
  'The `jitsu logs` commands allow you to read the logs related to your app.',
  'The default number of lines to show is 10.',
  '',
  'Example usages:',
  'jitsu logs all',
  'jitsu logs all <number of lines to show>',
  'jitsu logs app <app name>',
  'jitsu logs app <app name> <number of lines to show>'
];

//
// ### function all (callback)
// #### @callback {function} Continuation to pass control to when complete.
// Queries the log API and retrieves the logs for all of the user's apps
//
logs.all = function (amount, callback) {
  if (!amount) {
    amount = 10;
  }

  jitsu.logs.byUser(jitsu.config.get('username'), amount, function (err, apps) {
    if (err) {
      return callback(err);
    }

    if (apps.length === 0) {
      jitsu.log.warn('No logs for ' + jitsu.config.get('username').magenta + ' from timespan');
      return callback();
    }

    function sortLength (lname, rname) {
      var llength = apps[lname].data.length,
          rlength = apps[rname].data.length;

      if (llength === rlength) {
        return 0;
      }

      return llength > rlength ? 1 : -1;
    }

    Object.keys(apps).sort(sortLength).forEach(function (app) {
      putLogs(apps[app], app, amount, true);
    });

    callback();
  });
};

logs.all.usage = [
  'Print the logs from all applications. The default number of',
  'lines to show is 10.',
  'jits logs all <number of lines to show>',
  '',
  'Example usage:',
  'jitsu logs all',
  'jitsu logs all 5'
];

//
// ### function app (appName, callback)
// #### @appName {string} the application to get the logs for
// #### @callback {function} Continuation to pass control to when complete.
// Queries the log API and retrieves the logs for the specified application
//
logs.app = function (appName, amount, callback) {
  //
  // This is defined so that it can get called once all the arguments are
  // sorted out.
  //
  function byApp(appName, amount, callback) {
    jitsu.logs.byApp(appName, amount, function (err, results) {
      if (err) {
        return callback(err);
      }
      putLogs(results, appName, amount);
      callback();
    });
  }

  function getAppName(callback) {
    jitsu.package.read(process.cwd(), function (err, pkg) {
      if (!err) {
        return callback(null, pkg.name);
      }

      jitsu.commands.commands.apps.list(function (err) {
        if (err) {
          return callback(err);
        }

        jitsu.log.error('You need to provide an app name');
        jitsu.prompt.get(["app name"], function (err, result) {
          if (err) {
            jitsu.log.error('Prompt error:');
            return callback(err);
          }

          // Plug in the app name and go
          appName = result["app name"];
          callback(null, appName);
        });
      });
    });
  }

  amount = amount || 100;

  if (!appName) {
    return getAppName(function (err, name) {
      return err ? callback(err) : byApp(name, 100, callback);
    });
  }

  byApp(appName, amount, callback);
}

logs.app.usage = [
  'Print the logs from specified application. The default number of',
  'lines to show is 10.',
  'jits logs app <app name> <number of lines to show>',
  '',
  'Example usage:',
  'jitsu logs app test',
  'jitsu logs app test 40'
];

//
// ### function putLogs (results, appName, amount, showApp)
// #### @results {Object} Logs object to output.
// #### @appName {string} App name associated with the log text.
// #### @showApp {boolean} Value indicating if the app name should be output.
// Parses, formats, and outputs the specified `results` to the user.
//
function putLogs (results, appName, amount, showApp) {
  results.data = results.data.filter(function (item) {
    return item.json && item.json.hasOwnProperty('message');
  });

  if (results.data.length === 0) {
    return jitsu.log.warn('No logs for ' + appName.magenta + ' in specified timespan');
  }

  var logLength = jitsu.config.get('loglength'),
      logged = 0;

  results.data.reverse().forEach(function (datum) {
    if (datum.json && datum.json.message != null) {
      datum.json.message.split('\n').forEach(function (line) {
        //
        //  Remark: I commented out this line, because we really
        //          shouldn't truncate logs by default, it's confusing
        //
          /*
            if (line.length > logLength) {
              line = line.substr(0, logLength - 3) + '...';
            }
          */
        var prefix = showApp
          ? datum.timestamp.grey + ' ' + datum.json.app.magenta + ': '
          : datum.timestamp.grey + ': '
          jitsu.log.data(prefix + line);
      });
    }
  });
}
<|endoftext|>


<commit_before>/* DOM Level2 Events implemented as described here:
 *
 * http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html
 *
 */
var core = require("./core").dom.level2.core,
    sys = require("sys");

var events = {};

events.EventException = function() {
    if (arguments.length > 0) {
        this._code = arguments[0];
    } else {
        this._code = 0;
    }
    if (arguments.length > 1) {
        this._message = arguments[1];
    } else {
        this._message = "Unspecified event type";
    }
    Error.call(this, this._message);
    if (Error.captureStackTrace) {
        Error.captureStackTrace(this, events.EventException);
    }
};
events.EventException.prototype = {
  get UNSPECIFIED_EVENT_TYPE_ERR() { return 0; },
  get code() { return this._code;}
};
events.EventException.prototype.__proto__ = Error.prototype;

events.Event = function(eventType) {
    this._eventType = eventType;
    this._type = null;
    this._bubbles = null;
    this._cancelable = null;
    this._target = null;
    this._currentTarget = null;
    this._eventPhase = null;
    this._timeStamp = null;
    this._preventDefault = false;
    this._stopPropagation = false;
};
events.Event.prototype = {
    initEvent: function(type, bubbles, cancelable) {
        this._type = type;
        this._bubbles = bubbles;
        this._cancelable = cancelable;
    },
    preventDefault: function() {
        if (this._cancelable) {
            this._preventDefault = true;
        }
    },
    stopPropagation: function() {
        this._stopPropagation = true;
    },
    get CAPTURING_PHASE() { return 1; },
    get AT_TARGET() { return 2; },
    get BUBBLING_PHASE() { return 3; },
    get eventType() { return this._eventType; },
    get type() { return this._type; },
    get bubbles() { return this._bubbles; },
    get cancelable() { return this._cancelable; },
    get target() { return this._target; },
    get currentTarget() { return this._currentTarget; },
    get eventPhase() { return this._eventPhase; },
    get timeStamp() { return this._timeStamp; }
};

events.HTMLEvent = function(eventType) {
    events.Event.call(this, eventType);
};
events.HTMLEvent.prototype.__proto__ = events.Event.prototype;

events.UIEvent = function(eventType) {
    events.Event.call(this, eventType);
    this.view = null;
    this.detail = null;
};
events.UIEvent.prototype = {
    initUIEvent: function(type, bubbles, cancelable, view, detail) {
        this.initEvent(type, bubbles, cancelable);
        this.view = view;
        this.detail = detail;
    },
};
events.UIEvent.prototype.__proto__ = events.Event.prototype;

events.MouseEvent = function(eventType) {
    events.UIEvent.call(this, eventType);
    this.screenX = null;
    this.screenY = null;
    this.clientX = null;
    this.clientY = null;
    this.ctrlKey = null;
    this.shiftKey = null;
    this.altKey = null;
    this.metaKey = null;
    this.button = null;
    this.relatedTarget = null;
};
events.MouseEvent.prototype = {
    initMouseEvent:   function(type,
                               bubbles,
                               cancelable,
                               view,
                               detail,
                               screenX,
                               screenY,
                               clientX,
                               clientY,
                               ctrlKey,
                               altKey,
                               shiftKey,
                               metaKey,
                               button,
                               relatedTarget) {
        this.initUIEvent(type, bubbles, cancelable, view, detail);
        this.screenX  = screenX
        this.screenY  = screenY
        this.clientX  = clientX
        this.clientY  = clientY
        this.ctrlKey  = ctrlKey
        this.shiftKey  = shiftKey
        this.altKey  = altKey
        this.metaKey  = metaKey
        this.button  = button
        this.relatedTarget  = relatedTarget
    }
};
events.MouseEvent.prototype.__proto__ = events.UIEvent.prototype;

events.MutationEvent = function(eventType) {
    events.Event.call(this, eventType);
    this.relatedNode = null;
    this.prevValue = null;
    this.newValue = null;
    this.attrName = null;
    this.attrChange = null;
};
events.MutationEvent.prototype = {
    initMutationEvent:   function(type,
                                  bubbles,
                                  cancelable,
                                  relatedNode,
                                  prevValue,
                                  newValue,
                                  attrName,
                                  attrChange) {
        this.initEvent(type, bubbles, cancelable);
        this.relatedNode = relatedNode;
        this.prevValue = prevValue;
        this.newValue = newValue;
        this.attrName = attrName;
        this.attrChange = attrChange;
    },
    get MODIFICATION() { return 1; },
    get ADDITION() { return 2; },
    get REMOVAL() { return 3; },
};
events.MutationEvent.prototype.__proto__ = events.Event.prototype;

events.EventTarget = function() {};
events.EventTarget.prototype = {
    addEventListener: function(type, listener, capturing) {
        this._listeners = this._listeners || {};
        var listeners = this._listeners[type] || {};
        capturing = (capturing === true);
        var capturingListeners = listeners[capturing] || [];
        for (var i=0; i < capturingListeners.length; i++) {
            if (capturingListeners[i] === listener) {
                return;
            }
        }
        capturingListeners.push(listener);
        listeners[capturing] = capturingListeners;
        this._listeners[type] = listeners;
    },

    removeEventListener: function(type, listener, capturing) {
        var listeners  = this._listeners && this._listeners[type];
        if (!listeners) return;
        var capturingListeners = listeners[(capturing === true)];
        if (!capturingListeners) return;
        for (var i=0; i < capturingListeners.length; i++) {
            if (capturingListeners[i] === listener) {
                capturingListeners.splice(i, 1);
                return;
            }
        }
    },

    dispatchEvent: function(event) {
        if (event == null) {
            throw new events.EventException(0, "Null event");
        }
        if (event._type == null || event._type == "") {
            throw new events.EventException(0, "Uninitialized event");
        }

        var nextTarget = null;
        var targetList = [];

        function _getListeners(target, type, capturing) {
            var listeners = target._listeners
                    && target._listeners[type]
                    && target._listeners[type][capturing];
            if (listeners && listeners.length) {
                return listeners;
            }
            return [];
        }

        function _dispatchEvent(event, iterator, capturing) {
            var target = iterator();
            while (target && !event._stopPropagation) {
                listeners = _getListeners(target, event._type, capturing);
                for (var y = 0; y < listeners.length; y++) {
                    event._currentTarget = target;
                    try {
                        listeners[y].call(target, event);
                    } catch (e) {
                        sys.log("Listener "
                            + sys.inspect(listeners[y])
                            + "\n\n on target \n\n"
                            + sys.inspect(target)
                            + "\n\n threw error \n\n"
                            + sys.inspect(e.stack)
                            + "\n\n handling event \n\n"
                            + sys.inspect(event));
                    }
                }
                target = iterator();
            }
            return !event._stopPropagation;
        }

        event._target = this;

        //per the spec we gather the list of targets first to ensure
        //against dom modifications during actual event dispatch
        nextTarget = this.parentNode;
        while (nextTarget) {
            targetList.push(nextTarget);
            nextTarget = nextTarget.parentNode;
        }

        var i = targetList.length,
        iterator = function() { return i >=0 ? targetList[--i] : null };

        event._eventPhase = event.CAPTURING_PHASE;
        if (!_dispatchEvent(event, iterator, true)) return event._preventDefault;

        i = 1;
        iterator = function() { return i-- ? event._target : null };
        event._eventPhase = event.AT_TARGET;
        if (!_dispatchEvent(event, iterator, false)) return event._preventDefault;

        var traditionalHandler = this["on" + event._type];
        if (traditionalHandler) {
          try {
            if (traditionalHandler(event) === false) {
              return true;
            }
          }
          catch (e) {
            sys.log("The on" + event._type + " handler"
              + "\n\n on target \n\n"
              + sys.inspect(this)
              + "\n\n threw error \n\n"
              + sys.inspect(e)
              + "\n\n handling event \n\n"
              + sys.inspect(event));
          }
        }

        if (event._bubbles && !event._stopPropagation) {
            i = 0;
            iterator = function() { return i < targetList.length ? targetList[i++] : null };
            event._eventPhase = event.BUBBLING_PHASE;
            _dispatchEvent(event, iterator, false);
        }

        return event._preventDefault;
    }

};

core.Node.prototype.__proto__ = events.EventTarget.prototype;

function getDocument(el) {
  return el.nodeType == 9 ? el : el.ownerDocument;
}

function mutationEventsEnabled(el) {
  return (el.nodeType == 1 || el.nodeType == 9); //TODO getDocument(el).isSupported('MutationEvents', '2.0');
}

function advise(clazz, method, advice) {
    var proto = clazz.prototype,
        impl = proto[method];

  proto[method] = function() {
    var args = Array.prototype.slice.call(arguments);
    var ret = impl.apply(this, arguments);
    args.unshift(ret);
    return advice.apply(this, args) || ret;
  };
}

function adviseBefore(clazz, method, advice) {
  var proto = clazz.prototype,
      impl = proto[method];

  proto[method] = function() {
    advice.apply(this, arguments);
    return impl.apply(this, arguments);
  };
}

function dispatchInsertionEvent(append) {
  return function(ret, newChild, refChild) {
    if ((append || refChild != null) && mutationEventsEnabled(this)) {
      var doc = getDocument(this),
          ev = doc.createEvent("MutationEvents");

      ev.initMutationEvent("DOMNodeInserted", true, false, this, null, null, null, null);
      newChild.dispatchEvent(ev);
      if (this.nodeType == 9 || this._attachedToDocument) {
        ev = doc.createEvent("MutationEvents");
        ev.initMutationEvent("DOMNodeInsertedIntoDocument", false, false, null, null, null, null, null);
        core.visitTree(newChild, function(el) {
          if (el.nodeType == 1) {
            el.dispatchEvent(ev);
            el._attachedToDocument = true;
          }
        });
      }
    }
  };
}

function dispatchRemovalEvent(oldChild) {
  if (mutationEventsEnabled(this)) {
    var doc = getDocument(this),
        ev = doc.createEvent("MutationEvents");

    ev.initMutationEvent("DOMNodeRemoved", true, false, this, null, null, null, null);
    oldChild.dispatchEvent(ev);

    ev = doc.createEvent("MutationEvents");
    ev.initMutationEvent("DOMNodeRemovedFromDocument", false, false, null, null, null, null, null);
    core.visitTree(oldChild, function(el) {
      if (el.nodeType == 1) {
        el.dispatchEvent(ev);
        el._attachedToDocument = false;
      }
    });
  }
}

function dispatchAttrEvent(change, arg) {
  return function(ret) {
    var target = this._parentNode,
        node = arguments[arg];

    if (mutationEventsEnabled(target)) {
      var doc = target.ownerDocument,
          attrChange = events.MutationEvent.prototype[change],
          prevVal = arg == 0 ? node.value : null,
          newVal = arg == 1 ? node.value : null,
          ev = doc.createEvent("MutationEvents");

      ev.initMutationEvent("DOMAttrModified", true, false, target, prevVal, newVal, node.name, attrChange);
      target.dispatchEvent(ev);
    }
  }
}

advise(core.Node, 'insertBefore', dispatchInsertionEvent());
advise(core.Node, 'appendChild', dispatchInsertionEvent(true));
adviseBefore(core.Node, 'removeChild', dispatchRemovalEvent);

advise(core.AttrNodeMap, 'removeNamedItem', dispatchAttrEvent('REMOVAL', 0));
advise(core.AttrNodeMap, 'setNamedItem', dispatchAttrEvent('ADDITION', 1));

core.Document.prototype.createEvent = function(eventType) {
    switch (eventType) {
        case "MutationEvents": return new events.MutationEvent(eventType);
        case "UIEvents": return new events.UIEvent(eventType);
        case "MouseEvents": return new events.MouseEvent(eventType);
        case "HTMLEvents": return new events.HTMLEvent(eventType);
    }
    return new events.Event(eventType);
};

exports.dom =
{
  level2 : {
    core   : core,
    events : events
  }
};

<commit_msg>Performance tuning: Converted closures into static functions on the constructor to avoid LazyCompilation upon each invocation.<commit_after>/* DOM Level2 Events implemented as described here:
 *
 * http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html
 *
 */
var core = require("./core").dom.level2.core,
    sys = require("sys");

var events = {};

events.EventException = function() {
    if (arguments.length > 0) {
        this._code = arguments[0];
    } else {
        this._code = 0;
    }
    if (arguments.length > 1) {
        this._message = arguments[1];
    } else {
        this._message = "Unspecified event type";
    }
    Error.call(this, this._message);
    if (Error.captureStackTrace) {
        Error.captureStackTrace(this, events.EventException);
    }
};
events.EventException.prototype = {
  get UNSPECIFIED_EVENT_TYPE_ERR() { return 0; },
  get code() { return this._code;}
};
events.EventException.prototype.__proto__ = Error.prototype;

events.Event = function(eventType) {
    this._eventType = eventType;
    this._type = null;
    this._bubbles = null;
    this._cancelable = null;
    this._target = null;
    this._currentTarget = null;
    this._eventPhase = null;
    this._timeStamp = null;
    this._preventDefault = false;
    this._stopPropagation = false;
};
events.Event.prototype = {
    initEvent: function(type, bubbles, cancelable) {
        this._type = type;
        this._bubbles = bubbles;
        this._cancelable = cancelable;
    },
    preventDefault: function() {
        if (this._cancelable) {
            this._preventDefault = true;
        }
    },
    stopPropagation: function() {
        this._stopPropagation = true;
    },
    get CAPTURING_PHASE() { return 1; },
    get AT_TARGET() { return 2; },
    get BUBBLING_PHASE() { return 3; },
    get eventType() { return this._eventType; },
    get type() { return this._type; },
    get bubbles() { return this._bubbles; },
    get cancelable() { return this._cancelable; },
    get target() { return this._target; },
    get currentTarget() { return this._currentTarget; },
    get eventPhase() { return this._eventPhase; },
    get timeStamp() { return this._timeStamp; }
};

events.HTMLEvent = function(eventType) {
    events.Event.call(this, eventType);
};
events.HTMLEvent.prototype.__proto__ = events.Event.prototype;

events.UIEvent = function(eventType) {
    events.Event.call(this, eventType);
    this.view = null;
    this.detail = null;
};
events.UIEvent.prototype = {
    initUIEvent: function(type, bubbles, cancelable, view, detail) {
        this.initEvent(type, bubbles, cancelable);
        this.view = view;
        this.detail = detail;
    },
};
events.UIEvent.prototype.__proto__ = events.Event.prototype;

events.MouseEvent = function(eventType) {
    events.UIEvent.call(this, eventType);
    this.screenX = null;
    this.screenY = null;
    this.clientX = null;
    this.clientY = null;
    this.ctrlKey = null;
    this.shiftKey = null;
    this.altKey = null;
    this.metaKey = null;
    this.button = null;
    this.relatedTarget = null;
};
events.MouseEvent.prototype = {
    initMouseEvent:   function(type,
                               bubbles,
                               cancelable,
                               view,
                               detail,
                               screenX,
                               screenY,
                               clientX,
                               clientY,
                               ctrlKey,
                               altKey,
                               shiftKey,
                               metaKey,
                               button,
                               relatedTarget) {
        this.initUIEvent(type, bubbles, cancelable, view, detail);
        this.screenX  = screenX
        this.screenY  = screenY
        this.clientX  = clientX
        this.clientY  = clientY
        this.ctrlKey  = ctrlKey
        this.shiftKey  = shiftKey
        this.altKey  = altKey
        this.metaKey  = metaKey
        this.button  = button
        this.relatedTarget  = relatedTarget
    }
};
events.MouseEvent.prototype.__proto__ = events.UIEvent.prototype;

events.MutationEvent = function(eventType) {
    events.Event.call(this, eventType);
    this.relatedNode = null;
    this.prevValue = null;
    this.newValue = null;
    this.attrName = null;
    this.attrChange = null;
};
events.MutationEvent.prototype = {
    initMutationEvent:   function(type,
                                  bubbles,
                                  cancelable,
                                  relatedNode,
                                  prevValue,
                                  newValue,
                                  attrName,
                                  attrChange) {
        this.initEvent(type, bubbles, cancelable);
        this.relatedNode = relatedNode;
        this.prevValue = prevValue;
        this.newValue = newValue;
        this.attrName = attrName;
        this.attrChange = attrChange;
    },
    get MODIFICATION() { return 1; },
    get ADDITION() { return 2; },
    get REMOVAL() { return 3; },
};
events.MutationEvent.prototype.__proto__ = events.Event.prototype;

events.EventTarget = function() {};

events.EventTarget.getListeners = function getListeners(target, type, capturing) {
    var listeners = target._listeners
            && target._listeners[type]
            && target._listeners[type][capturing];
    if (listeners && listeners.length) {
        return listeners;
    }
    return [];
};

events.EventTarget.dispatch = function dispatch(event, iterator, capturing) {
    var target = iterator();
    while (target && !event._stopPropagation) {
        listeners = events.EventTarget.getListeners(target, event._type, capturing);
        for (var y = 0; y < listeners.length; y++) {
            event._currentTarget = target;
            try {
                listeners[y].call(target, event);
            } catch (e) {
                sys.log("Listener "
                    + sys.inspect(listeners[y])
                    + "\n\n on target \n\n"
                    + sys.inspect(target)
                    + "\n\n threw error \n\n"
                    + sys.inspect(e.stack)
                    + "\n\n handling event \n\n"
                    + sys.inspect(event));
            }
        }
        target = iterator();
    }
    return !event._stopPropagation;
};

events.EventTarget.forwardIterator = function forwardIterator(list) {
  var i = 0, len = list.length;
  return function iterator() { return i < len ? list[i++] : null };
};

events.EventTarget.backwardIterator = function backwardIterator(list) {
  var i = list.length;
  return function iterator() { return i >=0 ? list[--i] : null };
};

events.EventTarget.singleIterator = function singleIterator(obj) {
  var i = 1;
  return function iterator() { return i-- ? obj : null };
};

events.EventTarget.prototype = {
    addEventListener: function(type, listener, capturing) {
        this._listeners = this._listeners || {};
        var listeners = this._listeners[type] || {};
        capturing = (capturing === true);
        var capturingListeners = listeners[capturing] || [];
        for (var i=0; i < capturingListeners.length; i++) {
            if (capturingListeners[i] === listener) {
                return;
            }
        }
        capturingListeners.push(listener);
        listeners[capturing] = capturingListeners;
        this._listeners[type] = listeners;
    },

    removeEventListener: function(type, listener, capturing) {
        var listeners  = this._listeners && this._listeners[type];
        if (!listeners) return;
        var capturingListeners = listeners[(capturing === true)];
        if (!capturingListeners) return;
        for (var i=0; i < capturingListeners.length; i++) {
            if (capturingListeners[i] === listener) {
                capturingListeners.splice(i, 1);
                return;
            }
        }
    },

    dispatchEvent: function(event) {
        if (event == null) {
            throw new events.EventException(0, "Null event");
        }
        if (event._type == null || event._type == "") {
            throw new events.EventException(0, "Uninitialized event");
        }

        var nextTarget = null;
        var targetList = [];

        event._target = this;

        //per the spec we gather the list of targets first to ensure
        //against dom modifications during actual event dispatch
        nextTarget = this.parentNode;
        while (nextTarget) {
            targetList.push(nextTarget);
            nextTarget = nextTarget.parentNode;
        }

        var iterator = events.EventTarget.backwardIterator(targetList);

        event._eventPhase = event.CAPTURING_PHASE;
        if (!events.EventTarget.dispatch(event, iterator, true)) return event._preventDefault;

        iterator = events.EventTarget.singleIterator(event._target);
        event._eventPhase = event.AT_TARGET;
        if (!events.EventTarget.dispatch(event, iterator, false)) return event._preventDefault;

        var traditionalHandler = this["on" + event._type];
        if (traditionalHandler) {
          try {
            if (traditionalHandler(event) === false) {
              return true;
            }
          }
          catch (e) {
            sys.log("The on" + event._type + " handler"
              + "\n\n on target \n\n"
              + sys.inspect(this)
              + "\n\n threw error \n\n"
              + sys.inspect(e)
              + "\n\n handling event \n\n"
              + sys.inspect(event));
          }
        }

        if (event._bubbles && !event._stopPropagation) {
            i = 0;
            iterator = events.EventTarget.forwardIterator(targetList);
            event._eventPhase = event.BUBBLING_PHASE;
            events.EventTarget.dispatch(event, iterator, false);
        }

        return event._preventDefault;
    }

};

core.Node.prototype.__proto__ = events.EventTarget.prototype;

function getDocument(el) {
  return el.nodeType == 9 ? el : el.ownerDocument;
}

function mutationEventsEnabled(el) {
  return (el.nodeType == 1 || el.nodeType == 9); //TODO getDocument(el).isSupported('MutationEvents', '2.0');
}

function advise(clazz, method, advice) {
    var proto = clazz.prototype,
        impl = proto[method];

  proto[method] = function() {
    var args = Array.prototype.slice.call(arguments);
    var ret = impl.apply(this, arguments);
    args.unshift(ret);
    return advice.apply(this, args) || ret;
  };
}

function adviseBefore(clazz, method, advice) {
  var proto = clazz.prototype,
      impl = proto[method];

  proto[method] = function() {
    advice.apply(this, arguments);
    return impl.apply(this, arguments);
  };
}

function dispatchInsertionEvent(append) {
  return function(ret, newChild, refChild) {
    if ((append || refChild != null) && mutationEventsEnabled(this)) {
      var doc = getDocument(this),
          ev = doc.createEvent("MutationEvents");

      ev.initMutationEvent("DOMNodeInserted", true, false, this, null, null, null, null);
      newChild.dispatchEvent(ev);
      if (this.nodeType == 9 || this._attachedToDocument) {
        ev = doc.createEvent("MutationEvents");
        ev.initMutationEvent("DOMNodeInsertedIntoDocument", false, false, null, null, null, null, null);
        core.visitTree(newChild, function(el) {
          if (el.nodeType == 1) {
            el.dispatchEvent(ev);
            el._attachedToDocument = true;
          }
        });
      }
    }
  };
}

function dispatchRemovalEvent(oldChild) {
  if (mutationEventsEnabled(this)) {
    var doc = getDocument(this),
        ev = doc.createEvent("MutationEvents");

    ev.initMutationEvent("DOMNodeRemoved", true, false, this, null, null, null, null);
    oldChild.dispatchEvent(ev);

    ev = doc.createEvent("MutationEvents");
    ev.initMutationEvent("DOMNodeRemovedFromDocument", false, false, null, null, null, null, null);
    core.visitTree(oldChild, function(el) {
      if (el.nodeType == 1) {
        el.dispatchEvent(ev);
        el._attachedToDocument = false;
      }
    });
  }
}

function dispatchAttrEvent(change, arg) {
  return function(ret) {
    var target = this._parentNode,
        node = arguments[arg];

    if (mutationEventsEnabled(target)) {
      var doc = target.ownerDocument,
          attrChange = events.MutationEvent.prototype[change],
          prevVal = arg == 0 ? node.value : null,
          newVal = arg == 1 ? node.value : null,
          ev = doc.createEvent("MutationEvents");

      ev.initMutationEvent("DOMAttrModified", true, false, target, prevVal, newVal, node.name, attrChange);
      target.dispatchEvent(ev);
    }
  }
}

advise(core.Node, 'insertBefore', dispatchInsertionEvent());
advise(core.Node, 'appendChild', dispatchInsertionEvent(true));
adviseBefore(core.Node, 'removeChild', dispatchRemovalEvent);

advise(core.AttrNodeMap, 'removeNamedItem', dispatchAttrEvent('REMOVAL', 0));
advise(core.AttrNodeMap, 'setNamedItem', dispatchAttrEvent('ADDITION', 1));

core.Document.prototype.createEvent = function(eventType) {
    switch (eventType) {
        case "MutationEvents": return new events.MutationEvent(eventType);
        case "UIEvents": return new events.UIEvent(eventType);
        case "MouseEvents": return new events.MouseEvent(eventType);
        case "HTMLEvents": return new events.HTMLEvent(eventType);
    }
    return new events.Event(eventType);
};

exports.dom =
{
  level2 : {
    core   : core,
    events : events
  }
};

<|endoftext|>


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

  exports.integrateCachebuster = function(grunt, init, done) {
    grunt.verbose.write("Integrating cachebuster into Laravel...");

    // add lines to composer.json
    var content = grunt.file.read('build/composer.json');
    content = content.replace(/("require"(?:.|[\r\n])*?)([ \t\r\n]*\})/, '$1,\n\t\t"themonkeys/cachebuster": "dev-master"$2');
    grunt.file.write('build/composer.json', content);

    // add lines to app/config/app.php
    content = grunt.file.read('build/app/config/app.php');
    content = content.replace(/(providers['"]\s*=>\s*array\((?:.|[\r\n])*?)([ \t\r\n]*\))/, '$1\n\t\t\'Themonkeys\\Cachebuster\\CachebusterServiceProvider\',$2');
    content = content.replace(/(aliases['"]\s*=>\s*array\((?:.|[\r\n])*?)([ \t\r\n]*\))/, '$1\n\t\t\'Bust\'            => \'Themonkeys\\Cachebuster\\Cachebuster\',$2');
    grunt.file.write('build/app/config/app.php', content);

    // add lines to .htaccess
    // BEFORE # Laravel framework
    content = grunt.file.read('build/public/.htaccess');
    content = content.replace(/(# -+[ \t\r\n]+# Laravel framework)/,
      '# ----------------------------------------------------------------------\n' +
      '# Remove cachebuster hash from request URLs if present\n' +
      '# ----------------------------------------------------------------------\n' +
      '<IfModule mod_rewrite.c>\n' +
        '\tRewriteRule ^(.*)-[0-9a-f]{32}(\\.(.*))$ $$1$$2 [DPI]\n' +
      '</IfModule>\n\n$1') +
      '\n\n' +

      '# ----------------------------------------------------------------------\n' +
      '# Allow Laravel to pre-process the css to add cachebusters to image urls\n' +
      '# ----------------------------------------------------------------------\n' +
      '<IfModule mod_rewrite.c>\n' +
        '\tRewriteCond %{REQUEST_URI} !^/index.php\n' +
        '\tRewriteRule ^(.*\\.css)$ index.php [L]\n' +
      '</IfModule>\n';
    grunt.file.write('build/public/.htaccess', content);

    content = grunt.file.read('build/app/routes.php') +
      '\n\n' +
      "// These routes will be cached, if you configure a non-zero bladeCacheExpiry.\n" +
      "// Full documentation at https://github.com/TheMonkeys/laravel-blade-cache-filter\n" +
      "Route::group(array('before' => 'cache', 'after' => 'cache'), function() {\n\n" +
        "\tRoute::get('/css/{filename}.css', function($filename) {\n" +
          "\t\treturn Bust::css(\"/css/$filename.css\");\n" +
        "\t});\n\n" +

        // TODO:
        // This is a temporarly fix for the monkeytestjs integration. should look at a way to fix it.
        "\tRoute::get('/tests/core/css/{filename}.css', function($filename) {\n" +
          "\t\treturn Bust::css(\"/tests/core/css/$filename.css\");\n" +
        "\t});\n\n" +
        "\tRoute::get('/tests/core/css/vendor/{filename}.css', function($filename) {\n" +
          "\t\treturn Bust::css(\"/tests/core/css/vendor/$filename.css\");\n" +
        "\t});\n\n" +
      "});\n" +
      "App::make('cachebuster.StripSessionCookiesFilter')->addPattern('|css/|');\n";

    grunt.file.write('build/app/routes.php', content);

    // add Bust calls to common.blade.php
    content = grunt.file.read('build/app/views/layouts/common.blade.php');
    content = content.replace(/\/(?:css|js)\/[^"]*\.(?:css|js)/g, '{{ Bust::url(\'$&\') }}');
    grunt.file.write('build/app/views/layouts/common.blade.php', content);

    grunt.verbose.ok();
    done();
  };

})(typeof exports === 'object' && exports || this);
<commit_msg>Laravel cachebuster css processor is routed only to URLs under /css so configure the .htaccess to match. Fixes compatibility with monkeytestjs.<commit_after>(function(exports) {
  "use strict";

  exports.integrateCachebuster = function(grunt, init, done) {
    grunt.verbose.write("Integrating cachebuster into Laravel...");

    // add lines to composer.json
    var content = grunt.file.read('build/composer.json');
    content = content.replace(/("require"(?:.|[\r\n])*?)([ \t\r\n]*\})/, '$1,\n\t\t"themonkeys/cachebuster": "dev-master"$2');
    grunt.file.write('build/composer.json', content);

    // add lines to app/config/app.php
    content = grunt.file.read('build/app/config/app.php');
    content = content.replace(/(providers['"]\s*=>\s*array\((?:.|[\r\n])*?)([ \t\r\n]*\))/, '$1\n\t\t\'Themonkeys\\Cachebuster\\CachebusterServiceProvider\',$2');
    content = content.replace(/(aliases['"]\s*=>\s*array\((?:.|[\r\n])*?)([ \t\r\n]*\))/, '$1\n\t\t\'Bust\'            => \'Themonkeys\\Cachebuster\\Cachebuster\',$2');
    grunt.file.write('build/app/config/app.php', content);

    // add lines to .htaccess
    // BEFORE # Laravel framework
    content = grunt.file.read('build/public/.htaccess');
    content = content.replace(/(# -+[ \t\r\n]+# Laravel framework)/,
      '# ----------------------------------------------------------------------\n' +
      '# Remove cachebuster hash from request URLs if present\n' +
      '# ----------------------------------------------------------------------\n' +
      '<IfModule mod_rewrite.c>\n' +
        '\tRewriteRule ^(.*)-[0-9a-f]{32}(\\.(.*))$ $$1$$2 [DPI]\n' +
      '</IfModule>\n\n$1') +
      '\n\n' +

      '# ----------------------------------------------------------------------\n' +
      '# Allow Laravel to pre-process the css to add cachebusters to image urls\n' +
      '# ----------------------------------------------------------------------\n' +
      '<IfModule mod_rewrite.c>\n' +
        '\tRewriteCond %{REQUEST_URI} !^/index.php\n' +
        '\tRewriteRule ^(css/.*\\.css)$ index.php [L]\n' +
      '</IfModule>\n';
    grunt.file.write('build/public/.htaccess', content);

    content = grunt.file.read('build/app/routes.php') +
      '\n\n' +
      "// These routes will be cached, if you configure a non-zero bladeCacheExpiry.\n" +
      "// Full documentation at https://github.com/TheMonkeys/laravel-blade-cache-filter\n" +
      "Route::group(array('before' => 'cache', 'after' => 'cache'), function() {\n\n" +
        "\tRoute::get('/css/{filename}.css', function($filename) {\n" +
          "\t\treturn Bust::css(\"/css/$filename.css\");\n" +
        "\t});\n\n" +
      "});\n" +
      "App::make('cachebuster.StripSessionCookiesFilter')->addPattern('|css/|');\n";

    grunt.file.write('build/app/routes.php', content);

    // add Bust calls to common.blade.php
    content = grunt.file.read('build/app/views/layouts/common.blade.php');
    content = content.replace(/\/(?:css|js)\/[^"]*\.(?:css|js)/g, '{{ Bust::url(\'$&\') }}');
    grunt.file.write('build/app/views/layouts/common.blade.php', content);

    grunt.verbose.ok();
    done();
  };

})(typeof exports === 'object' && exports || this);
<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */
var AuthorizationError = require('../errors/authorizationerror')
  , ForbiddenError = require('../errors/forbiddenerror');

/**
 * Handle authorization decisions from resource owners.
 *
 * Obtaining authorization via OAuth 2.0 consists of a sequence of discrete
 * steps.  First, the client requests authorization from the user (in this case
 * using an authorization server as an intermediary).  The authorization server
 * conducts an approval dialog with the user to obtain permission.  After access
 * has been allowed, a grant is issued to the client which can be exchanged for
 * an access token.
 *
 * This middleware is used to process a user's decision about whether to allow
 * or deny access.  The client that initiated the authorization transaction will
 * be sent a response, including a grant if access was allowed.
 *
 * The exact form of the grant will depend on the type requested by the client.
 * The `server`'s response handling functions are used to issue the grant and
 * send the response.   An application can implement support for these types as
 * necessary, including taking advantage of bundled grant middleware.
 *
 * Callbacks:
 *
 * An optional `parse` callback can be passed as an argument, for which the
 * function signature is as follows:
 *
 *     function(req, done) { ... }
 *
 * `req` is the request, which can be parsed for any additional parameters found
 * in query as required by the service provider.  `done` is a callback which
 * must be invoked with the following signature:
 *
 *     done(err, params);
 *
 * `params` are the additional parameters parsed from the request.  These will
 * be set on the transaction at `req.oauth2.res`.  If an error occurs, `done`
 * should be invoked with `err` set in idomatic Node.js fashion.
 *
 * Options:
 *
 *     cancelField    name of field that is set if user denied access (default: 'cancel')
 *     userProperty   property of `req` which contains the authenticated user (default: 'user')
 *     sessionKey     key under which transactions are stored in the session (default: 'authorize')
 *
 * Examples:
 *
 *     app.post('/dialog/authorize/decision',
 *       login.ensureLoggedIn(),
 *       server.decision());
 *
 *     app.post('/dialog/authorize/decision',
 *       login.ensureLoggedIn(),
 *       server.decision(function(req, done) {
 *         return done(null, { scope: req.scope })
 *       }));
 *
 * @param {Server} server
 * @param {Object} options
 * @param {Function} parse
 * @return {Function}
 * @api protected
 */
module.exports = function(server, options, parse) {
  if (typeof options == 'function') {
    parse = options;
    options = undefined;
  }
  options = options || {};
  parse = parse || function(req, done) { return done(); };

  if (!server) { throw new TypeError('oauth2orize.decision middleware requires a server argument'); }

  var cancelField = options.cancelField || 'cancel'
    , userProperty = options.userProperty || 'user'
    , key = options.sessionKey || 'authorize';

  return function decision(req, res, next) {
    if (!req.session) { return next(new Error('OAuth2orize requires session support. Did you forget app.use(express.session(...))?')); }
    if (!req.body) { return next(new Error('OAuth2orize requires body parsing. Did you forget app.use(express.bodyParser())?')); }
    if (!req.oauth2) { return next(new Error('OAuth2orize requires transaction support. Did you forget oauth2orize.transactionLoader(...)?')); }
    if (!req.session[key]) { return next(new ForbiddenError('Unable to load OAuth 2.0 transactions from session')); }

    parse(req, function(err, ares) {
      if (err) { return next(err); }

      var tid = req.oauth2.transactionID;
      req.oauth2.user = req[userProperty];
      req.oauth2.res = ares || req.oauth2.info || {};

      if (req.oauth2.res.allow === undefined) {
        if (!req.body[cancelField]) { req.oauth2.res.allow = true; }
        else { req.oauth2.res.allow = false; }
      }

      // proxy end() to delete the transaction
      var end = res.end;
      res.end = function(chunk, encoding) {
        delete req.session[key][tid];
        res.end = end;
        res.end(chunk, encoding);
      };

      server._respond(req.oauth2, res, function(err) {
        if (err) { return next(err); }
        return next(new AuthorizationError('Unsupported response type: ' + req.oauth2.req.type, 'unsupported_response_type'));
      });
    });
  };
};
<commit_msg>Remove req.oauth2.info assumption from decision middleware.<commit_after>/**
 * Module dependencies.
 */
var AuthorizationError = require('../errors/authorizationerror')
  , ForbiddenError = require('../errors/forbiddenerror');

/**
 * Handle authorization decisions from resource owners.
 *
 * Obtaining authorization via OAuth 2.0 consists of a sequence of discrete
 * steps.  First, the client requests authorization from the user (in this case
 * using an authorization server as an intermediary).  The authorization server
 * conducts an approval dialog with the user to obtain permission.  After access
 * has been allowed, a grant is issued to the client which can be exchanged for
 * an access token.
 *
 * This middleware is used to process a user's decision about whether to allow
 * or deny access.  The client that initiated the authorization transaction will
 * be sent a response, including a grant if access was allowed.
 *
 * The exact form of the grant will depend on the type requested by the client.
 * The `server`'s response handling functions are used to issue the grant and
 * send the response.   An application can implement support for these types as
 * necessary, including taking advantage of bundled grant middleware.
 *
 * Callbacks:
 *
 * An optional `parse` callback can be passed as an argument, for which the
 * function signature is as follows:
 *
 *     function(req, done) { ... }
 *
 * `req` is the request, which can be parsed for any additional parameters found
 * in query as required by the service provider.  `done` is a callback which
 * must be invoked with the following signature:
 *
 *     done(err, params);
 *
 * `params` are the additional parameters parsed from the request.  These will
 * be set on the transaction at `req.oauth2.res`.  If an error occurs, `done`
 * should be invoked with `err` set in idomatic Node.js fashion.
 *
 * Options:
 *
 *     cancelField    name of field that is set if user denied access (default: 'cancel')
 *     userProperty   property of `req` which contains the authenticated user (default: 'user')
 *     sessionKey     key under which transactions are stored in the session (default: 'authorize')
 *
 * Examples:
 *
 *     app.post('/dialog/authorize/decision',
 *       login.ensureLoggedIn(),
 *       server.decision());
 *
 *     app.post('/dialog/authorize/decision',
 *       login.ensureLoggedIn(),
 *       server.decision(function(req, done) {
 *         return done(null, { scope: req.scope })
 *       }));
 *
 * @param {Server} server
 * @param {Object} options
 * @param {Function} parse
 * @return {Function}
 * @api protected
 */
module.exports = function(server, options, parse) {
  if (typeof options == 'function') {
    parse = options;
    options = undefined;
  }
  options = options || {};
  parse = parse || function(req, done) { return done(); };

  if (!server) { throw new TypeError('oauth2orize.decision middleware requires a server argument'); }

  var cancelField = options.cancelField || 'cancel'
    , userProperty = options.userProperty || 'user'
    , key = options.sessionKey || 'authorize';

  return function decision(req, res, next) {
    if (!req.session) { return next(new Error('OAuth2orize requires session support. Did you forget app.use(express.session(...))?')); }
    if (!req.body) { return next(new Error('OAuth2orize requires body parsing. Did you forget app.use(express.bodyParser())?')); }
    if (!req.oauth2) { return next(new Error('OAuth2orize requires transaction support. Did you forget oauth2orize.transactionLoader(...)?')); }
    if (!req.session[key]) { return next(new ForbiddenError('Unable to load OAuth 2.0 transactions from session')); }

    parse(req, function(err, ares) {
      if (err) { return next(err); }

      var tid = req.oauth2.transactionID;
      req.oauth2.user = req[userProperty];
      req.oauth2.res = ares || {};

      if (req.oauth2.res.allow === undefined) {
        if (!req.body[cancelField]) { req.oauth2.res.allow = true; }
        else { req.oauth2.res.allow = false; }
      }

      // proxy end() to delete the transaction
      var end = res.end;
      res.end = function(chunk, encoding) {
        delete req.session[key][tid];
        res.end = end;
        res.end(chunk, encoding);
      };

      server._respond(req.oauth2, res, function(err) {
        if (err) { return next(err); }
        return next(new AuthorizationError('Unsupported response type: ' + req.oauth2.req.type, 'unsupported_response_type'));
      });
    });
  };
};
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Telefonica Investigación y Desarrollo, S.A.U
 *
 * This file is part of fiware-iotagent-lib
 *
 * fiware-iotagent-lib is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * fiware-iotagent-lib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with fiware-iotagent-lib.
 * If not, seehttp://www.gnu.org/licenses/.
 *
 * For those usages not covered by the GNU Affero General Public License
 * please contact with::daniel.moranjimenez@telefonica.com
 */

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const Configuration = new Schema({
    url: String,
    resource: String,
    iotagent: String,
    token: String,
    apikey: String,
    type: String,
    service: String,
    protocol: String,
    description: String,
    subservice: String,
    cbHost: String,
    timezone: String,
    commands: Array,
    staticAttributes: Array,
    lazy: Array,
    attributes: Array,
    internalAttributes: Array,
    timestamp: Boolean,
    expressionLanguage: String,
    explicitAttrs: Boolean
});

function load(db) {
    Configuration.index({ apikey: 1, resource: 1, protocol: 1 }, { unique: true });
    module.exports.model = db.model('Configuration', Configuration);
    module.exports.internalSchema = Configuration;
}

module.exports.load = load;
<commit_msg>rever model<commit_after>/*
 * Copyright 2014 Telefonica Investigación y Desarrollo, S.A.U
 *
 * This file is part of fiware-iotagent-lib
 *
 * fiware-iotagent-lib is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * fiware-iotagent-lib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with fiware-iotagent-lib.
 * If not, seehttp://www.gnu.org/licenses/.
 *
 * For those usages not covered by the GNU Affero General Public License
 * please contact with::daniel.moranjimenez@telefonica.com
 */

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const Configuration = new Schema({
    url: String,
    resource: String,
    iotagent: String,
    token: String,
    apikey: String,
    type: String,
    service: String,
    protocol: String,
    description: String,
    subservice: String,
    cbHost: String,
    timezone: String,
    commands: Array,
    staticAttributes: Array,
    lazy: Array,
    attributes: Array,
    internalAttributes: Array
});

function load(db) {
    Configuration.index({ apikey: 1, resource: 1, protocol: 1 }, { unique: true });
    module.exports.model = db.model('Configuration', Configuration);
    module.exports.internalSchema = Configuration;
}

module.exports.load = load;
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var url = require('url');
var http = require('http');
var mime = require('mime');
var zlib = require('zlib');
var chalk = require('chalk');
var html = require('basisjs-tools-ast').html;
var logMsg = require('./utils').logMsg;
var logWarn = require('./utils').logWarn;
var logError = require('./utils').logError;
var files = require('./files');
var plugin = require('./plugin');
var virtualPath = require('./http/virtualPath');
var originalReqUrl = new WeakMap();

function isContentModified(req, res, date){
  if (req.headers['if-modified-since'])
  {
    var headerDate = parseInt(new Date(req.headers['if-modified-since']) / 1000);
    var contentDate = parseInt(date / 1000);

    if (isNaN(headerDate))
    {
      logWarn('http', 'Invalid date in If-Modified-Since header');
      headerDate = Infinity; // cheapest way response with no changed
    }

    if (headerDate >= (contentDate || 0))
    {
      responseToClient(req, res, null, {
        status: 304,
        mtime: date
      });
      return false;
    }
  }

  return true;
}

function responseToClient(req, res, content, options, postfix){
  var headers = {};

  for (var header in options.headers)
    headers[header] = options.headers[header];

  if (content && !headers['Content-Type'])
    headers['Content-Type'] = options.contentType || 'application/octet-stream';

  if (options.mtime)
    headers['Last-Modified'] = options.mtime.toGMTString();

  if (options.nocache)
  {
    headers['Cache-Control'] = 'no-cache';
    headers['Pragma'] = 'no-cache';
  }
  else
  {
    if (options.expires)
    {
      headers['Cache-Control'] = 'max-age=' + options.expires;
      headers['Expires'] = (new Date(Number(new Date) + 1000 * options.expires)).toGMTString();
    }
  }

  if (options.encoding && content && content.length > 1024)
  {
    if (options.file && options.file.zip)
    {
      if (options.encoding in options.file.zip === false)
        options.file.zip[options.encoding] = zlib[options.encoding + 'Sync'](content);

      headers['Content-Encoding'] = options.encoding;
      content = options.file.zip[options.encoding];
    }
  }

  logMsg('http', reqTransition(req) + ' ' + chalk.green(options.status || 200) + (postfix ? ' ' + postfix : ''));
  res.writeHead(options.status || 200, headers);
  res.end(content);
}

function responseError(req, res, status, message, logReason){
  status = status || 500;

  logMsg('http', req.url + ' ' + chalk.bgRed.white(status) + (logReason ? ' ' + chalk.gray(logReason) : ''));
  res.writeHead(status);
  res.end(message || 'Internal server error');
}

function redirect(req, res, location, status){
  status = status || 301;

  logMsg('http', req.url + chalk.gray(' → ') + location + ' ' + chalk.green(status));

  res.writeHead(status, {
    Location: location
  });
  res.end();
}

function processHtml(req, filename, data, options){
  var ast = html.parse(String(data), { location: false });

  if (req.rewritten)
    html.injectToHead(ast, {
      type: 'tag',
      name: 'base',
      attribs: {
        href: '//' + req.headers.host + path.dirname(files.relativePath(filename)) + '/'
      }
    }, true);

  if (options.resCache)
  {
    var resourceScript = {
      type: 'tag',
      name: 'script',
      attribs: {
        src: '/basisjs-tools/resourceCache.js'
      },
      children: []
    };

    var firstScript = html.getElementByName(ast.head, 'script') || html.getElementByName(ast, 'script');
    if (firstScript)
      html.insertBefore(firstScript, resourceScript);
    else
      html.injectToHead(ast, resourceScript);
  }

  if (options.sync)
  {
    html.injectToBody(ast, {
      type: 'tag',
      name: 'script',
      attribs: {
        src: '/basisjs-tools/ws.js',
        async: undefined,
        defer: undefined
      },
      children: []
    });

    if (options.inspect)
      html.injectToBody(ast, {
        type: 'tag',
        name: 'script',
        attribs: {
          src: options.inspect,
          async: undefined,
          defer: undefined
        },
        children: []
      });
  }

  return html.translate(ast);
}

function reqTransition(req){
  var original = originalReqUrl.get(req);
  var originalUrl = original.url;
  var currentUrl = req.url;

  if (original.host !== req.headers.host)
  {
    originalUrl = original.host + originalUrl;
    currentUrl = req.headers.host + currentUrl;
  }

  return originalUrl !== currentUrl ? originalUrl + chalk.gray(' → ') + currentUrl : currentUrl;
}

module.exports = function createServer(options, fsWatcher){
  function resolveEncoding(req){
    if (options.gzip)
    {
      var encoding = req.headers['accept-encoding'];

      if (encoding)
        return encoding.toLowerCase().replace(/^.*?\b(gzip|deflate)\b.*$|.*/, '$1');
    }

    return '';
  }

  function resolvePathnameFile(req, res, callback){
    var location = url.parse(req.url, true, true);
    var relFilename = location.pathname;
    var filename = files.absolutePath(relFilename);

    if (relFilename == '/favicon.ico' && !fs.existsSync(filename))
      return callback(__dirname + '/assets/favicon.ico');

    for (var path in symlinks)
      if (relFilename.indexOf(path) === 0 && (relFilename === path || relFilename[path.length] === '/'))
      {
        filename = symlinks[path] + relFilename.substr(path.length);
        logMsg('http', relFilename + ' symlink to ' + filename, true);
        break;
      }

    files.exists(filename, function(error){
      if (error)
      {
        responseError(req, res, 404, 'File ' + filename + ' not found', (error && !options.verbose ? chalk.gray(error) : ''));
        logMsg('', 'full path: ' + filename, true);
        logMsg('', 'reason: ' + chalk.gray(error || 'file not found'), true);

        if (req.headers['x-basis-resource'])
          fsWatcher.awaitFile(filename);

        return;
      }

      if (fs.statSync(filename).isDirectory())
      {
        // /path -> /path/
        if (!/\/$/.test(relFilename))
          return redirect(req, res, relFilename + '/');

        if (fs.existsSync(filename + '/index.html'))
          return callback(filename + '/index.html');

        if (fs.existsSync(filename + '/index.htm'))
          return callback(filename + '/index.htm');

        return responseError(req, res, 404, 'Path ' + filename + ' is not a file');
      }

      return callback(filename);
    });
  }

  function normalizeFilename(filename){
    return path.resolve('/' + filename)
      // windows issues: cut drive in beginning and replaces `\` to `/`
      .replace(/^[a-z]:/i, '')
      .replace(/\\/g, '/');
  }

  function createPluginApi(api, name){
    api.addSymlink = httpServer.addSymlink;
    api.addMiddleware = function(fn){
      httpServer.use(fn);
    };
    api.addVirtualFile = function(filename, content){
      var filename = '/basisjs-tools/plugin:' +
                     path.basename(path.dirname(name).replace(/^\.$/, '') || name) +
                     normalizeFilename(filename);
      var contentType = mime.lookup(filename, 'text/plain');
      var file = {
        content: content,
        zip: {}
      };

      virtualPath.add(filename, function(api){
        api.responseToClient(content, {
          contentType: contentType,
          encoding: api.encoding,
          file: file
        }, chalk.green('(from cache)'));
      });

      return filename;
    };
  }

  function defaultRequestHandler(req, res){
    var reqPathname = url.parse(req.url).pathname;

    resolvePathnameFile(req, res, function(filename){
      var filename = path.normalize(filename);

      req.url = files.relativePath(filename);

      if (!isContentModified(req, res, fs.statSync(filename).mtime))
        return;

      if (!options.readCache)
        files.remove(filename);

      files.readFileIfNeeded(filename, function(err, filename, data){
        if (err)
          return responseError(req, res, 500, 'File read error: ' + err);

        var file = files.get(filename);
        var contentType = mime.lookup(filename, 'text/plain');
        var isTextFile = /^text\/|^application\/(javascript|json|.+\+xml$)/.test(contentType);
        var responseOptions = {
          contentType: contentType + (isTextFile ? '; charset=utf-8' : ''),
          encoding: isTextFile && resolveEncoding(req), // gzip, deflate
          mtime: file.mtime,
          file: file,
          nocache: true
          //expires: contentType == 'text/html' ? 0 : 60 * 60 // 1 hour
        };

        if (options.resCache && req.headers['x-basis-resource'])
        {
          fsWatcher.startWatch(filename);
          files.addToCache(filename, String(data), reqPathname);
        }

        if (contentType == 'text/html')
          data = processHtml(req, filename, data, options);

        responseToClient(
          req,
          res,
          data,
          responseOptions,
          data !== file.content ? chalk.yellow('(file read)') : chalk.green('(from cache)')
        );
      });
    });
  }

  function processRequest(req, res, middleware){
    logMsg('http', req.url + chalk.gray(' → ') + chalk.yellow(middleware.fn.name || '<anonymous-middleware>'), true);
    middleware.fn(req, res, function next(){
      if (middleware.next)
        processRequest(req, res, middleware.next);
    });
  }

  var symlinks = {};
  var requestProcessPipelineFinal = {
    fn: defaultRequestHandler,
    next: null
  };
  var requestProcessPipelineHead = requestProcessPipelineFinal;
  var requestProcessPipelineTail = null;

  var httpServer = http.createServer(function(req, res){
    originalReqUrl.set(req, {
      host: req.headers.host,
      url: req.url
    });

    processRequest(req, res, requestProcessPipelineHead);
  }).on('error', function(error){
    console.log(
      chalk.bgRed.white('ERROR') + ' ' +
      (error.code == 'EADDRINUSE' ? 'Port ' + chalk.green(options.port) + ' already in use' : error)
    );
  });

  httpServer.addSymlink = function(from, to){
    from = path.normalize(from).replace(/\\/g, '/').replace(/\/$/, '');
    to = path.normalize(to).replace(/\\/g, '/').replace(/\/$/, '');
    symlinks[from] = to;
  };
  httpServer.addVirtualPath = function(path, fn){
    if (typeof fn == 'string')
    {
      var filename = fn;
      fn = function(httpApi){
        files.readFileIfNeeded(filename, function(err, filename, content){
          if (err)
            return httpApi.resposeError(500, err);

          httpApi.responseToClient(content, {
            contentType: 'text/html'
          });
        });
      };
    }

    virtualPath.add(path, fn);
  };
  httpServer.resolveEncoding = resolveEncoding;
  httpServer.isContentModified = isContentModified;
  httpServer.responseToClient = responseToClient;
  httpServer.responseError = responseError;
  httpServer.redirect = redirect;
  httpServer.use = function(middleware){
    var listItem = {
      fn: middleware,
      next: requestProcessPipelineFinal
    };

    if (requestProcessPipelineTail)
      requestProcessPipelineTail.next = listItem;
    else
      requestProcessPipelineHead = listItem;

    requestProcessPipelineTail = listItem;
  };
  httpServer.log = function(message, verboseOnly){
    return logMsg('http', message, verboseOnly);
  };
  httpServer.warn = function(message){
    return logWarn('http', message);
  };
  httpServer.error = function(message){
    return logError('http', message);
  };

  plugin.extendApi(createPluginApi);

  return httpServer;
};
<commit_msg>decode pathname when resolve to file name<commit_after>var fs = require('fs');
var path = require('path');
var url = require('url');
var http = require('http');
var mime = require('mime');
var zlib = require('zlib');
var chalk = require('chalk');
var html = require('basisjs-tools-ast').html;
var logMsg = require('./utils').logMsg;
var logWarn = require('./utils').logWarn;
var logError = require('./utils').logError;
var files = require('./files');
var plugin = require('./plugin');
var virtualPath = require('./http/virtualPath');
var originalReqUrl = new WeakMap();

function isContentModified(req, res, date){
  if (req.headers['if-modified-since'])
  {
    var headerDate = parseInt(new Date(req.headers['if-modified-since']) / 1000);
    var contentDate = parseInt(date / 1000);

    if (isNaN(headerDate))
    {
      logWarn('http', 'Invalid date in If-Modified-Since header');
      headerDate = Infinity; // cheapest way response with no changed
    }

    if (headerDate >= (contentDate || 0))
    {
      responseToClient(req, res, null, {
        status: 304,
        mtime: date
      });
      return false;
    }
  }

  return true;
}

function responseToClient(req, res, content, options, postfix){
  var headers = {};

  for (var header in options.headers)
    headers[header] = options.headers[header];

  if (content && !headers['Content-Type'])
    headers['Content-Type'] = options.contentType || 'application/octet-stream';

  if (options.mtime)
    headers['Last-Modified'] = options.mtime.toGMTString();

  if (options.nocache)
  {
    headers['Cache-Control'] = 'no-cache';
    headers['Pragma'] = 'no-cache';
  }
  else
  {
    if (options.expires)
    {
      headers['Cache-Control'] = 'max-age=' + options.expires;
      headers['Expires'] = (new Date(Number(new Date) + 1000 * options.expires)).toGMTString();
    }
  }

  if (options.encoding && content && content.length > 1024)
  {
    if (options.file && options.file.zip)
    {
      if (options.encoding in options.file.zip === false)
        options.file.zip[options.encoding] = zlib[options.encoding + 'Sync'](content);

      headers['Content-Encoding'] = options.encoding;
      content = options.file.zip[options.encoding];
    }
  }

  logMsg('http', reqTransition(req) + ' ' + chalk.green(options.status || 200) + (postfix ? ' ' + postfix : ''));
  res.writeHead(options.status || 200, headers);
  res.end(content);
}

function responseError(req, res, status, message, logReason){
  status = status || 500;

  logMsg('http', req.url + ' ' + chalk.bgRed.white(status) + (logReason ? ' ' + chalk.gray(logReason) : ''));
  res.writeHead(status);
  res.end(message || 'Internal server error');
}

function redirect(req, res, location, status){
  status = status || 301;

  logMsg('http', req.url + chalk.gray(' → ') + location + ' ' + chalk.green(status));

  res.writeHead(status, {
    Location: location
  });
  res.end();
}

function processHtml(req, filename, data, options){
  var ast = html.parse(String(data), { location: false });

  if (req.rewritten)
    html.injectToHead(ast, {
      type: 'tag',
      name: 'base',
      attribs: {
        href: '//' + req.headers.host + path.dirname(files.relativePath(filename)) + '/'
      }
    }, true);

  if (options.resCache)
  {
    var resourceScript = {
      type: 'tag',
      name: 'script',
      attribs: {
        src: '/basisjs-tools/resourceCache.js'
      },
      children: []
    };

    var firstScript = html.getElementByName(ast.head, 'script') || html.getElementByName(ast, 'script');
    if (firstScript)
      html.insertBefore(firstScript, resourceScript);
    else
      html.injectToHead(ast, resourceScript);
  }

  if (options.sync)
  {
    html.injectToBody(ast, {
      type: 'tag',
      name: 'script',
      attribs: {
        src: '/basisjs-tools/ws.js',
        async: undefined,
        defer: undefined
      },
      children: []
    });

    if (options.inspect)
      html.injectToBody(ast, {
        type: 'tag',
        name: 'script',
        attribs: {
          src: options.inspect,
          async: undefined,
          defer: undefined
        },
        children: []
      });
  }

  return html.translate(ast);
}

function reqTransition(req){
  var original = originalReqUrl.get(req);
  var originalUrl = original.url;
  var currentUrl = req.url;

  if (original.host !== req.headers.host)
  {
    originalUrl = original.host + originalUrl;
    currentUrl = req.headers.host + currentUrl;
  }

  return originalUrl !== currentUrl ? originalUrl + chalk.gray(' → ') + currentUrl : currentUrl;
}

module.exports = function createServer(options, fsWatcher){
  function resolveEncoding(req){
    if (options.gzip)
    {
      var encoding = req.headers['accept-encoding'];

      if (encoding)
        return encoding.toLowerCase().replace(/^.*?\b(gzip|deflate)\b.*$|.*/, '$1');
    }

    return '';
  }

  function resolvePathnameFile(req, res, callback){
    var location = url.parse(req.url, true, true);
    var relFilename = decodeURIComponent(location.pathname);
    var filename = files.absolutePath(relFilename);

    if (relFilename == '/favicon.ico' && !fs.existsSync(filename))
      return callback(__dirname + '/assets/favicon.ico');

    for (var path in symlinks)
      if (relFilename.indexOf(path) === 0 && (relFilename === path || relFilename[path.length] === '/'))
      {
        filename = symlinks[path] + relFilename.substr(path.length);
        logMsg('http', relFilename + ' symlink to ' + filename, true);
        break;
      }

    files.exists(filename, function(error){
      if (error)
      {
        responseError(req, res, 404, 'File ' + filename + ' not found', (error && !options.verbose ? chalk.gray(error) : ''));
        logMsg('', 'full path: ' + filename, true);
        logMsg('', 'reason: ' + chalk.gray(error || 'file not found'), true);

        if (req.headers['x-basis-resource'])
          fsWatcher.awaitFile(filename);

        return;
      }

      if (fs.statSync(filename).isDirectory())
      {
        // /path -> /path/
        if (!/\/$/.test(relFilename))
          return redirect(req, res, relFilename + '/');

        if (fs.existsSync(filename + '/index.html'))
          return callback(filename + '/index.html');

        if (fs.existsSync(filename + '/index.htm'))
          return callback(filename + '/index.htm');

        return responseError(req, res, 404, 'Path ' + filename + ' is not a file');
      }

      return callback(filename);
    });
  }

  function normalizeFilename(filename){
    return path.resolve('/' + filename)
      // windows issues: cut drive in beginning and replaces `\` to `/`
      .replace(/^[a-z]:/i, '')
      .replace(/\\/g, '/');
  }

  function createPluginApi(api, name){
    api.addSymlink = httpServer.addSymlink;
    api.addMiddleware = function(fn){
      httpServer.use(fn);
    };
    api.addVirtualFile = function(filename, content){
      var filename = '/basisjs-tools/plugin:' +
                     path.basename(path.dirname(name).replace(/^\.$/, '') || name) +
                     normalizeFilename(filename);
      var contentType = mime.lookup(filename, 'text/plain');
      var file = {
        content: content,
        zip: {}
      };

      virtualPath.add(filename, function(api){
        api.responseToClient(content, {
          contentType: contentType,
          encoding: api.encoding,
          file: file
        }, chalk.green('(from cache)'));
      });

      return filename;
    };
  }

  function defaultRequestHandler(req, res){
    var reqPathname = url.parse(req.url).pathname;

    resolvePathnameFile(req, res, function(filename){
      var filename = path.normalize(filename);

      req.url = files.relativePath(filename);

      if (!isContentModified(req, res, fs.statSync(filename).mtime))
        return;

      if (!options.readCache)
        files.remove(filename);

      files.readFileIfNeeded(filename, function(err, filename, data){
        if (err)
          return responseError(req, res, 500, 'File read error: ' + err);

        var file = files.get(filename);
        var contentType = mime.lookup(filename, 'text/plain');
        var isTextFile = /^text\/|^application\/(javascript|json|.+\+xml$)/.test(contentType);
        var responseOptions = {
          contentType: contentType + (isTextFile ? '; charset=utf-8' : ''),
          encoding: isTextFile && resolveEncoding(req), // gzip, deflate
          mtime: file.mtime,
          file: file,
          nocache: true
          //expires: contentType == 'text/html' ? 0 : 60 * 60 // 1 hour
        };

        if (options.resCache && req.headers['x-basis-resource'])
        {
          fsWatcher.startWatch(filename);
          files.addToCache(filename, String(data), reqPathname);
        }

        if (contentType == 'text/html')
          data = processHtml(req, filename, data, options);

        responseToClient(
          req,
          res,
          data,
          responseOptions,
          data !== file.content ? chalk.yellow('(file read)') : chalk.green('(from cache)')
        );
      });
    });
  }

  function processRequest(req, res, middleware){
    logMsg('http', req.url + chalk.gray(' → ') + chalk.yellow(middleware.fn.name || '<anonymous-middleware>'), true);
    middleware.fn(req, res, function next(){
      if (middleware.next)
        processRequest(req, res, middleware.next);
    });
  }

  var symlinks = {};
  var requestProcessPipelineFinal = {
    fn: defaultRequestHandler,
    next: null
  };
  var requestProcessPipelineHead = requestProcessPipelineFinal;
  var requestProcessPipelineTail = null;

  var httpServer = http.createServer(function(req, res){
    originalReqUrl.set(req, {
      host: req.headers.host,
      url: req.url
    });

    processRequest(req, res, requestProcessPipelineHead);
  }).on('error', function(error){
    console.log(
      chalk.bgRed.white('ERROR') + ' ' +
      (error.code == 'EADDRINUSE' ? 'Port ' + chalk.green(options.port) + ' already in use' : error)
    );
  });

  httpServer.addSymlink = function(from, to){
    from = path.normalize(from).replace(/\\/g, '/').replace(/\/$/, '');
    to = path.normalize(to).replace(/\\/g, '/').replace(/\/$/, '');
    symlinks[from] = to;
  };
  httpServer.addVirtualPath = function(path, fn){
    if (typeof fn == 'string')
    {
      var filename = fn;
      fn = function(httpApi){
        files.readFileIfNeeded(filename, function(err, filename, content){
          if (err)
            return httpApi.resposeError(500, err);

          httpApi.responseToClient(content, {
            contentType: 'text/html'
          });
        });
      };
    }

    virtualPath.add(path, fn);
  };
  httpServer.resolveEncoding = resolveEncoding;
  httpServer.isContentModified = isContentModified;
  httpServer.responseToClient = responseToClient;
  httpServer.responseError = responseError;
  httpServer.redirect = redirect;
  httpServer.use = function(middleware){
    var listItem = {
      fn: middleware,
      next: requestProcessPipelineFinal
    };

    if (requestProcessPipelineTail)
      requestProcessPipelineTail.next = listItem;
    else
      requestProcessPipelineHead = listItem;

    requestProcessPipelineTail = listItem;
  };
  httpServer.log = function(message, verboseOnly){
    return logMsg('http', message, verboseOnly);
  };
  httpServer.warn = function(message){
    return logWarn('http', message);
  };
  httpServer.error = function(message){
    return logError('http', message);
  };

  plugin.extendApi(createPluginApi);

  return httpServer;
};
<|endoftext|>


<commit_before>import raven from "raven"
import { assign } from "lodash"

const shouldLogError = originalError => {
  if (originalError && originalError.statusCode) {
    return originalError.statusCode !== 404
  }
  return true
}

export default function graphqlErrorHandler(
  req,
  { isProduction, enableSentry }
) {
  return error => {
    if (enableSentry) {
      if (shouldLogError(error.originalError)) {
        raven.captureException(
          error,
          assign(
            {},
            {
              tags: { graphql: "exec_error" },
              extra: {
                source: error.source && error.source.body,
                positions: error.positions,
                path: error.path,
              },
            },
            raven.parsers.parseRequest(req)
          )
        )
      }
    }
    return {
      message: error.message,
      locations: error.locations,
      stack: isProduction ? null : error.stack,
    }
  }
}
<commit_msg>Dont send 401 or 403 to Sentry either<commit_after>import raven from "raven"
import { assign } from "lodash"

const blacklistHttpStatuses = [401, 403, 404]
const shouldLogError = originalError => {
  if (originalError && originalError.statusCode) {
    return !blacklistHttpStatuses.includes(originalError.statusCode)
  }
  return true
}

export default function graphqlErrorHandler(
  req,
  { isProduction, enableSentry }
) {
  return error => {
    if (enableSentry) {
      if (shouldLogError(error.originalError)) {
        raven.captureException(
          error,
          assign(
            {},
            {
              tags: { graphql: "exec_error" },
              extra: {
                source: error.source && error.source.body,
                positions: error.positions,
                path: error.path,
              },
            },
            raven.parsers.parseRequest(req)
          )
        )
      }
    }
    return {
      message: error.message,
      locations: error.locations,
      stack: isProduction ? null : error.stack,
    }
  }
}
<|endoftext|>


<commit_before>/**
 * Converts usage strings into objects to compare against later
 */
class ParsedUsage {

	/**
	 * @param {KlasaClient} client The klasa client
	 * @param {Command} command The command this parsed usage is for
	 */
	constructor(client, command) {
		Object.defineProperty(this, 'client', { value: client });
		this.names = [command.name, ...command.aliases];
		this.commands = this.names.length === 1 ? this.names[0] : `(${this.names.join('|')})`;
		this.deliminatedUsage = command.usageString !== '' ? ` ${command.usageString.split(' ').join(command.usageDelim)}` : '';
		this.usageString = command.usageString;
		this.parsedUsage = this.parseUsage();
		this.nearlyFullUsage = `${this.commands}${this.deliminatedUsage}`;
	}

	/**
	 * Creates a full usage string including prefix and commands/aliases for documentation/help purposes
	 * @param {external:Message} msg a message to check to get the current prefix
	 * @returns {string}
	 */
	fullUsage(msg) {
		const prefix = msg.guildSettings.prefix;
		return `${prefix.length !== 1 ? `${prefix} ` : prefix}${this.nearlyFullUsage}`;
	}

	/**
	 * Method responsible for building the usage object to check against
	 * @private
	 * @returns {Object}
	 */
	parseUsage() {
		let usage = {
			tags: [],
			opened: 0,
			current: '',
			openReq: false,
			last: false,
			char: 0,
			from: 0,
			at: '',
			fromto: ''
		};

		this.usageString.split('').forEach((com, i) => {
			usage.char = i + 1;
			usage.from = usage.char - usage.current.length;
			usage.at = `at char #${usage.char} '${com}'`;
			usage.fromto = `from char #${usage.from} to #${usage.char} '${usage.current}'`;

			if (usage.last && com !== ' ') {
				throw `${usage.at}: there can't be anything else after the repeat tag.`;
			}

			if (this[com]) {
				usage = this[com](usage);
			} else {
				usage.current += com;
			}
		});

		if (usage.opened) throw `from char #${this.usageString.length - usage.current.length} '${this.usageString.substr(-usage.current.length - 1)}' to end: a tag was left open`;
		if (usage.current) throw `from char #${(this.usageString.length + 1) - usage.current.length} to end '${usage.current}' a literal was found outside a tag.`;

		return usage.tags;
	}

	['<'](usage) {
		if (usage.opened) throw `${usage.at}: you might not open a tag inside another tag.`;
		if (usage.current) throw `${usage.fromto}: there can't be a literal outside a tag`;
		usage.opened++;
		usage.openReq = true;
		return usage;
	}

	['>'](usage) {
		if (!usage.opened) throw `${usage.at}: invalid close tag found`;
		if (!usage.openReq) throw `${usage.at}: Invalid closure of '[${usage.current}' with '>'`;
		usage.opened--;
		if (usage.current) {
			usage.tags.push({
				type: 'required',
				possibles: this.parseTag(usage.current, usage.tags.length + 1)
			});
			usage.current = '';
		} else { throw `${usage.at}: empty tag found`; }
		return usage;
	}

	['['](usage) {
		if (usage.opened) throw `${usage.at}: you might not open a tag inside another tag.`;
		if (usage.current) throw `${usage.fromto}: there can't be a literal outside a tag`;
		usage.opened++;
		usage.openReq = false;
		return usage;
	}

	[']'](usage) {
		if (!usage.opened) throw `${usage.at}: invalid close tag found`;
		if (usage.openReq) throw `${usage.at}: Invalid closure of '<${usage.current}' with ']'`;
		usage.opened--;
		if (usage.current === '...') {
			if (usage.tags.length < 1) { throw `${usage.fromto}: there can't be a loop at the begining`; }
			usage.tags.push({ type: 'repeat' });
			usage.last = true;
			usage.current = '';
		} else if (usage.current) {
			usage.tags.push({
				type: 'optional',
				possibles: this.parseTag(usage.current, usage.tags.length + 1)
			});
			usage.current = '';
		} else { throw `${usage.at}: empty tag found`; }
		return usage;
	}

	[' '](usage) {
		if (usage.opened) throw `${usage.at}: spaces aren't allowed inside a tag`;
		if (usage.current) throw `${usage.fromto}: there can't be a literal outside a tag.`;
		return usage;
	}

	['\n'](usage) {
		throw `${usage.at}: there can't be a line break in the command!`;
	}

	parseTag(tag, count) {
		const literals = [];
		const types = [];
		const toRet = [];

		const members = tag.split('|');

		members.forEach((elemet, i) => {
			const current = `at tag #${count} at bound #${i + 1}`;

			const result = /^([^:]+)(?::([^{}]+))?(?:{([^,]+)?(?:,(.+))?})?$/i.exec(elemet);

			if (!result) throw `${current}: invalid syntax, non specific`;

			const fill = {
				name: result[1],
				type: result[2] ? result[2].toLowerCase() : 'literal'
			};

			if (result[3]) {
				const proto = ' in the type length (min): ';

				if (fill.type === 'literal') throw `${current + proto}you cannot set a length for a literal type`;

				if (isNaN(result[3])) throw `${current + proto}must be a number`;

				const temp = parseFloat(result[3]);
				if ((fill.type === 'string' || fill.type === 'str') && temp % 1 !== 0) throw `${current + proto}the string type must have an integer length`;

				fill.min = temp;
			}

			if (result[4]) {
				const proto = ' in the type length (max): ';
				if (fill.type === 'literal') throw `${current + proto}you canno't set a length for a literal type`;

				if (isNaN(result[4])) throw `${current + proto}must be a number`;

				const temp = parseFloat(result[4]);

				if ((fill.type === 'string' || fill.type === 'str') && temp % 1 !== 0) throw `${current + proto}the string type must have an integer length`;
				fill.max = temp;
			}

			if (fill.type === 'literal') {
				if (literals.includes(fill.name)) throw `${current}: there can't be two literals with the same text.`;

				literals.push(fill.name);
			} else if (members.length > 1) {
				if (fill.type === 'string' && members.length - 1 !== i) throw `${current}: the String type is vague, you must specify it at the last bound`;
				if (types.includes(fill.type)) throw `${current}: there can't be two bounds with the same type (${fill.type})`;
				types.push(fill.type);
			}

			toRet.push(fill);
		});

		return toRet;
	}

}

module.exports = ParsedUsage;
<commit_msg>finish documenting parsedUsage<commit_after>/**
 * Converts usage strings into objects to compare against later
 */
class ParsedUsage {

	/**
	 * @param {KlasaClient} client The klasa client
	 * @param {Command} command The command this parsed usage is for
	 */
	constructor(client, command) {
		/**
		 * The client this CommandMessage was created with.
		 * @name CommandMessage#client
		 * @type {KlasaClient}
		 * @readonly
		 */
		Object.defineProperty(this, 'client', { value: client });

		/**
		 * All names and aliases for the command
		 * @type {string[]}
		 */
		this.names = [command.name, ...command.aliases];

		/**
		 * The compiled string for all names/aliases in a usage string
		 * @type {string}
		 */
		this.commands = this.names.length === 1 ? this.names[0] : `(${this.names.join('|')})`;

		/**
		 * The usage string re-deliminated with the usageDelim
		 * @type {string}
		 */
		this.deliminatedUsage = command.usageString !== '' ? ` ${command.usageString.split(' ').join(command.usageDelim)}` : '';

		/**
		 * The usage string
		 * @type {string}
		 */
		this.usageString = command.usageString;

		/**
		 * The usage object to compare against later
		 * @type {Object[]}
		 */
		this.parsedUsage = this.parseUsage();

		/**
		 * The concatenated string of this.commands and this.deliminatedUsage
		 * @type {string}
		 */
		this.nearlyFullUsage = `${this.commands}${this.deliminatedUsage}`;
	}

	/**
	 * Creates a full usage string including prefix and commands/aliases for documentation/help purposes
	 * @param {external:Message} msg a message to check to get the current prefix
	 * @returns {string}
	 */
	fullUsage(msg) {
		const prefix = msg.guildSettings.prefix;
		return `${prefix.length !== 1 ? `${prefix} ` : prefix}${this.nearlyFullUsage}`;
	}

	/**
	 * Method responsible for building the usage object to check against
	 * @private
	 * @returns {Object}
	 */
	parseUsage() {
		let usage = {
			tags: [],
			opened: 0,
			current: '',
			openReq: false,
			last: false,
			char: 0,
			from: 0,
			at: '',
			fromto: ''
		};

		this.usageString.split('').forEach((com, i) => {
			usage.char = i + 1;
			usage.from = usage.char - usage.current.length;
			usage.at = `at char #${usage.char} '${com}'`;
			usage.fromto = `from char #${usage.from} to #${usage.char} '${usage.current}'`;

			if (usage.last && com !== ' ') {
				throw `${usage.at}: there can't be anything else after the repeat tag.`;
			}

			if (this[com]) {
				usage = this[com](usage);
			} else {
				usage.current += com;
			}
		});

		if (usage.opened) throw `from char #${this.usageString.length - usage.current.length} '${this.usageString.substr(-usage.current.length - 1)}' to end: a tag was left open`;
		if (usage.current) throw `from char #${(this.usageString.length + 1) - usage.current.length} to end '${usage.current}' a literal was found outside a tag.`;

		return usage.tags;
	}

	['<'](usage) {
		if (usage.opened) throw `${usage.at}: you might not open a tag inside another tag.`;
		if (usage.current) throw `${usage.fromto}: there can't be a literal outside a tag`;
		usage.opened++;
		usage.openReq = true;
		return usage;
	}

	['>'](usage) {
		if (!usage.opened) throw `${usage.at}: invalid close tag found`;
		if (!usage.openReq) throw `${usage.at}: Invalid closure of '[${usage.current}' with '>'`;
		usage.opened--;
		if (usage.current) {
			usage.tags.push({
				type: 'required',
				possibles: this.parseTag(usage.current, usage.tags.length + 1)
			});
			usage.current = '';
		} else { throw `${usage.at}: empty tag found`; }
		return usage;
	}

	['['](usage) {
		if (usage.opened) throw `${usage.at}: you might not open a tag inside another tag.`;
		if (usage.current) throw `${usage.fromto}: there can't be a literal outside a tag`;
		usage.opened++;
		usage.openReq = false;
		return usage;
	}

	[']'](usage) {
		if (!usage.opened) throw `${usage.at}: invalid close tag found`;
		if (usage.openReq) throw `${usage.at}: Invalid closure of '<${usage.current}' with ']'`;
		usage.opened--;
		if (usage.current === '...') {
			if (usage.tags.length < 1) { throw `${usage.fromto}: there can't be a loop at the begining`; }
			usage.tags.push({ type: 'repeat' });
			usage.last = true;
			usage.current = '';
		} else if (usage.current) {
			usage.tags.push({
				type: 'optional',
				possibles: this.parseTag(usage.current, usage.tags.length + 1)
			});
			usage.current = '';
		} else { throw `${usage.at}: empty tag found`; }
		return usage;
	}

	[' '](usage) {
		if (usage.opened) throw `${usage.at}: spaces aren't allowed inside a tag`;
		if (usage.current) throw `${usage.fromto}: there can't be a literal outside a tag.`;
		return usage;
	}

	['\n'](usage) {
		throw `${usage.at}: there can't be a line break in the command!`;
	}

	parseTag(tag, count) {
		const literals = [];
		const types = [];
		const toRet = [];

		const members = tag.split('|');

		members.forEach((elemet, i) => {
			const current = `at tag #${count} at bound #${i + 1}`;

			const result = /^([^:]+)(?::([^{}]+))?(?:{([^,]+)?(?:,(.+))?})?$/i.exec(elemet);

			if (!result) throw `${current}: invalid syntax, non specific`;

			const fill = {
				name: result[1],
				type: result[2] ? result[2].toLowerCase() : 'literal'
			};

			if (result[3]) {
				const proto = ' in the type length (min): ';

				if (fill.type === 'literal') throw `${current + proto}you cannot set a length for a literal type`;

				if (isNaN(result[3])) throw `${current + proto}must be a number`;

				const temp = parseFloat(result[3]);
				if ((fill.type === 'string' || fill.type === 'str') && temp % 1 !== 0) throw `${current + proto}the string type must have an integer length`;

				fill.min = temp;
			}

			if (result[4]) {
				const proto = ' in the type length (max): ';
				if (fill.type === 'literal') throw `${current + proto}you canno't set a length for a literal type`;

				if (isNaN(result[4])) throw `${current + proto}must be a number`;

				const temp = parseFloat(result[4]);

				if ((fill.type === 'string' || fill.type === 'str') && temp % 1 !== 0) throw `${current + proto}the string type must have an integer length`;
				fill.max = temp;
			}

			if (fill.type === 'literal') {
				if (literals.includes(fill.name)) throw `${current}: there can't be two literals with the same text.`;

				literals.push(fill.name);
			} else if (members.length > 1) {
				if (fill.type === 'string' && members.length - 1 !== i) throw `${current}: the String type is vague, you must specify it at the last bound`;
				if (types.includes(fill.type)) throw `${current}: there can't be two bounds with the same type (${fill.type})`;
				types.push(fill.type);
			}

			toRet.push(fill);
		});

		return toRet;
	}

}

module.exports = ParsedUsage;
<|endoftext|>