<commit_before>/* Copyright (c) 2012-2017 LevelUP contributors
 * See list at <https://github.com/level/levelup#contributing>
 * MIT License
 * <https://github.com/level/levelup/blob/master/LICENSE.md>
 */

var EventEmitter = require('events').EventEmitter
var inherits = require('util').inherits
var extend = require('xtend')
var DeferredLevelDOWN = require('deferred-leveldown')
var IteratorStream = require('level-iterator-stream')
var Batch = require('./batch')
var errors = require('level-errors')
var assert = require('assert')
var promisify = require('./promisify')

var WriteError = errors.WriteError
var ReadError = errors.ReadError
var NotFoundError = errors.NotFoundError
var OpenError = errors.OpenError
var InitializationError = errors.InitializationError

// Possible AbstractLevelDOWN#status values:
//  - 'new'     - newly created, not opened or closed
//  - 'opening' - waiting for the database to be opened, post open()
//  - 'open'    - successfully opened the database, available for use
//  - 'closing' - waiting for the database to be closed, post close()
//  - 'closed'  - database has been successfully closed, should not be
//                 used except for another open() operation

function LevelUP (db, options, callback) {
  if (!(this instanceof LevelUP)) {
    return new LevelUP(db, options, callback)
  }

  var error

  EventEmitter.call(this)
  this.setMaxListeners(Infinity)

  if (typeof options === 'function') {
    callback = options
    options = {}
  }

  options = options || {}

  if (!db || typeof db !== 'object') {
    error = new InitializationError('Must provide db')
    if (typeof callback === 'function') {
      return process.nextTick(callback, error)
    }
    throw error
  }

  assert.equal(typeof db.status, 'string', '.status required, old abstract-leveldown')

  this.options = getOptions(options)
  this._db = db
  this.db = new DeferredLevelDOWN(db)
  this.open(callback)
}

LevelUP.prototype.emit = EventEmitter.prototype.emit
LevelUP.prototype.once = EventEmitter.prototype.once
inherits(LevelUP, EventEmitter)

LevelUP.prototype.open = function (callback) {
  var self = this
  var promise

  if (!callback) [ callback, promise ] = promisify()

  if (this.isOpen()) {
    process.nextTick(callback, null, self)
    return promise
  }

  if (this._isOpening()) {
    this.once('open', function () { callback(null, self) })
    return promise
  }

  this.emit('opening')

  this.db.open(this.options, function (err) {
    if (err) {
      return callback(new OpenError(err))
    }
    self.db = self._db
    callback(null, self)
    self.emit('open')
    self.emit('ready')
  })

  return promise
}

LevelUP.prototype.close = function (callback) {
  var self = this
  var promise

  if (!callback) [ callback, promise ] = promisify()

  if (this.isOpen()) {
    this.db.close(function () {
      self.emit('closed')
      callback.apply(null, arguments)
    })
    this.emit('closing')
    this.db = new DeferredLevelDOWN(this._db)
  } else if (this.isClosed()) {
    process.nextTick(callback)
  } else if (this.db.status === 'closing') {
    this.once('closed', callback)
  } else if (this._isOpening()) {
    this.once('open', function () {
      self.close(callback)
    })
  }

  return promise
}

LevelUP.prototype.isOpen = function () {
  return this.db.status === 'open'
}

LevelUP.prototype._isOpening = function () {
  return this.db.status === 'opening'
}

LevelUP.prototype.isClosed = function () {
  return (/^clos|new/).test(this.db.status)
}

LevelUP.prototype.get = function (key, options, callback) {
  if (key === null || key === undefined) {
    throw new ReadError('get() requires a key argument')
  }

  var promise

  callback = getCallback(options, callback)

  if (!callback) [ callback, promise ] = promisify()

  if (maybeError(this, callback)) { return promise }

  options = getOptions(options)

  this.db.get(key, options, function (err, value) {
    if (err) {
      if ((/notfound/i).test(err) || err.notFound) {
        err = new NotFoundError('Key not found in database [' + key + ']', err)
      } else {
        err = new ReadError(err)
      }
      return callback(err)
    }
    callback(null, value)
  })

  return promise
}

LevelUP.prototype.put = function (key, value, options, callback) {
  if (key === null || key === undefined) {
    throw new WriteError('put() requires a key argument')
  }

  var self = this
  var promise

  callback = getCallback(options, callback)

  if (!callback) [ callback, promise ] = promisify()

  if (maybeError(this, callback)) { return promise }

  options = getOptions(options)

  this.db.put(key, value, options, function (err) {
    if (err) {
      return callback(new WriteError(err))
    }
    self.emit('put', key, value)
    callback()
  })

  return promise
}

LevelUP.prototype.del = function (key, options, callback) {
  if (key === null || key === undefined) {
    throw new WriteError('del() requires a key argument')
  }

  var self = this
  var promise

  callback = getCallback(options, callback)

  if (!callback) [ callback, promise ] = promisify()

  if (maybeError(this, callback)) { return promise }

  options = getOptions(options)

  this.db.del(key, options, function (err) {
    if (err) {
      return callback(new WriteError(err))
    }
    self.emit('del', key)
    callback()
  })

  return promise
}

LevelUP.prototype.batch = function (arr, options, callback) {
  if (!arguments.length) {
    return new Batch(this)
  }

  if (!Array.isArray(arr)) {
    throw new WriteError('batch() requires an array argument')
  }

  var self = this
  var promise

  callback = getCallback(options, callback)

  if (!callback) [ callback, promise ] = promisify()

  if (maybeError(this, callback)) { return promise }

  options = getOptions(options)

  arr = arr.map(function (op) {
    if (!op.type && op.key !== undefined && op.value !== undefined) { op.type = 'put' }
    return op
  })

  this.db.batch(arr, options, function (err) {
    if (err) {
      return callback(new WriteError(err))
    }
    self.emit('batch', arr)
    callback()
  })

  return promise
}

LevelUP.prototype.readStream =
LevelUP.prototype.createReadStream = function (options) {
  options = extend({ keys: true, values: true }, options)
  if (typeof options.limit !== 'number') { options.limit = -1 }
  return new IteratorStream(this.db.iterator(options), options)
}

LevelUP.prototype.keyStream =
LevelUP.prototype.createKeyStream = function (options) {
  return this.createReadStream(extend(options, { keys: true, values: false }))
}

LevelUP.prototype.valueStream =
LevelUP.prototype.createValueStream = function (options) {
  return this.createReadStream(extend(options, { keys: false, values: true }))
}

LevelUP.prototype.toString = function () {
  return 'LevelUP'
}

function getCallback (options, callback) {
  return typeof options === 'function' ? options : callback
}

function getOptions (options) {
  return typeof options === 'object' && options !== null ? options : {}
}

function maybeError (db, callback) {
  if (!db._isOpening() && !db.isOpen()) {
    process.nextTick(callback, new ReadError('Database is not open'))
    return true
  }
}

LevelUP.errors = errors
module.exports = LevelUP
<commit_msg>add default export<commit_after>/* Copyright (c) 2012-2017 LevelUP contributors
 * See list at <https://github.com/level/levelup#contributing>
 * MIT License
 * <https://github.com/level/levelup/blob/master/LICENSE.md>
 */

var EventEmitter = require('events').EventEmitter
var inherits = require('util').inherits
var extend = require('xtend')
var DeferredLevelDOWN = require('deferred-leveldown')
var IteratorStream = require('level-iterator-stream')
var Batch = require('./batch')
var errors = require('level-errors')
var assert = require('assert')
var promisify = require('./promisify')

var WriteError = errors.WriteError
var ReadError = errors.ReadError
var NotFoundError = errors.NotFoundError
var OpenError = errors.OpenError
var InitializationError = errors.InitializationError

// Possible AbstractLevelDOWN#status values:
//  - 'new'     - newly created, not opened or closed
//  - 'opening' - waiting for the database to be opened, post open()
//  - 'open'    - successfully opened the database, available for use
//  - 'closing' - waiting for the database to be closed, post close()
//  - 'closed'  - database has been successfully closed, should not be
//                 used except for another open() operation

function LevelUP (db, options, callback) {
  if (!(this instanceof LevelUP)) {
    return new LevelUP(db, options, callback)
  }

  var error

  EventEmitter.call(this)
  this.setMaxListeners(Infinity)

  if (typeof options === 'function') {
    callback = options
    options = {}
  }

  options = options || {}

  if (!db || typeof db !== 'object') {
    error = new InitializationError('Must provide db')
    if (typeof callback === 'function') {
      return process.nextTick(callback, error)
    }
    throw error
  }

  assert.equal(typeof db.status, 'string', '.status required, old abstract-leveldown')

  this.options = getOptions(options)
  this._db = db
  this.db = new DeferredLevelDOWN(db)
  this.open(callback)
}

LevelUP.prototype.emit = EventEmitter.prototype.emit
LevelUP.prototype.once = EventEmitter.prototype.once
inherits(LevelUP, EventEmitter)

LevelUP.prototype.open = function (callback) {
  var self = this
  var promise

  if (!callback) [ callback, promise ] = promisify()

  if (this.isOpen()) {
    process.nextTick(callback, null, self)
    return promise
  }

  if (this._isOpening()) {
    this.once('open', function () { callback(null, self) })
    return promise
  }

  this.emit('opening')

  this.db.open(this.options, function (err) {
    if (err) {
      return callback(new OpenError(err))
    }
    self.db = self._db
    callback(null, self)
    self.emit('open')
    self.emit('ready')
  })

  return promise
}

LevelUP.prototype.close = function (callback) {
  var self = this
  var promise

  if (!callback) [ callback, promise ] = promisify()

  if (this.isOpen()) {
    this.db.close(function () {
      self.emit('closed')
      callback.apply(null, arguments)
    })
    this.emit('closing')
    this.db = new DeferredLevelDOWN(this._db)
  } else if (this.isClosed()) {
    process.nextTick(callback)
  } else if (this.db.status === 'closing') {
    this.once('closed', callback)
  } else if (this._isOpening()) {
    this.once('open', function () {
      self.close(callback)
    })
  }

  return promise
}

