<commit_before>/*jslint white: true nomen: true plusplus: true */
/*global mx, mxui, window, document, mendix, dojo, require, console, define, module, logger */
/**
	Signature
	========================

	@file      : Signature.js
	@version   : 2.1
	@author    : Maxim Oei, Richard Edens, Roeland Salij
	@date      : 22-08-2014
	@copyright : Mendix Technology BV
	@license   : Apache License, Version 2.0, January 2004

	Documentation
    ========================
	Complete any delivery service App with this Signature widget.
    This widget allows you to save a signature to an attribute.
*/
(function() {
    require([
        'mxui/widget/_WidgetBase', 'dijit/_Widget', 'dijit/_TemplatedMixin',
        'mxui/dom', 'dojo/dom', 'dojo/dom-construct', 'dojo/ready', 'dojo/query', 'dojo/dom-prop', 'dojo/dom-geometry', 'dojo/dom-class', 'dojo/dom-style', 'dojo/on', 'dojo/_base/lang', 'dojo/_base/declare'
    ], function(_WidgetBase, _Widget, _Templated, domMx,dom, domConstruct, domReady, domQuery, domProp, domGeom, domClass, domStyle, on, lang, declare) {

        return declare('Signature.widget.Signature', [ _WidgetBase, _Widget, _Templated ], {
            _contextGuid: null,
            _contextObj: null,
            _handle: null,

            _smoothingpct: 0.9,

            _mxObject: null,
            _attribute: null,
            _path: null,

            _canvas: null,
            _reset: null,
            _context: null,

            _timer: null,

            _touchSupport: false,
            _bezierBuf: null,

            templatePath: dojo.moduleUrl('Signature', 'widget/templates/Signature.html'),

            postCreate: function() {
                console.log('Signature - postCreate');

                this._setupWidget();
                this._createUI();
                this._setupEvents();
            },

            startup: function() {
                this.set('disabled', this.readonly);

                var path = this.dataUrl.split('/');
                this._attribute = path[path.length - 1];
                this._path = path.splice(0, path.length - 1);
            },

            update: function(obj, callback) {
                if (obj) {
                    obj.fetch(this._path, dojo.hitch(this, function(obj) {
                        this._updateObject(obj, callback);
                    }));
                } else {
                    this._updateObject(null, callback);
                }
            },

            enable: function() {
                dojo.attr(this._reset, 'disabled', false);
                dojo.removeClass(this.domNode, 'signhereSignature_disabled');
            },

            disable: function() {
                dojo.attr(this._reset, 'disabled', true);
                dojo.addClass(this.domNode, 'signhereSignature_disabled');
            },

            _setupWidget: function() {
                var t = this._smoothingpct,
                    u = 1 - t;

                this._bezier1 = t * t * t;
                this._bezier2 = 3 * t * t * u;
                this._bezier3 = 3 * t * u * u;
                this._bezier4 = u * u * u;

                this._bezierBuf = [];

                this._touchSupport = ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch;
            },

            _createUI: function() {
                var $ = domConstruct.create,
                    sizeProperties = {
                        'width': this.width + 'px',
                        'height': this.height + 'px'
                    },
                    allProperties = lang.mixin(sizeProperties, {
                        'style': 'border: ' + this.gridborder + 'px solid ' + this.gridcolor
                    });

                this._canvas = $('canvas', allProperties);
                this._image  = $('img', allProperties);

                this._reset = $('button', {
                    'class': 'btn',
                    'style': {
                        'width': (this.width + 4) + 'px'
                    },
                    'innerHTML':  this.resetcaption
                });

                this.domNode.appendChild(this._canvas);
                this.domNode.appendChild(this._image);
                this.domNode.appendChild(this._reset);

                domStyle.set(this.domNode, sizeProperties);

                this._context = this._canvas.getContext('2d');
            },

            _updateObject: function(obj, callback) {
                this._mxObject = obj;

                this._resetCanvas();

                if (this._attribute && obj && obj.get(this._attribute)) {
                    this._showImage();
                } else {
                    this._hideImage();
                }

                this.set('disabled', obj ? false : true);

                mendix.lang.nullExec(callback);
            },

            _showImage: function() {
                this._image.src = this._mxObject.get(this.dataUrl);

                dojo.replaceClass(this.domNode, 'signature_set', 'signature_unset');
            },

            _hideImage: function() {
                this._image.src = '';

                domClass.replace(this.domNode, 'signature_unset', 'signature_set');
            },

            _drawGrid: function() {
                if (!this.showgrid) return;

                var x = this.gridx,
                    y = this.gridy,
                    context = this._context,
                    width   = this._canvas.width,
                    height  = this._canvas.height;

                context.beginPath();

                for (; x < width; x += this.gridx) {
                    context.moveTo(x, 0);
                    context.lineTo(x, this._canvas.height);
                }

                for (; y < height; y += this.gridy) {
                    context.moveTo(0, y);
                    context.lineTo(this._canvas.width, y);
                }

                context.lineWidth = 1;
                context.strokeStyle = this.gridcolor;
                context.stroke();
            },

            _setupEvents: function() {
                this.connect(this._canvas, (this._touchSupport ? 'touchstart' : 'mousedown'), '_eventMouseDown');
                this.connect(this._reset, 'click', dojo.hitch(this, this._eventResetClicked));

                // This prevents the 'dragging image' annoyance when someone tries to
                // draw on the image.
                this.connect(
                    this._image,
                    this._touchSupport ? 'touchstart' : 'mousedown',
                    function(e) {
                        dojo.stopEvent(e);
                        return false;
                    }
                );
            },

            _getCoords: function(e) {
                var pos   = dojo.position(this._canvas, true),
                    pageX = e.targetTouches ? e.targetTouches[0].pageX : e.pageX,
                    pageY = e.targetTouches ? e.targetTouches[0].pageY : e.pageY,
                    x     = Math.floor(pageX - pos.x),
                    y     = Math.floor(pageY - pos.y);

                return { x: x, y: y };
            },

            _beginCurve: function(e) {
                this._bezierBuf = [];
                this._handlers = [];

                this._stopTimeout();

                this._context.strokeStyle = this.pencolor;
                this._context.lineJoin    = 'round';
                this._context.lineWidth   = this.pensize;

                this._context.beginPath();

                this._handlers.push(this.connect(window, this._touchSupport ? 'touchmove' : 'mousemove', dojo.hitch(this, this._eventMouseMove)));
                this._handlers.push(this.connect(window, this._touchSupport ? 'touchend' : 'mouseup', dojo.hitch(this, this._eventMouseUp)));
            },

            _updateCurve: function(e) {
                console.log(this.id + '.updateCurve');

                var context = this._context,
                    buf = this._bezierBuf,
                    pos = this._getCoords(e),
                    bp = null;

                this._stopTimeout();

                if (this._movedTo) {
                    buf.push(pos);

                    if (buf.length === 4) {
                        bp = this._bezierPoint.apply(this, buf);

                        context.lineTo(bp.x, bp.y);
                        context.stroke();

                        buf.shift();
                        buf[0] = bp;
                    }
                } else {
                    context.moveTo(pos.x, pos.y);
                    this._movedTo = true;
                }
            },

            _endCurve: function() {
                var buf = this._bezierBuf,
                    i = 0,
                    pos = null,
                    j = 0,
                    handlers = null;

                this._stopTimeout();

                // Finish last points in Bezier buffer
                while(buf[i]) {
                    pos = buf[i];
                    this._context.lineTo(pos.x, pos.y);
                    i++;
                }
                this._context.stroke();

                this._bezierBuf = null;

                while(this._handlers[j]){
                    handlers = this._handlers[j];
                    this.disconnect(handlers);
                    j++;
                }

                this._timer = setTimeout(dojo.hitch(this, this._finalizeSignature), this.timeout);
            },

            _eventMouseDown: function(e) {
                console.log(this.id + '._eventMouseDown');

                dojo.stopEvent(e);

                if (!this.get('disabled')) {
                    this._beginCurve(e);
                }
            },

            _eventMouseMove: function(e) {
                console.log(this.id + '._eventMouseMove');

                dojo.stopEvent(e);

                this._updateCurve(e);
            },

            _eventMouseUp: function(e) {
                console.log(this.id + '._eventMouseUp');

                dojo.stopEvent(e);

                this._endCurve();
            },

            _eventResetClicked: function(e) {
                console.log(this.id + '._eventResetClicked');

                if (!this.get('disabled')) {
                    this._resetMxObject();
                    this._resetCanvas();

                    this._hideImage();
                }
            },

            _resetCanvas: function() {
                window.alert("Reset the canvas");
                console.log(this.id + '.resetCanvas');

                this._context.clearRect(0, 0, this._canvas.width, this._canvas.height);

                this._bezierBuf = [];

                this._drawGrid();
            },

            _resetMxObject: function() {
                console.log(this.id + '.resetMxObject');

                this._mxObject.set(this.dataUrl, '');
            },

            _stopTimeout: function() {
                console.log(this.id + '._stopTimeout');

                if (this._timer) {
                    clearTimeout(this._timer);
                }
            },

            _finalizeSignature: function() {
                console.log(this.id + '.finalizeSignature');

                var mxobj = this._mxObject;
                if (mxobj) {
                    if (mxobj.has(this.dataUrl)) {
                        mxobj.set(this.dataUrl, this._canvas.toDataURL());
                    } else {
                        logger.error(this.id + '.finalizeSignature: no dataUrl attribute found.');
                    }
                }

                this._showImage();
            },

            _bezierPoint: function(c1, c2, c3, c4) {
                return {
                    x: c1.x * this._bezier1 + c2.x * this._bezier2 +
                        c3.x * this._bezier3 + c4.x * this._bezier4,
                    y: c1.y * this._bezier1 + c2.y * this._bezier2 +
                        c3.y * this._bezier3 + c4.y * this._bezier4
                };
            },

            _setDisabledAttr: function(value) {
                var argumentsCopy = [];

                if (typeof this._attribute === 'undefined' || this._attribute === null) {
                    this._attribute = '';
                }
                if (this.readonly || !this._mxObject || this._mxObject.isReadonlyAttr(this._attribute)) {
                    value = true;
                }

                return this.inherited(arguments, [ value ]);
            }
        });
    });
}());
<commit_msg>Removed window alert.<commit_after>/*jslint white: true nomen: true plusplus: true */
/*global mx, mxui, window, document, mendix, dojo, require, console, define, module, logger */
/**
	Signature
	========================

	@file      : Signature.js
	@version   : 2.1
	@author    : Maxim Oei, Richard Edens, Roeland Salij
	@date      : 22-08-2014
	@copyright : Mendix Technology BV
	@license   : Apache License, Version 2.0, January 2004

	Documentation
    ========================
	Complete any delivery service App with this Signature widget.
    This widget allows you to save a signature to an attribute.
*/
(function() {
    require([
        'mxui/widget/_WidgetBase', 'dijit/_Widget', 'dijit/_TemplatedMixin',
        'mxui/dom', 'dojo/dom', 'dojo/dom-construct', 'dojo/ready', 'dojo/query', 'dojo/dom-prop', 'dojo/dom-geometry', 'dojo/dom-class', 'dojo/dom-style', 'dojo/on', 'dojo/_base/lang', 'dojo/_base/declare'
    ], function(_WidgetBase, _Widget, _Templated, domMx,dom, domConstruct, domReady, domQuery, domProp, domGeom, domClass, domStyle, on, lang, declare) {

        return declare('Signature.widget.Signature', [ _WidgetBase, _Widget, _Templated ], {
            _contextGuid: null,
            _contextObj: null,
            _handle: null,

            _smoothingpct: 0.9,

            _mxObject: null,
            _attribute: null,
            _path: null,

            _canvas: null,
            _reset: null,
            _context: null,

            _timer: null,

            _touchSupport: false,
            _bezierBuf: null,

            templatePath: dojo.moduleUrl('Signature', 'widget/templates/Signature.html'),

            postCreate: function() {
                console.log('Signature - postCreate');

                this._setupWidget();
                this._createUI();
                this._setupEvents();
            },

            startup: function() {
                this.set('disabled', this.readonly);

                var path = this.dataUrl.split('/');
                this._attribute = path[path.length - 1];
                this._path = path.splice(0, path.length - 1);
            },

            update: function(obj, callback) {
                if (obj) {
                    obj.fetch(this._path, dojo.hitch(this, function(obj) {
                        this._updateObject(obj, callback);
                    }));
                } else {
                    this._updateObject(null, callback);
                }
            },

            enable: function() {
                dojo.attr(this._reset, 'disabled', false);
                dojo.removeClass(this.domNode, 'signhereSignature_disabled');
            },

            disable: function() {
                dojo.attr(this._reset, 'disabled', true);
                dojo.addClass(this.domNode, 'signhereSignature_disabled');
            },

            _setupWidget: function() {
                var t = this._smoothingpct,
                    u = 1 - t;

                this._bezier1 = t * t * t;
                this._bezier2 = 3 * t * t * u;
                this._bezier3 = 3 * t * u * u;
                this._bezier4 = u * u * u;

                this._bezierBuf = [];

                this._touchSupport = ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch;
            },

            _createUI: function() {
                var $ = domConstruct.create,
                    sizeProperties = {
                        'width': this.width + 'px',
                        'height': this.height + 'px'
                    },
                    allProperties = lang.mixin(sizeProperties, {
                        'style': 'border: ' + this.gridborder + 'px solid ' + this.gridcolor
                    });

                this._canvas = $('canvas', allProperties);
                this._image  = $('img', allProperties);

                this._reset = $('button', {
                    'class': 'btn',
                    'style': {
                        'width': (this.width + 4) + 'px'
                    },
                    'innerHTML':  this.resetcaption
                });

                this.domNode.appendChild(this._canvas);
                this.domNode.appendChild(this._image);
                this.domNode.appendChild(this._reset);

                domStyle.set(this.domNode, sizeProperties);

                this._context = this._canvas.getContext('2d');
            },

            _updateObject: function(obj, callback) {
                this._mxObject = obj;

                this._resetCanvas();

                if (this._attribute && obj && obj.get(this._attribute)) {
                    this._showImage();
                } else {
                    this._hideImage();
                }

                this.set('disabled', obj ? false : true);

                mendix.lang.nullExec(callback);
            },

            _showImage: function() {
                this._image.src = this._mxObject.get(this.dataUrl);

                dojo.replaceClass(this.domNode, 'signature_set', 'signature_unset');
            },

            _hideImage: function() {
                this._image.src = '';

                domClass.replace(this.domNode, 'signature_unset', 'signature_set');
            },

            _drawGrid: function() {
                if (!this.showgrid) return;

                var x = this.gridx,
                    y = this.gridy,
                    context = this._context,
                    width   = this._canvas.width,
                    height  = this._canvas.height;

                context.beginPath();

                for (; x < width; x += this.gridx) {
                    context.moveTo(x, 0);
                    context.lineTo(x, this._canvas.height);
                }

                for (; y < height; y += this.gridy) {
                    context.moveTo(0, y);
                    context.lineTo(this._canvas.width, y);
                }

                context.lineWidth = 1;
                context.strokeStyle = this.gridcolor;
                context.stroke();
            },

            _setupEvents: function() {
                this.connect(this._canvas, (this._touchSupport ? 'touchstart' : 'mousedown'), '_eventMouseDown');
                this.connect(this._reset, 'click', dojo.hitch(this, this._eventResetClicked));

                // This prevents the 'dragging image' annoyance when someone tries to
                // draw on the image.
                this.connect(
                    this._image,
                    this._touchSupport ? 'touchstart' : 'mousedown',
                    function(e) {
                        dojo.stopEvent(e);
                        return false;
                    }
                );
            },

            _getCoords: function(e) {
                var pos   = dojo.position(this._canvas, true),
                    pageX = e.targetTouches ? e.targetTouches[0].pageX : e.pageX,
                    pageY = e.targetTouches ? e.targetTouches[0].pageY : e.pageY,
                    x     = Math.floor(pageX - pos.x),
                    y     = Math.floor(pageY - pos.y);

                return { x: x, y: y };
            },

            _beginCurve: function(e) {
                this._bezierBuf = [];
                this._handlers = [];

                this._stopTimeout();

                this._context.strokeStyle = this.pencolor;
                this._context.lineJoin    = 'round';
                this._context.lineWidth   = this.pensize;

                this._context.beginPath();

                this._handlers.push(this.connect(window, this._touchSupport ? 'touchmove' : 'mousemove', dojo.hitch(this, this._eventMouseMove)));
                this._handlers.push(this.connect(window, this._touchSupport ? 'touchend' : 'mouseup', dojo.hitch(this, this._eventMouseUp)));
            },

            _updateCurve: function(e) {
                console.log(this.id + '.updateCurve');

                var context = this._context,
                    buf = this._bezierBuf,
                    pos = this._getCoords(e),
                    bp = null;

                this._stopTimeout();

                if (this._movedTo) {
                    buf.push(pos);

                    if (buf.length === 4) {
                        bp = this._bezierPoint.apply(this, buf);

                        context.lineTo(bp.x, bp.y);
                        context.stroke();

                        buf.shift();
                        buf[0] = bp;
                    }
                } else {
                    context.moveTo(pos.x, pos.y);
                    this._movedTo = true;
                }
            },

            _endCurve: function() {
                var buf = this._bezierBuf,
                    i = 0,
                    pos = null,
                    j = 0,
                    handlers = null;

                this._stopTimeout();

                // Finish last points in Bezier buffer
                while(buf[i]) {
                    pos = buf[i];
                    this._context.lineTo(pos.x, pos.y);
                    i++;
                }
                this._context.stroke();

                this._bezierBuf = null;

                while(this._handlers[j]){
                    handlers = this._handlers[j];
                    this.disconnect(handlers);
                    j++;
                }

                this._timer = setTimeout(dojo.hitch(this, this._finalizeSignature), this.timeout);
            },

            _eventMouseDown: function(e) {
                console.log(this.id + '._eventMouseDown');

                dojo.stopEvent(e);

                if (!this.get('disabled')) {
                    this._beginCurve(e);
                }
            },

            _eventMouseMove: function(e) {
                console.log(this.id + '._eventMouseMove');

                dojo.stopEvent(e);

                this._updateCurve(e);
            },

            _eventMouseUp: function(e) {
                console.log(this.id + '._eventMouseUp');

                dojo.stopEvent(e);

                this._endCurve();
            },

            _eventResetClicked: function(e) {
                console.log(this.id + '._eventResetClicked');

                if (!this.get('disabled')) {
                    this._resetMxObject();
                    this._resetCanvas();

                    this._hideImage();
                }
            },

            _resetCanvas: function() {
                console.log(this.id + '.resetCanvas');

                this._context.clearRect(0, 0, this._canvas.width, this._canvas.height);

                this._bezierBuf = [];

                this._drawGrid();
            },

            _resetMxObject: function() {
                console.log(this.id + '.resetMxObject');

                this._mxObject.set(this.dataUrl, '');
            },

            _stopTimeout: function() {
                console.log(this.id + '._stopTimeout');

                if (this._timer) {
                    clearTimeout(this._timer);
                }
            },

            _finalizeSignature: function() {
                console.log(this.id + '.finalizeSignature');

                var mxobj = this._mxObject;
                if (mxobj) {
                    if (mxobj.has(this.dataUrl)) {
                        mxobj.set(this.dataUrl, this._canvas.toDataURL());
                    } else {
                        logger.error(this.id + '.finalizeSignature: no dataUrl attribute found.');
                    }
                }

                this._showImage();
            },

            _bezierPoint: function(c1, c2, c3, c4) {
                return {
                    x: c1.x * this._bezier1 + c2.x * this._bezier2 +
                        c3.x * this._bezier3 + c4.x * this._bezier4,
                    y: c1.y * this._bezier1 + c2.y * this._bezier2 +
                        c3.y * this._bezier3 + c4.y * this._bezier4
                };
            },

            _setDisabledAttr: function(value) {
                var argumentsCopy = [];

                if (typeof this._attribute === 'undefined' || this._attribute === null) {
                    this._attribute = '';
                }
                if (this.readonly || !this._mxObject || this._mxObject.isReadonlyAttr(this._attribute)) {
                    value = true;
                }

                return this.inherited(arguments, [ value ]);
            }
        });
    });
}());
<|endoftext|>


