<commit_before>/*
CinsImp
CinsTalk Base Namespace and Utilities

*********************************************************************************
Copyright (c) 2009-2015, Joshua Hawcroft
All rights reserved.

 May all beings have happiness and the cause of happiness.
 May all beings be free of suffering and the cause of suffering.
 May all beings rejoice for the supreme happiness which is without suffering.
 May all beings abide in the great equanimity; free of attachment and delusion.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the product nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/*

Dependencies
------------

n/a

*/

var Xtalk = {

/*****************************************************************************************
Constants
*/

/* token.flags to aid parsing: */
	FLAG_OPERATOR: 	1,
	FLAG_ORDINAL: 	2,
	FLAG_KEYWORD: 	4,		/* reserved keyword */
	FLAG_SPECIAL:	8,
	FLAG_IDENTIFIER:16,		/* legal for use as a variable or handler name */

/* types of ID_ABORT: */
	ABORT_ITERATION: 0,		/* equivalent to "next repeat" or Javascript "continue" */
	ABORT_LOOP: 1,			/* equivalent to "exit repeat" or Javascript "break" */
	ABORT_EVENT: 2, 		/* equivalent to "exit to user";
							   aborts processing of all currently executing system events */

/* types of ID_LOOP: */
	LOOP_FOREVER: 0,		/* infinite loop; no condition */
	LOOP_WHILE: 1,			/* iterate until condition evaluates to true */
	LOOP_UNTIL: 2,			/* iterate until condition evaluates to false */
	LOOP_LIMIT: 3,			/* iterate a specified number of times */
	LOOP_COUNT_UP: 4,		/* loop with a counter within a specific range */
	LOOP_COUNT_DOWN: 5,

/* tokens and syntax tree nodes: */
	ID_LITERAL_INTEGER: -1,
	ID_LITERAL_REAL: -2,
	ID_LITERAL_STRING: -3,
	ID_LITERAL_BOOLEAN: -4,

	ID_CONSTANT: -5,
	ID_PROPERTY: -6,
	ID_REFERENCE: -7,
	ID_FUNCTION_CALL: -8,
	ID_MESSAGE_SEND: -9,
	ID_GLOBAL: -10,
	ID_LOOP: -11,
	ID_ABORT: -12,
	ID_RETURN: -13,
	ID_HANDLER: -14,
	ID_EXPRESSION: -15,
	ID_BLOCK: -16,
	ID_LIST: -17,
	ID_WORD: -18,
	ID_CONDITION_BLOCK: -19,
	ID_CONDITION_CASE: -20,
	ID_ORDINAL: -21,

	ID_INVALID: 0,

	ID_PAREN_OPEN: 1,
	ID_PAREN_CLOSE: 2,
	ID_COMMA: 3,
	ID_NUMBER_OF: 4,
	ID_EOL: 5,
	ID_NOT_WITHIN: 6,
	ID_WITHIN: 7,
	ID_NOT_IN: 8,
	ID_IN: 9,
	ID_CONTAINS: 10,
	ID_EQUAL: 11,
	ID_NOT_EQUAL: 12,
	ID_EXISTS: 13,
	ID_NOT_EXISTS: 14,
	ID_IDIV: 15,
	ID_RDIV: 16,
	ID_MOD: 17,
	ID_MULTIPLY: 18,
	ID_ADD: 19,
	ID_SUBTRACT: 20,
	ID_NEGATE: 21,
	ID_EXPONENT: 22,
	ID_LAND: 23,
	ID_LOR: 24,
	ID_LNOT: 25,
	ID_LESS_EQUAL: 26,
	ID_LESS: 27,
	ID_MORE_EQUAL: 27,
	ID_MORE: 28,
	ID_CONCAT_SPACE: 29,
	ID_CONCAT: 30,

	ID_ANY: 31,
	ID_MIDDLE: 32,
	ID_LAST: 33,
	ID_FIRST: 34,
	ID_SECOND: 35,
	ID_THIRD: 36,
	ID_FOURTH: 37,
	ID_FIFTH: 38,
	ID_SIXTH: 39,
	ID_SEVENTH: 40,
	ID_EIGHTH: 41,
	ID_NINTH: 42,
	ID_TENTH: 43,

	ID_THE: 50,
	ID_IN: 51,
	ID_OF: 52,
	ID_TO: 53,
	ID_ID: 54,
	ID_END: 55,
	ID_EXIT: 56,
	ID_FUNCTION: 57,
	ID_GLOBAL: 58,
	ID_IF: 59,
	ID_ELSE: 60,
	ID_NEXT: 61,
	ID_ON: 62,
	ID_PASS: 63,
	ID_REPEAT: 64,
	ID_RETURN: 65,

	ID_DOWN: 66,
	ID_WHILE: 67,
	ID_UNTIL: 68,
	ID_FOREVER: 69,
	ID_WITH: 70,
	ID_FOR: 71,
	ID_TIMES: 72,

	ID_JUMP: 90,
	ID_JUMP_IF_TRUE: 91,
	ID_JUMP_IF_FALSE: 92,

/*****************************************************************************************
Module Globals
*/
	_error_line: 0,		/* if an error occurs, what physical line is closest ? */

	_legacy_hc: false,	/* should the language allow the use of certain keywords that
						   were permitted in HyperTalk ? */

/*****************************************************************************************
Utilities
*/

/*
	Returns the number of words in the supplied string.
 */
	_word_count: function(in_string)
	{
		if (in_string == '') return 0;
		return in_string.split(' ').length;
	},

/*****************************************************************************************
Error Handling
*/

/*
	Looks at the supplied object and determines a string description of it suitable
	for an error message.
*/
	_object_desc: function(in_object)
	{
		if (typeof in_object != 'object') return in_object;

		if (in_object.id)
			return Xtalk.Lexer.describe(in_object);
		else if (in_object.errorDesc)
			return in_object.errorDesc;
	},

/*
 	Invoked by the parser to raise a syntax error.
 */
	_error_syntax: function(in_message)
	{
		for (var a = 1; a < arguments.length; a++)
			in_message = in_message.replace('^'+(a-1), this._object_desc(arguments[a]));
		throw Error("Syntax Error: " + Xtalk._error_line + ': ' + in_message);
	}

};

<commit_msg>additional constants for loop counter execution<commit_after>/*
CinsImp
CinsTalk Base Namespace and Utilities

*********************************************************************************
Copyright (c) 2009-2015, Joshua Hawcroft
All rights reserved.

 May all beings have happiness and the cause of happiness.
 May all beings be free of suffering and the cause of suffering.
 May all beings rejoice for the supreme happiness which is without suffering.
 May all beings abide in the great equanimity; free of attachment and delusion.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the product nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/*

Dependencies
------------

n/a

*/

var Xtalk = {

/*****************************************************************************************
Constants
*/

/* token.flags to aid parsing: */
	FLAG_OPERATOR: 	1,
	FLAG_ORDINAL: 	2,
	FLAG_KEYWORD: 	4,		/* reserved keyword */
	FLAG_SPECIAL:	8,
	FLAG_IDENTIFIER:16,		/* legal for use as a variable or handler name */

/* types of ID_ABORT: */
	ABORT_ITERATION: 0,		/* equivalent to "next repeat" or Javascript "continue" */
	ABORT_LOOP: 1,			/* equivalent to "exit repeat" or Javascript "break" */
	ABORT_EVENT: 2, 		/* equivalent to "exit to user";
							   aborts processing of all currently executing system events */

/* types of ID_LOOP: */
	LOOP_FOREVER: 0,		/* infinite loop; no condition */
	LOOP_WHILE: 1,			/* iterate until condition evaluates to true */
	LOOP_UNTIL: 2,			/* iterate until condition evaluates to false */
	LOOP_LIMIT: 3,			/* iterate a specified number of times */
	LOOP_COUNT_UP: 4,		/* loop with a counter within a specific range */
	LOOP_COUNT_DOWN: 5,

/* tokens and syntax tree nodes: */
	ID_LITERAL_INTEGER: -1,
	ID_LITERAL_REAL: -2,
	ID_LITERAL_STRING: -3,
	ID_LITERAL_BOOLEAN: -4,

	ID_CONSTANT: -5,
	ID_PROPERTY: -6,
	ID_REFERENCE: -7,
	ID_FUNCTION_CALL: -8,
	ID_MESSAGE_SEND: -9,
	ID_GLOBAL: -10,
	ID_LOOP: -11,
	ID_ABORT: -12,
	ID_RETURN: -13,
	ID_HANDLER: -14,
	ID_EXPRESSION: -15,
	ID_BLOCK: -16,
	ID_LIST: -17,
	ID_WORD: -18,
	ID_CONDITION_BLOCK: -19,
	ID_CONDITION_CASE: -20,
	ID_ORDINAL: -21,

	ID_INVALID: 0,

	ID_PAREN_OPEN: 1,
	ID_PAREN_CLOSE: 2,
	ID_COMMA: 3,
	ID_NUMBER_OF: 4,
	ID_EOL: 5,
	ID_NOT_WITHIN: 6,
	ID_WITHIN: 7,
	ID_NOT_IN: 8,
	ID_IN: 9,
	ID_CONTAINS: 10,
	ID_EQUAL: 11,
	ID_NOT_EQUAL: 12,
	ID_EXISTS: 13,
	ID_NOT_EXISTS: 14,
	ID_IDIV: 15,
	ID_RDIV: 16,
	ID_MOD: 17,
	ID_MULTIPLY: 18,
	ID_ADD: 19,
	ID_SUBTRACT: 20,
	ID_NEGATE: 21,
	ID_EXPONENT: 22,
	ID_LAND: 23,
	ID_LOR: 24,
	ID_LNOT: 25,
	ID_LESS_EQUAL: 26,
	ID_LESS: 27,
	ID_MORE_EQUAL: 27,
	ID_MORE: 28,
	ID_CONCAT_SPACE: 29,
	ID_CONCAT: 30,

	ID_ANY: 31,
	ID_MIDDLE: 32,
	ID_LAST: 33,
	ID_FIRST: 34,
	ID_SECOND: 35,
	ID_THIRD: 36,
	ID_FOURTH: 37,
	ID_FIFTH: 38,
	ID_SIXTH: 39,
	ID_SEVENTH: 40,
	ID_EIGHTH: 41,
	ID_NINTH: 42,
	ID_TENTH: 43,

	ID_THE: 50,
	ID_IN: 51,
	ID_OF: 52,
	ID_TO: 53,
	ID_ID: 54,
	ID_END: 55,
	ID_EXIT: 56,
	ID_FUNCTION: 57,
	ID_GLOBAL: 58,
	ID_IF: 59,
	ID_ELSE: 60,
	ID_NEXT: 61,
	ID_ON: 62,
	ID_PASS: 63,
	ID_REPEAT: 64,
	ID_RETURN: 65,

	ID_DOWN: 66,
	ID_WHILE: 67,
	ID_UNTIL: 68,
	ID_FOREVER: 69,
	ID_WITH: 70,
	ID_FOR: 71,
	ID_TIMES: 72,

	ID_JUMP: 90,
	ID_JUMP_IF_TRUE: 91,
	ID_JUMP_IF_FALSE: 92,

	/* field: 'which' provides an integer index for the specific loop counter */
	ID_COUNT_INIT: 93,	/* configure a counter variable */
	ID_COUNT_INC: 94,
	ID_COUNT_DEC: 95,
	ID_COUNT_VALUE: 96, /* push the counter variable on the operand stack */

/*****************************************************************************************
Module Globals
*/
	_error_line: 0,		/* if an error occurs, what physical line is closest ? */

	_legacy_hc: false,	/* should the language allow the use of certain keywords that
						   were permitted in HyperTalk ? */

/*****************************************************************************************
Utilities
*/

/*
	Returns the number of words in the supplied string.
 */
	_word_count: function(in_string)
	{
		if (in_string == '') return 0;
		return in_string.split(' ').length;
	},

/*****************************************************************************************
Error Handling
*/

/*
	Looks at the supplied object and determines a string description of it suitable
	for an error message.
*/
	_object_desc: function(in_object)
	{
		if (typeof in_object != 'object') return in_object;

		if (in_object.id)
			return Xtalk.Lexer.describe(in_object);
		else if (in_object.errorDesc)
			return in_object.errorDesc;
	},

/*
 	Invoked by the parser to raise a syntax error.
 */
	_error_syntax: function(in_message)
	{
		for (var a = 1; a < arguments.length; a++)
			in_message = in_message.replace('^'+(a-1), this._object_desc(arguments[a]));
		throw Error("Syntax Error: " + Xtalk._error_line + ': ' + in_message);
	}

};