LevelUP.prototype.isOpen = function () {
  return this.db.status === 'open'
}

LevelUP.prototype._isOpening = function () {
  return this.db.status === 'opening'
}

LevelUP.prototype.isClosed = function () {
  return (/^clos|new/).test(this.db.status)
}

LevelUP.prototype.get = function (key, options, callback) {
  if (key === null || key === undefined) {
    throw new ReadError('get() requires a key argument')
  }

  var promise

  callback = getCallback(options, callback)

  if (!callback) [ callback, promise ] = promisify()

  if (maybeError(this, callback)) { return promise }

  options = getOptions(options)

  this.db.get(key, options, function (err, value) {
    if (err) {
      if ((/notfound/i).test(err) || err.notFound) {
        err = new NotFoundError('Key not found in database [' + key + ']', err)
      } else {
        err = new ReadError(err)
      }
      return callback(err)
    }
    callback(null, value)
  })

  return promise
}

LevelUP.prototype.put = function (key, value, options, callback) {
  if (key === null || key === undefined) {
    throw new WriteError('put() requires a key argument')
  }

  var self = this
  var promise

  callback = getCallback(options, callback)

  if (!callback) [ callback, promise ] = promisify()

  if (maybeError(this, callback)) { return promise }

  options = getOptions(options)

  this.db.put(key, value, options, function (err) {
    if (err) {
      return callback(new WriteError(err))
    }
    self.emit('put', key, value)
    callback()
  })

  return promise
}

LevelUP.prototype.del = function (key, options, callback) {
  if (key === null || key === undefined) {
    throw new WriteError('del() requires a key argument')
  }

  var self = this
  var promise

  callback = getCallback(options, callback)

  if (!callback) [ callback, promise ] = promisify()

  if (maybeError(this, callback)) { return promise }

  options = getOptions(options)

  this.db.del(key, options, function (err) {
    if (err) {
      return callback(new WriteError(err))
    }
    self.emit('del', key)
    callback()
  })

  return promise
}

LevelUP.prototype.batch = function (arr, options, callback) {
  if (!arguments.length) {
    return new Batch(this)
  }

  if (!Array.isArray(arr)) {
    throw new WriteError('batch() requires an array argument')
  }

  var self = this
  var promise

  callback = getCallback(options, callback)

  if (!callback) [ callback, promise ] = promisify()

  if (maybeError(this, callback)) { return promise }

  options = getOptions(options)

  arr = arr.map(function (op) {
    if (!op.type && op.key !== undefined && op.value !== undefined) { op.type = 'put' }
    return op
  })

  this.db.batch(arr, options, function (err) {
    if (err) {
      return callback(new WriteError(err))
    }
    self.emit('batch', arr)
    callback()
  })

  return promise
}

LevelUP.prototype.readStream =
LevelUP.prototype.createReadStream = function (options) {
  options = extend({ keys: true, values: true }, options)
  if (typeof options.limit !== 'number') { options.limit = -1 }
  return new IteratorStream(this.db.iterator(options), options)
}

LevelUP.prototype.keyStream =
LevelUP.prototype.createKeyStream = function (options) {
  return this.createReadStream(extend(options, { keys: true, values: false }))
}

LevelUP.prototype.valueStream =
LevelUP.prototype.createValueStream = function (options) {
  return this.createReadStream(extend(options, { keys: false, values: true }))
}

LevelUP.prototype.toString = function () {
  return 'LevelUP'
}

function getCallback (options, callback) {
  return typeof options === 'function' ? options : callback
}

function getOptions (options) {
  return typeof options === 'object' && options !== null ? options : {}
}

function maybeError (db, callback) {
  if (!db._isOpening() && !db.isOpen()) {
    process.nextTick(callback, new ReadError('Database is not open'))
    return true
  }
}

LevelUP.errors = errors
module.exports = LevelUP.default = LevelUP
<|endoftext|>


<commit_before>'use babel'

const noop = () => {}

// The logger's main purpose it to only write to console output when atom is
// in development mode.
export default class Logger {
    constructor(shouldLog=atom.inDevMode.bind(atom)) {
        if (shouldLog()) {
            this.error = console.error.bind(console)
            this.log = console.log.bind(console)
            this.info = console.info.bind(console)
            this.debug = console.debug.bind(console)
        }
        else {
            this.error = noop
            this.log = noop
            this.info = noop
            this.debug = noop
        }
    }
}

export const defaultLogger = new Logger()
<commit_msg>enhanced logger output<commit_after>'use babel'

const noop = () => {}

// The logger's main purpose it to only write to console output when atom is
// in development mode.
export default class Logger {
    constructor(shouldLog=atom.inDevMode.bind(atom)) {
        if (shouldLog()) {
            this.error = console.error.bind(console, 'code-annotations:')
            this.log = console.log.bind(console, 'code-annotations:')
            this.info = console.info.bind(console, 'code-annotations:')
            this.debug = console.debug.bind(console, 'code-annotations:')
        }
        else {
            this.error = noop
            this.log = noop
            this.info = noop
            this.debug = noop
        }
    }
}

export const defaultLogger = new Logger()
<|endoftext|>


<commit_before>var Logger = require('./Logger');
var Filter = require('./Filter');
var Formatter = require('./Formatter');
var Handler = require('./Handler');
var handlers = require('./handlers');

/**
 * Manager, which holds the hierarchy of loggers.
 *
 * @private
 */
function Manager() {
	/** @type {Object} */
	this.root = null;

	/** @type {Object} */
	this._loggers = {};
}

/**
 * Get a logger with the specified name, creating it
 * if it doesn't yet exist. This name is a dot-separated hierarchical
 * name, such as "a", "a.b", "a.b.c" or similar.
 *
 * @param  {string} name
 * @return {Object}
 */
Manager.prototype.getLogger = function(name) {
	var parts = name.split('.');
	var currentName = '';
	var prevLogger = this.root;
	for (var i = 1, len = parts.length; i <= len; i++) {
		currentName = parts.slice(0, i).join('.');
		if (!this._loggers[currentName]) {
			this._loggers[currentName] = new Logger(this, prevLogger, currentName);
		}
		prevLogger = this._loggers[currentName];
	}

	return this._loggers[name];
};

/**
 *  Removes all the loggers.
 */
Manager.prototype.clear = function() {
	var names = Object.keys(this._loggers);
	var name = '';

	for (var i = 0, len = names.length; i < len; i++) {
		name = names[i];
		this._loggers[name] = null;
		delete this._loggers[name];
	}
	this.root = null;
};

var manager = new Manager();
manager.root = new Logger(manager, null, 'root', Logger.WARNING);

var baseExports = {
	NOTSET:   Logger.NOTSET,
	DEBUG:    Logger.DEBUG,
	INFO:     Logger.INFO,
	WARNING:  Logger.WARNING,
	ERROR:    Logger.ERROR,
	CRITICAL: Logger.CRITICAL,

	getLevelName: Logger.getLevelName,

	getLoggerClass: function() {
		return Logger;
	},

	getLogger: function(name) {
		name = name || '';

		if (!name) {
			return manager.root;
		} else {
			return manager.getLogger(name);
		}
	},

	basicConfig: function(options) {
		var filename = options.filename;
		var format = options.format || '%(levelname):%(name):%(message)';
		var timeFormat = options.timeFormat || '';
		var handler = null;
		var formatter = null;

		if (filename) {
			var encoding = options.encoding || '';
			handler = new handlers.FileHandler(filename, encoding);
		} else {
			handler = new handlers.ConsoleHandler();
		}

		formatter = new Formatter(format, timeFormat);
		handler.setFormatter(formatter);
		manager.root.addHandler(handler);
		var level = options.level;
		if (level) {
			manager.root.setLevel(level);
		}
	},

	Filter: Filter,
	Formatter: Formatter,
	Handler: Handler,

	_test_reset: reset // For tests only.
};

module.exports = Object.assign(baseExports, handlers);

/** @private */
function reset() {
	manager.clear();
	manager.root = new Logger(manager, null, 'root', Logger.WARNING);
}<commit_msg>refactoring<commit_after>var Logger = require('./Logger');
var Filter = require('./Filter');
var Formatter = require('./Formatter');
var Handler = require('./Handler');
var handlers = require('./handlers');

var manager = null;

/**
 * Manager, which holds the hierarchy of loggers.
 *
 * @private
 */
function Manager() {
	/** @type {Object} */
	this.root = null;

	/** @type {Object} */
	this._loggers = {};
}

/**
 * Get a logger with the specified name, creating it
 * if it doesn't yet exist. This name is a dot-separated hierarchical
 * name, such as "a", "a.b", "a.b.c" or similar.
 *
 * @param  {string} name
 * @return {Object}
 */
Manager.prototype.getLogger = function(name) {
	var parts = name.split('.');
	var currentName = '';
	var prevLogger = this.root;
	for (var i = 1, len = parts.length; i <= len; i++) {
		currentName = parts.slice(0, i).join('.');
		if (!this._loggers[currentName]) {
			this._loggers[currentName] = new Logger(this, prevLogger, currentName);
		}
		prevLogger = this._loggers[currentName];
	}

	return this._loggers[name];
};

/**
 *  Removes all the loggers.
 */
Manager.prototype.clear = function() {
	var names = Object.keys(this._loggers);
	var name = '';

	for (var i = 0, len = names.length; i < len; i++) {
		name = names[i];
		this._loggers[name] = null;
		delete this._loggers[name];
	}
	this.root = null;
};

manager = new Manager();
manager.root = new Logger(manager, null, 'root', Logger.WARNING);

/**
 * Return the class to be used when instantiating a logger.
 *
 * @return {Function}
 */
function getLoggerClass() {
	return Logger;
}

/**
 * Return a logger with the specified name, creating it if necessary.
 * If no name is specified, return the root logger.
 *
 * @param  {string} name
 * @return {Object}
 */
function getLogger(name) {
	name = name || '';

	if (!name) {
		return manager.root;
	} else {
		return manager.getLogger(name);
	}
}

/**
 * Do basic configuration for the logging system.
 *
 * @param  {Object} options
 */