<commit_before>const { getOAuthRequestToken, getAccessToken } = require('../sharer/twitterHelper')
const Twitter = require('twitter')
const chalk = require('chalk')

// Init
const init = ({ twitter_consumer_key, twitter_consumer_secret }, app) => {
  const consumerKey = twitter_consumer_key
  const consumerSecret = twitter_consumer_secret

  if (!consumerKey || !consumerSecret) {
    console.warn(chalk.bgYellow('TWITTER consumerSecret not found! Therefore TWITTER feature will not work'))
    return
  }

  // EXPRESS
  app.get('/twitter/request_token', (req, res) => {
    try {
      let { oauth_callback } = req.query
      oauth_callback = Buffer.from(oauth_callback, 'base64').toString('utf8')
      getOAuthRequestToken({ consumerKey, consumerSecret, oauth_callback })
        .then(result => res.send(JSON.stringify(result)))
        .catch(error => {
          console.log('/twitter/request_token error/getOAuthRequestToken', { error })
          res.status(500).send(error.toString())
        })
    } catch (error) {
      console.log('/twitter/request_token error', { error })
      res.status(500).send(error.toString())
    }
  })

  // TWITTER hook callback
  app.get('/twitter/access_token', (req, res) => {
    try {
      const { oauth_token, oauth_verifier, oauth_token_secret } = req.query
      let result = getAccessToken({ oauth_token, oauth_token_secret, oauth_verifier, consumerKey, consumerSecret })
        .then(result => res.send(JSON.stringify(result)))
        .catch(error => {
          console.log('/twitter/access_token error/getAccessToken', { error })
          res.status(500).send(error.toString())
        })
    } catch (error) {
      console.log('/twitter/access_token error', { error })
      res.status(500).send(error.toString())
    }
  })

  app.post('/twitter/post', (req, res) => {
    try {
      const { accessToken, status } = req.body
      const tokenSplit = accessToken.split('_')
      const oauth_access_token = tokenSplit[0]
      const oauth_access_token_secret = tokenSplit[1]

      const client = new Twitter({
        consumer_key: consumerKey,
        consumer_secret: consumerSecret,
        access_token_key: oauth_access_token,
        access_token_secret: oauth_access_token_secret
      })

      client.post('statuses/update', { status }, (error, tweet, response) => {
        if (error) {
          console.log({ error })
          return res.status(500).send(JSON.stringify({ error }))
        }
        res.send(JSON.stringify({ tweet }))
        // console.log(tweet);  // Tweet body.
        // console.log(response);  // Raw response object.
      })
    } catch (error) {
      res.status(500).send(error.toString())
    }
  })
}
module.exports = init
<commit_msg>chore(TWITTER): refactor unused vars<commit_after>const { getOAuthRequestToken, getAccessToken } = require('../sharer/twitterHelper')
const Twitter = require('twitter')
const chalk = require('chalk')