<|endoftext|>


<commit_before>const path = require('path');
const helpers = require('yeoman-test');
const assert = require('yeoman-assert');

describe('yo kk578:node-server MyNodeServerProject', () => {
	const dummies = [
		path.join(__dirname, '../generators/node'),
		[helpers.createDummyGenerator(), 'kk578:app']
	];

	before(() => {
		return helpers.run(path.join(__dirname, '../generators/node-server'))
			.withGenerators(dummies)
			.inDir(path.join(__dirname, './tmp/node-server'))
			.withArguments('MyNodeServerProject')
			.withPrompts({
				name: 'The Tester',
				email: 'tester@test.test',
				gitRemoteUrl: 'git@test.test:KK578/MyNodeProject.git'
			})
			.toPromise();
	});

	it('should add new dependencies to package.json', () => {
		assert.fileContent('package.json', /browser-sync/);
		assert.fileContent('package.json', /grunt-contrib-uglify/);
	});

	it('should not copy files from development', () => {
		assert.noFile(['build/', 'node_modules/']);
	});
});
<commit_msg>Add tests for controller files to be generated.<commit_after>const path = require('path');
const helpers = require('yeoman-test');
const assert = require('yeoman-assert');

describe('yo kk578:node-server MyNodeServerProject', () => {
	const dummies = [
		path.join(__dirname, '../generators/node'),
		[helpers.createDummyGenerator(), 'kk578:app']
	];

	before(() => {
		return helpers.run(path.join(__dirname, '../generators/node-server'))
			.withGenerators(dummies)
			.inDir(path.join(__dirname, './tmp/node-server'))
			.withArguments('MyNodeServerProject')
			.withPrompts({
				name: 'The Tester',
				email: 'tester@test.test',
				gitRemoteUrl: 'git@test.test:KK578/MyNodeProject.git'
			})
			.toPromise();
	});

	it('should generate extra dependencies to package.json', () => {
		assert.fileContent('package.json', /"express"/);
		assert.fileContent('package.json', /"browser-sync"/);
		assert.fileContent('package.json', /"grunt-express-server"/);
		assert.fileContent('package.json', /"grunt-contrib-watch"/);
		assert.fileContent('package.json', /"grunt-contrib-uglify"/);
	});

	it('should generate grunt configs for dependencies', () => {
		assert.file([
			'configs/grunt/express.js',
			'configs/grunt/watch.js',
			'configs/grunt/uglify.js'
		]);
	});

	it('should generate controller scripts for express', () => {
		assert.file([
			'server/development.js',
			'server/production.js',
			'server/server.js'
		]);
		assert.file([
			'server/configs/browser-sync.js',
			'server/configs/logs.js',
			'server/configs/router.js',
			'server/configs/setup.js'
		]);
		assert.file(['server/routes/static.js']);
	});

	it('should not copy files from development', () => {
		assert.noFile(['build/', 'node_modules/']);
	});
});
<|endoftext|>


<commit_before>/*
 * Copyright 2014-2015 Fabian Tollenaar <fabian@starting-point.nl>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License 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.
 */

const deep = require('deep-get-set')
const DevNull = require('dev-null-stream')
const _ = require('lodash')
const config = require('./config/config')

module.exports = function (app) {
  function createPipedProvider (providerConfig, nmea0183Listener) {
    var result = {
      id: providerConfig.id,
      pipeElements: providerConfig.pipeElements.reduce((result, config) => {
        if (typeof config.enabled === 'undefined' || config.enabled) {
          result.push(createPipeElement(config))
        }
        return result
      }, [])
    }

    result.pipeElements.forEach(function (pipeElement) {
      if (typeof pipeElement.on === 'function') {
        pipeElement.on('nmea0183', nmea0183Listener)
      }
    })

    for (var i = result.pipeElements.length - 2; i >= 0; i--) {
      result.pipeElements[i].pipe(result.pipeElements[i + 1])
    }

    result.pipeElements[result.pipeElements.length - 1].pipe(new DevNull())
    result.pipeElements[result.pipeElements.length - 1].on('data', msg => {
      app.handleMessage(providerConfig.id, msg)
    })
    app.emit('pipedProvidersStarted', providerConfig)
    return result
  }

  function createPipeElement (elementConfig) {
    var options = elementConfig.options || {}
    options.app = app

    if (elementConfig.optionMappings) {
      elementConfig.optionMappings.forEach(function (mapping) {
        if (deep(app, mapping.fromAppProperty)) {
          options[mapping.toOption] = deep(app, mapping.fromAppProperty)
        }
      })
    }
    try {
      return new (require(elementConfig.type))(options)
    } catch (e) {
      return new (require(__dirname + '/../' + elementConfig.type))(options)
    }
  }

  function startProviders () {
    var nmea0183Listener = function (sentence) {
      app.signalk.emit('nmea0183', sentence)
    }
    if (app.config.settings.pipedProviders) {
      piped = app.config.settings.pipedProviders.reduce((result, config) => {
        if (typeof config.enabled === 'undefined' || config.enabled) {
          result.push(createPipedProvider(config, nmea0183Listener))
        }
        return result
      }, [])

      return piped.filter(function (n) {
        return n != null
      })
    } else {
      console.error('No pipedProviders in the settings file')
      return []
    }
  }

  function restartProviders () {
    app.providers.forEach(function (providerHolder) {
      providerHolder.pipeElements[0].end()
    })
    app.providers = startProviders()
  }

  app.get('/providers', (req, res, next) => {
    var providers = app.config.settings.pipedProviders.map(provider => {
      var p = { id: provider.id }
      var type = provider.pipeElements[0].type
      if (
        type == 'providers/execute' &&
        provider.pipeElements[0].options.command.indexOf('actisense-serial') !=
          -1
      ) {
        p.type = 'Actisense NTG-1'
        p.source = provider.pipeElements[0].options.command
      } else if (
        type == 'providers/serialport' &&
        provider.pipeElements.find(
          element => element.type == 'providers/nmea0183-signalk'
        )
      ) {
        p.type = 'NMEA 0183 Serial'
        p.source = provider.pipeElements[0].options.device
        p.baudrate = provider.pipeElements[0].options.baudrate
      } else if (
        type == 'providers/tcp' &&
        provider.pipeElements.find(
          element => element.type == 'providers/nmea0183-signalk'
        )
      ) {
        p.type = 'NMEA 0183 Network'
        p.source =
          provider.pipeElements[0].options.host +
          ':' +
          provider.pipeElements[0].options.port
      } else if (type == 'providers/filestream') {
        p.type = 'File Stream'
        p.source = provider.pipeElements[0].options.filename
      } else if (type == 'providers/execute') {
        p.type = 'Execute'
        p.source = provider.pipeElements[0].options.command
      } else {
        p.type = 'Unknown'
      }
      p.enabled = _.isUndefined(provider.enabled) ? true : provider.enabled
      var logging = provider.pipeElements.find(
        element => element.type == 'providers/log'
      )
      p.logging = _.isUndefined(logging)
        ? false
        : _.isUndefined(logging.enabled) ? true : logging.enabled
      p.json = JSON.stringify(provider, null, 2)
      return p
    })
    res.json(providers)
  })

  app.put('/providers/:id', (req, res, next) => {
    var existing = app.config.settings.pipedProviders.find(
      provider => provider.id == req.params.id
    )
    if (!existing) {
      res.status(401).send(`Can't find provider with id ${req.params.id}`)
      return
    }
    var provider = req.body
    console.log(`provider: ${JSON.stringify(provider)}`)
    if (provider.json) {
      var idx = app.config.settings.pipedProviders.findIndex(
        provider => provider.id == req.params.id
      )
      try {
        app.config.settings.pipedProviders[idx] = JSON.parse(provider.json)
      } catch (e) {
        console.log(e)
        res.status(500).send('Unable to parse json input string')
        return
      }
    } else {
      if (!applyProviderSettings(existing, provider, res)) {
        return
      }
    }
    config.writeSettingsFile(app, app.config.settings, err => {
      if (err) {
        res.status(500).send('Unable to save to settings file')
      } else {
        try {
          restartProviders()
        } catch (err) {
          console.log(err)
          res.status(500).send('Unable to restart providers')
          return
        }
        res.send('Provider updated')
      }
    })
  })

  app.post('/providers/:id', (req, res, next) => {
    var existing = app.config.settings.pipedProviders.find(
      provider => provider.id == req.params.id
    )

    if (existing) {
      res.status(401).send(`Provider with Name ${req.params.id} already exists`)
      return
    }

    var provider = req.body
    var template = providerTemalates[provider.type]
    if (!template) {
      res.status(500).send(`Unknown provider type: ${provider.type}`)
      return
    }
    var newProvider = JSON.parse(JSON.stringify(template))
    newProvider.id = req.params.id
    applyProviderSettings(newProvider, provider)
    app.config.settings.pipedProviders.push(newProvider)

    config.writeSettingsFile(app, app.config.settings, err => {
      if (err) {
        res.status(500).send('Unable to save to settings file')
      } else {
        try {
          restartProviders()
        } catch (err) {
          console.log(err)
          res.status(500).send('Unable to restart providers')
          return
        }
        res.send('Provider added')
      }
    })
  })

  app.delete('/providers/:id', (req, res, next) => {
    var idx = app.config.settings.pipedProviders.findIndex(
      p => p.id == req.params.id
    )
    if (idx == -1) {
      res.status(401).send(`Provider with name ${req.params.id} not found`)
      return
    }
    app.config.settings.pipedProviders.splice(idx, 1)

    config.writeSettingsFile(app, app.config.settings, err => {
      if (err) {
        res.status(500).send('Unable to save to settings file')
      } else {
        try {
          restartProviders()
        } catch (err) {
          console.log(err)
          res.status(500).send('Unable to restart providers')
          return
        }
        res.send('Provider deleted')
      }
    })
  })

  return (api = {
    start: startProviders
  })
}

function applyProviderSettings (existing, provider, res) {
  if (provider.type == 'Unknown') {
    res.status(401).send(`Can't update an Unknown type`)
    return false
  } else if (provider.type == 'Actisense NTG-1') {
    existing.pipeElements[0].options.command = provider.source
  } else if (provider.type == 'NMEA 0183 Serial') {
    existing.pipeElements[0].options.device = provider.source
    existing.pipeElements[0].options.baudrate = Number(provider.baudrate)
  } else if (provider.type == 'NMEA 0183 Network') {
    var parts = provider.source.split(':')
    existing.pipeElements[0].options.host = parts[0]
    existing.pipeElements[0].options.port = Number(parts[1])
  } else if (provider.type == 'File Stream') {
    existing.pipeElements[0].options.filename = provider.source
  } else if (provider.type == 'Execute') {
    existing.pipeElements[0].options.command = provider.source
  }

  existing.enabled = provider.enabled

  if (provider.type !== 'File Stream') {
    var logging = existing.pipeElements.find(
      element => element.type == 'providers/log'
    )
    if (logging) {
      logging.enabled = provider.logging
    } else {
      var config = {
        type: 'providers/log',
        enabled: false,
        options: {
          discriminator: discriminatorByType[provider.type]
        }
      }
      var idx = existing.pipeElements.findIndex(
        element => element.type == 'providers/liner'
      )
      idx = idx == -1 ? 1 : idx + 1
      existing.pipeElements.splice(idx, 0, config)
    }
  }
  return true
}