function basicConfig(options) {
	var filename = options.filename;
	var format = options.format || '%(levelname):%(name):%(message)';
	var timeFormat = options.timeFormat || '';
	var handler = null;
	var formatter = null;

	if (filename) {
		var encoding = options.encoding || '';
		handler = new handlers.FileHandler(filename, encoding);
	} else {
		handler = new handlers.ConsoleHandler();
	}

	formatter = new Formatter(format, timeFormat);
	handler.setFormatter(formatter);
	manager.root.addHandler(handler);
	var level = options.level;
	if (level) {
		manager.root.setLevel(level);
	}
}

var baseExports = {
	NOTSET:   Logger.NOTSET,
	DEBUG:    Logger.DEBUG,
	INFO:     Logger.INFO,
	WARNING:  Logger.WARNING,
	ERROR:    Logger.ERROR,
	CRITICAL: Logger.CRITICAL,

	getLevelName: Logger.getLevelName,
	getLoggerClass: getLoggerClass,
	getLogger: getLogger,
	basicConfig: basicConfig,

	Filter: Filter,
	Formatter: Formatter,
	Handler: Handler,

	_test_reset: reset // For tests only.
};

module.exports = Object.assign(baseExports, handlers);

/** @private */
function reset() {
	manager.clear();
	manager.root = new Logger(manager, null, 'root', Logger.WARNING);
}<|endoftext|>


<commit_before>'use strict';

const util = require('util');
const moment = require('moment');
const winston = require('winston');
const app = require('./app');
const errors = require('./errors');

const logging = {};
module.exports = logging;

// A formatter function for use with Winston. Use this for readable, consistent
// logging across an application.
//
// options:
//   timestamp: true, false, or a function that returns a formatted timestamp
//   level: a logging level, typically error, warn, info, verbose, debug, or silly
//   label: a component label or null for none
//   message: a log message or an empty string for none
//   meta: an object containing additional information, may be or contain an error
logging.formatter = options => {
  return formatTimestamp(options.timestamp) + formatLevel(options.level) +
    formatLabel(options.label) + formatMessage(options.message, options.meta);
};

function formatTimestamp(timestamp) {
  if (timestamp === true) {
    return moment().format('YYYY-MM-DDTHH:mm:ss.SSZZ') + ' ';
  }
  if (typeof timestamp === 'function') {
    return timestamp() + ' ';
  }
  return '';
}

function formatLevel(level) {
  return level ? '[' + level.toUpperCase() + '] ' : '';
}

function formatLabel(label) {
  return label ? '[' + label + '] ' : '';
}

function formatMessage(message, meta) {
  let error;
  if (typeof meta === 'object') {
    // If metadata is an error, or has one in an error property, remove it for separate handling.
    if (meta.stack) {
      error = meta;
      meta = undefined;
    } else if (typeof meta.error === 'object' && meta.error.stack) {
      error = meta.error;
      delete meta.error;
    }

    // Metadata is an empty object by default; replace by undefined for easier handling.
    if (meta && Object.keys(meta).length == 0) {
      meta = undefined;
    }
  }

  // Only put the metadata on a separate line if it spans lines, itself.
  const formattedMeta = util.inspect(meta);
  const multiMeta = formattedMeta.indexOf('\n') != -1;
  let result = '';

  if (message) {
    result += message;
    if (meta && !multiMeta) {
      result += ' ';
    } else if (meta || error) {
      result += '\n  ';
    }
  }

  if (meta) {
    result += multiMeta ? indent(formattedMeta) : formattedMeta;
    if (error) {
      result += '\n  ';
    }
  }

  if (error) {
    result += indent(errors.stackWithCause(error));
  }
  return result;
}

function indent(text) {
  return text.replace(/(\r\n|\n|\r)/gm, '$1  ');
}

logging.configureWinston = (cfAppEnv) => {
  const level = app.config.isProd() ? 'verbose' : 'debug';
  const formatter = logging.formatter;
  const timestamp = !cfAppEnv || !cfAppEnv.isLocal;
  const transport = new (winston.transports.Console)({ level, formatter, timestamp });
  winston.configure({ transports: [transport] });
};

logging.configureWinstonForTests = (suppressConsoleWarn, filename = 'test.log') => {
  const formatter = logging.formatter;
  const timestamp = true;
  const transports = [];
  transports.push(new (winston.transports.File)({ level: 'silly', filename, json: false, formatter, timestamp }));
  if (!suppressConsoleWarn) {
    transports.push(new (winston.transports.Console)({ level: 'warn', formatter, timestamp }));
  }
  winston.configure({ transports });
};

logging.morganToWinstonStream = (level = 'verbose') => {
  return {
    write: message => {
      winston.log(level, message.trim());
    }
  };
};
<commit_msg>Fix timestamp bug in logging.configureWinston()<commit_after>'use strict';

const util = require('util');
const moment = require('moment');
const winston = require('winston');
const app = require('./app');
const errors = require('./errors');

const logging = {};
module.exports = logging;

// A formatter function for use with Winston. Use this for readable, consistent
// logging across an application.
//
// options:
//   timestamp: true, false, or a function that returns a formatted timestamp
//   level: a logging level, typically error, warn, info, verbose, debug, or silly
//   label: a component label or null for none
//   message: a log message or an empty string for none
//   meta: an object containing additional information, may be or contain an error
logging.formatter = options => {
  return formatTimestamp(options.timestamp) + formatLevel(options.level) +
    formatLabel(options.label) + formatMessage(options.message, options.meta);
};

function formatTimestamp(timestamp) {
  if (timestamp === true) {
    return moment().format('YYYY-MM-DDTHH:mm:ss.SSZZ') + ' ';
  }
  if (typeof timestamp === 'function') {
    return timestamp() + ' ';
  }
  return '';
}

function formatLevel(level) {
  return level ? '[' + level.toUpperCase() + '] ' : '';
}

function formatLabel(label) {
  return label ? '[' + label + '] ' : '';
}

function formatMessage(message, meta) {
  let error;
  if (typeof meta === 'object') {
    // If metadata is an error, or has one in an error property, remove it for separate handling.
    if (meta.stack) {
      error = meta;
      meta = undefined;
    } else if (typeof meta.error === 'object' && meta.error.stack) {
      error = meta.error;
      delete meta.error;
    }

    // Metadata is an empty object by default; replace by undefined for easier handling.
    if (meta && Object.keys(meta).length == 0) {
      meta = undefined;
    }
  }

  // Only put the metadata on a separate line if it spans lines, itself.
  const formattedMeta = util.inspect(meta);
  const multiMeta = formattedMeta.indexOf('\n') != -1;
  let result = '';

  if (message) {
    result += message;
    if (meta && !multiMeta) {
      result += ' ';
    } else if (meta || error) {
      result += '\n  ';
    }
  }

  if (meta) {
    result += multiMeta ? indent(formattedMeta) : formattedMeta;
    if (error) {
      result += '\n  ';
    }
  }

  if (error) {
    result += indent(errors.stackWithCause(error));
  }
  return result;
}

function indent(text) {
  return text.replace(/(\r\n|\n|\r)/gm, '$1  ');
}

logging.configureWinston = (cfAppEnv) => {
  const level = app.config.isProd() ? 'verbose' : 'debug';
  const formatter = logging.formatter;
  const timestamp = !cfAppEnv || cfAppEnv.isLocal;
  const transport = new (winston.transports.Console)({ level, formatter, timestamp });
  winston.configure({ transports: [transport] });
};

logging.configureWinstonForTests = (suppressConsoleWarn, filename = 'test.log') => {
  const formatter = logging.formatter;
  const timestamp = true;
  const transports = [];
  transports.push(new (winston.transports.File)({ level: 'silly', filename, json: false, formatter, timestamp }));
  if (!suppressConsoleWarn) {
    transports.push(new (winston.transports.Console)({ level: 'warn', formatter, timestamp }));
  }
  winston.configure({ transports });
};

logging.morganToWinstonStream = (level = 'verbose') => {
  return {
    write: message => {
      winston.log(level, message.trim());
    }
  };
};
<|endoftext|>


<commit_before>var through = require('through2')
var pump = require('pump')
var allContainers = require('docker-allcontainers')
var parser = require('./parser')

function loghose (opts) {
  opts = opts || {}
  var result = through.obj()
  var events = opts.events || allContainers(opts)
  var streams = {}
  var oldDestroy = result.destroy

  result.setMaxListeners(0)

  result.destroy = function () {
    Object.keys(streams).forEach(detachContainer)
    events.destroy()
    oldDestroy.call(this)
  }

  events.on('start', attachContainer)
  events.on('stop', function (meta) {
    detachContainer(meta.id)
  })

  function detachContainer (id) {
    if (streams[id]) {
      streams[id].destroy()
      delete streams[id]
    }
  }

  return result

  function attachContainer (data, container) {
    // we are trying to tap into this container
    // we should not do that, or we might be stuck in
    // an output loop
    if (!opts.includeCurrentContainer && data.id.indexOf(process.env.HOSTNAME) === 0) {
      return
    }

    container.inspect(function (err, info) {
      if (err) {
        throw err
      }

      container.attach({stream: true, stdout: true, stderr: true}, function (err, stream) {
        if (err) {
          throw err
        }
        opts.tty = info.Config.Tty
        streams[data.id] = stream
        pump(
          stream,
          parser(data, opts)
        ).pipe(result, {end: false}).on('error', function () {
          /* continue, let's wait for docker restart */
        })
      })
    })
  }
}

module.exports = loghose
<commit_msg>ignore errors in inspect/attach<commit_after>var through = require('through2')
var pump = require('pump')
var allContainers = require('docker-allcontainers')
var parser = require('./parser')