// Init
const init = ({ twitter_consumer_key, twitter_consumer_secret }, app) => {
  const consumerKey = twitter_consumer_key
  const consumerSecret = twitter_consumer_secret

  if (!consumerKey || !consumerSecret) {
    console.warn(chalk.bgYellow('TWITTER consumerSecret not found! Therefore TWITTER feature will not work'))
    return
  }

  // EXPRESS
  app.get('/twitter/request_token', (req, res) => {
    try {
      let { oauth_callback } = req.query
      oauth_callback = Buffer.from(oauth_callback, 'base64').toString('utf8')
      getOAuthRequestToken({ consumerKey, consumerSecret, oauth_callback })
        .then(result => res.send(JSON.stringify(result)))
        .catch(error => {
          console.log('/twitter/request_token error/getOAuthRequestToken', { error })
          res.status(500).send(error.toString())
        })
    } catch (error) {
      console.log('/twitter/request_token error', { error })
      res.status(500).send(error.toString())
    }
  })

  // TWITTER hook callback
  app.get('/twitter/access_token', (req, res) => {
    try {
      const { oauth_token, oauth_verifier, oauth_token_secret } = req.query
      getAccessToken({ oauth_token, oauth_token_secret, oauth_verifier, consumerKey, consumerSecret })
        .then(result => res.send(JSON.stringify(result)))
        .catch(error => {
          console.log('/twitter/access_token error/getAccessToken', { error })
          res.status(500).send(error.toString())
        })
    } catch (error) {
      console.log('/twitter/access_token error', { error })
      res.status(500).send(error.toString())
    }
  })

  app.post('/twitter/post', (req, res) => {
    try {
      const { accessToken, status } = req.body
      const tokenSplit = accessToken.split('_')
      const oauth_access_token = tokenSplit[0]
      const oauth_access_token_secret = tokenSplit[1]

      const client = new Twitter({
        consumer_key: consumerKey,
        consumer_secret: consumerSecret,
        access_token_key: oauth_access_token,
        access_token_secret: oauth_access_token_secret
      })

      client.post('statuses/update', { status }, (error, tweet, response) => {
        if (error) {
          console.log({ error })
          return res.status(500).send(JSON.stringify({ error }))
        }
        res.send(JSON.stringify({ tweet }))
        // console.log(tweet);  // Tweet body.
        // console.log(response);  // Raw response object.
      })
    } catch (error) {
      res.status(500).send(error.toString())
    }
  })
}
module.exports = init
<|endoftext|>


<commit_before>// stats.js
// ------------------------------------------------------------------
//
// created: Mon Oct 15 17:23:24 2018
// last saved: <2021-May-04 18:10:38>

/* jshint esversion:9, node:true, strict:implied */

const common      = require('./common.js'),
      utility     = require('./utility.js'),
      promiseWrap = require('./promiseWrap.js'),
      urljoin     = require('url-join'),
      sprintf     = require('sprintf-js').sprintf,
      request     = require('request'),
      dateFormat  = require('dateformat');

function utcOffset_apigeeTimeFormat(date) {
  var s = dateFormat(date, "isoUtcDateTime");
  s = s.slice(0, -4);
  return s.slice(-5);
}

function getTimeRange(start, end) {
  start = dateFormat(start, 'mm/dd/yyyy') + ' ' + utcOffset_apigeeTimeFormat(start);
  end = dateFormat(end, 'mm/dd/yyyy') + ' ' + utcOffset_apigeeTimeFormat(end);
  return start + '~' + end;
}

function Stat(conn) {this.conn = conn;}

Stat.prototype.get = promiseWrap(function(options, cb) {
  // GET "$mgmtserver/v1/o/$ORG/e/$ENV/stats/apis?select=sum(message_count)&timeRange=01/01/2018%2000:00~08/01/2018%2000:00&timeUnit=month"

  // var options = {
  //       environment : 'test',
  //       dimension: 'apis',
  //       metric: 'sum(message_count)',
  //       startTime: startTime,
  //       endTime : endTime,
  //       timeUnit : 'month',
  //       cacheCheck : fn
  //     };

  if ( ! cb) { cb = options; options = {}; }
  var conn = this.conn;
  var env = options.environmentName || options.environment;
  if (!env) {
    throw new Error("missing environment name");
  }
  if (!options.dimension) {
    throw new Error("missing dimension");
  }
  if (!options.metric) {
    throw new Error("missing metric");
  }
  common.insureFreshToken(conn, function(requestOptions) {
    var query = sprintf('?select=%s&timeUnit=%s&timeRange=%s',
                        options.metric,
                        options.timeUnit,
                        getTimeRange(options.startTime, options.endTime));

    requestOptions.url =
      urljoin(conn.urlBase, 'e', env, 'stats', options.dimension) + query;

    if (conn.verbosity>0) {
      utility.logWrite(sprintf('GET %s', requestOptions.url));
    }

    // it takes a long time to retrieve some stats data. So let's
    // allow the use of a cache via an upcall.
    if (typeof options.cacheCheck == 'function') {
      let uniquifier = sprintf('%s-%s-%s-%s-%s-%s-%s',
                               conn.orgname, env, options.dimension, options.metric,
                               dateFormat(options.startTime, 'yyyymmdd'),
                               dateFormat(options.endTime, 'yyyymmdd'), options.timeUnit);
      let cacheResponse = options.cacheCheck(requestOptions.url, uniquifier);
      if (cacheResponse) {
        if (cacheResponse.data) {
          return cb(null, {data: JSON.parse(cacheResponse.data) });
        }
        else if (cacheResponse.cachefile) {
          return request.get(requestOptions, common.callback(conn, [200], function(e, data){
            cb(e, {cachefile: cacheResponse.cachefile, data:data});
          }));
        }
      }
    }
    return request.get(requestOptions, common.callback(conn, [200], function(e, data){
      cb(e, {data:data});
    }));
  });
});

module.exports = Stat;
<commit_msg>add smarts for percentiles in stat.js<commit_after>// stats.js
// ------------------------------------------------------------------
//
// created: Mon Oct 15 17:23:24 2018
// last saved: <2021-July-28 14:24:06>

/* jshint esversion:9, node:true, strict:implied */

const common      = require('./common.js'),
      utility     = require('./utility.js'),
      promiseWrap = require('./promiseWrap.js'),
      urljoin     = require('url-join'),
      sprintf     = require('sprintf-js').sprintf,
      request     = require('request'),
      dateFormat  = require('dateformat');

function utcOffset_apigeeTimeFormat(date) {
  var s = dateFormat(date, "isoUtcDateTime");
  s = s.slice(0, -4);
  return s.slice(-5);
}

function getTimeRange(start, end) {
  start = dateFormat(start, 'mm/dd/yyyy') + ' ' + utcOffset_apigeeTimeFormat(start);
  end = dateFormat(end, 'mm/dd/yyyy') + ' ' + utcOffset_apigeeTimeFormat(end);
  return start + '~' + end;
}

function Stat(conn) {this.conn = conn;}