const discriminatorByType = {
  'Actisense NTG-1': 'A',
  'NMEA 0183 Serial': 'N',
  'NMEA 0183 Network': 'N',
  Execute: 'I'
}

const providerTemalates = {
  'Actisense NTG-1': {
    pipeElements: [
      {
        type: 'providers/execute',
        options: {
          command: 'actisense-serial /dev/actisense',
          toChildProcess: 'nmea2000out'
        }
      },
      {
        type: 'providers/liner'
      },
      {
        type: 'providers/log',
        enabled: false,
        options: {
          discriminator: 'A'
        }
      },
      {
        type: 'providers/n2kAnalyzer'
      },
      {
        type: 'providers/n2k-signalk'
      }
    ]
  },
  'NMEA 0183 Serial': {
    pipeElements: [
      {
        type: 'providers/serialport',
        options: {
          device: '/dev/ttyUSB2',
          baudrate: 4800
        }
      },
      {
        type: 'providers/log',
        enabled: false,
        options: {
          discriminator: 'N'
        }
      },
      {
        type: 'providers/nmea0183-signalk',
        optionMappings: [
          {
            fromAppProperty: 'selfId',
            toOption: 'selfId'
          },
          {
            fromAppProperty: 'selfType',
            toOption: 'selfType'
          }
        ]
      }
    ]
  },
  'NMEA 0183 Network': {
    pipeElements: [
      {
        type: 'providers/tcp',
        options: {
          host: 'localhost',
          port: 10110
        }
      },
      {
        type: 'providers/log',
        enabled: false,
        options: {
          discriminator: 'N'
        }
      },
      {
        type: 'providers/nmea0183-signalk',
        optionMappings: [
          {
            fromAppProperty: 'selfId',
            toOption: 'selfId'
          },
          {
            fromAppProperty: 'selfType',
            toOption: 'selfType'
          }
        ]
      }
    ]
  },
  'File Stream': {
    pipeElements: [
      {
        type: 'providers/filestream',
        options: {
          filename: ''
        },
        optionMappings: [
          {
            fromAppProperty: 'argv.filename',
            toOption: 'filename'
          }
        ]
      },
      {
        type: 'providers/liner'
      },
      {
        type: 'providers/multiplexedlog',
        optionMappings: [
          {
            fromAppProperty: 'selfId',
            toOption: 'selfId'
          },
          {
            fromAppProperty: 'selfType',
            toOption: 'selfType'
          }
        ]
      }
    ]
  },
  Execute: {
    pipeElements: [
      {
        type: 'providers/execute',
        options: {
          command: ''
        }
      },
      {
        type: 'providers/liner'
      },
      {
        type: 'providers/log',
        enabled: false,
        options: {
          discriminator: 'I'
        }
      },
      {
        type: 'providers/from_json'
      }
    ]
  }
}
<commit_msg>fix: include providers/liner in default NMEA 0183 Network config<commit_after>/*
 * Copyright 2014-2015 Fabian Tollenaar <fabian@starting-point.nl>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License 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.
 */

const deep = require('deep-get-set')
const DevNull = require('dev-null-stream')
const _ = require('lodash')
const config = require('./config/config')

module.exports = function (app) {
  function createPipedProvider (providerConfig, nmea0183Listener) {
    var result = {
      id: providerConfig.id,
      pipeElements: providerConfig.pipeElements.reduce((result, config) => {
        if (typeof config.enabled === 'undefined' || config.enabled) {
          result.push(createPipeElement(config))
        }
        return result
      }, [])
    }

    result.pipeElements.forEach(function (pipeElement) {
      if (typeof pipeElement.on === 'function') {
        pipeElement.on('nmea0183', nmea0183Listener)
      }
    })

    for (var i = result.pipeElements.length - 2; i >= 0; i--) {
      result.pipeElements[i].pipe(result.pipeElements[i + 1])
    }

    result.pipeElements[result.pipeElements.length - 1].pipe(new DevNull())
    result.pipeElements[result.pipeElements.length - 1].on('data', msg => {
      app.handleMessage(providerConfig.id, msg)
    })
    app.emit('pipedProvidersStarted', providerConfig)
    return result
  }

  function createPipeElement (elementConfig) {
    var options = elementConfig.options || {}
    options.app = app

    if (elementConfig.optionMappings) {
      elementConfig.optionMappings.forEach(function (mapping) {
        if (deep(app, mapping.fromAppProperty)) {
          options[mapping.toOption] = deep(app, mapping.fromAppProperty)
        }
      })
    }
    try {
      return new (require(elementConfig.type))(options)
    } catch (e) {
      return new (require(__dirname + '/../' + elementConfig.type))(options)
    }
  }

  function startProviders () {
    var nmea0183Listener = function (sentence) {
      app.signalk.emit('nmea0183', sentence)
    }
    if (app.config.settings.pipedProviders) {
      piped = app.config.settings.pipedProviders.reduce((result, config) => {
        if (typeof config.enabled === 'undefined' || config.enabled) {
          result.push(createPipedProvider(config, nmea0183Listener))
        }
        return result
      }, [])

      return piped.filter(function (n) {
        return n != null
      })
    } else {
      console.error('No pipedProviders in the settings file')
      return []
    }
  }

  function restartProviders () {
    app.providers.forEach(function (providerHolder) {
      providerHolder.pipeElements[0].end()
    })
    app.providers = startProviders()
  }

  app.get('/providers', (req, res, next) => {
    var providers = app.config.settings.pipedProviders.map(provider => {
      var p = { id: provider.id }
      var type = provider.pipeElements[0].type
      if (
        type == 'providers/execute' &&
        provider.pipeElements[0].options.command.indexOf('actisense-serial') !=
          -1
      ) {
        p.type = 'Actisense NTG-1'
        p.source = provider.pipeElements[0].options.command
      } else if (
        type == 'providers/serialport' &&
        provider.pipeElements.find(
          element => element.type == 'providers/nmea0183-signalk'
        )
      ) {
        p.type = 'NMEA 0183 Serial'
        p.source = provider.pipeElements[0].options.device
        p.baudrate = provider.pipeElements[0].options.baudrate
      } else if (
        type == 'providers/tcp' &&
        provider.pipeElements.find(
          element => element.type == 'providers/nmea0183-signalk'
        )
      ) {
        p.type = 'NMEA 0183 Network'
        p.source =
          provider.pipeElements[0].options.host +
          ':' +
          provider.pipeElements[0].options.port
      } else if (type == 'providers/filestream') {
        p.type = 'File Stream'
        p.source = provider.pipeElements[0].options.filename
      } else if (type == 'providers/execute') {
        p.type = 'Execute'
        p.source = provider.pipeElements[0].options.command
      } else {
        p.type = 'Unknown'
      }
      p.enabled = _.isUndefined(provider.enabled) ? true : provider.enabled
      var logging = provider.pipeElements.find(
        element => element.type == 'providers/log'
      )
      p.logging = _.isUndefined(logging)
        ? false
        : _.isUndefined(logging.enabled) ? true : logging.enabled
      p.json = JSON.stringify(provider, null, 2)
      return p
    })
    res.json(providers)
  })

  app.put('/providers/:id', (req, res, next) => {
    var existing = app.config.settings.pipedProviders.find(
      provider => provider.id == req.params.id
    )
    if (!existing) {
      res.status(401).send(`Can't find provider with id ${req.params.id}`)
      return
    }
    var provider = req.body
    console.log(`provider: ${JSON.stringify(provider)}`)
    if (provider.json) {
      var idx = app.config.settings.pipedProviders.findIndex(
        provider => provider.id == req.params.id
      )
      try {
        app.config.settings.pipedProviders[idx] = JSON.parse(provider.json)
      } catch (e) {
        console.log(e)
        res.status(500).send('Unable to parse json input string')
        return
      }
    } else {
      if (!applyProviderSettings(existing, provider, res)) {
        return
      }
    }
    config.writeSettingsFile(app, app.config.settings, err => {
      if (err) {
        res.status(500).send('Unable to save to settings file')
      } else {
        try {
          restartProviders()
        } catch (err) {
          console.log(err)
          res.status(500).send('Unable to restart providers')
          return
        }
        res.send('Provider updated')
      }
    })
  })

  app.post('/providers/:id', (req, res, next) => {
    var existing = app.config.settings.pipedProviders.find(
      provider => provider.id == req.params.id
    )

    if (existing) {
      res.status(401).send(`Provider with Name ${req.params.id} already exists`)
      return
    }

    var provider = req.body
    var template = providerTemalates[provider.type]
    if (!template) {
      res.status(500).send(`Unknown provider type: ${provider.type}`)
      return
    }
    var newProvider = JSON.parse(JSON.stringify(template))
    newProvider.id = req.params.id
    applyProviderSettings(newProvider, provider)
    app.config.settings.pipedProviders.push(newProvider)

    config.writeSettingsFile(app, app.config.settings, err => {
      if (err) {
        res.status(500).send('Unable to save to settings file')
      } else {
        try {
          restartProviders()
        } catch (err) {
          console.log(err)
          res.status(500).send('Unable to restart providers')
          return
        }
        res.send('Provider added')
      }
    })
  })

  app.delete('/providers/:id', (req, res, next) => {
    var idx = app.config.settings.pipedProviders.findIndex(
      p => p.id == req.params.id
    )
    if (idx == -1) {
      res.status(401).send(`Provider with name ${req.params.id} not found`)
      return
    }
    app.config.settings.pipedProviders.splice(idx, 1)

    config.writeSettingsFile(app, app.config.settings, err => {
      if (err) {
        res.status(500).send('Unable to save to settings file')
      } else {
        try {
          restartProviders()
        } catch (err) {
          console.log(err)
          res.status(500).send('Unable to restart providers')
          return
        }
        res.send('Provider deleted')
      }
    })
  })

  return (api = {
    start: startProviders
  })
}

function applyProviderSettings (existing, provider, res) {
  if (provider.type == 'Unknown') {
    res.status(401).send(`Can't update an Unknown type`)
    return false
  } else if (provider.type == 'Actisense NTG-1') {
    existing.pipeElements[0].options.command = provider.source
  } else if (provider.type == 'NMEA 0183 Serial') {
    existing.pipeElements[0].options.device = provider.source
    existing.pipeElements[0].options.baudrate = Number(provider.baudrate)
  } else if (provider.type == 'NMEA 0183 Network') {
    var parts = provider.source.split(':')
    existing.pipeElements[0].options.host = parts[0]
    existing.pipeElements[0].options.port = Number(parts[1])
  } else if (provider.type == 'File Stream') {
    existing.pipeElements[0].options.filename = provider.source
  } else if (provider.type == 'Execute') {
    existing.pipeElements[0].options.command = provider.source
  }

  existing.enabled = provider.enabled

  if (provider.type !== 'File Stream') {
    var logging = existing.pipeElements.find(
      element => element.type == 'providers/log'
    )
    if (logging) {
      logging.enabled = provider.logging
    } else {
      var config = {
        type: 'providers/log',
        enabled: false,
        options: {
          discriminator: discriminatorByType[provider.type]
        }
      }
      var idx = existing.pipeElements.findIndex(
        element => element.type == 'providers/liner'
      )
      idx = idx == -1 ? 1 : idx + 1
      existing.pipeElements.splice(idx, 0, config)
    }
  }
  return true
}