function loghose (opts) {
  opts = opts || {}
  var result = through.obj()
  var events = opts.events || allContainers(opts)
  var streams = {}
  var oldDestroy = result.destroy

  result.setMaxListeners(0)

  result.destroy = function () {
    Object.keys(streams).forEach(detachContainer)
    events.destroy()
    oldDestroy.call(this)
  }

  events.on('start', attachContainer)
  events.on('stop', function (meta) {
    detachContainer(meta.id)
  })

  function detachContainer (id) {
    if (streams[id]) {
      streams[id].destroy()
      delete streams[id]
    }
  }

  return result

  function attachContainer (data, container) {
    // we are trying to tap into this container
    // we should not do that, or we might be stuck in
    // an output loop
    if (!opts.includeCurrentContainer && data.id.indexOf(process.env.HOSTNAME) === 0) {
      return
    }

    container.inspect(function (err, info) {
      if (err) {
        // container might not exists anymore ...
        return
      }

      container.attach({stream: true, stdout: true, stderr: true}, function (err, stream) {
        if (err) {
           // no stream availaable
          return
        }
        opts.tty = info.Config.Tty
        streams[data.id] = stream
        pump(
          stream,
          parser(data, opts)
        ).pipe(result, {end: false}).on('error', function () {
          /* continue, let's wait for docker restart */
        })
      })
    })
  }
}

module.exports = loghose
<|endoftext|>


<commit_before>var Bookshelf = require('bookshelf');
var hooker    = require('hooker');
var path      = require('path');
var Promise   = require('bluebird');

var Manager = function(root, bookshelf) {
  if (!root) {
    throw new Error('Manager requires a path to model directory');
  }

  this.root = path.normalize(root);

  if (bookshelf) {
    this.initialize(bookshelf);
  } else {
    hooker.hook(Bookshelf, 'initialize', {
      once: true,
      post: this.initialize.bind(this)
    });
  }
};

Manager.manage = function(model) {
  if (!Manager.manages(model)) {
    Manager._managed.push(model);
  }

  return model;
};

Manager.manages = function(model) {
  if (!model instanceof Function) {
    return false;
  }

  return Manager._managed.indexOf(model) !== -1
};

Manager._managed = [];

Manager.prototype.initialize = function(bookshelf) {
  this.bookshelf  = bookshelf;
  this.knex       = this.bookshelf.knex;
  this.schema     = this.knex.schema;

  bookshelf.plugin('registry');

  hooker.hook(bookshelf, ['collection', 'model'], function(name, value) {
    if (!value) {
      return hooker.preempt(this.get(name));
    }
  }.bind(this));

  return this;
};

Manager.prototype._cache = {};

Manager.prototype.create = function(name, properties) {
  var Model = this.get(name);
  var model = new Model();

  return this.save(model, properties).catch(function(error) {
    console.error(error.stack);
    throw error;
  });
};

Manager.prototype.fetch = function(name, properties, related) {
  return this.forge(name, properties).fetch({
    withRelated: related,
  });
};

Manager.prototype.forge = function(name, properties) {
  var Model = this.get(name);

  // Model may already be instantiated
  if (Model instanceof this.bookshelf.Model) {
    Model = Model.constructor;
  }

  return Model.forge(properties);
};

Manager.prototype.get = function(Model) {
  if (!this.bookshelf) {
    throw new Error('Manager has not been initialized with instance of Bookshelf');
  }

  var name;

  if (typeof Model === 'string') {
    name = Model;

    if (this._cache[name]) {
      return this._cache[name];
    }

    var file = path.join(this.root, name);

    try {
      Model = require(file);
    } catch (e) {
      throw new Error('Could not find module `' + name + '` at `' + file + '.js`');
    }
  }

  if (Manager.manages(Model)) {
    Model = Model(this.bookshelf);
  }

  if (!this.isModel(Model) && !this.isCollection(Model)) {
    throw new Error('Expected a String, Model, Collection, or a Managed Model/Collection, got: ' + typeof Model);
  }

  if (this.isCollection(Model) && typeof Model.prototype.model === 'string') {
    Model.prototype.model = this.get(Model.prototype.model);
  }

  if (name) {
    if (this.isModel(Model)) {
      this._cache[name] = this.bookshelf.model(name, Model);
    } else if (this.isCollection(Model)) {
      this._cache[name] = this.bookshelf.collection(name, Model);
    }
  }

  return Model;
};

Manager.prototype.isModel = function(model) {
  if (!model || this.isCollection(model)) {
    return false;
  }

  return model instanceof this.bookshelf.Model || model.prototype instanceof this.bookshelf.Model;
};

Manager.prototype.isCollection = function(model) {
  if (!model) {
    return false;
  }

  return model instanceof this.bookshelf.Collection || model.prototype instanceof this.bookshelf.Collection;
};

Manager.prototype.save = function(model, properties) {
  if (this.isModel(model)) {
    return this.saveModel(model, properties);
  } else if (this.isCollection(model)) {
    return this.saveCollection(model, properties);
  }

  throw new Error('Object should be an instance of Model or Collection, not ' + typeof model);
};

Manager.prototype.saveCollection = function(collection, models) {
  return collection.invokeThen('save').then(function() {
    return this.set(collection, models);
  }.bind(this)).then(function() {
    return collection.invokeThen('save');
  }).then(function() {
    return collection;
  }).catch(function(error) {
    console.error(error.stack);
    throw error;
  });
};

Manager.prototype.saveModel = function(model, properties) {
  return this.set(model, properties).then(function(model) {
    return model.save();
  }).catch(function(error) {
    console.error(error.stack);
    throw error;
  });
}

Manager.prototype.set = function(model, properties) {
  if (this.isModel(model)) {
    return this.setModel(model, properties);
  } else if (this.isCollection(model)) {
    return this.setCollection(model, properties);
  }

  throw new Error('Object should be an instance of Model or Collection, not ' + typeof model);
};

Manager.prototype.setModel = function(model, properties) {
  var promises = [];

  properties = properties || {};

  if (!model.cid) {
    model = model.forge();
  }

  if (properties && properties.id) {
    promises.push(function() {
      return this.fetch(model, { id: properties.id }).then(function(result) {
        model = result;
      });
    }.bind(this));
  } else {
    promises.push(function() {
      return model.save();
    });
  }

  Object.keys(properties).forEach(function(key) {
    var value     = properties[key];
    var relation  = model[key] instanceof Function ? model[key].call(model) : null;
    var type      = relation ? relation.relatedData.type : 'scalar';
    var method    = 'set' + type.charAt(0).toUpperCase() + type.slice(1);
    var setter    = this[method].bind(this);

    promises.push(function() {
      return setter(model, key, value, relation);
    });
  }.bind(this));

  return Promise.reduce(promises, function(values, promise) {
    return promise();
  }, []);
};

Manager.prototype.setBelongsTo = function(model, key, value, relation) {
  var Target = relation.relatedData.target;
  var target = new Target();

  return this.save(target, value).then(function(target) {
    var fk = relation.relatedData.foreignKey;

    model.set(fk, target.id);

    return model.save();
  }).then(function(model) {
    return model.load(key);
  });
};

Manager.prototype.setBelongsToMany = function(model, key, models, relation) {
  var Collection = this.bookshelf.Collection.extend({
    model: relation.relatedData.target,
  });

  var collection = Collection.forge();

  return this.setCollection(collection, models).then(function() {
    return model.load(key);
  }).then(function() {
    return model.related(key).mapThen(function(target) {
      if (!collection.findWhere({ id: target.id })) {
        return model.related(key).detach(target);
      }
    });
  }).then(function() {
    return collection.mapThen(function(target) {
      if (!model.related(key).findWhere({ id: target.id })) {
        return model.related(key).attach(target);
      }
    });
  }).then(function() {
    return model;
  });
};

Manager.prototype.setHasMany = function(model, key, models, relation) {
  var Collection = this.bookshelf.Collection.extend({
    model: relation.relatedData.target,
  });

  var collection = Collection.forge();

  return this.setCollection(collection, models).then(function() {
    return model.load(key);
  }).then(function() {
    var fk = relation.relatedData.foreignKey;

    if (!fk) {
      throw new Error('`' + key + '` relation is missing `foreignKey` in `this.hasMany(Target, foreignKey)`');
    }

    return collection.mapThen(function(target) {
      var properties = {};

      properties[fk] = model.id;

      return this.save(target, properties);
    }.bind(this));
  }.bind(this)).then(function() {
    return model.related(key).mapThen(function(target) {
      if (!collection.findWhere({ id: target.id })) {
        return target.destroy();
      }
    })
  }).then(function() {
    return collection.mapThen(function(target) {
      if (!model.related(key).findWhere({ id: target.id })) {
        model.related(key).add(target);
      }
    });
  }).then(function() {
    return model;
  });
};

Manager.prototype.setScalar = Promise.method(function(model, key, value) {
  if (key.indexOf('_pivot_') === 0) {
    return model;
  }

  if (model.get(key) === value) {
    return model;
  }

  model.set(key, value);

  return model;
});

Manager.prototype.setCollection = function(collection, targets) {
  targets = targets || [];

  return Promise.map(targets, function(target) {
    var promise;

    if (this.isModel(target)) {
      promise = target.save();
    } else {
      promise = this.save(collection.model, target);
    }

    return promise.then(function(target) {
      collection.add(target);

      return target;
    });
  }.bind(this)).then(function() {
    return collection;
  });
};

module.exports = Manager;
<commit_msg>Only save if there have been changes<commit_after>var Bookshelf = require('bookshelf');
var hooker    = require('hooker');
var path      = require('path');
var Promise   = require('bluebird');

var Manager = function(root, bookshelf) {
  if (!root) {
    throw new Error('Manager requires a path to model directory');
  }

  this.root = path.normalize(root);

  if (bookshelf) {
    this.initialize(bookshelf);
  } else {
    hooker.hook(Bookshelf, 'initialize', {
      once: true,
      post: this.initialize.bind(this)
    });
  }
};

Manager.manage = function(model) {
  if (!Manager.manages(model)) {
    Manager._managed.push(model);
  }

  return model;
};

Manager.manages = function(model) {
  if (!model instanceof Function) {
    return false;
  }

  return Manager._managed.indexOf(model) !== -1
};

Manager._managed = [];

Manager.prototype.initialize = function(bookshelf) {
  this.bookshelf  = bookshelf;
  this.knex       = this.bookshelf.knex;
  this.schema     = this.knex.schema;

  bookshelf.plugin('registry');

  hooker.hook(bookshelf, ['collection', 'model'], function(name, value) {
    if (!value) {
      return hooker.preempt(this.get(name));
    }
  }.bind(this));

  return this;
};