Stat.prototype.get = promiseWrap(function(options, cb) {
  // GET "$mgmtserver/v1/o/$ORG/e/$ENV/stats/apis?select=sum(message_count)&timeRange=01/01/2018%2000:00~08/01/2018%2000:00&timeUnit=month"

  // var options = {
  //       environment : 'test',
  //       dimension: 'apis',
  //       metric: 'sum(message_count)',
  //       startTime: startTime,
  //       endTime : endTime,
  //       timeUnit : 'month',
  //       limit : 1024,
  //       optimize : true/false,
  //       cacheCheck : fn
  //     };

  if ( ! cb) { cb = options; options = {}; }
  var conn = this.conn;
  var env = options.environmentName || options.environment;
  if (!env) {
    throw new Error("missing environment name");
  }
  if (!options.dimension) {
    throw new Error("missing dimension");
  }
  if (!options.metric) {
    throw new Error("missing metric");
  }
  common.insureFreshToken(conn, function(requestOptions) {
    var query = sprintf('?select=%s&timeUnit=%s&timeRange=%s',
                        options.metric,
                        options.timeUnit,
                        getTimeRange(options.startTime, options.endTime));

    if (options.limit) {
      query += '&limit=' + options.limit;
    }
    if (options.optimize) {
      query += '&_optimize=js';
    }
    if (options.metric.indexOf('percentile')>=0) {
      query += '&t=agg_percentile';
    }
    if (options.filter) {
      // filter=(apiproxy%20eq%20%%27${APIPROXY}%27)
      query += '&filter=' + options.filter;
    }
    requestOptions.url =
      urljoin(conn.urlBase, 'e', env, 'stats', options.dimension) + query;

    if (conn.verbosity>0) {
      utility.logWrite(sprintf('GET %s', requestOptions.url));
    }

    // it takes a long time to retrieve some stats data. So let's
    // allow the use of a cache via an upcall.
    if (typeof options.cacheCheck == 'function') {
      let uniquifier = sprintf('%s-%s-%s-%s-%s-%s-%s',
                               conn.orgname, env, options.dimension, options.metric,
                               dateFormat(options.startTime, 'yyyymmdd'),
                               dateFormat(options.endTime, 'yyyymmdd'), options.timeUnit);
      let cacheResponse = options.cacheCheck(requestOptions.url, uniquifier);
      if (cacheResponse) {
        if (cacheResponse.data) {
          return cb(null, {data: JSON.parse(cacheResponse.data) });
        }
        else if (cacheResponse.cachefile) {
          return request.get(requestOptions, common.callback(conn, [200], function(e, data){
            cb(e, {cachefile: cacheResponse.cachefile, data:data});
          }));
        }
      }
    }
    return request.get(requestOptions, common.callback(conn, [200], function(e, data){
      cb(e, {data:data});
    }));
  });
});

module.exports = Stat;
<|endoftext|>


<commit_before>/**
 * Copyright 2012-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"). You
 * may not use this file except in compliance with the License. A copy of
 * the License is located at
 *
 *     http://aws.amazon.com/apache2.0/
 *
 * or in the "license" file accompanying this file. This file is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
 * ANY KIND, either express or implied. See the License for the specific
 * language governing permissions and limitations under the License.
 */

var AWS = require('./core');
require('./sequential_executor');
require('./service_interface/json');
require('./service_interface/query');
require('./service_interface/rest');
require('./service_interface/rest_json');
require('./service_interface/rest_xml');

/**
 * The namespace used to register global event listeners for request building
 * and sending.
 */
AWS.EventListeners = {
  /**
   * @!attribute VALIDATE_CREDENTIALS
   *   A request listener that validates whether the request is being
   *   sent with credentials.
   *   Handles the {AWS.Request~validate 'validate' Request event}
   *   @example Sending a request without validating credentials
   *     var listener = AWS.EventListeners.Core.VALIDATE_CREDENTIALS;
   *     request.removeListener('validate', listener);
   *   @readonly
   *   @return [Function]
   * @!attribute VALIDATE_REGION
   *   A request listener that validates whether the region is set
   *   for a request.
   *   Handles the {AWS.Request~validate 'validate' Request event}
   *   @example Sending a request without validating region configuration
   *     var listener = AWS.EventListeners.Core.VALIDATE_REGION;
   *     request.removeListener('validate', listener);
   *   @readonly
   *   @return [Function]
   * @!attribute VALIDATE_PARAMETERS
   *   A request listener that validates input parameters in a request.
   *   Handles the {AWS.Request~validate 'validate' Request event}
   *   @example Sending a request without validating parameters
   *     var listener = AWS.EventListeners.Core.VALIDATE_PARAMETERS;
   *     request.removeListener('validate', listener);
   *   @example Disable parameter validation globally
   *     AWS.EventListeners.Core.removeListener('validate',
   *       AWS.EventListeners.Core.VALIDATE_REGION);
   *   @readonly
   *   @return [Function]
   * @!attribute SEND
   *   A request listener that initiates the HTTP connection for a
   *   request being sent. Handles the {AWS.Request~send 'send' Request event}
   *   @example Replacing the HTTP handler
   *     var listener = AWS.EventListeners.Core.SEND;
   *     request.removeListener('send', listener);
   *     request.on('send', function(response) {
   *       customHandler.send(response);
   *     });
   *   @return [Function]
   *   @readonly
   * @!attribute HTTP_DATA
   *   A request listener that reads data from the HTTP connection in order
   *   to build the response data.
   *   Handles the {AWS.Request~httpData 'httpData' Request event}.
   *   Remove this handler if you are overriding the 'httpData' event and
   *   do not want extra data processing and buffering overhead.
   *   @example Disabling default data processing
   *     var listener = AWS.EventListeners.Core.HTTP_DATA;
   *     request.removeListener('httpData', listener);
   *   @return [Function]
   *   @readonly
   */
  Core: {} /* doc hack */
};

AWS.EventListeners = {
  Core: new AWS.SequentialExecutor().addNamedListeners(function(add, addAsync) {
    addAsync('VALIDATE_CREDENTIALS', 'validate',
        function VALIDATE_CREDENTIALS(req, doneCallback) {
      req.service.config.getCredentials(function(err) {
        if (err) {
          err = AWS.util.error(err,
            {code: 'SigningError', message: 'Missing credentials in config'});
        }
        doneCallback(err);
      });
    });

    add('VALIDATE_REGION', 'validate', function VALIDATE_REGION(req) {
      if (!req.service.config.region && !req.service.api.globalEndpoint) {
        throw AWS.util.error(new Error(),
          {code: 'SigningError', message: 'Missing region in config'});
      }
    });

    add('VALIDATE_PARAMETERS', 'validate', function VALIDATE_PARAMETERS(req) {
      var rules = req.service.api.operations[req.operation].input;
      new AWS.ParamValidator().validate(rules, req.params);
    });

    add('SET_CONTENT_LENGTH', 'afterBuild', function SET_CONTENT_LENGTH(req) {
      if (req.httpRequest.headers['Content-Length'] === undefined) {
        var length = AWS.util.string.byteLength(req.httpRequest.body);
        req.httpRequest.headers['Content-Length'] = length;
      }
    });

    add('SET_HTTP_HOST', 'afterBuild', function SET_HTTP_HOST(req) {
      req.httpRequest.headers['Host'] = req.httpRequest.endpoint.hostname;
    });

    addAsync('SIGN', 'sign', function SIGN(req, doneCallback) {
      if (!req.service.api.signatureVersion) return doneCallback(); // none

      req.service.config.getCredentials(function (err, credentials) {
        try {
          if (err) return doneCallback(err);

          var date = AWS.util.date.getDate();
          var sigVersion = req.service.api.signatureVersion;
          var SignerClass = AWS.Signers.RequestSigner.getVersion(sigVersion);
          var signer = new SignerClass(req.httpRequest,
            req.service.api.signingName || req.service.api.endpointPrefix);

          // clear old authorization headers
          delete req.httpRequest.headers['Authorization'];
          delete req.httpRequest.headers['Date'];
          delete req.httpRequest.headers['X-Amz-Date'];

          // add new authorization
          signer.addAuthorization(credentials, date);
          doneCallback();
        } catch (e) {
          doneCallback(e);
        }
      });
    });

    add('SETUP_ERROR', 'extractError', function SETUP_ERROR(resp) {
      if (this.service.successfulResponse(resp, this)) {
        // throwing null will stop the error extraction chain
        // but will not set an error for data extraction
        throw null;
      }

      resp.error = AWS.util.error(new Error(),
        {code: 'UnknownError', message: 'An unknown error occurred.'});
      resp.data = null;
    });

    add('SETUP_DATA', 'extractData', function SETUP_DATA(resp) {
      resp.data = {};
      resp.error = null;
    });

    add('SEND', 'send', function SEND(resp) {
      function callback(httpResp) {
        resp.httpStream = httpResp;

        var headers = [httpResp.statusCode, httpResp.headers, resp];
        resp.request.emitEvent('httpHeaders', headers);

        if (resp.httpStream) {
          if (AWS.HttpClient.streamsApiVersion === 2) { // streams2 API check
            httpResp.on('readable', function onReadable() {
              var data = httpResp.read();
              if (data !== null) {
                resp.request.emitEvent('httpData', [data, resp]);
              }
            });
          } else { // legacy streams API
            httpResp.on('data', function onData(data) {
              resp.request.emitEvent('httpData', [data, resp]);
            });
          }

          httpResp.on('end', function onEnd() {
            resp.request.emitEvent('httpDone', [resp]);
          });
        }
      }

      function error(err) {
        err = AWS.util.error(err, {
          code: 'NetworkingError',
          region: resp.request.httpRequest.region,
          hostname: resp.request.httpRequest.endpoint.hostname,
          retryable: true
        });
        resp.request.emitEvent('httpError', [err, resp]);
      }

      var http = AWS.HttpClient.getInstance();
      var httpOptions = resp.request.service.config.httpOptions || {};
      http.handleRequest(this.httpRequest, httpOptions, callback, error);
    });

    add('HTTP_HEADERS', 'httpHeaders',
        function HTTP_HEADERS(statusCode, headers, resp) {
      resp.httpResponse.statusCode = statusCode;
      resp.httpResponse.headers = headers;
      resp.httpResponse.body = new Buffer('');
      resp.httpResponse.buffers = [];
    });

    add('HTTP_DATA', 'httpData', function HTTP_DATA(chunk, resp) {
      if (chunk) resp.httpResponse.buffers.push(chunk);
    });

    add('HTTP_DONE', 'httpDone', function HTTP_DONE(resp) {
      // convert buffers array into single buffer
      if (resp.httpResponse.buffers && resp.httpResponse.buffers.length > 0) {
        var body = AWS.util.buffer.concat(resp.httpResponse.buffers);
        resp.httpResponse.body = body;
      }
      delete resp.httpResponse.buffers;

      this.completeRequest(resp);
    });

    add('HTTP_ERROR', 'httpError', function HTTP_ERROR(error, resp) {
      resp.error = error;
      this.completeRequest(resp);
    });

    add('FINALIZE_ERROR', 'retry', function FINALIZE_ERROR(resp) {
      resp.error.statusCode = resp.httpResponse.statusCode;
      if (resp.error.retryable === undefined) {
        resp.error.retryable = this.service.retryableError(resp.error, this);
      }
    });

    add('INVALIDATE_CREDENTIALS', 'retry', function INVALIDATE_CREDENTIALS(resp) {
      switch (resp.error.code) {
        case 'RequestExpired': // EC2 only
        case 'ExpiredTokenException':
        case 'ExpiredToken':
          resp.error.retryable = true;
          resp.request.service.config.credentials.expired = true;
      }
    });

    add('REDIRECT', 'retry', function REDIRECT(resp) {
      if (resp.error && resp.error.statusCode >= 300 &&
          resp.error.statusCode < 400 && resp.httpResponse.headers['location']) {
        this.httpRequest.endpoint =
          new AWS.Endpoint(resp.httpResponse.headers['location']);
        resp.error.redirect = true;
        resp.error.retryable = true;
      }
    });

    add('RETRY_CHECK', 'retry', function RETRY_CHECK(resp) {
      if (resp.error) {
        if (resp.error.redirect && resp.redirectCount < this.service.config.maxRedirects) {
          resp.redirectCount++;
        } else if (resp.error.retryable && resp.retryCount < this.service.numRetries()) {
          resp.retryCount++;
        } else {
          throw resp.error;
        }
      }
    });

    addAsync('RETRY_SIGN', 'retry', function RETRY_SIGN(resp, doneCallback) {
      this.emitEvent('sign', resp, doneCallback);
    });

    addAsync('RETRY_DELAY_SEND', 'retry', function RETRY_DELAY_SEND(resp, doneCallback) {
      var delay = 0;
      if (!resp.error.redirect) {
        delay = this.service.retryDelays()[resp.retryCount-1] || 0;
      }

      resp.error = null;
      resp.data = null;

      setTimeout(function() {
        resp.request.emitEvent('send', resp, doneCallback);
      }, delay);

    });

  }),

  Logger: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    add('LOG_REQUEST', 'complete', function LOG_REQUEST(resp) {
      var req = resp.request;
      var logger = req.service.config.logger;
      if (!logger) return;

      function buildMessage() {
        var time = AWS.util.date.getDate().getTime();
        var delta = (time - req.startTime.getTime()) / 1000;
        var ansi = logger.isTTY ? true : false;
        var status = resp.httpResponse.statusCode;
        var params = require('util').inspect(req.params, true, true);

        var message = '';
        if (ansi) message += '\x1B[33m';
        message += '[AWS ' + req.service.serviceIdentifier + ' ' + status;
        message += ' ' + delta.toString() + 's ' + resp.retryCount + ' retries]';
        if (ansi) message += '\x1B[0;1m';
        message += ' ' + req.operation + '(' + params + ')';
        if (ansi) message += '\x1B[0m';
        return message;
      }

      var message = buildMessage();
      if (typeof logger.log === 'function') {
        logger.log(message);
      } else if (typeof logger.write === 'function') {
        logger.write(message + '\n');
      }
    });
  }),

  Json: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    var svc = AWS.ServiceInterface.Json;
    add('BUILD', 'build', svc.buildRequest);
    add('EXTRACT_DATA', 'extractData', svc.extractData);
    add('EXTRACT_ERROR', 'extractError', svc.extractError);
  }),

  Rest: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    var svc = AWS.ServiceInterface.Rest;
    add('BUILD', 'build', svc.buildRequest);
    add('EXTRACT_DATA', 'extractData', svc.extractData);
    add('EXTRACT_ERROR', 'extractError', svc.extractError);
  }),

  RestJson: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    var svc = AWS.ServiceInterface.RestJson;
    add('BUILD', 'build', svc.buildRequest);
    add('EXTRACT_DATA', 'extractData', svc.extractData);
    add('EXTRACT_ERROR', 'extractError', svc.extractError);
  }),

  RestXml: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    var svc = AWS.ServiceInterface.RestXml;
    add('BUILD', 'build', svc.buildRequest);
    add('EXTRACT_DATA', 'extractData', svc.extractData);
    add('EXTRACT_ERROR', 'extractError', svc.extractError);
  }),

  Query: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    var svc = AWS.ServiceInterface.Query;
    add('BUILD', 'build', svc.buildRequest);
    add('EXTRACT_DATA', 'extractData', svc.extractData);
    add('EXTRACT_ERROR', 'extractError', svc.extractError);
  })
};
<commit_msg>Fix the Host header. Fixes https://github.com/aws/aws-sdk-js/issues/165<commit_after>/**
 * Copyright 2012-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"). You
 * may not use this file except in compliance with the License. A copy of
 * the License is located at
 *
 *     http://aws.amazon.com/apache2.0/
 *
 * or in the "license" file accompanying this file. This file is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
 * ANY KIND, either express or implied. See the License for the specific
 * language governing permissions and limitations under the License.
 */