const discriminatorByType = {
  'Actisense NTG-1': 'A',
  'NMEA 0183 Serial': 'N',
  'NMEA 0183 Network': 'N',
  Execute: 'I'
}

const providerTemalates = {
  'Actisense NTG-1': {
    pipeElements: [
      {
        type: 'providers/execute',
        options: {
          command: 'actisense-serial /dev/actisense',
          toChildProcess: 'nmea2000out'
        }
      },
      {
        type: 'providers/liner'
      },
      {
        type: 'providers/log',
        enabled: false,
        options: {
          discriminator: 'A'
        }
      },
      {
        type: 'providers/n2kAnalyzer'
      },
      {
        type: 'providers/n2k-signalk'
      }
    ]
  },
  'NMEA 0183 Serial': {
    pipeElements: [
      {
        type: 'providers/serialport',
        options: {
          device: '/dev/ttyUSB2',
          baudrate: 4800
        }
      },
      {
        type: 'providers/log',
        enabled: false,
        options: {
          discriminator: 'N'
        }
      },
      {
        type: 'providers/nmea0183-signalk',
        optionMappings: [
          {
            fromAppProperty: 'selfId',
            toOption: 'selfId'
          },
          {
            fromAppProperty: 'selfType',
            toOption: 'selfType'
          }
        ]
      }
    ]
  },
  'NMEA 0183 Network': {
    pipeElements: [
      {
        type: 'providers/tcp',
        options: {
          host: 'localhost',
          port: 10110
        }
      },
      {
        type: 'providers/liner'
      },
      {
        type: 'providers/log',
        enabled: false,
        options: {
          discriminator: 'N'
        }
      },
      {
        type: 'providers/nmea0183-signalk',
        optionMappings: [
          {
            fromAppProperty: 'selfId',
            toOption: 'selfId'
          },
          {
            fromAppProperty: 'selfType',
            toOption: 'selfType'
          }
        ]
      }
    ]
  },
  'File Stream': {
    pipeElements: [
      {
        type: 'providers/filestream',
        options: {
          filename: ''
        },
        optionMappings: [
          {
            fromAppProperty: 'argv.filename',
            toOption: 'filename'
          }
        ]
      },
      {
        type: 'providers/liner'
      },
      {
        type: 'providers/multiplexedlog',
        optionMappings: [
          {
            fromAppProperty: 'selfId',
            toOption: 'selfId'
          },
          {
            fromAppProperty: 'selfType',
            toOption: 'selfType'
          }
        ]
      }
    ]
  },
  Execute: {
    pipeElements: [
      {
        type: 'providers/execute',
        options: {
          command: ''
        }
      },
      {
        type: 'providers/liner'
      },
      {
        type: 'providers/log',
        enabled: false,
        options: {
          discriminator: 'I'
        }
      },
      {
        type: 'providers/from_json'
      }
    ]
  }
}
<|endoftext|>


<commit_before>var coffea = require('../..');
var Stream = require('stream').PassThrough;

describe('away.js', function() {
    describe('on RPL_AWAY', function() {
        it('should emit "away" [single-network]', function (done) {
            var client = coffea(null, false);
            var st1 = new Stream();
            var st2 = new Stream();
            var st1_id = client.add(st1);
            client.nick('me', st1_id);

            client.once("away", function (event) {
                event.user.getNick().should.equal('you');
                event.message.should.equal('not here');
                done();
            });

            st1.write(':irc.local 301 me you :not here\r\n');
        });

        it('should emit "away" [multi-network]', function (done) {
            var client = coffea(null, false);
            var st1 = new Stream();
            var st2 = new Stream();
            var st1_id = client.add(st1);
            var st2_id = client.add(st2);
            client.nick('you', st1_id);
            client.nick('me', st2_id);

            client.once("away", function (event) {
                if (event.network === st1_id) {
                    event.user.getNick().should.equal('me');
                    event.message.should.equal('auto away');
                } else {
                    event.user.getNick().should.equal('you');
                    event.message.should.equal('not here');
                }
                done();
            });

            st1.write(':irc.local 301 you me :auto away\r\n');
            st2.write(':irc.local 301 me you :not here\r\n');
        });

        it('should emit "{network}:away" [multi-network]', function (done) {
            var client = coffea(null, false);
            var st1 = new Stream();
            var st2 = new Stream();
            var st1_id = client.add(st1);
            var st2_id = client.add(st2);
            client.nick('you', st1_id);
            client.nick('me', st2_id);

            var tests = 0;
            client.once(st1_id + ":away", function (event) {
                event.user.getNick().should.equal('me');
                event.message.should.equal('auto away');
                tests++;
                if(tests >= 2) {
                    done();
                }
            });

            client.once(st2_id + ":away", function (event) {
                event.user.getNick().should.equal('you');
                event.message.should.equal('not here');
                tests++;
                if(tests >= 2) {
                    done();
                }
            });

            st1.write(':irc.local 301 you me :auto away\r\n');
            st2.write(':irc.local 301 me you :not here\r\n');
        });
    });

    describe('client.away()', function () {
        it('should send a valid AWAY command', function (done) {
            var client = coffea(null, false);
            var st1 = new Stream();
            var st2 = new Stream();
            var st1_id = client.add(st1);
            client.nick('me', st1_id);

            client.once('data', function () {
                client.once('data', function (data) {
                    data.string.should.equal('AWAY :not here')
                    done();
                });
            });

            client.away('not here', st1_id);
        })
    });
});
<commit_msg>fix node v0.11 tests<commit_after>var coffea = require('../..');
var Stream = require('stream').PassThrough;

describe('away.js', function() {
    describe('on RPL_AWAY', function() {
        it('should emit "away" [single-network]', function (done) {
            var client = coffea(null, false);
            var st1 = new Stream();
            var st2 = new Stream();
            var st1_id = client.add(st1);
            client.nick('me', st1_id);

            client.once("away", function (event) {
                event.user.getNick().should.equal('you');
                event.message.should.equal('not here');
                done();
            });

            st1.write(':irc.local 301 me you :not here\r\n');
        });

        it('should emit "away" [multi-network]', function (done) {
            var client = coffea(null, false);
            var st1 = new Stream();
            var st2 = new Stream();
            var st1_id = client.add(st1);
            var st2_id = client.add(st2);
            client.nick('you', st1_id);
            client.nick('me', st2_id);

            client.once("away", function (event) {
                if (event.network === st1_id) {
                    event.user.getNick().should.equal('me');
                    event.message.should.equal('auto away');
                } else {
                    event.user.getNick().should.equal('you');
                    event.message.should.equal('not here');
                }
                done();
            });

            st1.write(':irc.local 301 you me :auto away\r\n');
            st2.write(':irc.local 301 me you :not here\r\n');
        });

        it('should emit "{network}:away" [multi-network]', function (done) {
            var client = coffea(null, false);
            var st1 = new Stream();
            var st2 = new Stream();
            var st1_id = client.add(st1);
            var st2_id = client.add(st2);
            client.nick('you', st1_id);
            client.nick('me', st2_id);

            var tests = 0;
            client.once(st1_id + ":away", function (event) {
                event.user.getNick().should.equal('me');
                event.message.should.equal('auto away');
                tests++;
                if(tests >= 2) {
                    done();
                }
            });

            client.once(st2_id + ":away", function (event) {
                event.user.getNick().should.equal('you');
                event.message.should.equal('not here');
                tests++;
                if(tests >= 2) {
                    done();
                }
            });

            st1.write(':irc.local 301 you me :auto away\r\n');
            st2.write(':irc.local 301 me you :not here\r\n');
        });
    });

    describe('client.away()', function () {
        it('should send a valid AWAY command', function (done) {
            var client = coffea(null, false);
            var st1 = new Stream();
            var st2 = new Stream();
            var st1_id = client.add(st1);

            client.once('data', function () {
                client.once('data', function (data) {
                    data.string.should.equal('AWAY :not here')
                    done();
                });
            });

            client.nick('me', st1_id);
            client.away('not here', st1_id);
        })
    });
});
<|endoftext|>


<commit_before>'use strict';

function BufferPlugin(rail, opt_options) {
  if (!(this instanceof BufferPlugin)) {
    return new BufferPlugin(rail, opt_options);
  }
  opt_options = opt_options || {};

  this._rail = rail;

  this.default = opt_options.default || false;
  this.max = opt_options.max || 134217728; // 128 MiB

  this._setup();
}
module.exports = BufferPlugin;

BufferPlugin.prototype._setup = function() {
  var self = this;

  this._rail.on('plugin-response', function(call, options, response) {
    // HEAD responses are buffered too, acting as stream terminator
    if (self.default || options.buffer && options.buffer !== false) {
      self.intercept(call);
    }
  });

  this._intercept = function(call, options, response) {
    self._interceptResponse(call, options, response);
  };
};

BufferPlugin.prototype.intercept = function(call) {
  call.__intercept('response', this._intercept);
};

BufferPlugin.prototype._interceptResponse = function(call, options, response) {
  var length = 0;
  var buffer = [];

  function onreadable() {
    var data = response.read();

    if (data) {
      length += data.length;
      buffer.push(data);

      // bailout
      //   aka. stuffing everything back into the readable stream
      if (length > this.max) {
        call.emit('warn', 'buffer', 'bailout', 'max length exceeded');

        response.removeListener('readable', onreadable);
        response.removeListener('end', onend);

        do {
          response.unshift(buffer.pop());
        } while (buffer.length);

        call.__emit('response', response);
      }
    }
  }

  function onend() {
    if (buffer.length) {
      response.buffer = Buffer.concat(buffer);
    } else {
      response.buffer = null;
    }
    call.__emit('response', response);
  }

  response.on('readable', onreadable);
  response.once('end', onend);
};
<commit_msg>plugins/buffer: update constructor<commit_after>'use strict';

function BufferPlugin(rail, options) {
  if (!(this instanceof BufferPlugin)) {
    return new BufferPlugin(rail, options);
  }
  this._rail = rail;

  this.default = options.default || false;
  this.max = options.max || 134217728; // 128 MiB

  this._setup();
}
module.exports = BufferPlugin;

BufferPlugin.prototype._setup = function() {
  var self = this;

  this._rail.on('plugin-response', function(call, options, response) {
    // HEAD responses are buffered too, acting as stream terminator
    if (self.default || options.buffer && options.buffer !== false) {
      self.intercept(call);
    }
  });

  this._intercept = function(call, options, response) {
    self._interceptResponse(call, options, response);
  };
};

BufferPlugin.prototype.intercept = function(call) {
  call.__intercept('response', this._intercept);
};

BufferPlugin.prototype._interceptResponse = function(call, options, response) {
  var length = 0;
  var buffer = [];

  function onreadable() {
    var data = response.read();

    if (data) {
      length += data.length;
      buffer.push(data);

      // bailout
      //   aka. stuffing everything back into the readable stream
      if (length > this.max) {
        call.emit('warn', 'buffer', 'bailout', 'max length exceeded');

        response.removeListener('readable', onreadable);
        response.removeListener('end', onend);

        do {
          response.unshift(buffer.pop());
        } while (buffer.length);

        call.__emit('response', response);
      }
    }
  }

  function onend() {
    if (buffer.length) {
      response.buffer = Buffer.concat(buffer);
    } else {
      response.buffer = null;
    }
    call.__emit('response', response);
  }

  response.on('readable', onreadable);
  response.once('end', onend);
};
<|endoftext|>