Manager.prototype._cache = {};

Manager.prototype.create = function(name, properties) {
  var Model = this.get(name);
  var model = new Model();

  return this.save(model, properties).catch(function(error) {
    console.error(error.stack);
    throw error;
  });
};

Manager.prototype.fetch = function(name, properties, related) {
  return this.forge(name, properties).fetch({
    withRelated: related,
  });
};

Manager.prototype.forge = function(name, properties) {
  var Model = this.get(name);

  // Model may already be instantiated
  if (Model instanceof this.bookshelf.Model) {
    Model = Model.constructor;
  }

  return Model.forge(properties);
};

Manager.prototype.get = function(Model) {
  if (!this.bookshelf) {
    throw new Error('Manager has not been initialized with instance of Bookshelf');
  }

  var name;

  if (typeof Model === 'string') {
    name = Model;

    if (this._cache[name]) {
      return this._cache[name];
    }

    var file = path.join(this.root, name);

    try {
      Model = require(file);
    } catch (e) {
      throw new Error('Could not find module `' + name + '` at `' + file + '.js`');
    }
  }

  if (Manager.manages(Model)) {
    Model = Model(this.bookshelf);
  }

  if (!this.isModel(Model) && !this.isCollection(Model)) {
    throw new Error('Expected a String, Model, Collection, or a Managed Model/Collection, got: ' + typeof Model);
  }

  if (this.isCollection(Model) && typeof Model.prototype.model === 'string') {
    Model.prototype.model = this.get(Model.prototype.model);
  }

  if (name) {
    if (this.isModel(Model)) {
      this._cache[name] = this.bookshelf.model(name, Model);
    } else if (this.isCollection(Model)) {
      this._cache[name] = this.bookshelf.collection(name, Model);
    }
  }

  return Model;
};

Manager.prototype.isModel = function(model) {
  if (!model || this.isCollection(model)) {
    return false;
  }

  return model instanceof this.bookshelf.Model || model.prototype instanceof this.bookshelf.Model;
};

Manager.prototype.isCollection = function(model) {
  if (!model) {
    return false;
  }

  return model instanceof this.bookshelf.Collection || model.prototype instanceof this.bookshelf.Collection;
};

Manager.prototype.save = function(model, properties) {
  if (this.isModel(model)) {
    return this.saveModel(model, properties);
  } else if (this.isCollection(model)) {
    return this.saveCollection(model, properties);
  }

  throw new Error('Object should be an instance of Model or Collection, not ' + typeof model);
};

Manager.prototype.saveCollection = function(collection, models) {
  return collection.invokeThen('save').then(function() {
    return this.set(collection, models);
  }.bind(this)).then(function() {
    return collection.invokeThen('save');
  }).then(function() {
    return collection;
  }).catch(function(error) {
    console.error(error.stack);
    throw error;
  });
};

Manager.prototype.saveModel = function(model, properties) {
  return this.set(model, properties).then(function(result) {
    return result.hasChanged() ? result.save() : result;
  }).catch(function(error) {
    console.error(error.stack);
    throw error;
  });
}

Manager.prototype.set = function(model, properties) {
  if (this.isModel(model)) {
    return this.setModel(model, properties);
  } else if (this.isCollection(model)) {
    return this.setCollection(model, properties);
  }

  throw new Error('Object should be an instance of Model or Collection, not ' + typeof model);
};

Manager.prototype.setModel = function(model, properties) {
  var promises = [];

  properties = properties || {};

  if (!model.cid) {
    model = model.forge();
  }

  if (properties && properties.id) {
    promises.push(function() {
      return this.fetch(model, { id: properties.id }).then(function(result) {
        return result;
      });
    }.bind(this));
  } else {
    promises.push(function() {
      return model.hasChanged() ? model.save() : model;
    });
  }

  Object.keys(properties).forEach(function(key) {
    var value     = properties[key];
    var relation  = model[key] instanceof Function ? model[key].call(model) : null;
    var type      = relation ? relation.relatedData.type : 'scalar';
    var method    = 'set' + type.charAt(0).toUpperCase() + type.slice(1);
    var setter    = this[method].bind(this);

    promises.push(function(result) {
      return setter(result, key, value, relation).then(function() {
        return result;
      });
    });
  }.bind(this));

  return Promise.reduce(promises, function(result, promise) {
    return promise(result);
  }, []);
};

Manager.prototype.setBelongsTo = function(model, key, value, relation) {
  var Target = relation.relatedData.target;
  var target = new Target();

  return this.save(target, value).then(function(target) {
    var fk = relation.relatedData.foreignKey;

    if (model.get(fk) !== target.id) {
      model.set(fk, target.id);
    }

    return model.hasChanged() ? model.save() : model;
  }).then(function(model) {
    return model.load(key);
  });
};

Manager.prototype.setBelongsToMany = function(model, key, models, relation) {
  var Collection = this.bookshelf.Collection.extend({
    model: relation.relatedData.target,
  });

  var collection = Collection.forge();

  return this.setCollection(collection, models).then(function() {
    return model.load(key);
  }).then(function() {
    return model.related(key).mapThen(function(target) {
      if (!collection.findWhere({ id: target.id })) {
        return model.related(key).detach(target);
      }
    });
  }).then(function() {
    return collection.mapThen(function(target) {
      if (!model.related(key).findWhere({ id: target.id })) {
        return model.related(key).attach(target);
      }
    });
  }).then(function() {
    return model;
  });
};

Manager.prototype.setHasMany = function(model, key, models, relation) {
  var Collection = this.bookshelf.Collection.extend({
    model: relation.relatedData.target,
  });

  var collection = Collection.forge();

  return this.setCollection(collection, models).then(function() {
    return model.load(key);
  }).then(function() {
    var fk = relation.relatedData.foreignKey;

    if (!fk) {
      throw new Error('`' + key + '` relation is missing `foreignKey` in `this.hasMany(Target, foreignKey)`');
    }

    return collection.mapThen(function(target) {
      var properties = {};

      properties[fk] = model.id;

      return this.save(target, properties);
    }.bind(this));
  }.bind(this)).then(function() {
    return model.related(key).mapThen(function(target) {
      if (!collection.findWhere({ id: target.id })) {
        return target.destroy();
      }
    })
  }).then(function() {
    return collection.mapThen(function(target) {
      if (!model.related(key).findWhere({ id: target.id })) {
        model.related(key).add(target);
      }
    });
  }).then(function() {
    return model;
  });
};

Manager.prototype.setScalar = Promise.method(function(model, key, value) {
  if (key.indexOf('_pivot_') === 0) {
    return model;
  }

  if (model.get(key) === value) {
    return model;
  }

  model.set(key, value);

  return model;
});

Manager.prototype.setCollection = function(collection, targets) {
  targets = targets || [];

  return Promise.map(targets, function(target) {
    var promise;

    if (this.isModel(target)) {
      promise = target.save();
    } else {
      promise = this.save(collection.model, target);
    }

    return promise.then(function(target) {
      collection.add(target);

      return target;
    });
  }.bind(this)).then(function() {
    return collection;
  });
};

module.exports = Manager;
<|endoftext|>


<commit_before>var State = require('./state')
  , SessionStore = require('./stores/session')
  , completeState = require('./middleware/complete')
  , completeStateError = require('./middleware/completeError')
  , unfinishedState = require('./middleware/unfinished')
  , MissingStateError = require('./errors/missingstateerror')
  , dispatch = require('./utils').dispatch
  , dispatchReal = dispatch
  , flatten = require('utils-flatten')
  , uri = require('url')
  , debug = require('debug')('flowstate');

function Manager(options, store) {
  if (!store) { store = new SessionStore(options); }

  this._states = {};
  this._yielders = {};
  this._store = store;
}

/*
Manager.prototype.use = function(name, state) {
  //begin = begin && flatten(Array.prototype.slice.call(begin, 0));
  //resume = resume && flatten(Array.prototype.slice.call(resume, 0));
  //finish = finish && flatten(Array.prototype.slice.call(finish, 0));

  var keys, key, i, len;

  this._states[name] = {
    launch: state.launch && flatten(Array.prototype.slice.call(state.launch, 0)),
    start: null,
    resume: state.resume && flatten(Array.prototype.slice.call(state.resume, 0)),
    exit: state.exit && flatten(Array.prototype.slice.call(state.exit, 0))
  };

  if (state.yields) {
    var keys = Object.keys(state.yields);
    for (i = 0, len = keys.length; i < len; ++i) {
      key = keys[i];
      this.yield(name, key, state.yields[key]);
    }
  }
}
*/

Manager.prototype.proc = function() {

}

Manager.prototype.yield = function(to, from, fns) {
  if (!Array.isArray(fns)) {
    fns = [ fns ];
  }

  fns = fns && flatten(Array.prototype.slice.call(fns, 0));
  this._yielders[to + '|' + from] = fns;
}

Manager.prototype.flow = function(name, options) {
  var args = Array.prototype.slice.call(arguments);
  args.unshift(this._store);
  args.unshift(this);

  return require('./middleware/flow').apply(null, args);
};

Manager.prototype.goto = function(name, options, req, res, next) {
  if (typeof next !== 'function') {
    next = res;
    res = req;
    req = options;
    options = undefined;
  }

  var flow = this._states[name];
  if (!flow) { throw new Error("Cannot find flow '" + name + "'"); }
  //if (!flow) { return next(new Error("Cannot find flow '" + name + "'")); }
  if (!flow.launch) { throw new Error("Unable to launch state '" + name + "'"); }

  if (options) {
    req.locals = options;
  }
  dispatch(flow.launch)(null, req, res, next);
}