var AWS = require('./core');
require('./sequential_executor');
require('./service_interface/json');
require('./service_interface/query');
require('./service_interface/rest');
require('./service_interface/rest_json');
require('./service_interface/rest_xml');

/**
 * The namespace used to register global event listeners for request building
 * and sending.
 */
AWS.EventListeners = {
  /**
   * @!attribute VALIDATE_CREDENTIALS
   *   A request listener that validates whether the request is being
   *   sent with credentials.
   *   Handles the {AWS.Request~validate 'validate' Request event}
   *   @example Sending a request without validating credentials
   *     var listener = AWS.EventListeners.Core.VALIDATE_CREDENTIALS;
   *     request.removeListener('validate', listener);
   *   @readonly
   *   @return [Function]
   * @!attribute VALIDATE_REGION
   *   A request listener that validates whether the region is set
   *   for a request.
   *   Handles the {AWS.Request~validate 'validate' Request event}
   *   @example Sending a request without validating region configuration
   *     var listener = AWS.EventListeners.Core.VALIDATE_REGION;
   *     request.removeListener('validate', listener);
   *   @readonly
   *   @return [Function]
   * @!attribute VALIDATE_PARAMETERS
   *   A request listener that validates input parameters in a request.
   *   Handles the {AWS.Request~validate 'validate' Request event}
   *   @example Sending a request without validating parameters
   *     var listener = AWS.EventListeners.Core.VALIDATE_PARAMETERS;
   *     request.removeListener('validate', listener);
   *   @example Disable parameter validation globally
   *     AWS.EventListeners.Core.removeListener('validate',
   *       AWS.EventListeners.Core.VALIDATE_REGION);
   *   @readonly
   *   @return [Function]
   * @!attribute SEND
   *   A request listener that initiates the HTTP connection for a
   *   request being sent. Handles the {AWS.Request~send 'send' Request event}
   *   @example Replacing the HTTP handler
   *     var listener = AWS.EventListeners.Core.SEND;
   *     request.removeListener('send', listener);
   *     request.on('send', function(response) {
   *       customHandler.send(response);
   *     });
   *   @return [Function]
   *   @readonly
   * @!attribute HTTP_DATA
   *   A request listener that reads data from the HTTP connection in order
   *   to build the response data.
   *   Handles the {AWS.Request~httpData 'httpData' Request event}.
   *   Remove this handler if you are overriding the 'httpData' event and
   *   do not want extra data processing and buffering overhead.
   *   @example Disabling default data processing
   *     var listener = AWS.EventListeners.Core.HTTP_DATA;
   *     request.removeListener('httpData', listener);
   *   @return [Function]
   *   @readonly
   */
  Core: {} /* doc hack */
};