<commit_before>var _ = require('koa-route')
var koa = require('koa')
var serve = require('koa-static')
var render = require('koa-ejs')
var path = require('path')
var fs = require('fs');
var assert = require('assert');

var socket = require('koa-socket');

var session = require('koa-session')
var parse = require('co-body')
var csrf = require('koa-csrf')

var app = koa();

require('koa-csrf')(app)

var email = require('./app_modules/email')

var auth = require('./app_modules/auth')
var db = require('./app_modules/db')
var user = require('./app_modules/user');
const ENV = process.env;
const SERVICE = auth.service(ENV.HLRDESK_HOST, ENV.PORT, '/signin', !ENV.HLRDESK_DEV);

if(ENV.HLRDESK_DEV) {
  app.use(require('./app_modules/koa-sassy').Sassy);
}

app.keys = ['TODO MAKE ME AN ENV VARIABLE', 'I SHOULD NOT BE HARDCODED', 'MY DOG HAS NO NOSE', 'HOW DOES HE SMELL?', 'AWFUL'];
app.use(session());

app.use(serve(path.join(__dirname, '..', 'public')));

if(ENV.NODE_TEST === 'true') {
  // e.g., /logmein?as=prabbit
  // see tests/sessions/* for available users
  require('./app_modules/mock-login')(app);
}

app.use(function*(next){
  const WHITELIST = ['/signin', '/logmein', '/logout'];
  const GREYLIST = WHITELIST.concat(['/calendar']);
  if (!this.session.user && WHITELIST.indexOf(this.request.path) === -1){
    this.session.login_redirect = this.request.path + this.request.search;
    this.redirect('https://cas.byu.edu/cas/login?service=' + SERVICE);
    return;
  }
  var is_admin = yield auth.isAdmin(this.session.user)
  if ( this.session.user && !is_admin && GREYLIST.indexOf(this.request.path) === -1){
    this.redirect('/calendar');
    return;
  }
  else{
    yield next;
  }
})

render(app, {
  root: path.join(__dirname, 'templates'),
  layout: 'layout',
  viewExt: 'html',
  cache: !ENV.HLRDESK_DEV,
  debug: ENV.HLRDESK_DEV,
  locals: {
    title: 'HLRDesk',
    token: function() {
      return this.session.token;
    }
  }
});

app.use(function *(next) {
  if(this.request.header['x-requested-with'] === 'XMLHttpRequest')
  {
    this.USE_LAYOUT = false;
  }
  else
  {
    if (this.session){
      var is_admin = yield auth.isAdmin(this.session.user)
      if (is_admin){
        this.USE_LAYOUT = 'layout';
        //TODO: May add read message check here. Likely the best spot
      }
      else{
        this.USE_LAYOUT = 'simple_layout';
      }
    }
    else{
      this.USE_LAYOUT = 'layout';
    }
  }
  captionClass = "undefined";
  yield next;
});

app.use(_.get("/", function *(next) {
  var rdir = this.session.login_redirect;
  if(rdir) {
    this.redirect(rdir);
    delete this.session.login_redirect;
    yield next;
    return;
  }
  yield this.render('layout', {layout: false, body:"", captionClass: "aboveLoader"});
  yield next;
}));

app.use(_.get("/message", function *() {
  var client = db();
  var all_messages = yield client.query("SELECT * FROM messages;");
  var all_tasks = yield client.query("Select * FROM tasks ORDER BY priority ASC");
  yield this.render('msg', {layout: this.USE_LAYOUT, all_messages: all_messages, all_tasks: all_tasks});
}));

app.use(_.get('/check-in', function *() {
  var inv = require('./app_modules/inventory');
  var items = yield inv.checked_out;

  var users = items.reduce(function(prev, item) {
    if(prev.indexOf(item.owner) === -1) {
      prev.push(item.owner);
    }
    return prev;
  }, []);

  var userDetails = yield user.contactInfo.apply(this, users);

  yield this.render('check-in', {
    items: items,
    user: userDetails,
    admin: this.session.user,
    moment: require('moment'),
    title: "Check In",
    layout: this.USE_LAYOUT
  });
}));

app.use(_.get('/check-out', function *() {
  yield this.render('check-out', {
    title: "Check Out",
    layout: this.USE_LAYOUT
  });
}));

app.use(_.get('/edit-catalog', function *() {
  var client = db();
  var media_types = yield client.query("SELECT * FROM media ORDER BY media ASC;");
  var lang = yield client.query("SELECT * FROM languages ORDER BY name ASC;");
  yield this.render('edit-catalog', {
    title: "Edit Item",
    layout: this.USE_LAYOUT,
    media_types: media_types,
    lang: lang
  });
}));

app.use(_.get('/viewHistory', function *() {
  var client = db();
  yield this.render('view-history', {
    title: "Item History",
    layout: this.USE_LAYOUT,
  });
}));

app.use(_.get("/extras", function *() {
  yield this.render('extras', {layout: this.USE_LAYOUT });
}));

app.use(_.get("/calendar", function *(next) {
  // temporary redirect so we can spend time integrating
  // the desktop application
  this.redirect('https://hlr.byu.edu/schedule/');
  yield next;

  //var client = db();
  //var isAdmin = yield auth.isAdmin(this.session.user);
  //var allCalendarEvents = yield client.query('SELECT * FROM calendar;');
  //yield this.render('calendar', {layout: this.USE_LAYOUT, date: new Date(), allCalendarEvents: allCalendarEvents, user: this.session.user, isAdmin:isAdmin});
}));

app.use(_.get("/signin", function *(next){
  ticket=this.request.query.ticket;
  var obj = yield auth.cas_login(ticket, SERVICE);
  auth.login(this, obj);
  if (yield auth.isAdmin(this.session.user)){
    this.redirect('/');
  }
  else {
    this.redirect('/calendar');
  }
  yield next;
}));

app.use(_.get("/languages", function*() {
  yield this.render('languages', {
    layout: this.USE_LAYOUT,
    languages: yield require('./app_modules/language').list
  });
}));

app.use(_.get("/media", function*() {
  yield this.render('media', {
    layout: this.USE_LAYOUT,
    media: yield require('./app_modules/media').list,
    csrf: this.csrf
  });
}));

app.use(_.post('/media', function*() {
  var media = require('./app_modules/media');
  var body = yield parse(this); // co-body or something

  try {
    this.assertCSRF(body.csrf);
    assert(yield auth.isAdmin(this.session.user));
  }catch(err) {
    this.status = 403
    this.body = {
      message: 'Unauthorized'
    };
    return;
  }

  if(body['delete']) {
    yield media.remove(body['delete']);
  }
  else if(body['create']) {
    yield media.add(body['new-media']);
  }

  this.redirect('/media');
}));

app.use(_.get("/logout", function *(){
  this.session = null;
  var s = this.request.query.service || null;
  var url = 'https://cas.byu.edu/cas/logout' + (s ? '?service=' + s : '');
  this.redirect(url);
}));

app.use(_.post("/employees",function *(){
  var client = db();
  var body = yield parse(this) // co-body or something
  this.assertCSRF(body.csrf);
  if (body.action == "add") {
    try {
      var to_mk=body.user;
      var status = yield auth.mkadmin(this.session.user, to_mk, true);
      if(!status){
        this.redirect('/employees?status='+status+'&toMk='+to_mk);
      }
      else{
        this.redirect('/employees');
      }
    }
    catch (err) {
      console.error(err);
      this.status = 403
      this.body = {
        message: 'This CSRF token is invalid!'
      }
      return
    }
  } else if (body.action == "remove") {
    try {
      to_del=body.user;
      override = (body.override=="true");
      status = yield auth.deladmin(this.session.user, to_del, override);
      if(!status){
        this.redirect('/employees?status='+status+'&toDel='+to_del);
      }
      else{
        this.redirect('/employees');
      }
    }
    catch (err) {
      this.status = 403
      this.body = {
        message: 'This CSRF token is invalid!'
      }
      return
    }
  }
  else
  {
    this.status = 400;
    this.body = {
      message: 'Invalid data'
    }
  }
}));

app.use(_.get("/employees",function *(){
  var isAdmin = yield auth.isAdmin(this.session.user);
  var client = db();
  var allAdmins = yield client.query("SELECT netid, email FROM users WHERE admin = TRUE;");
  var netids = allAdmins.rows.map(function (a){return a.netid});
  var ldapDetails = yield user.ldapInfo.apply(null, netids);
  var names = Object.keys(ldapDetails).map(function(k){return ldapDetails[k].cn});
  if (isAdmin){
    if (this.request.query.status == "false"){
      yield this.render('mkadmin', {layout: this.USE_LAYOUT, csrf: this.csrf, allAdminsFromDB: allAdmins, alert : true, to_mk : this.request.query.toMk, namesFromDB : names});
    }
    else{
      yield this.render('mkadmin', {layout: this.USE_LAYOUT, csrf: this.csrf, allAdminsFromDB: allAdmins, alert : false, to_mk : undefined, namesFromDB : names});
    }
  }
  else{
    this.status = 403
    this.body = {
      message: 'Wrong place friend!'
    }
    return
  }
}));

socket.start(app);

socket.use(function*(next){
  this.socket.user = yield auth.getUser(this.data.token);
  yield next;
});

// Load in all socket files
fs.readdir(path.join(__dirname, 'sockets'), function (err, files) {
  if(err) {
    throw new Error(err);
  }
  var socket_files = files.filter(function(file) {
    return file.match(/\.js$/);
  });
  socket_files.forEach(function(file){
    try {
      require(path.join(__dirname, 'sockets', file))(socket, app);
    }
    catch(e) {
      console.error("Initializing sockets/" + file + " failed.", e);
      throw e;
    }
  });
});

module.exports = app.server;
<commit_msg>Refied admin query<commit_after>var _ = require('koa-route')
var koa = require('koa')
var serve = require('koa-static')
var render = require('koa-ejs')
var path = require('path')
var fs = require('fs');
var assert = require('assert');

var socket = require('koa-socket');

var session = require('koa-session')
var parse = require('co-body')
var csrf = require('koa-csrf')

var app = koa();

require('koa-csrf')(app)

var email = require('./app_modules/email')

var auth = require('./app_modules/auth')
var db = require('./app_modules/db')
var user = require('./app_modules/user');
const ENV = process.env;
const SERVICE = auth.service(ENV.HLRDESK_HOST, ENV.PORT, '/signin', !ENV.HLRDESK_DEV);

if(ENV.HLRDESK_DEV) {
  app.use(require('./app_modules/koa-sassy').Sassy);
}

app.keys = ['TODO MAKE ME AN ENV VARIABLE', 'I SHOULD NOT BE HARDCODED', 'MY DOG HAS NO NOSE', 'HOW DOES HE SMELL?', 'AWFUL'];
app.use(session());

app.use(serve(path.join(__dirname, '..', 'public')));

if(ENV.NODE_TEST === 'true') {
  // e.g., /logmein?as=prabbit
  // see tests/sessions/* for available users
  require('./app_modules/mock-login')(app);
}

app.use(function*(next){
  const WHITELIST = ['/signin', '/logmein', '/logout'];
  const GREYLIST = WHITELIST.concat(['/calendar']);
  if (!this.session.user && WHITELIST.indexOf(this.request.path) === -1){
    this.session.login_redirect = this.request.path + this.request.search;
    this.redirect('https://cas.byu.edu/cas/login?service=' + SERVICE);
    return;
  }
  var is_admin = yield auth.isAdmin(this.session.user)
  if ( this.session.user && !is_admin && GREYLIST.indexOf(this.request.path) === -1){
    this.redirect('/calendar');
    return;
  }
  else{
    yield next;
  }
})