Manager.prototype._complete = function(options, err, req, res, next) {
  var self = this
    , store = this._store

  var cont = options.continue;
  var through = options.through;
  var getHandle = options.getHandle || function(req) {
    return (req.query && req.query.state) || (req.body && req.body.state);
  }

  debug('complete %O (handle: %s, modified: %o, new: %o)', req.state, req.state.handle,
    req.state.isModified(), req.state.isNew());

  function dispatch() {
    return self._dispatch(options, err, req, res, next);
  }

  function proceed(h, ystate) {
    if (!h) {
      console.log('P0');

      // TODO: Clean this up
      if (through) {
        return self._through(through, err, req, res, next);
      }

      console.log('P00');
      console.log(err);

      // No state to resume.  `next` middleware is expected to implement
      // default behavior for responding to the request.
      if (options.postFns) {
        dispatchReal(options.postFns)(err, req, res, function(err) {
          if (cont) {
            console.log('NEED TO CONTINUE TO: ' + cont);
            res.redirect(cont);
            return;
          }

          return next(err);
        });
        return;
      } else {
        if (cont) {
          console.log('NEED TO DEF CONTINUE TO: ' + cont);
          res.redirect(cont);
          return;
        }

        return next(err);
      }
    }

    store.load(req, h, function(ierr, state) {
      if (ierr) { return err ? next(err) : next(ierr); }
      if (!state) {
        if (err) { return next(err); }
        return (ystate && ystate.state)
          ? next(new MissingStateError("Failed to load parent state", h))
          : next(new MissingStateError("Failed to load state", h));
      }

      // Resume the parent state by setting its state at `req.state` and
      // dispatching.  The state that is yeilding control back to the parent
      // state is made available at `req.yieldState` so the context can be used
      // to inform how to continuing processing the request.
      req.state = new State(req, state, h);
      req.yieldState = ystate;
      dispatch();
    });
  }

  if (req._state) {
    console.log('C1');

    // The state to be resumed has been loaded in an optimized manner.  Dispatch
    // directly to the state, yielding the current state, avoiding any
    // unnecessary operations against the state store.  Specifically, the state
    // being resumed is already loaded and the yeilding state is not persisted
    // and therefore does not need to be destroyed.  Furthermore, the yielding
    // state has parent state, and does not need saved in order to be kept.
    req.yieldState = req.state;
    req.state = req._state;
    delete req._state;
    return dispatch();
  } else {
    console.log('C2');

    function continue1() {
      if (req.state.isExternal()) {
        console.log('C2-1');
        console.log(req.state);

        if (req.state.isModified()) {
          // NEW
          console.log('IN COMPLETE');

          return self._continue(null, req, res, next);
        }

        proceed(null, req.state);
      } else if (req.state.isNew() && !req.yieldStateStack) {
        console.log('C2-2');

        // The current state is a new state, and the first state to be completed
        // in this transaction.  Resume the parent state, as indicated by the
        // state parameter carried in the request.
        proceed(getHandle(req), req.state);
      } else {
        console.log('C2-3');

        // The current state is an existing state.  Resume the parent state as
        // indicated by the parent property of the state itself.
        return proceed(req.state.state, req.state);
        // NEW:
        //return proceed(req.state.returnTo, req.state);
      }
    }

    function continue0() {
    // The current state is complete, and is yielding to its parent state, if
    // any.
    //if (req.state.isKeeped()) {
    //if (0) {
    if (req.state.returnTo) {
      // NEW condition, can be cleaned up, probably
      if (req.state.isNew() || req.state.isModified()) {
        req.state.save(function(ierr) {
          if (ierr) { return next(ierr); }
          continue1();
        });
      } else if (req.state.state || !req.state.isModified()) {
        // TODO: Clean this up and make it more generic
        //if (req.state.returnTo && !req.state.state && req.url !== req.state.returnTo) {
        //if (req.state.returnTo && req.url !== req.state.returnTo) {
        //if (ru !== req.state.recipient) {
        //  return continue1();
        //}
        if (!req.state.isComplete()) {
          return continue1();
        }

        // Resuming a parent state, current state is implicity complete
        req.state.destroy(function(ierr) {
          if (ierr) { return err ? next(err) : next(ierr); }
          continue1();
        });
      } else {
        continue1();
      }
    } else {
      // Remove the current state from any persistent storage, due to the
      // fact that it is complete.
      req.state.destroy(function(ierr) {
        if (ierr) { return err ? next(err) : next(ierr); }
        continue1();
      });
    }
  }
  } // continue0

  //if (options.postFns && req.state._meta.preventDefault == true) {
  //if (options.postFns) {
  if (0) {
    dispatchReal(options.postFns)(err, req, res, function(err) {
      // TODO: handle err, with test case
      continue0();
    });
  } else {
    continue0();
  }
}

Manager.prototype._through = function(through, err, req, res, next) {
  req.yieldState = req.state;
  req.state = new State(req, { name: through }, undefined, false, true);
  return this._dispatch(null, err, req, res, next);
}

Manager.prototype._dispatch = function(options, err, req, res, next) {
  // NEW yieldstate return to option.
  var name = req.state.name || (req.yieldState && req.yieldState.returnTo);
  var through = options ? options.through : null;

  if (!name) { return next(new Error("Cannot resume unnamed flow")); }

  if (through && through !== req.state.name) {
    req._state = req.state;
    req.state = new State(req, { name: through }, undefined, false, true);
    req.state.state = req._state.handle;
    return this._dispatch(null, err, req, res, next);
  }

  debug('resume %O (handle: %s) yielding %O', req.state, req.state.handle, req.yieldState);

  var self = this;

  function cont(err) {
    // TODO: Test case for transition error
    self._continue(err, req, res, next);
  }

  // TODO: Make sure transition errors get plumbed through correctly
  this._yield(options, err, req, res, cont);
}

Manager.prototype._continue = function(err, req, res, next) {
  // NEW yieldstate return to option.
  var name = req.state.name || (req.yieldState && req.yieldState.returnTo);
  name = uri.parse(name).pathname; // TODO: test case for query parsing

  var state = this._states[name];

  // NEW
  var url = req.yieldState && req.yieldState.returnTo;
  if (url) {
    return res.redirect(url);
  }

  //return;

  if (!state) { return next(new Error("Unknown state '" + name + "'")); }
  if (!state.resume) { return next(new Error("Unable to resume state '" + name + "'")); }

  // TODO: Allow for options here?
  var complete = completeState(this, {});
  var completeError = completeStateError(this, {});
  var unfinished = unfinishedState();

  var stack = state.resume.concat([complete, completeError]);
  if (state.exit) {
    stack.push.apply(stack, state.exit)
  }
  stack.push(unfinished);

  req._skipCompleteStateError = false;
  dispatch(stack)(err, req, res, next);
}

Manager.prototype._yield = function(options, err, req, res, next) {
  var t = req.state.name || (req.yieldState && req.yieldState.returnTo)
    , f = req.yieldState.name || req.originalUrl || req.url;

  t = uri.parse(t).pathname; // TODO: test case for query parsing
  f = uri.parse(f).pathname; // TODO: test case for query parsing

  req.yieldStateStack = req.yieldStateStack || [];
  req.yieldStateStack.unshift(req.yieldState);

  var stack = this._yielders[t + '|' + f];
  if (!stack) {
    if (options && options.postFns) {
      dispatchReal(options.postFns)(err, req, res, function(err) {
        // TODO: handle err, with test case
        return next(err);
      });
      return;
    }

    return next(err);
  }
  dispatch(stack)(err, req, res, next);
}

module.exports = Manager;
<commit_msg>Remove Dispatcher#goto.<commit_after>var State = require('./state')
  , SessionStore = require('./stores/session')
  , completeState = require('./middleware/complete')
  , completeStateError = require('./middleware/completeError')
  , unfinishedState = require('./middleware/unfinished')
  , MissingStateError = require('./errors/missingstateerror')
  , dispatch = require('./utils').dispatch
  , dispatchReal = dispatch
  , flatten = require('utils-flatten')
  , uri = require('url')
  , debug = require('debug')('flowstate');

function Manager(options, store) {
  if (!store) { store = new SessionStore(options); }

  this._states = {};
  this._yielders = {};
  this._store = store;
}

/*
Manager.prototype.use = function(name, state) {
  //begin = begin && flatten(Array.prototype.slice.call(begin, 0));
  //resume = resume && flatten(Array.prototype.slice.call(resume, 0));
  //finish = finish && flatten(Array.prototype.slice.call(finish, 0));

  var keys, key, i, len;

  this._states[name] = {
    launch: state.launch && flatten(Array.prototype.slice.call(state.launch, 0)),
    start: null,
    resume: state.resume && flatten(Array.prototype.slice.call(state.resume, 0)),
    exit: state.exit && flatten(Array.prototype.slice.call(state.exit, 0))
  };

  if (state.yields) {
    var keys = Object.keys(state.yields);
    for (i = 0, len = keys.length; i < len; ++i) {
      key = keys[i];
      this.yield(name, key, state.yields[key]);
    }
  }
}
*/

Manager.prototype.proc = function() {

}

Manager.prototype.yield = function(to, from, fns) {
  if (!Array.isArray(fns)) {
    fns = [ fns ];
  }

  fns = fns && flatten(Array.prototype.slice.call(fns, 0));
  this._yielders[to + '|' + from] = fns;
}

Manager.prototype.flow = function(name, options) {
  var args = Array.prototype.slice.call(arguments);
  args.unshift(this._store);
  args.unshift(this);

  return require('./middleware/flow').apply(null, args);
};

/*
Manager.prototype.goto = function(name, options, req, res, next) {
  if (typeof next !== 'function') {
    next = res;
    res = req;
    req = options;
    options = undefined;
  }

  var flow = this._states[name];
  if (!flow) { throw new Error("Cannot find flow '" + name + "'"); }
  //if (!flow) { return next(new Error("Cannot find flow '" + name + "'")); }
  if (!flow.launch) { throw new Error("Unable to launch state '" + name + "'"); }

  if (options) {
    req.locals = options;
  }
  dispatch(flow.launch)(null, req, res, next);
}
*/