AWS.EventListeners = {
  Core: new AWS.SequentialExecutor().addNamedListeners(function(add, addAsync) {
    addAsync('VALIDATE_CREDENTIALS', 'validate',
        function VALIDATE_CREDENTIALS(req, doneCallback) {
      req.service.config.getCredentials(function(err) {
        if (err) {
          err = AWS.util.error(err,
            {code: 'SigningError', message: 'Missing credentials in config'});
        }
        doneCallback(err);
      });
    });

    add('VALIDATE_REGION', 'validate', function VALIDATE_REGION(req) {
      if (!req.service.config.region && !req.service.api.globalEndpoint) {
        throw AWS.util.error(new Error(),
          {code: 'SigningError', message: 'Missing region in config'});
      }
    });

    add('VALIDATE_PARAMETERS', 'validate', function VALIDATE_PARAMETERS(req) {
      var rules = req.service.api.operations[req.operation].input;
      new AWS.ParamValidator().validate(rules, req.params);
    });

    add('SET_CONTENT_LENGTH', 'afterBuild', function SET_CONTENT_LENGTH(req) {
      if (req.httpRequest.headers['Content-Length'] === undefined) {
        var length = AWS.util.string.byteLength(req.httpRequest.body);
        req.httpRequest.headers['Content-Length'] = length;
      }
    });

    add('SET_HTTP_HOST', 'afterBuild', function SET_HTTP_HOST(req) {
      req.httpRequest.headers['Host'] = req.httpRequest.endpoint.host;
    });

    addAsync('SIGN', 'sign', function SIGN(req, doneCallback) {
      if (!req.service.api.signatureVersion) return doneCallback(); // none

      req.service.config.getCredentials(function (err, credentials) {
        try {
          if (err) return doneCallback(err);

          var date = AWS.util.date.getDate();
          var sigVersion = req.service.api.signatureVersion;
          var SignerClass = AWS.Signers.RequestSigner.getVersion(sigVersion);
          var signer = new SignerClass(req.httpRequest,
            req.service.api.signingName || req.service.api.endpointPrefix);

          // clear old authorization headers
          delete req.httpRequest.headers['Authorization'];
          delete req.httpRequest.headers['Date'];
          delete req.httpRequest.headers['X-Amz-Date'];

          // add new authorization
          signer.addAuthorization(credentials, date);
          doneCallback();
        } catch (e) {
          doneCallback(e);
        }
      });
    });

    add('SETUP_ERROR', 'extractError', function SETUP_ERROR(resp) {
      if (this.service.successfulResponse(resp, this)) {
        // throwing null will stop the error extraction chain
        // but will not set an error for data extraction
        throw null;
      }

      resp.error = AWS.util.error(new Error(),
        {code: 'UnknownError', message: 'An unknown error occurred.'});
      resp.data = null;
    });

    add('SETUP_DATA', 'extractData', function SETUP_DATA(resp) {
      resp.data = {};
      resp.error = null;
    });

    add('SEND', 'send', function SEND(resp) {
      function callback(httpResp) {
        resp.httpStream = httpResp;

        var headers = [httpResp.statusCode, httpResp.headers, resp];
        resp.request.emitEvent('httpHeaders', headers);

        if (resp.httpStream) {
          if (AWS.HttpClient.streamsApiVersion === 2) { // streams2 API check
            httpResp.on('readable', function onReadable() {
              var data = httpResp.read();
              if (data !== null) {
                resp.request.emitEvent('httpData', [data, resp]);
              }
            });
          } else { // legacy streams API
            httpResp.on('data', function onData(data) {
              resp.request.emitEvent('httpData', [data, resp]);
            });
          }

          httpResp.on('end', function onEnd() {
            resp.request.emitEvent('httpDone', [resp]);
          });
        }
      }

      function error(err) {
        err = AWS.util.error(err, {
          code: 'NetworkingError',
          region: resp.request.httpRequest.region,
          hostname: resp.request.httpRequest.endpoint.hostname,
          retryable: true
        });
        resp.request.emitEvent('httpError', [err, resp]);
      }

      var http = AWS.HttpClient.getInstance();
      var httpOptions = resp.request.service.config.httpOptions || {};
      http.handleRequest(this.httpRequest, httpOptions, callback, error);
    });

    add('HTTP_HEADERS', 'httpHeaders',
        function HTTP_HEADERS(statusCode, headers, resp) {
      resp.httpResponse.statusCode = statusCode;
      resp.httpResponse.headers = headers;
      resp.httpResponse.body = new Buffer('');
      resp.httpResponse.buffers = [];
    });

    add('HTTP_DATA', 'httpData', function HTTP_DATA(chunk, resp) {
      if (chunk) resp.httpResponse.buffers.push(chunk);
    });

    add('HTTP_DONE', 'httpDone', function HTTP_DONE(resp) {
      // convert buffers array into single buffer
      if (resp.httpResponse.buffers && resp.httpResponse.buffers.length > 0) {
        var body = AWS.util.buffer.concat(resp.httpResponse.buffers);
        resp.httpResponse.body = body;
      }
      delete resp.httpResponse.buffers;

      this.completeRequest(resp);
    });

    add('HTTP_ERROR', 'httpError', function HTTP_ERROR(error, resp) {
      resp.error = error;
      this.completeRequest(resp);
    });

    add('FINALIZE_ERROR', 'retry', function FINALIZE_ERROR(resp) {
      resp.error.statusCode = resp.httpResponse.statusCode;
      if (resp.error.retryable === undefined) {
        resp.error.retryable = this.service.retryableError(resp.error, this);
      }
    });

    add('INVALIDATE_CREDENTIALS', 'retry', function INVALIDATE_CREDENTIALS(resp) {
      switch (resp.error.code) {
        case 'RequestExpired': // EC2 only
        case 'ExpiredTokenException':
        case 'ExpiredToken':
          resp.error.retryable = true;
          resp.request.service.config.credentials.expired = true;
      }
    });

    add('REDIRECT', 'retry', function REDIRECT(resp) {
      if (resp.error && resp.error.statusCode >= 300 &&
          resp.error.statusCode < 400 && resp.httpResponse.headers['location']) {
        this.httpRequest.endpoint =
          new AWS.Endpoint(resp.httpResponse.headers['location']);
        resp.error.redirect = true;
        resp.error.retryable = true;
      }
    });

    add('RETRY_CHECK', 'retry', function RETRY_CHECK(resp) {
      if (resp.error) {
        if (resp.error.redirect && resp.redirectCount < this.service.config.maxRedirects) {
          resp.redirectCount++;
        } else if (resp.error.retryable && resp.retryCount < this.service.numRetries()) {
          resp.retryCount++;
        } else {
          throw resp.error;
        }
      }
    });

    addAsync('RETRY_SIGN', 'retry', function RETRY_SIGN(resp, doneCallback) {
      this.emitEvent('sign', resp, doneCallback);
    });

    addAsync('RETRY_DELAY_SEND', 'retry', function RETRY_DELAY_SEND(resp, doneCallback) {
      var delay = 0;
      if (!resp.error.redirect) {
        delay = this.service.retryDelays()[resp.retryCount-1] || 0;
      }

      resp.error = null;
      resp.data = null;

      setTimeout(function() {
        resp.request.emitEvent('send', resp, doneCallback);
      }, delay);

    });

  }),

  Logger: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    add('LOG_REQUEST', 'complete', function LOG_REQUEST(resp) {
      var req = resp.request;
      var logger = req.service.config.logger;
      if (!logger) return;

      function buildMessage() {
        var time = AWS.util.date.getDate().getTime();
        var delta = (time - req.startTime.getTime()) / 1000;
        var ansi = logger.isTTY ? true : false;
        var status = resp.httpResponse.statusCode;
        var params = require('util').inspect(req.params, true, true);

        var message = '';
        if (ansi) message += '\x1B[33m';
        message += '[AWS ' + req.service.serviceIdentifier + ' ' + status;
        message += ' ' + delta.toString() + 's ' + resp.retryCount + ' retries]';
        if (ansi) message += '\x1B[0;1m';
        message += ' ' + req.operation + '(' + params + ')';
        if (ansi) message += '\x1B[0m';
        return message;
      }

      var message = buildMessage();
      if (typeof logger.log === 'function') {
        logger.log(message);
      } else if (typeof logger.write === 'function') {
        logger.write(message + '\n');
      }
    });
  }),

  Json: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    var svc = AWS.ServiceInterface.Json;
    add('BUILD', 'build', svc.buildRequest);
    add('EXTRACT_DATA', 'extractData', svc.extractData);
    add('EXTRACT_ERROR', 'extractError', svc.extractError);
  }),

  Rest: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    var svc = AWS.ServiceInterface.Rest;
    add('BUILD', 'build', svc.buildRequest);
    add('EXTRACT_DATA', 'extractData', svc.extractData);
    add('EXTRACT_ERROR', 'extractError', svc.extractError);
  }),

  RestJson: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    var svc = AWS.ServiceInterface.RestJson;
    add('BUILD', 'build', svc.buildRequest);
    add('EXTRACT_DATA', 'extractData', svc.extractData);
    add('EXTRACT_ERROR', 'extractError', svc.extractError);
  }),

  RestXml: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    var svc = AWS.ServiceInterface.RestXml;
    add('BUILD', 'build', svc.buildRequest);
    add('EXTRACT_DATA', 'extractData', svc.extractData);
    add('EXTRACT_ERROR', 'extractError', svc.extractError);
  }),

  Query: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    var svc = AWS.ServiceInterface.Query;
    add('BUILD', 'build', svc.buildRequest);
    add('EXTRACT_DATA', 'extractData', svc.extractData);
    add('EXTRACT_ERROR', 'extractError', svc.extractError);
  })
};
<|endoftext|>


<commit_before>/* jslint node: true, esnext: true */

"use strict";

const myScopeReporter = require('scope-reporter'),
	endpoint = require('./endpoint'),
	llm = require('loglevel-mixin'),
	stm = require('statetransition-mixin'),
	scopeDefinitions = require('./scopeDefinitions');

const actions = stm.prepareActions({
	start: {
		stopped: {
			target: "running",
			during: "starting",
			timeout: 5000
		}
	},
	stop: {
		running: {
			target: "stopped",
			during: "stopping",
			timeout: 5000
		},
		starting: {
			target: "stopped",
			during: "stopping",
			timeout: 5000
		}
	},
	remove: {
		stopped: {
			target: "removed"
		}
	}
});

// Steps plain attributes without special handling
// may be extended by some properties like writable,...
const ATTRIBUTES = ['description'];