render(app, {
  root: path.join(__dirname, 'templates'),
  layout: 'layout',
  viewExt: 'html',
  cache: !ENV.HLRDESK_DEV,
  debug: ENV.HLRDESK_DEV,
  locals: {
    title: 'HLRDesk',
    token: function() {
      return this.session.token;
    }
  }
});

app.use(function *(next) {
  if(this.request.header['x-requested-with'] === 'XMLHttpRequest')
  {
    this.USE_LAYOUT = false;
  }
  else
  {
    if (this.session){
      var is_admin = yield auth.isAdmin(this.session.user)
      if (is_admin){
        this.USE_LAYOUT = 'layout';
        //TODO: May add read message check here. Likely the best spot
      }
      else{
        this.USE_LAYOUT = 'simple_layout';
      }
    }
    else{
      this.USE_LAYOUT = 'layout';
    }
  }
  captionClass = "undefined";
  yield next;
});

app.use(_.get("/", function *(next) {
  var rdir = this.session.login_redirect;
  if(rdir) {
    this.redirect(rdir);
    delete this.session.login_redirect;
    yield next;
    return;
  }
  yield this.render('layout', {layout: false, body:"", captionClass: "aboveLoader"});
  yield next;
}));

app.use(_.get("/message", function *() {
  var client = db();
  var all_messages = yield client.query("SELECT * FROM messages;");
  var all_tasks = yield client.query("Select * FROM tasks ORDER BY priority ASC");
  yield this.render('msg', {layout: this.USE_LAYOUT, all_messages: all_messages, all_tasks: all_tasks});
}));

app.use(_.get('/check-in', function *() {
  var inv = require('./app_modules/inventory');
  var items = yield inv.checked_out;

  var users = items.reduce(function(prev, item) {
    if(prev.indexOf(item.owner) === -1) {
      prev.push(item.owner);
    }
    return prev;
  }, []);

  var userDetails = yield user.contactInfo.apply(this, users);

  yield this.render('check-in', {
    items: items,
    user: userDetails,
    admin: this.session.user,
    moment: require('moment'),
    title: "Check In",
    layout: this.USE_LAYOUT
  });
}));

app.use(_.get('/check-out', function *() {
  yield this.render('check-out', {
    title: "Check Out",
    layout: this.USE_LAYOUT
  });
}));

app.use(_.get('/edit-catalog', function *() {
  var client = db();
  var media_types = yield client.query("SELECT * FROM media ORDER BY media ASC;");
  var lang = yield client.query("SELECT * FROM languages ORDER BY name ASC;");
  yield this.render('edit-catalog', {
    title: "Edit Item",
    layout: this.USE_LAYOUT,
    media_types: media_types,
    lang: lang
  });
}));

app.use(_.get('/viewHistory', function *() {
  var client = db();
  yield this.render('view-history', {
    title: "Item History",
    layout: this.USE_LAYOUT,
  });
}));

app.use(_.get("/extras", function *() {
  yield this.render('extras', {layout: this.USE_LAYOUT });
}));

app.use(_.get("/calendar", function *(next) {
  // temporary redirect so we can spend time integrating
  // the desktop application
  this.redirect('https://hlr.byu.edu/schedule/');
  yield next;

  //var client = db();
  //var isAdmin = yield auth.isAdmin(this.session.user);
  //var allCalendarEvents = yield client.query('SELECT * FROM calendar;');
  //yield this.render('calendar', {layout: this.USE_LAYOUT, date: new Date(), allCalendarEvents: allCalendarEvents, user: this.session.user, isAdmin:isAdmin});
}));

app.use(_.get("/signin", function *(next){
  ticket=this.request.query.ticket;
  var obj = yield auth.cas_login(ticket, SERVICE);
  auth.login(this, obj);
  if (yield auth.isAdmin(this.session.user)){
    this.redirect('/');
  }
  else {
    this.redirect('/calendar');
  }
  yield next;
}));

app.use(_.get("/languages", function*() {
  yield this.render('languages', {
    layout: this.USE_LAYOUT,
    languages: yield require('./app_modules/language').list
  });
}));

app.use(_.get("/media", function*() {
  yield this.render('media', {
    layout: this.USE_LAYOUT,
    media: yield require('./app_modules/media').list,
    csrf: this.csrf
  });
}));

app.use(_.post('/media', function*() {
  var media = require('./app_modules/media');
  var body = yield parse(this); // co-body or something

  try {
    this.assertCSRF(body.csrf);
    assert(yield auth.isAdmin(this.session.user));
  }catch(err) {
    this.status = 403
    this.body = {
      message: 'Unauthorized'
    };
    return;
  }

  if(body['delete']) {
    yield media.remove(body['delete']);
  }
  else if(body['create']) {
    yield media.add(body['new-media']);
  }

  this.redirect('/media');
}));

app.use(_.get("/logout", function *(){
  this.session = null;
  var s = this.request.query.service || null;
  var url = 'https://cas.byu.edu/cas/logout' + (s ? '?service=' + s : '');
  this.redirect(url);
}));

app.use(_.post("/employees",function *(){
  var client = db();
  var body = yield parse(this) // co-body or something
  this.assertCSRF(body.csrf);
  if (body.action == "add") {
    try {
      var to_mk=body.user;
      var status = yield auth.mkadmin(this.session.user, to_mk, true);
      if(!status){
        this.redirect('/employees?status='+status+'&toMk='+to_mk);
      }
      else{
        this.redirect('/employees');
      }
    }
    catch (err) {
      console.error(err);
      this.status = 403
      this.body = {
        message: 'This CSRF token is invalid!'
      }
      return
    }
  } else if (body.action == "remove") {
    try {
      to_del=body.user;
      override = (body.override=="true");
      status = yield auth.deladmin(this.session.user, to_del, override);
      if(!status){
        this.redirect('/employees?status='+status+'&toDel='+to_del);
      }
      else{
        this.redirect('/employees');
      }
    }
    catch (err) {
      this.status = 403
      this.body = {
        message: 'This CSRF token is invalid!'
      }
      return
    }
  }
  else
  {
    this.status = 400;
    this.body = {
      message: 'Invalid data'
    }
  }
}));

app.use(_.get("/employees",function *(){
  var isAdmin = yield auth.isAdmin(this.session.user);
  var client = db();
  var allAdmins = yield client.query("SELECT netid, email, telephone, admin FROM users WHERE admin = TRUE;");
  var netids = allAdmins.rows.map(function (a){return a.netid});
  var ldapDetails = yield user.ldapInfo.apply(null, netids);
  var names = Object.keys(ldapDetails).map(function(k){return ldapDetails[k].cn});
  if (isAdmin){
    if (this.request.query.status == "false"){
      yield this.render('mkadmin', {layout: this.USE_LAYOUT, csrf: this.csrf, allAdminsFromDB: allAdmins, alert : true, to_mk : this.request.query.toMk, namesFromDB : names});
    }
    else{
      yield this.render('mkadmin', {layout: this.USE_LAYOUT, csrf: this.csrf, allAdminsFromDB: allAdmins, alert : false, to_mk : undefined, namesFromDB : names});
    }
  }
  else{
    this.status = 403
    this.body = {
      message: 'Wrong place friend!'
    }
    return
  }
}));

socket.start(app);

socket.use(function*(next){
  this.socket.user = yield auth.getUser(this.data.token);
  yield next;
});

// Load in all socket files
fs.readdir(path.join(__dirname, 'sockets'), function (err, files) {
  if(err) {
    throw new Error(err);
  }
  var socket_files = files.filter(function(file) {
    return file.match(/\.js$/);
  });
  socket_files.forEach(function(file){
    try {
      require(path.join(__dirname, 'sockets', file))(socket, app);
    }
    catch(e) {
      console.error("Initializing sockets/" + file + " failed.", e);
      throw e;
    }
  });
});

module.exports = app.server;
<|endoftext|>


<commit_before>'use strict';

var teoria = require('teoria');