Manager.prototype._complete = function(options, err, req, res, next) {
  var self = this
    , store = this._store

  var cont = options.continue;
  var through = options.through;
  var getHandle = options.getHandle || function(req) {
    return (req.query && req.query.state) || (req.body && req.body.state);
  }

  debug('complete %O (handle: %s, modified: %o, new: %o)', req.state, req.state.handle,
    req.state.isModified(), req.state.isNew());

  function dispatch() {
    return self._dispatch(options, err, req, res, next);
  }

  function proceed(h, ystate) {
    if (!h) {
      console.log('P0');

      // TODO: Clean this up
      if (through) {
        return self._through(through, err, req, res, next);
      }

      console.log('P00');
      console.log(err);

      // No state to resume.  `next` middleware is expected to implement
      // default behavior for responding to the request.
      if (options.postFns) {
        dispatchReal(options.postFns)(err, req, res, function(err) {
          if (cont) {
            console.log('NEED TO CONTINUE TO: ' + cont);
            res.redirect(cont);
            return;
          }

          return next(err);
        });
        return;
      } else {
        if (cont) {
          console.log('NEED TO DEF CONTINUE TO: ' + cont);
          res.redirect(cont);
          return;
        }

        return next(err);
      }
    }

    store.load(req, h, function(ierr, state) {
      if (ierr) { return err ? next(err) : next(ierr); }
      if (!state) {
        if (err) { return next(err); }
        return (ystate && ystate.state)
          ? next(new MissingStateError("Failed to load parent state", h))
          : next(new MissingStateError("Failed to load state", h));
      }

      // Resume the parent state by setting its state at `req.state` and
      // dispatching.  The state that is yeilding control back to the parent
      // state is made available at `req.yieldState` so the context can be used
      // to inform how to continuing processing the request.
      req.state = new State(req, state, h);
      req.yieldState = ystate;
      dispatch();
    });
  }

  if (req._state) {
    console.log('C1');

    // The state to be resumed has been loaded in an optimized manner.  Dispatch
    // directly to the state, yielding the current state, avoiding any
    // unnecessary operations against the state store.  Specifically, the state
    // being resumed is already loaded and the yeilding state is not persisted
    // and therefore does not need to be destroyed.  Furthermore, the yielding
    // state has parent state, and does not need saved in order to be kept.
    req.yieldState = req.state;
    req.state = req._state;
    delete req._state;
    return dispatch();
  } else {
    console.log('C2');

    function continue1() {
      if (req.state.isExternal()) {
        console.log('C2-1');
        console.log(req.state);

        if (req.state.isModified()) {
          // NEW
          console.log('IN COMPLETE');

          return self._continue(null, req, res, next);
        }

        proceed(null, req.state);
      } else if (req.state.isNew() && !req.yieldStateStack) {
        console.log('C2-2');

        // The current state is a new state, and the first state to be completed
        // in this transaction.  Resume the parent state, as indicated by the
        // state parameter carried in the request.
        proceed(getHandle(req), req.state);
      } else {
        console.log('C2-3');

        // The current state is an existing state.  Resume the parent state as
        // indicated by the parent property of the state itself.
        return proceed(req.state.state, req.state);
        // NEW:
        //return proceed(req.state.returnTo, req.state);
      }
    }

    function continue0() {
    // The current state is complete, and is yielding to its parent state, if
    // any.
    //if (req.state.isKeeped()) {
    //if (0) {
    if (req.state.returnTo) {
      // NEW condition, can be cleaned up, probably
      if (req.state.isNew() || req.state.isModified()) {
        req.state.save(function(ierr) {
          if (ierr) { return next(ierr); }
          continue1();
        });
      } else if (req.state.state || !req.state.isModified()) {
        // TODO: Clean this up and make it more generic
        //if (req.state.returnTo && !req.state.state && req.url !== req.state.returnTo) {
        //if (req.state.returnTo && req.url !== req.state.returnTo) {
        //if (ru !== req.state.recipient) {
        //  return continue1();
        //}
        if (!req.state.isComplete()) {
          return continue1();
        }

        // Resuming a parent state, current state is implicity complete
        req.state.destroy(function(ierr) {
          if (ierr) { return err ? next(err) : next(ierr); }
          continue1();
        });
      } else {
        continue1();
      }
    } else {
      // Remove the current state from any persistent storage, due to the
      // fact that it is complete.
      req.state.destroy(function(ierr) {
        if (ierr) { return err ? next(err) : next(ierr); }
        continue1();
      });
    }
  }
  } // continue0

  //if (options.postFns && req.state._meta.preventDefault == true) {
  //if (options.postFns) {
  if (0) {
    dispatchReal(options.postFns)(err, req, res, function(err) {
      // TODO: handle err, with test case
      continue0();
    });
  } else {
    continue0();
  }
}

Manager.prototype._through = function(through, err, req, res, next) {
  req.yieldState = req.state;
  req.state = new State(req, { name: through }, undefined, false, true);
  return this._dispatch(null, err, req, res, next);
}

Manager.prototype._dispatch = function(options, err, req, res, next) {
  // NEW yieldstate return to option.
  var name = req.state.name || (req.yieldState && req.yieldState.returnTo);
  var through = options ? options.through : null;

  if (!name) { return next(new Error("Cannot resume unnamed flow")); }

  if (through && through !== req.state.name) {
    req._state = req.state;
    req.state = new State(req, { name: through }, undefined, false, true);
    req.state.state = req._state.handle;
    return this._dispatch(null, err, req, res, next);
  }

  debug('resume %O (handle: %s) yielding %O', req.state, req.state.handle, req.yieldState);

  var self = this;

  function cont(err) {
    // TODO: Test case for transition error
    self._continue(err, req, res, next);
  }

  // TODO: Make sure transition errors get plumbed through correctly
  this._yield(options, err, req, res, cont);
}

Manager.prototype._continue = function(err, req, res, next) {
  // NEW yieldstate return to option.
  var name = req.state.name || (req.yieldState && req.yieldState.returnTo);
  name = uri.parse(name).pathname; // TODO: test case for query parsing

  var state = this._states[name];

  // NEW
  var url = req.yieldState && req.yieldState.returnTo;
  if (url) {
    return res.redirect(url);
  }

  //return;

  if (!state) { return next(new Error("Unknown state '" + name + "'")); }
  if (!state.resume) { return next(new Error("Unable to resume state '" + name + "'")); }

  // TODO: Allow for options here?
  var complete = completeState(this, {});
  var completeError = completeStateError(this, {});
  var unfinished = unfinishedState();

  var stack = state.resume.concat([complete, completeError]);
  if (state.exit) {
    stack.push.apply(stack, state.exit)
  }
  stack.push(unfinished);

  req._skipCompleteStateError = false;
  dispatch(stack)(err, req, res, next);
}

Manager.prototype._yield = function(options, err, req, res, next) {
  var t = req.state.name || (req.yieldState && req.yieldState.returnTo)
    , f = req.yieldState.name || req.originalUrl || req.url;

  t = uri.parse(t).pathname; // TODO: test case for query parsing
  f = uri.parse(f).pathname; // TODO: test case for query parsing

  req.yieldStateStack = req.yieldStateStack || [];
  req.yieldStateStack.unshift(req.yieldState);

  var stack = this._yielders[t + '|' + f];
  if (!stack) {
    if (options && options.postFns) {
      dispatchReal(options.postFns)(err, req, res, function(err) {
        // TODO: handle err, with test case
        return next(err);
      });
      return;
    }

    return next(err);
  }
  dispatch(stack)(err, req, res, next);
}

module.exports = Manager;
<|endoftext|>


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

"use strict";
const log4js = require('log4js');
const logger = log4js.getLogger('kronos-service-manager:manager');
logger.setLevel(log4js.levels.ERROR);

const path = require("path");
const events = require('events');

const flow = require("./flow");
const progressReporter = require("./progressReporter");

const uti = require("uti");

const flowDefinition = require('kronos-flow');
const flowValidator = flowDefinition.validator;
const flowSchema = flowDefinition.schema;

const kronosStep = require('kronos-step');
const stepValidator = kronosStep.validator;
const stepSchema = kronosStep.schema;

/*
 * creates a kronos service manager.
 * Options:
 *    flows - flow declaration to load
 *    validateSchema - do schema validation; defaults to false
 *
 * @param {Object} options
 * @return {Promise} a promise with the service manager as its value
 */
exports.manager = function (options) {
  logger.debug(`Create a new kronos-service-manager instance`);

  if (!options) {
    options = {};
  }

  if (!options.hasOwnProperty("validateSchema")) {
    options.validateSchema = false;
  }

  if (!options.progressReporter) {
    options.progressReporter = progressReporter.defaultProgressReporter();
  }

  const flowDefinitions = {};
  const stepImplementations = {};
  const endpointSchemeImplementations = {};

  const manager = Object.create(new events.EventEmitter(), {
    flowDefinitions: {
      value: flowDefinitions
    },
    stepImplementations: {
      value: stepImplementations
    },
    endpointSchemeImplementations: {
      value: endpointSchemeImplementations
    }
  });

  manager.registerEndpointScheme = function (name, endpointScheme) {
    endpointSchemeImplementations[name] = endpointScheme;
  };

  manager.registerStepImplementation = function (name, aStep) {
    stepImplementations[name] = kronosStep.createStepImplementation(name, aStep);
  };

  /**
   * stops exectution and frees all used resources.
   * @return Promise
   */
  manager.shutdown = function () {
    logger.debug(`Shutdown the kronos-service-manager instance`);
    return new Promise(function (resolve, reject) {
      // TODO stop running flows
      resolve(manager);
    });
  };

  /**
   * declareFlows function - declares new flows
   * Events:
   * 	emits 'flowDeclard' event for every newly created flow
   * @param  {type} flowDef          A JSON Object which describes the flows
   * @param  {type} progressReporter Optional: A Progresss reporter.
   * @return {type}                  dictionary of the newly created flows
   */
  manager.declareFlows = function (flowDef, progressReporter) {
    logger.debug(`declareFlows`);

    function _declare() {
      const flows = flow.create(manager, flowDef, progressReporter);

      for (let fn in flows) {
        flowDefinitions[fn] = flows[fn];
        manager.emit('flowDeclared', flows[fn]);
      }

      return flows;
    }

    if (options.validateSchema) {
      // Check if the given flow matches the flow schema
      if (flowValidator.validate(flowDef, flowSchema)) {
        // The given flow matches the schema
        return _declare();
      } else {
        // The schema validator got an error
        const errors = flowValidator.getLastErrors();
        logger.error(errors);
        throw (errors);
      }
    } else {
      return _declare();
    }
  };

  /**
   * brings a declared flow to live state
   */
  manager.intializeFlow = function (flowName) {
    logger.debug(`Intialize Flow '${flowName}'`);

    const flow = flowDefinitions[flowName];
    //flow.initialize.apply(flow, manager);
    flow.initialize(manager);
  };

  manager.stopFlow = function (flowName) {
    logger.debug(`Stop Flow '${flowName}'`);

    return new Promise(function (resolve, reject) {
      const flow = flowDefinitions[flowName];
      resolve(flow);
    });
  };

  manager.deleteFlow = function (flowName) {
    logger.debug(`Delete Flow '${flowName}'`);

    const p = manager.stopFlow(flowName).then(function (flow) {
      console.log(`A delete ${flow}`);

      //const flow = flowDefinitions[flowName];
      delete flowDefinitions[flowName];
      manager.emit('flowDeleted', flow);
    });

    console.log(`P: ${p}`);
    return p;
  };

  return new Promise(function (resolve, reject) {
    require('kronos-service-manager-addon').registerWithManager(manager);

    return uti.initialize({
        definitionFileName: path.join(__dirname, '..', 'uti.json')
      })
      .then(function (resloved) {
        logger.debug(`Manager Promise: 'Then'`);

        if (options.flows) {
          logger.debug(`Manager Promise: 'Then': declareFlows`);
          manager.declareFlows(options.flows, options.progressReporter);
        }

        resolve(manager);
      }, reject);
  });
};
<commit_msg>feat: emit endpointSchemeRegistered and stepImplementationRegistered events<commit_after>/* jslint node: true, esnext: true */