const BaseStep = {
	"name": "kronos-step",
	"description": "This step is the base class for step implementations",

	/**
	 * Creates the properties for a given object
	 * @param {Object} manager The kronos service manager
	 * @param {String} (mandatory) name The Name of the step
	 * @param {Object} (optional) stepDefinition The step definition
	 *
	 */
	prepareProperties(manager, scopeReporter, name, stepConfiguration) {
		let endpoints = {};
		let interceptedEndpoints = {};

		// TODO ther is no better way ?
		const type = stepConfiguration.type ? stepConfiguration.type : this.name;

		const props = {
			name: {
				value: name
			},
			type: {
				value: type
			},
			endpoints: {
				value: endpoints
			},
			interceptedEndpoints: {
				value: interceptedEndpoints
			},
			manager: {
				value: manager
			},
			/**
			 * @return {Boolean} if step is in a running state
			 */
			isRunning: {
				get: function () {
					return this.state === 'running' || this.state === 'starting';
				}
			}
		};

		ATTRIBUTES.forEach(a => {
			if (stepConfiguration[a] !== undefined) {
				props[a] = {
					value: stepConfiguration[a]
				};
			}
		});

		return props;
	},

	/**
	 * Called to initialize step
	 * Please note 'this' is not jet present
	 */
	initialize(manager, scopeReporter, name, stepConfiguration, props) {},

	/**
	 * Called when step instance properties are present.
	 *
	 */
	finalize(manager, scopeReporter, stepConfiguration) {},

	/**
	 * This method could be overwritten by a derived object to setup default endpoints.
	 * This method may be overwritten by derived classes.
	 * This will be called by the initialize method
	 * @param {Object} scopeReporter This reporter is used to report parsing errors
	 * @param {Object} stepConfiguration The default step configuration
	 * @api protected
	 */
	createPredefinedEndpoints(scopeReporter, stepConfiguration) {
		//"description": "logging endpoint. All logging goes through this endpoint"

		if (this.endpoints.log) return;

		const logEndpoint = new endpoint.SendEndpointDefault("log", this);

		this.addEndpoint(logEndpoint);

		// get the default loglevel for this step
		let logLevel = llm.defaultLogLevels[stepConfiguration.logLevel] || llm.defaultLogLevels.info;

		// create the properties to store the loglevel
		llm.defineLogLevelProperties(this, llm.defaultLogLevels, logLevel);

		this.log = function (level, args) {
			if (logEndpoint.isConnected()) {
				logEndpoint.send(args);
			} else {
				console.log(`${level}: ${args}`);
			}
		};
	},

	/**
	 * This function mixes the endpoint definitions of a step.
	 * So that extensions comming from the flow will be mixed into
	 * the definition from the step (The definition from the prototype).
	 * Only the 'endpoints' part will be extended
	 *
	 * @param def The step definition from the flow or step itslef.
	 * @return definition The new extended step definition
	 */
	inheritEndpoints(def) {
		const prototype = Object.getPrototypeOf(this);
		if (prototype && prototype.endpoints) {
			if (def && def.endpoints) {
				// need to mix the definition

				const newEndpointDef = {};
				Object.assign(newEndpointDef, prototype.endpoints, def.endpoints);
				def.endpoints = newEndpointDef;
			} else {
				if (!def) {
					def = {};
				}
				// just take the prototype definition
				def.endpoints = prototype.endpoints;
			}
		}
		return def;
	},

	/**
	 * Creates the endpoint objects defined as a combination from
	 * implementation and definition
	 * @param {Object} scopeReporter This reporter is used to report parsing errors
	 * @param {Object} def The step configuration
	 * @api protected
	 */
	createEndpoints(scopeReporter, def) {
		if (def && def.endpoints) {
			Object.keys(def.endpoints).forEach(name => {
				if (this.endpoints[name]) return;
				this.createEndpoint(scopeReporter, name, def.endpoints[name]);
			});
		}
	},

	createEndpoint(scopeReporter, name, def) {
		let ep;
		if (def.in) ep = new endpoint.ReceiveEndpoint(name, this);
		if (def.out) ep = new endpoint.SendEndpoint(name, this);

		let interceptors;

		if (def.interceptors) {
			interceptors = def.interceptors.map(ic => {
				const InterceptorClass = this.manager.interceptors[ic.type];

				console.log(`INTERCEPTOR: ${ic.type} -> ${InterceptorClass}`);

				if (InterceptorClass) {
					return new InterceptorClass(endpoint, ic);
				} else {
					// error
				}
			});
		}

		this.addEndpoint(ep, interceptors);
	},

	/**
	 * Sends a 'stepStateChanged' event to the manager.
	 * arguments are:
	 *  step,oldState,newState
	 * @param {String} oldState
	 * @param {String} newState
	 */
	stateChanged(oldState, newState) {
		this.trace(level => ({
			"message": "state changed",
			"oldState": oldState,
			"newState": newState
		}));
		this.manager.emit('stepStateChanged', this, oldState, newState);
	},

	/**
	 * Returns the string representation of this step
	 * @return {String} human readable name
	 */
	toString() {
		return this.name;
	},

	/**
	 * Deliver json representation
	 * @param {Objects} options
	 *  with the following flags:
	 *    includeRuntimeInfo - include runtime informtion like state
	 *    includeName - name of the step
	 *    includeDefaults - include all properties also the inherited and not overwittern ones
	 * @return json representation
	 */
	toJSONWithOptions(options) {
		const json = {
			type: this.type,
			endpoints: {}
		};

		if (options.includeName) {
			json.name = this.name;
		}

		if (options.includeRuntimeInfo) {
			json.state = this.state;
		}

		for (const endpointName in this.endpoints) {
			const ep = this.endpoints[endpointName];
			if (ep.isDefault) {
				if (options.includeDefaults) {
					json.endpoints[endpointName] = ep.toJSON();
				}
			} else {
				json.endpoints[endpointName] = ep.toJSON();
			}

		}

		ATTRIBUTES.forEach(a => {
			json[a] = this[a];
		});

		return json;
	},

	toJSON() {
		return this.toJSONWithOptions({
			includeRuntimeInfo: false,
			includeDefaults: false,
			includeName: false
		});
	},

	/**
	 * Add
	 * in: ep -> i1 -> i2 -> i3*
	 * out: i1* -> i2 -> i3 -> ep
	 * @param {Endpoint} ep
	 * @param {Array} interceptors
	 */
	addEndpoint(ep, interceptors) {
		this.endpoints[ep.name] = ep;

		if (interceptors === undefined || interceptors.length === 0) {
			this.interceptedEndpoints[ep.name] = ep;
			return;
		}

		if (ep.isIn) {
			// interceptors after endpoint
			this.interceptedEndpoints[ep.name] = interceptors.reduce((previous, current) => previous.connected = current, ep);
		}

		if (ep.isOut) {
			// interceptors before endpoint
			this.interceptedEndpoints[ep.name] = interceptors.reduce((previous, current) => {
				if (previous) {
					previous.connected = current;
				} else {
					this.interceptedEndpoints[ep.name] = current;
				}
				return current;
			});
		}
	},

	/**
	 * @return {Step} newly created step
	 */
	createInstance(manager, scopeReporter, stepDefinition) {
		const props = this.prepareProperties(manager, scopeReporter, stepDefinition.name, stepDefinition);
		this.initialize(manager, scopeReporter, stepDefinition.name, stepDefinition, props);
		const newInstance = Object.create(this, props);

		stm.defineStateTransitionProperties(newInstance, actions, "stopped");

		// mix the endpoints from the prototype with the new definition
		stepDefinition = newInstance.inheritEndpoints(stepDefinition);

		newInstance.createEndpoints(scopeReporter, stepDefinition);
		newInstance.createPredefinedEndpoints(scopeReporter, stepDefinition);
		newInstance.finalize(scopeReporter, stepDefinition);

		return newInstance;
	}
};

// define the logger methods
llm.defineLoggerMethods(BaseStep, llm.defaultLogLevels, createLogfunction());

stm.defineActionMethods(BaseStep, actions, true);

/**
 * Returns a logger function.
 */
function createLogfunction() {

	// Set an own function for preparing the stacktrace.
	// this is needed to get the some details later on
	/* MF disabled for now prevents mocha from functioning
		Error.prepareStackTrace = function (err, stackObj) {
			return stackObj[0];
		};
	*/

	/**
	 * This function will create the logs.
	 * Uses the GELF log format
	 */
	return function (level, arg) {
		const logevent = llm.makeLogEvent(level, arg, {
			"step-type": this.type,
			"step-name": this.name
		});

		if (typeof arg === 'object') {
			if (arg instanceof Error) {
				// The 'arg' is an Error Object
				const stack = arg.stack;

				if (stack.getLineNumber) {
					logevent.line = stack.getLineNumber();
				}
				if (stack.getFileName) {
					logevent._file_name = stack.getFileName();
				}
				logevent._error_name = arg.name;
				logevent.short_message = arg.message;
			} else {
				// The 'arg' is a normal object. Copy all the properties

				if (arg.short_message !== undefined) {
					logevent.short_message = arg.short_message;
					delete(arg.short_message);
				}
				if (arg.full_message !== undefined) {
					logevent.full_message = arg.full_message;
					delete(arg.full_message);
				}
			}
		}
		if (this.endpoints.log.isConnected) {
			this.endpoints.log.send(logevent);
		} else {
			console.log(logevent);
		}
	};
}

module.exports.BaseStep = BaseStep;
<commit_msg>fix:(endpoint): Fix a bug in the endpoint creation<commit_after>/* jslint node: true, esnext: true */

"use strict";

const myScopeReporter = require('scope-reporter'),
	endpoint = require('./endpoint'),
	llm = require('loglevel-mixin'),
	stm = require('statetransition-mixin'),
	scopeDefinitions = require('./scopeDefinitions');

const actions = stm.prepareActions({
	start: {
		stopped: {
			target: "running",
			during: "starting",
			timeout: 5000
		}
	},
	stop: {
		running: {
			target: "stopped",
			during: "stopping",
			timeout: 5000
		},
		starting: {
			target: "stopped",
			during: "stopping",
			timeout: 5000
		}
	},
	remove: {
		stopped: {
			target: "removed"
		}
	}
});

// Steps plain attributes without special handling
// may be extended by some properties like writable,...
const ATTRIBUTES = ['description'];