var NOTE = /^([a-h])(x|#|bb|b?)(-?\d*)/
function plugin(Score) {
  Score.on('created', function(score) {
    score.forEach(function(event) {
      if(NOTE.test(event.value)) {
        try {
          var note = teoria.note(event.value);
          event.merge({ value: note, type: 'note' });
        } catch(e) {}
      } else {
        try {
          var chord = teoria.chord(event.value);
          event.merge({ value: chord, type: 'chord' });
        } catch(e) {}
      }
    });
  });

  Score.Note = teoria.TeoriaNote;
  Score.Chord = teoria.TeoriaChord;
}

module.exports = plugin;
<commit_msg>Better plugin encapsulation. Serveral Score instances.<commit_after>'use strict';

var teoria = require('teoria');

var NOTE = /^([a-h])(x|#|bb|b?)(-?\d*)/

function plugin(Score) {

  var _parser = Score.parser;

  Score.parser = function(time, repr) {
    return teoriaEvents(_parser(time, repr));
  }

  Score.Note = teoria.TeoriaNote;
  Score.Chord = teoria.TeoriaChord;
}

function teoriaEvents(events) {
  events.forEach(function(event) {
    if(NOTE.test(event.value)) {
      try {
        var note = teoria.note(event.value);
        event.merge({ value: note, type: 'note' });
      } catch(e) {}
    } else {
      try {
        var chord = teoria.chord(event.value);
        event.merge({ value: chord, type: 'chord' });
      } catch(e) {}
    }
  });
}

module.exports = plugin;
<|endoftext|>


<commit_before>'use strict';
var _ = require('lodash');
var BBPromise = require('bluebird');
var model = require('hoist-model');
var Subscription = model.Subscription;
var Bucket = model.Bucket;
var BouncerToken = model.BouncerToken;
var ConnectorSetting = model.ConnectorSetting;
var SubscriptionWrapper = require('./subscription_wrapper');
var logger = require('hoist-logger');
var fs = require('fs');
var config = require('config');
var path = require('path');
var Authorization = require('hoist-connector-pipeline/lib/authorization');
var HoistContext = require('hoist-context');
var EventPipeline = require('hoist-events-pipeline');
var throat = require('throat')(BBPromise);

function PollerService() {

}

PollerService.prototype.start = function () {
  logger.info('starting poller service');
  //mark as running
  this.running = true;
  //start poll
  logger.info('starting loop');
  this.loop = this.poll().cancellable();
};
PollerService.prototype.stop = function () {
  return BBPromise.try(function () {
    logger.info('stopping poller service');
    //mark as stopped
    this.running = false;
    //cancel loop
    /* istanbul ignore else */
    if (this.loop) {
      if (this.loop.isCancellable()) {
        logger.info('cancelling loop');
        this.loop.cancel();
      } else {
        logger.warn('loop isn\'t cancellable for some reason');
      }
      //delete loop
      logger.info('deleting loop promise reference');
      delete this.loop;
    }
  }, [], this);

};
PollerService.prototype.poll = function () {
  //load subscriptions
  logger.info('loading subscriptions');
  return this.loadSubscriptions()
    .cancellable()
    .bind(this)
    //for each
    .then(function (subscriptions) {
      logger.debug({
        subscriptions: subscriptions
      }, 'polling each subscription');
      return _.map(subscriptions, throat(1, _.bind(function (subscription) {
        return this.pollSubscription(subscription);
      }, this)));
    })
    //poll subscription
    .then(function (pollPromises) {
      logger.info('settling all polls');
      return BBPromise.settle(pollPromises).cancellable();
    })
    .then(function () {
      //loop
      /* istanbul ignore else */
      if (this.running) {
        logger.info('pausing');
        return BBPromise.delay(1000)
          .cancellable()
          .bind(this)
          .then(function () {
            logger.info('looping');
            return this.poll();
          });
      } else {
        logger.info('poller stopped so stopping');
      }
    }).catch(function (err) {
      logger.error(err, 'error during poll loop');
      if (!(err instanceof APILimitReachedError) && !(err instanceof ConnectorRequiresAuthorizationError)) {
        logger.alert(err);
      }
    });

};
PollerService.prototype.loadSubscriptions = function () {
  var query = Subscription.find({})
    .populate('application');
  return BBPromise.resolve(query.exec());
};
PollerService.prototype.pollSubscription = function (subscription) {
  logger.debug({
    subscription: subscription
  }, 'polling subscription');
  return BBPromise.try(function () {
      //wrap subscription
      var context = {
        subscription: new SubscriptionWrapper(subscription),
        application: subscription.application
      };

      return context;
    }, [], this)
    .bind(this)
    .then(function buildContext(context) {
      return ConnectorSetting.findOneAsync({
        key: context.subscription._subscription.connector,
        application: context.application._id,
        environment: 'live'
      }).then(function (connectorSettings) {
        context.connectorSettings = connectorSettings;
        return context;
      });
    })
    .then(function (context) {
      logger.debug({
        context: context
      }, 'setting context');
      //load buckets
      //load bouncer tokens based on buckets
      var query = {
        application: context.application._id,
        environment: 'live'
      };
      //load only buckets with authTokens attached
      query['meta.authToken.' + context.connectorSettings.key] = {
        $exists: true
      };
      logger.info('finding all auth buckets');
      return Bucket.findAsync(query)
        .then(function (buckets) {
          logger.debug({
            buckets: buckets
          }, 'found buckets');
          context.buckets = buckets;
          return context;
        });
    }).then(function (context) {
      //for each bouncer token
      //poll subscription
      logger.info('polling all buckets');
      var polls = _.map(context.buckets, throat(4, _.bind(function (bucket) {
        this.pollContext(context, bucket);
      }, this)));
      polls.push(this.pollContext(context));
      return [polls, context];
    }).spread(function (polls, context) {
      logger.info('settling root poll calls');
      //also poll without a bucket for private connections
      return BBPromise.settle(polls).then(function () {
        return context;
      });
    }).then(function (context) {
      //save changes to subscription
      logger.info('saving updates to subscription');
      return context.subscription.save();
    });
};

PollerService.prototype.pollContext = function (context, bucket) {
  logger.debug({
    context: context
  }, 'polling context');
  return BBPromise.try(function () {
      /* istanbul ignore else */
      if (bucket) {
        return BouncerToken.findOneAsync({
          _id: bucket.meta.authToken[context.connectorSettings.key]
        });
      }
    }, [], this)
    .bind(this)
    .then(function (bouncerToken) {
      var connectorsPath = path.resolve(config.get('Hoist.connectors.path'));
      var pollerPath = path.join(connectorsPath, context.connectorSettings.connectorType, config.get('Hoist.connectors.currentDirectoryName'), 'lib/poll.js');
      pollerPath = fs.realpathSync(pollerPath);
      logger.debug({
        path: pollerPath
      }, 'loading poller');

      var pollerMethod = require(pollerPath);
      var pollContext = {
        settings: context.connectorSettings.settings,
        connectorKey: context.connectorSettings.key,
        subscription: context.subscription,
        application: context.application.toObject()
      };
      if (bouncerToken) {
        pollContext.authorization = new Authorization(bouncerToken);
      }
      if (bucket) {
        pollContext.bucket = bucket.toObject();
      }
      logger.info({
        application: pollContext.application._id
      }, 'calling poll');
      return pollerMethod(pollContext, _.bind(function (eventName, payload) {
        return this.raiseEvent(pollContext, eventName, payload);
      }, this)).then(function () {
        logger.info({
          application: pollContext.application._id
        }, 'poll done');
      });
    });
};
PollerService.prototype.raiseEvent = function (context, eventName, payload) {
  var eventPipeline = new EventPipeline(HoistContext, model);
  logger.debug({
    context: context,
    eventName: eventName,
    payload: payload
  }, 'raising event');
  logger.info({
    eventName: eventName
  }, 'raising event');
  HoistContext.get()
    .then(function (hoistContext) {
      hoistContext.application = context.application;
      hoistContext.bucket = context.bucket;
      hoistContext.environment = 'live';
    }).then(function () {
      eventPipeline.raise(eventName, payload);
    });
};

module.exports = PollerService;
<commit_msg>remove bade code<commit_after>'use strict';
var _ = require('lodash');
var BBPromise = require('bluebird');
var model = require('hoist-model');
var Subscription = model.Subscription;
var Bucket = model.Bucket;
var BouncerToken = model.BouncerToken;
var ConnectorSetting = model.ConnectorSetting;
var SubscriptionWrapper = require('./subscription_wrapper');
var logger = require('hoist-logger');
var fs = require('fs');
var config = require('config');
var path = require('path');
var Authorization = require('hoist-connector-pipeline/lib/authorization');
var HoistContext = require('hoist-context');
var EventPipeline = require('hoist-events-pipeline');
var throat = require('throat')(BBPromise);

function PollerService() {

}

PollerService.prototype.start = function () {
  logger.info('starting poller service');
  //mark as running
  this.running = true;
  //start poll
  logger.info('starting loop');
  this.loop = this.poll().cancellable();
};
PollerService.prototype.stop = function () {
  return BBPromise.try(function () {
    logger.info('stopping poller service');
    //mark as stopped
    this.running = false;
    //cancel loop
    /* istanbul ignore else */
    if (this.loop) {
      if (this.loop.isCancellable()) {
        logger.info('cancelling loop');
        this.loop.cancel();
      } else {
        logger.warn('loop isn\'t cancellable for some reason');
      }
      //delete loop
      logger.info('deleting loop promise reference');
      delete this.loop;
    }
  }, [], this);

};
PollerService.prototype.poll = function () {
  //load subscriptions
  logger.info('loading subscriptions');
  return this.loadSubscriptions()
    .cancellable()
    .bind(this)
    //for each
    .then(function (subscriptions) {
      logger.debug({
        subscriptions: subscriptions
      }, 'polling each subscription');
      return _.map(subscriptions, throat(1, _.bind(function (subscription) {
        return this.pollSubscription(subscription);
      }, this)));
    })
    //poll subscription
    .then(function (pollPromises) {
      logger.info('settling all polls');
      return BBPromise.settle(pollPromises).cancellable();
    })
    .then(function () {
      //loop
      /* istanbul ignore else */
      if (this.running) {
        logger.info('pausing');
        return BBPromise.delay(1000)
          .cancellable()
          .bind(this)
          .then(function () {
            logger.info('looping');
            return this.poll();
          });
      } else {
        logger.info('poller stopped so stopping');
      }
    }).catch(function (err) {
      logger.error(err, 'error during poll loop');
    });

};
PollerService.prototype.loadSubscriptions = function () {
  var query = Subscription.find({})
    .populate('application');
  return BBPromise.resolve(query.exec());
};
PollerService.prototype.pollSubscription = function (subscription) {
  logger.debug({
    subscription: subscription
  }, 'polling subscription');
  return BBPromise.try(function () {
      //wrap subscription
      var context = {
        subscription: new SubscriptionWrapper(subscription),
        application: subscription.application
      };

      return context;
    }, [], this)
    .bind(this)
    .then(function buildContext(context) {
      return ConnectorSetting.findOneAsync({
        key: context.subscription._subscription.connector,
        application: context.application._id,
        environment: 'live'
      }).then(function (connectorSettings) {
        context.connectorSettings = connectorSettings;
        return context;
      });
    })
    .then(function (context) {
      logger.debug({
        context: context
      }, 'setting context');
      //load buckets
      //load bouncer tokens based on buckets
      var query = {
        application: context.application._id,
        environment: 'live'
      };
      //load only buckets with authTokens attached
      query['meta.authToken.' + context.connectorSettings.key] = {
        $exists: true
      };
      logger.info('finding all auth buckets');
      return Bucket.findAsync(query)
        .then(function (buckets) {
          logger.debug({
            buckets: buckets
          }, 'found buckets');
          context.buckets = buckets;
          return context;
        });
    }).then(function (context) {
      //for each bouncer token
      //poll subscription
      logger.info('polling all buckets');
      var polls = _.map(context.buckets, throat(4, _.bind(function (bucket) {
        this.pollContext(context, bucket);
      }, this)));
      polls.push(this.pollContext(context));
      return [polls, context];
    }).spread(function (polls, context) {
      logger.info('settling root poll calls');
      //also poll without a bucket for private connections
      return BBPromise.settle(polls).then(function () {
        return context;
      });
    }).then(function (context) {
      //save changes to subscription
      logger.info('saving updates to subscription');
      return context.subscription.save();
    });
};

PollerService.prototype.pollContext = function (context, bucket) {
  logger.debug({
    context: context
  }, 'polling context');
  return BBPromise.try(function () {
      /* istanbul ignore else */
      if (bucket) {
        return BouncerToken.findOneAsync({
          _id: bucket.meta.authToken[context.connectorSettings.key]
        });
      }
    }, [], this)
    .bind(this)
    .then(function (bouncerToken) {
      var connectorsPath = path.resolve(config.get('Hoist.connectors.path'));
      var pollerPath = path.join(connectorsPath, context.connectorSettings.connectorType, config.get('Hoist.connectors.currentDirectoryName'), 'lib/poll.js');
      pollerPath = fs.realpathSync(pollerPath);
      logger.debug({
        path: pollerPath
      }, 'loading poller');

      var pollerMethod = require(pollerPath);
      var pollContext = {
        settings: context.connectorSettings.settings,
        connectorKey: context.connectorSettings.key,
        subscription: context.subscription,
        application: context.application.toObject()
      };
      if (bouncerToken) {
        pollContext.authorization = new Authorization(bouncerToken);
      }
      if (bucket) {
        pollContext.bucket = bucket.toObject();
      }
      logger.info({
        application: pollContext.application._id
      }, 'calling poll');
      return pollerMethod(pollContext, _.bind(function (eventName, payload) {
        return this.raiseEvent(pollContext, eventName, payload);
      }, this)).then(function () {
        logger.info({
          application: pollContext.application._id
        }, 'poll done');
      });
    });
};
PollerService.prototype.raiseEvent = function (context, eventName, payload) {
  var eventPipeline = new EventPipeline(HoistContext, model);
  logger.debug({
    context: context,
    eventName: eventName,
    payload: payload
  }, 'raising event');
  logger.info({
    eventName: eventName
  }, 'raising event');
  HoistContext.get()
    .then(function (hoistContext) {
      hoistContext.application = context.application;
      hoistContext.bucket = context.bucket;
      hoistContext.environment = 'live';
    }).then(function () {
      eventPipeline.raise(eventName, payload);
    });
};

module.exports = PollerService;
<|endoftext|>


<commit_before>
"use strict";

import {ListController} from '../controllers/ListController';
import {CrudController} from '../controllers/CrudController';
import {Navigation} from '../services/Navigation';

let nav = new Navigation();
let defaults = {
    list: {
        options: {
            controller: ListController,
            controllerAs: 'list',
            templateUrl: '../monad/templates/list.html'
        }
    },
    create: {
        options: {
            controller: CrudController,
            controllerAs: 'crud'
        },
        resolve: {$mapping: {item: 'Manager'}}
    },
    update: {
        options: {
            controller: CrudController,
            controllerAs: 'crud'
        },
        resolve: {$mapping: {item: 'Manager'}}
    }
};
let interfacer = angular.module('monad.interface', []);

class Component {

    constructor(name, dependencies = [], configFn = undefined) {
        this.name = name;
        this.$manager = undefined;
        this.dependencies = dependencies;
        this.configFn = configFn;
        this.queued = [];
        this.$bootstrapped = false;
        this.defaults = angular.extend({}, defaults);
        this.settings = {};

        for (let prop in interfacer) {
            if (typeof interfacer[prop] == 'function') {
                this[prop] = (...args) => {
                    this.queued.push([prop].concat(args));
                    return this;
                };
            }
        }
    }

    bootstrap() {
        if (this.$bootstrapped) {
            return;
        }
        this.$bootstrapped = true;
        let deps = [];
        this.dependencies.map(dep => {
            if (typeof dep == 'string' && monad.exists(dep)) {
                dep = monad.component(dep);
            }
            if (typeof dep == 'object' && dep instanceof Component) {
                dep.bootstrap();
                deps.push(dep.name);
            } else {
                deps.push(dep);
            }
        });
        this.ngmod = angular.module(this.name, deps, this.configFn);
        this.queued.map(proxy => {
            let fn = proxy.shift();
            if (typeof fn == 'string') {
                this.ngmod[fn](...proxy);
            } else {
                fn.apply(this, proxy);
            }
        });
    }

    extend(...components) {
        components.map(component => {
            this.dependencies.push(component);
            if (typeof component == 'string') {
                if (monad.exists(component)) {
                    component = monad.component(component);
                } else {
                    throw `Component ${component} is undefined and cannot be extended upon.`;
                }
            }
            this.defaults = merge(this.defaults, component.defaults);
        });
        return this;
    }

    authentication(auth) {
        this.defaults = merge(this.defaults, {
            list: {resolve: {Authentication: auth}},
            create: {resolve: {Authentication: auth}},
            update: {resolve: {Authentication: auth}}
        });
        return this;
    }

    list(url, options = {}, resolve = {}) {
        // It's easier if we can specify 'columns' on the options:
        if ('columns' in options) {
            let columns = options.columns;
            resolve.columns = () => columns;
            delete options.columns;
        }

        if (!('menu' in options) || options.menu) {
            nav.register(options.menu || 'main', '/:language' + url, 'monad.navigation.' + normalize(this.name, '.$1'));
        }
        delete(options.menu);

        this.settings.list = {url, options, resolve};
        this.queued.push([addTarget, 'list']);
        return this;
    }

    create(url, options = {}, resolve = {}) {
        options.templateUrl = options.templateUrl || this.name + '/schema.html';
        delete options.create;
        this.settings.create = {url, options, resolve};
        this.queued.push([addTarget, 'create']);
        return this;
    }

    update(url, options = {}, resolve = {}) {
        options.templateUrl = options.templateUrl || this.name + '/schema.html';
        if (options.create) {
            this.create(options.create, options, resolve);
            delete options.create;
        }
        this.settings.update = {url, options, resolve};
        this.queued.push([addTarget, 'update']);
        return this;
    }

    manager(Manager) {
        this.$manager = {name: normalize(this.name) + 'Manager', obj: Manager};
        this.service(this.$manager.name, this.$manager.obj);
        return this;
    }

};

/**
 * Private helper-functions:
 * {{{
 */
function addTarget(type) {
    let settings = merge(this.defaults[type], this.settings[type]);
    settings.resolve = settings.resolve || {};
    settings.resolve.Manager = settings.resolve.Manager || [normalize(this.name) + 'Manager', Manager => Manager];
    settings.resolve.module = () => this;
    if ('$mapping' in settings.resolve) {
        let $mapping = angular.copy(settings.resolve.$mapping);
        settings.resolve.$mapping = () => $mapping;
    }
    if (type == 'create') {
        settings.resolve.item = [this.$manager.name, Manager => new Manager.model];
    }
    settings.options.resolve = settings.resolve;
    delete settings.options.template; // Don't do this.
    this.ngmod.config(['$routeProvider', '$translatePartialLoaderProvider', ($routeProvider, $translatePartialLoaderProvider) => {
        $routeProvider.when('/:language' + settings.url, settings.options);
        $translatePartialLoaderProvider.addPart(this.name);
    }]);
};

function normalize(name, replace = undefined) {
    if (replace == undefined) {
        replace = match => match.substring(1).toUpperCase();
    }
    return name.replace(/\/(\w)/g, replace);
};

function merge(...args) {
    let merged = {};
    args.map(arg => {
        if (arg == undefined || arg == null || typeof arg != 'object') {
            return;
        }
        for (let prop in arg) {
            if (!(prop in merged)) {
                merged[prop] = arg[prop];
                continue;
            }
            if (typeof merged[prop] != typeof arg[prop]) {
                merged[prop] = arg[prop];
                continue;
            }
            if (angular.isArray(merged[prop]) != angular.isArray(arg[prop])) {
                merged[prop] = arg[prop];
                continue;
            }
            if (angular.isArray(merged[prop]) && angular.isArray(arg[prop])) {
                arg[prop].map(elem => {
                    if (merged[prop].indexOf(elem) == -1) {
                        merged[prop].push(elem);
                    }
                });
                continue;
            }
            if (typeof arg[prop] != 'object') {
                merged[prop] = arg[prop];
                continue;
            }
            merged[prop] = merge(merged[prop], arg[prop]);
        }
    });
    return merged;
};

/** }}} */

export {Component};

<commit_msg>store auth and component name<commit_after>
"use strict";

import {ListController} from '../controllers/ListController';
import {CrudController} from '../controllers/CrudController';
import {Navigation} from '../services/Navigation';

let nav = new Navigation();
let defaults = {
    list: {
        options: {
            controller: ListController,
            controllerAs: 'list',
            templateUrl: '../monad/templates/list.html'
        }
    },
    create: {
        options: {
            controller: CrudController,
            controllerAs: 'crud'
        },
        resolve: {$mapping: {item: 'Manager'}}
    },
    update: {
        options: {
            controller: CrudController,
            controllerAs: 'crud'
        },
        resolve: {$mapping: {item: 'Manager'}}
    }
};
let interfacer = angular.module('monad.interface', []);

class Component {

    constructor(name, dependencies = [], configFn = undefined) {
        this.name = name;
        this.$manager = undefined;
        this.dependencies = dependencies;
        this.configFn = configFn;
        this.queued = [];
        this.$bootstrapped = false;
        this.defaults = angular.extend({}, defaults);
        this.settings = {};

        for (let prop in interfacer) {
            if (typeof interfacer[prop] == 'function') {
                this[prop] = (...args) => {
                    this.queued.push([prop].concat(args));
                    return this;
                };
            }
        }
    }

    bootstrap() {
        if (this.$bootstrapped) {
            return;
        }
        this.$bootstrapped = true;
        let deps = [];
        this.dependencies.map(dep => {
            if (typeof dep == 'string' && monad.exists(dep)) {
                dep = monad.component(dep);
            }
            if (typeof dep == 'object' && dep instanceof Component) {
                dep.bootstrap();
                deps.push(dep.name);
            } else {
                deps.push(dep);
            }
        });
        this.ngmod = angular.module(this.name, deps, this.configFn);
        this.queued.map(proxy => {
            let fn = proxy.shift();
            if (typeof fn == 'string') {
                this.ngmod[fn](...proxy);
            } else {
                fn.apply(this, proxy);
            }
        });
    }

    extend(...components) {
        components.map(component => {
            this.dependencies.push(component);
            if (typeof component == 'string') {
                if (monad.exists(component)) {
                    component = monad.component(component);
                } else {
                    throw `Component ${component} is undefined and cannot be extended upon.`;
                }
            }
            this.defaults = merge(this.defaults, component.defaults);
        });
        return this;
    }

    authentication(auth) {
        this.defaults = merge(this.defaults, {
            list: {resolve: {Authentication: auth}},
            create: {resolve: {Authentication: auth}},
            update: {resolve: {Authentication: auth}}
        });
        this.Authentication = auth;
        return this;
    }

    list(url, options = {}, resolve = {}) {
        // It's easier if we can specify 'columns' on the options:
        if ('columns' in options) {
            let columns = options.columns;
            resolve.columns = () => columns;
            delete options.columns;
        }

        if (!('menu' in options) || options.menu) {
            nav.register(this.name, options.menu || 'main', '/:language' + url, 'monad.navigation.' + normalize(this.name, '.$1'));
        }
        delete(options.menu);

        this.settings.list = {url, options, resolve};
        this.queued.push([addTarget, 'list']);
        return this;
    }

    create(url, options = {}, resolve = {}) {
        options.templateUrl = options.templateUrl || this.name + '/schema.html';
        delete options.create;
        this.settings.create = {url, options, resolve};
        this.queued.push([addTarget, 'create']);
        return this;
    }

    update(url, options = {}, resolve = {}) {
        options.templateUrl = options.templateUrl || this.name + '/schema.html';
        if (options.create) {
            this.create(options.create, options, resolve);
            delete options.create;
        }
        this.settings.update = {url, options, resolve};
        this.queued.push([addTarget, 'update']);
        return this;
    }

    manager(Manager) {
        this.$manager = {name: normalize(this.name) + 'Manager', obj: Manager};
        this.service(this.$manager.name, this.$manager.obj);
        return this;
    }

};

/**
 * Private helper-functions:
 * {{{
 */
function addTarget(type) {
    let settings = merge(this.defaults[type], this.settings[type]);
    settings.resolve = settings.resolve || {};
    settings.resolve.Manager = settings.resolve.Manager || [normalize(this.name) + 'Manager', Manager => Manager];
    settings.resolve.module = () => this;
    if ('$mapping' in settings.resolve) {
        let $mapping = angular.copy(settings.resolve.$mapping);
        settings.resolve.$mapping = () => $mapping;
    }
    if (type == 'create') {
        settings.resolve.item = [this.$manager.name, Manager => new Manager.model];
    }
    settings.options.resolve = settings.resolve;
    delete settings.options.template; // Don't do this.
    this.ngmod.config(['$routeProvider', '$translatePartialLoaderProvider', ($routeProvider, $translatePartialLoaderProvider) => {
        $routeProvider.when('/:language' + settings.url, settings.options);
        $translatePartialLoaderProvider.addPart(this.name);
    }]);
};

function normalize(name, replace = undefined) {
    if (replace == undefined) {
        replace = match => match.substring(1).toUpperCase();
    }
    return name.replace(/\/(\w)/g, replace);
};

function merge(...args) {
    let merged = {};
    args.map(arg => {
        if (arg == undefined || arg == null || typeof arg != 'object') {
            return;
        }
        for (let prop in arg) {
            if (!(prop in merged)) {
                merged[prop] = arg[prop];
                continue;
            }
            if (typeof merged[prop] != typeof arg[prop]) {
                merged[prop] = arg[prop];
                continue;
            }
            if (angular.isArray(merged[prop]) != angular.isArray(arg[prop])) {
                merged[prop] = arg[prop];
                continue;
            }
            if (angular.isArray(merged[prop]) && angular.isArray(arg[prop])) {
                arg[prop].map(elem => {
                    if (merged[prop].indexOf(elem) == -1) {
                        merged[prop].push(elem);
                    }
                });
                continue;
            }
            if (typeof arg[prop] != 'object') {
                merged[prop] = arg[prop];
                continue;
            }
            merged[prop] = merge(merged[prop], arg[prop]);
        }
    });
    return merged;
};

/** }}} */

export {Component};

<|endoftext|>