"use strict";
const log4js = require('log4js');
const logger = log4js.getLogger('kronos-service-manager:manager');
logger.setLevel(log4js.levels.ERROR);

const path = require("path");
const events = require('events');

const flow = require("./flow");
const progressReporter = require("./progressReporter");

const uti = require("uti");

const flowDefinition = require('kronos-flow');
const flowValidator = flowDefinition.validator;
const flowSchema = flowDefinition.schema;

const kronosStep = require('kronos-step');
const stepValidator = kronosStep.validator;
const stepSchema = kronosStep.schema;

/*
 * creates a kronos service manager.
 * Options:
 *    flows - flow declaration to load
 *    validateSchema - do schema validation; defaults to false
 *
 * @param {Object} options
 * @return {Promise} a promise with the service manager as its value
 */
exports.manager = function (options) {
  logger.debug(`Create a new kronos-service-manager instance`);

  if (!options) {
    options = {};
  }

  if (!options.hasOwnProperty("validateSchema")) {
    options.validateSchema = false;
  }

  if (!options.progressReporter) {
    options.progressReporter = progressReporter.defaultProgressReporter();
  }

  const flowDefinitions = {};
  const stepImplementations = {};
  const endpointSchemeImplementations = {};

  const manager = Object.create(new events.EventEmitter(), {
    flowDefinitions: {
      value: flowDefinitions
    },
    stepImplementations: {
      value: stepImplementations
    },
    endpointSchemeImplementations: {
      value: endpointSchemeImplementations
    }
  });

  /**
   * Events:
   * 	emits 'endpointSchemeRegistered' event for every newly registered endpoint schema
   */
  manager.registerEndpointScheme = function (name, endpointScheme) {
    endpointSchemeImplementations[name] = endpointScheme;
    manager.emit('endpointSchemeRegistered', endpointScheme);
  };

  /**
   * Events:
   * 	emits 'stepImplementationRegistered' event for every newly registered step implementation
   */
  manager.registerStepImplementation = function (name, aStep) {
    const si = kronosStep.createStepImplementation(name, aStep)
    stepImplementations[name] = si;
    manager.emit('stepImplementationRegistered', si);
  };

  /**
   * stops exectution and frees all used resources.
   * @return Promise
   */
  manager.shutdown = function () {
    logger.debug(`Shutdown the kronos-service-manager instance`);
    return new Promise(function (resolve, reject) {
      // TODO stop running flows
      resolve(manager);
    });
  };

  /**
   * declareFlows function - declares new flows
   * Events:
   * 	emits 'flowDeclard' event for every newly created flow
   * @param  {type} flowDef          A JSON Object which describes the flows
   * @param  {type} progressReporter Optional: A Progresss reporter.
   * @return {type}                  dictionary of the newly created flows
   */
  manager.declareFlows = function (flowDef, progressReporter) {
    logger.debug(`declareFlows`);

    function _declare() {
      const flows = flow.create(manager, flowDef, progressReporter);

      for (let fn in flows) {
        flowDefinitions[fn] = flows[fn];
        manager.emit('flowDeclared', flows[fn]);
      }

      return flows;
    }

    if (options.validateSchema) {
      // Check if the given flow matches the flow schema
      if (flowValidator.validate(flowDef, flowSchema)) {
        // The given flow matches the schema
        return _declare();
      } else {
        // The schema validator got an error
        const errors = flowValidator.getLastErrors();
        logger.error(errors);
        throw (errors);
      }
    } else {
      return _declare();
    }
  };

  /**
   * brings a declared flow to live state
   */
  manager.intializeFlow = function (flowName) {
    logger.debug(`Intialize Flow '${flowName}'`);

    const flow = flowDefinitions[flowName];
    //flow.initialize.apply(flow, manager);
    flow.initialize(manager);
  };

  manager.stopFlow = function (flowName) {
    logger.debug(`Stop Flow '${flowName}'`);

    return new Promise(function (resolve, reject) {
      const flow = flowDefinitions[flowName];
      resolve(flow);
    });
  };

  manager.deleteFlow = function (flowName) {
    logger.debug(`Delete Flow '${flowName}'`);

    const p = manager.stopFlow(flowName).then(function (flow) {
      console.log(`A delete ${flow}`);

      //const flow = flowDefinitions[flowName];
      delete flowDefinitions[flowName];
      manager.emit('flowDeleted', flow);
    });

    console.log(`P: ${p}`);
    return p;
  };

  return new Promise(function (resolve, reject) {
    require('kronos-service-manager-addon').registerWithManager(manager);

    return uti.initialize({
        definitionFileName: path.join(__dirname, '..', 'uti.json')
      })
      .then(function (resloved) {
        logger.debug(`Manager Promise: 'Then'`);

        if (options.flows) {
          logger.debug(`Manager Promise: 'Then': declareFlows`);
          manager.declareFlows(options.flows, options.progressReporter);
        }

        resolve(manager);
      }, reject);
  });
};
<|endoftext|>


<commit_before>var path = require('path'),
    fs = require('fs');

/*
    The Manager module manages the users list (load/save), the submodules,
    also loads and distributes the application configuration.
*/

module.exports = {

    /*
     * Submodules binded to the manager
     */

    submodules: {
        auth: require(path.join(process.cwd(), 'lib/auth')),
        trigger: require(path.join(process.cwd(), 'lib/trigger')),
        twitter: require(path.join(process.cwd(), 'lib/twitter'))
    },

    /*
     * Attributes
     */

    config: null,
    users: {},

    /*
     * Initialization
     */

    init: function(config) {
        this.config = config;
        this.config.users_file = path.join(process.cwd(), this.config.users_file);

        this.load(); // Load the users
        // this.trigger.init(); // Initiate the triggers

        return this;
    },

    /*
     * User list : loading / saving
     */

    load: function() {
        if(fs.existsSync(this.config.users_file)) {
            var data = fs.readFileSync(this.config.users_file, 'utf-8');
            this.users = JSON.parse(data);
        } else {
            console.log('No user list found at the specified location. Creating a new one.');
        }
    },

    save: function() {
        var data = JSON.stringify(this.users);
        fs.writeFile(this.config.users_file, data, 'utf-8', function(err) {
            err && console.log(err);
        });
    },

    /*
     * User list : management
     */

    set: function(details) {
        var user = {
            id: details.id,
            name: details.name,
            access_token: details.access_token,
            access_token_secret: details.access_token_secret,
            gmt: 0, // Default value
            hour: 17 // Default value
        };

        this.users[details.id] = user;
        this.save();

        // Tell the trigger that a user has been set
    },

    unset: function(id) {
        this.users[id] = null;

        // Tell the trigger that a user has been deleted
    }

};<commit_msg>The manager module now initiates the auth module<commit_after>var path = require('path'),
    fs = require('fs');

/*
    The Manager module manages the user list (load/save), the submodules,
    also loads and distributes the application configuration.
*/

module.exports = {

    /*
     * Submodules binded to the manager
     */

    submodules: {
        auth: require(path.join(process.cwd(), 'lib/auth')),
        trigger: require(path.join(process.cwd(), 'lib/trigger')),
        twitter: require(path.join(process.cwd(), 'lib/twitter'))
    },

    /*
     * Attributes
     */

    config: null,
    users: {},

    /*
     * Initialization
     */

    init: function(config) {
        this.config = config;
        this.config.users_file = path.join(process.cwd(), this.config.users_file);

        this.load(); // Load the users

        this.submodules.auth.init(config, this);

        return this;
    },

    /*
     * User list : loading / saving
     */

    load: function() {
        if(fs.existsSync(this.config.users_file)) {
            var data = fs.readFileSync(this.config.users_file, 'utf-8');
            this.users = JSON.parse(data);
        } else {
            console.log('No user list found at the specified location. Creating a new one.');
        }
    },

    save: function() {
        var data = JSON.stringify(this.users);
        fs.writeFile(this.config.users_file, data, 'utf-8', function(err) {
            err && console.log(err);
        });
    },

    /*
     * User list : management
     */

    set: function(details) {
        var user = {
            id: details.id,
            name: details.name,
            access_token: details.access_token,
            access_token_secret: details.access_token_secret,
            gmt: 0, // Default value
            hour: 17 // Default value
        };

        this.users[details.id] = user;
        this.save();

        // Tell the trigger that a user has been set
    },

    unset: function(id) {
        this.users[id] = null;

        // Tell the trigger that a user has been deleted
    }

};<|endoftext|>