const BaseStep = {
	"name": "kronos-step",
	"description": "This step is the base class for step implementations",

	/**
	 * Creates the properties for a given object
	 * @param {Object} manager The kronos service manager
	 * @param {String} (mandatory) name The Name of the step
	 * @param {Object} (optional) stepDefinition The step definition
	 *
	 */
	prepareProperties(manager, scopeReporter, name, stepConfiguration) {
		let endpoints = {};
		let interceptedEndpoints = {};

		// TODO ther is no better way ?
		const type = stepConfiguration.type ? stepConfiguration.type : this.name;

		const props = {
			name: {
				value: name
			},
			type: {
				value: type
			},
			endpoints: {
				value: endpoints
			},
			interceptedEndpoints: {
				value: interceptedEndpoints
			},
			manager: {
				value: manager
			},
			/**
			 * @return {Boolean} if step is in a running state
			 */
			isRunning: {
				get: function () {
					return this.state === 'running' || this.state === 'starting';
				}
			}
		};

		ATTRIBUTES.forEach(a => {
			if (stepConfiguration[a] !== undefined) {
				props[a] = {
					value: stepConfiguration[a]
				};
			}
		});

		return props;
	},

	/**
	 * Called to initialize step
	 * Please note 'this' is not jet present
	 */
	initialize(manager, scopeReporter, name, stepConfiguration, props) {},

	/**
	 * Called when step instance properties are present.
	 *
	 */
	finalize(manager, scopeReporter, stepConfiguration) {},

	/**
	 * This method could be overwritten by a derived object to setup default endpoints.
	 * This method may be overwritten by derived classes.
	 * This will be called by the initialize method
	 * @param {Object} scopeReporter This reporter is used to report parsing errors
	 * @param {Object} stepConfiguration The default step configuration
	 * @api protected
	 */
	createPredefinedEndpoints(scopeReporter, stepConfiguration) {
		//"description": "logging endpoint. All logging goes through this endpoint"

		if (this.endpoints.log) return;

		const logEndpoint = new endpoint.SendEndpointDefault("log", this);

		this.addEndpoint(logEndpoint);

		// get the default loglevel for this step
		let logLevel = llm.defaultLogLevels[stepConfiguration.logLevel] || llm.defaultLogLevels.info;

		// create the properties to store the loglevel
		llm.defineLogLevelProperties(this, llm.defaultLogLevels, logLevel);

		this.log = function (level, args) {
			if (logEndpoint.isConnected()) {
				logEndpoint.send(args);
			} else {
				console.log(`${level}: ${args}`);
			}
		};
	},

	/**
	 * This function mixes the endpoint definitions of a step.
	 * So that extensions comming from the flow will be mixed into
	 * the definition from the step (The definition from the prototype).
	 * Only the 'endpoints' part will be extended
	 *
	 * @param def The step definition from the flow or step itslef.
	 * @return definition The new extended step definition
	 */
	inheritEndpoints(def) {
		const prototype = Object.getPrototypeOf(this);
		if (prototype && prototype.endpoints) {
			if (def && def.endpoints) {
				// need to mix the definition

				const newEndpointDef = {};
				Object.assign(newEndpointDef, prototype.endpoints, def.endpoints);
				def.endpoints = newEndpointDef;
			} else {
				if (!def) {
					def = {};
				}
				// just take the prototype definition
				def.endpoints = prototype.endpoints;
			}
		}
		return def;
	},

	/**
	 * Creates the endpoint objects defined as a combination from
	 * implementation and definition
	 * @param {Object} scopeReporter This reporter is used to report parsing errors
	 * @param {Object} def The step configuration
	 * @api protected
	 */
	createEndpoints(scopeReporter, def) {
		if (def && def.endpoints) {
			Object.keys(def.endpoints).forEach(name => {
				this.createEndpoint(scopeReporter, name, def.endpoints[name]);
			});
		}
	},

	createEndpoint(scopeReporter, name, def) {
		let ep;
		if (def.in) ep = new endpoint.ReceiveEndpoint(name, this);
		if (def.out) ep = new endpoint.SendEndpoint(name, this);

		let interceptors;

		if (def.interceptors) {
			interceptors = def.interceptors.map(ic => {
				const InterceptorClass = this.manager.interceptors[ic.type];

				console.log(`INTERCEPTOR: ${ic.type} -> ${InterceptorClass}`);

				if (InterceptorClass) {
					return new InterceptorClass(endpoint, ic);
				} else {
					// error
				}
			});
		}

		this.addEndpoint(ep, interceptors);
	},

	/**
	 * Sends a 'stepStateChanged' event to the manager.
	 * arguments are:
	 *  step,oldState,newState
	 * @param {String} oldState
	 * @param {String} newState
	 */
	stateChanged(oldState, newState) {
		this.trace(level => ({
			"message": "state changed",
			"oldState": oldState,
			"newState": newState
		}));
		this.manager.emit('stepStateChanged', this, oldState, newState);
	},

	/**
	 * Returns the string representation of this step
	 * @return {String} human readable name
	 */
	toString() {
		return this.name;
	},

	/**
	 * Deliver json representation
	 * @param {Objects} options
	 *  with the following flags:
	 *    includeRuntimeInfo - include runtime informtion like state
	 *    includeName - name of the step
	 *    includeDefaults - include all properties also the inherited and not overwittern ones
	 * @return json representation
	 */
	toJSONWithOptions(options) {
		const json = {
			type: this.type,
			endpoints: {}
		};

		if (options.includeName) {
			json.name = this.name;
		}

		if (options.includeRuntimeInfo) {
			json.state = this.state;
		}

		for (const endpointName in this.endpoints) {
			const ep = this.endpoints[endpointName];
			if (ep.isDefault) {
				if (options.includeDefaults) {
					json.endpoints[endpointName] = ep.toJSON();
				}
			} else {
				json.endpoints[endpointName] = ep.toJSON();
			}

		}

		ATTRIBUTES.forEach(a => {
			json[a] = this[a];
		});

		return json;
	},

	toJSON() {
		return this.toJSONWithOptions({
			includeRuntimeInfo: false,
			includeDefaults: false,
			includeName: false
		});
	},

	/**
	 * Add
	 * in: ep -> i1 -> i2 -> i3*
	 * out: i1* -> i2 -> i3 -> ep
	 * @param {Endpoint} ep
	 * @param {Array} interceptors
	 */
	addEndpoint(ep, interceptors) {
		this.endpoints[ep.name] = ep;

		if (interceptors === undefined || interceptors.length === 0) {
			this.interceptedEndpoints[ep.name] = ep;
			return;
		}

		if (ep.isIn) {
			// interceptors after endpoint
			this.interceptedEndpoints[ep.name] = interceptors.reduce((previous, current) => previous.connected = current, ep);
		}

		if (ep.isOut) {
			// interceptors before endpoint
			this.interceptedEndpoints[ep.name] = interceptors.reduce((previous, current) => {
				if (previous) {
					previous.connected = current;
				} else {
					this.interceptedEndpoints[ep.name] = current;
				}
				return current;
			});
		}
	},

	/**
	 * @return {Step} newly created step
	 */
	createInstance(manager, scopeReporter, stepDefinition) {
		const props = this.prepareProperties(manager, scopeReporter, stepDefinition.name, stepDefinition);
		this.initialize(manager, scopeReporter, stepDefinition.name, stepDefinition, props);
		const newInstance = Object.create(this, props);

		stm.defineStateTransitionProperties(newInstance, actions, "stopped");

		// mix the endpoints from the prototype with the new definition
		stepDefinition = newInstance.inheritEndpoints(stepDefinition);

		newInstance.createEndpoints(scopeReporter, stepDefinition);
		newInstance.createPredefinedEndpoints(scopeReporter, stepDefinition);
		newInstance.finalize(scopeReporter, stepDefinition);

		return newInstance;
	}
};

// define the logger methods
llm.defineLoggerMethods(BaseStep, llm.defaultLogLevels, createLogfunction());

stm.defineActionMethods(BaseStep, actions, true);

/**
 * Returns a logger function.
 */
function createLogfunction() {

	// Set an own function for preparing the stacktrace.
	// this is needed to get the some details later on
	/* MF disabled for now prevents mocha from functioning
		Error.prepareStackTrace = function (err, stackObj) {
			return stackObj[0];
		};
	*/

	/**
	 * This function will create the logs.
	 * Uses the GELF log format
	 */
	return function (level, arg) {
		const logevent = llm.makeLogEvent(level, arg, {
			"step-type": this.type,
			"step-name": this.name
		});

		if (typeof arg === 'object') {
			if (arg instanceof Error) {
				// The 'arg' is an Error Object
				const stack = arg.stack;

				if (stack.getLineNumber) {
					logevent.line = stack.getLineNumber();
				}
				if (stack.getFileName) {
					logevent._file_name = stack.getFileName();
				}
				logevent._error_name = arg.name;
				logevent.short_message = arg.message;
			} else {
				// The 'arg' is a normal object. Copy all the properties

				if (arg.short_message !== undefined) {
					logevent.short_message = arg.short_message;
					delete(arg.short_message);
				}
				if (arg.full_message !== undefined) {
					logevent.full_message = arg.full_message;
					delete(arg.full_message);
				}
			}
		}
		if (this.endpoints.log.isConnected) {
			this.endpoints.log.send(logevent);
		} else {
			console.log(logevent);
		}
	};
}

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


<commit_before>import { curry, map, tap } from 'ramda';

/* eslint-disable max-len */
/**
 * Runs the given list of functions in order with the supplied object, then returns the object.
 * Also known as the normal order sequencing combinator.
 *
 * Acts as a transducer if a transformer is given as second parameter.
 *
 * @func seq
 * @aliases sequencing
 * @memberOf RA
 * @since {@link https://char0n.github.io/ramda-adjunct/2.3.0|v2.3.0}
 * @category Function
 * @sig [(a -> *), (a -> *), ...] -> a -> a
 * @param {Array} fns The list of functions to call in order with `x` whose return values will be thrown away
 * @param {*} x
 * @return {*} `x`
 * @see {@link http://ramdajs.com/docs/#tap|tap}, {@link http://www.cs.rpi.edu/academics/courses/spring11/proglang/handouts/lambda-calculus-chapter.pdf|sequencing combinator explained}
 * @example
 *
 * RA.seq([console.info, console.log])('foo'); //=> prints 'foo' via info then log
 */
/* eslint-enable max-len */

const seq = curry((fns, x) => tap(tx => map(fn => fn(tx))(fns))(x));

export default seq;
<commit_msg>docs(seq): add composition usage example<commit_after>import { curry, map, tap } from 'ramda';

/* eslint-disable max-len */
/**
 * Runs the given list of functions in order with the supplied object, then returns the object.
 * Also known as the normal order sequencing combinator.
 *
 * Acts as a transducer if a transformer is given as second parameter.
 *
 * @func seq
 * @aliases sequencing
 * @memberOf RA
 * @since {@link https://char0n.github.io/ramda-adjunct/2.3.0|v2.3.0}
 * @category Function
 * @sig [(a -> *), (a -> *), ...] -> a -> a
 * @param {Array} fns The list of functions to call in order with `x` whose return values will be thrown away
 * @param {*} x
 * @return {*} `x`
 * @see {@link http://ramdajs.com/docs/#tap|tap}, {@link http://www.cs.rpi.edu/academics/courses/spring11/proglang/handouts/lambda-calculus-chapter.pdf|sequencing combinator explained}
 * @example
 *
 * RA.seq([console.info, console.log])('foo'); //=> prints 'foo' via info then log
 *
 * // usage in composition
 * R.pipe(
 *   R.concat('prefix '),
 *   RA.seq([
 *     console.info, //=> prints 'prefix test'
 *     console.log //=> prints 'prefix test'
 *   ]),
 *   R.toUpper
 * )('test'); //=> 'PREFIX TEST'
 */
/* eslint-enable max-len */

const seq = curry((fns, x) => tap(tx => map(fn => fn(tx))(fns))(x));

export default seq;
<|endoftext|>


<commit_before>$(document).ready(function() {
  return alert('2333');
});
<commit_msg>Delete resize.js<commit_after><|endoftext|>


<commit_before>'use strict';

describe('Articles E2E Tests:', function () {
  describe('Test articles page', function () {
    it('Should report missing credentials', function () {
      browser.get('http://localhost:3001/articles');
      expect(element.all(by.repeater('article in articles')).count()).toEqual(0);
    });
  });
});
<commit_msg>questions e2e test<commit_after>'use strict';

describe('Questions E2E Tests:', function () {
  describe('Test questions page', function () {
    it('Should report missing credentials', function () {
      browser.get('http://localhost:3001/questions');
      expect(element.all(by.repeater('question in questions')).count()).toEqual(0);
    });
  });
});
<|endoftext|>