<commit_before>"use strict";

var arr_slice = Array.prototype.slice;

function slice (array, start, end) {
  return arr_slice.call(array, start, end);
}

function store (value) {
  return (is_immutable(value)
          ? value
          : api(store_object({}, value)));
}

function store_object (storage, value) {
  for (var name in value) {
    storage[name] = store(value[name]);
  }
  return storage;
}

function store_array (value) {
}

function store_date (value) {
}

function is_immutable (value) {
  return typeof value !== "object";
}

function is_api (value) {
  return (typeof value === "function" &&
          typeof value.patch === "function");
}

function api (storage, deleted, previous) {
  deleted = deleted || {};

  if (!previous) {
    previous = function prev () { return null; };
    previous.keys = function keys () { return []; };
    previous.dump = function dump () { return {}; };
    previous.back = function back () { return previous; };
  }

  function get (name) {
    return (deleted[name]
            ? null
            : (name in storage
               ? storage[name]
               : previous(name)));
  }

  get.patch = patch;
  get.rm = rm;
  get.keys = keys;
  get.dump = dump;
  get.back = back;

  return get;

  function patch (diff_in) {
    // diff_in can be a tree of updated values to to patch on top of
    // current values.

    if (arguments.length >= 2) {
      diff_in = {};
      diff_in[arguments[0]] = arguments[1];
    }

    var storage_diff = {};

    var name, old, value;
    for (name in diff_in) {
      old = get(name);
      value = diff_in[name];

      storage_diff[name] = (!is_immutable(value) && is_api(old)
                            ? old.patch(value)
                            : store(value));
    }

    return update(storage_diff, {});
  }

  function rm (name) {
    if (arguments.length > 1) {
      var element = get(name);
      console.log(element, is_api(element));
      if (is_api(element)) {
        return patch(name, element.rm.apply(null, slice(arguments, 1)));
      }
    }

    var deleted_diff = {};

    deleted_diff[name] = true;

    return update({}, deleted_diff);
  }

  function update (storage_diff, deleted_diff) {
    return api(storage_diff, deleted_diff, get);
  }

  function keys () {
    var ks = previous.keys().filter(function (name) {
      return !deleted[name];
    });

    for (var name in storage) {
      ks.push(name);
    }

    return ks;
  }

  function dump () {
    var value = {};

    keys().forEach(function (name) {
      var element = get(name);
      value[name] = is_api(element) ? element.dump() : element;
    });

    return value;
  }

  function back () {
    return previous;
  }

  // get.on = on;
  // get.map = map;
  // get.forEach = forEach;
  // get.filter = filter;
  // get.reduce = reduce;
}

var v1 = store({a: 1, b: 2, c: 3});
var v2 = v1.patch({b: 4, d: [1,5]});
var v3 = v2.patch({a: {e: 7}}).patch("h", 8);
var v4 = v3.rm("a").rm("b").rm("c").rm("d", "0");

var v5 = store({a: {b: 2, c: 3}, d: {e: 5, f: 7}});
var v6 = v5.patch({a: {b: 8, g: {h: 9}}});
var v7 = v6.rm("a", "g", "h");

var assert = require("assert");

console.log(v1.keys(), v2.back().keys());
console.log("1", v1.dump());
console.log("2", v2.dump());
console.log("3", v3.dump());
console.log("4", v4.dump());
console.log("5", v5.dump());
console.log("6", v6.dump());
console.log("7", v7.dump());

assert.deepEqual(v1.dump(), { a: 1, b: 2, c: 3 });
assert.deepEqual(v2.dump(), { b: 4, d: { '0': 1, '1': 5 }, a: 1, c: 3 });
assert.deepEqual(v3.dump(), { h: 8, a: { e: 7 }, b: 4, d: { '0': 1, '1': 5 }, c: 3 });
assert.deepEqual(v4.dump(), { d: { '1': 5 }, h: 8 });
assert.deepEqual(v5.dump(), { a: { b: 2, c: 3 }, d: { e: 5, f: 7 } });
assert.deepEqual(v6.dump(), { a: { b: 8, g: { h: 9 }, c: 3 }, d: { e: 5, f: 7 } });
assert.deepEqual(v7.dump(), { a: { g: {}, b: 8, c: 3 }, d: { e: 5, f: 7 } });
<commit_msg>Compact method to compact history.<commit_after>"use strict";

var arr_slice = Array.prototype.slice;

function slice (array, start, end) {
  return arr_slice.call(array, start, end);
}

function store (value) {
  return (is_immutable(value)
          ? value
          : api(store_object({}, value)));
}

function store_object (storage, value) {
  for (var name in value) {
    storage[name] = store(value[name]);
  }
  return storage;
}

function store_array (value) {
}

function store_date (value) {
}

function is_immutable (value) {
  return typeof value !== "object";
}

function is_api (value) {
  return (typeof value === "function" &&
          typeof value.patch === "function");
}

function api (storage, deleted, previous) {
  deleted = deleted || {};

  if (!previous) {
    previous = function prev () { return null; };
    previous.keys = function keys () { return []; };
    previous.dump = function dump () { return {}; };
    previous.back = function back () { return previous; };
  }

  function get (name) {
    return (deleted[name]
            ? null
            : (name in storage
               ? storage[name]
               : previous(name)));
  }

  get.patch = patch;
  get.rm = rm;
  get.keys = keys;
  get.dump = dump;
  get.back = back;
  get.compact = compact;

  return get;

  function patch (diff_in) {
    // diff_in can be a tree of updated values to to patch on top of
    // current values.

    if (arguments.length >= 2) {
      diff_in = {};
      diff_in[arguments[0]] = arguments[1];
    }

    var storage_diff = {};

    var name, old, value;
    for (name in diff_in) {
      old = get(name);
      value = diff_in[name];

      storage_diff[name] = (!is_immutable(value) && is_api(old)
                            ? old.patch(value)
                            : store(value));
    }

    return update(storage_diff, {});
  }

  function rm (name) {
    if (arguments.length > 1) {
      var element = get(name);
      if (is_api(element)) {
        return patch(name, element.rm.apply(null, slice(arguments, 1)));
      }
    }

    var deleted_diff = {};

    deleted_diff[name] = true;

    return update({}, deleted_diff);
  }

  function update (storage_diff, deleted_diff) {
    return api(storage_diff, deleted_diff, get);
  }

  function keys () {
    var ks = previous.keys().filter(function (name) {
      return !deleted[name];
    });

    for (var name in storage) {
      ks.push(name);
    }

    return ks;
  }

  function dump () {
    var value = {};

    keys().forEach(function (name) {
      var element = get(name);
      value[name] = is_api(element) ? element.dump() : element;
    });

    return value;
  }

  function back () {
    return previous;
  }

  function compact () {
    return store(dump());
  }
  // get.on = on;
  // get.map = map;
  // get.forEach = forEach;
  // get.filter = filter;
  // get.reduce = reduce;
}

var v1 = store({a: 1, b: 2, c: 3});
var v2 = v1.patch({b: 4, d: [1,5]});
var v3 = v2.patch({a: {e: 7}}).patch("h", 8);
var v4 = v3.rm("a").rm("b").rm("c").rm("d", "0");

var v5 = store({a: {b: 2, c: 3}, d: {e: 5, f: 7}});
var v6 = v5.patch({a: {b: 8, g: {h: 9}}});
var v7 = v6.rm("a", "g", "h");

var assert = require("assert");

console.log("1", v1.dump());
console.log("2", v2.dump());
console.log("3", v3.dump());
console.log("4", v4.dump());
console.log("5", v5.dump());
console.log("6", v6.dump());
console.log("7", v7.dump());

assert.deepEqual(v1.dump(), { a: 1, b: 2, c: 3 });
assert.deepEqual(v2.dump(), { b: 4, d: { '0': 1, '1': 5 }, a: 1, c: 3 });
assert.deepEqual(v3.dump(), { h: 8, a: { e: 7 }, b: 4, d: { '0': 1, '1': 5 }, c: 3 });
assert.deepEqual(v4.dump(), { d: { '1': 5 }, h: 8 });
assert.deepEqual(v5.dump(), { a: { b: 2, c: 3 }, d: { e: 5, f: 7 } });
assert.deepEqual(v6.dump(), { a: { b: 8, g: { h: 9 }, c: 3 }, d: { e: 5, f: 7 } });
assert.deepEqual(v7.dump(), { a: { g: {}, b: 8, c: 3 }, d: { e: 5, f: 7 } });
assert.deepEqual(v4.dump(), v4.compact().dump());
assert.deepEqual(v4.compact().back().dump(), {});
<|endoftext|>


<commit_before>'use strict'

var Cache = require('lru-cache')

var opts = {
  plugin: 'nodezoo-info',
  role: 'info',
  size: 99999,
  wait: 222
}

module.exports = function (options) {
  var seneca = this
  var extend = seneca.util.deepextend

  opts = extend(opts, options)
  opts.cache = Cache(options.size)

  seneca.add({role: opts.role, cmd: 'get'}, get)
  seneca.add({role: opts.role, res: 'part'}, update)

  return {
    name: opts.plugin
  }
}

function get (msg, done) {
  var seneca = this
  var name = msg.name

  seneca.act({role: opts.role, req: 'part', name: name})

  function respond () {
    done(null, (opts.cache.get(name) || {}))
  }

  setTimeout(respond, opts.wait)
}

function update (msg, done) {
  done()

  var name = msg.name
  var data = opts.cache.get(name) || {}

  data[msg.part] = msg.data
  data.name = name

  opts.cache.set(name, data)
  this.act('role:info,info:updated', {data: data})
}
<commit_msg>pass along the update flag to part modules<commit_after>'use strict'

var Cache = require('lru-cache')

var opts = {
  plugin: 'nodezoo-info',
  role: 'info',
  size: 99999,
  wait: 222
}

module.exports = function (options) {
  var seneca = this
  var extend = seneca.util.deepextend

  opts = extend(opts, options)
  opts.cache = Cache(options.size)

  seneca.add({role: opts.role, cmd: 'get'}, get)
  seneca.add({role: opts.role, res: 'part'}, update)

  return {
    name: opts.plugin
  }
}

function get (msg, done) {
  var seneca = this
  var name = msg.name

  seneca.act({role: opts.role, req: 'part', name: name, update: msg.update})

  function respond () {
    done(null, (opts.cache.get(name) || {}))
  }

  setTimeout(respond, opts.wait)
}

function update (msg, done) {
  done()

  var name = msg.name
  var data = opts.cache.get(name) || {}

  data[msg.part] = msg.data
  data.name = name

  opts.cache.set(name, data)
  this.act('role:info,info:updated', {data: data})
}
<|endoftext|>


<commit_before>/*
 * Copyright 2016, Lorenzo Mangani (lorenzo.mangani@gmail.com)
 * Copyright 2015, Rao Chenlin (rao.chenlin@gmail.com)
 *
 * This file is part of Sentinl (http://github.com/sirensolutions/sentinl)
 *
 * 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.
 */

import later from 'later';
import _ from 'lodash';
import masterRoute from './server/routes/routes';
import getScheduler from './server/lib/scheduler';
import helpers from './server/lib/helpers';
import getElasticsearchClient from './server/lib/get_elasticsearch_client';
import getConfiguration from './server/lib/get_configuration';
import fs from 'fs';
import phantom from './server/lib/phantom';

import userIndexMappings from './server/mappings/user_index';
import coreIndexMappings from './server/mappings/core_index';
import alarmIndexMappings from './server/mappings/alarm_index';
import templateMappings from './server/mappings/template';

import watchConfiguration from './server/lib/saved_objects/watch';
import scriptConfiguration from './server/lib/saved_objects/script';
import userConfiguration from './server/lib/saved_objects/user';
import SavedObjectsAPIMiddleware from './server/lib/saved_objects_api';

/**
* Initializes Sentinl app.
*
* @param {object} server - Kibana server.
*/
const init = _.once((server) => {
  const config = getConfiguration(server);
  const scheduler = getScheduler(server);

  if (fs.existsSync('/etc/sentinl.json')) {
    server.plugins.sentinl.status.red('Setting configuration values in /etc/sentinl.json is not supported anymore, please copy ' +
                                      'your Sentinl configuration values to config/kibi.yml or config/kibana.yml, ' +
                                      'remove /etc/sentinl.json and restart.');
    return;
  }

  server.log(['status', 'info', 'Sentinl'], 'Sentinl Initializing');

  // Object to hold different runtime values.
  server.sentinlStore = {
    schedule: {}
  };

  // Install PhantomJS lib. The lib is needed to take screenshots by report action.
  const phantomPath = _.has(config, 'settings.report.phantomjs_path') ? config.settings.report.phantomjs_path : undefined;
  phantom.install(phantomPath)
  .then((phantomPackage) => {
    server.log(['status', 'info', 'Sentinl', 'report'], `Phantom installed at ${phantomPackage.binary}`);
    server.expose('phantomjs_path', phantomPackage.binary);
  })
  .catch((err) => server.log(['status', 'error', 'Sentinl', 'report'], `Failed to install phantomjs: ${err}`));

  // Load Sentinl routes.
  masterRoute(server);

  // Create indexes and doc types with mappings.
  if (server.plugins.saved_objects_api) { // Kibi: savedObjectsAPI.
    _.forEach([watchConfiguration, scriptConfiguration, userConfiguration], (schema) => {
      server.plugins.saved_objects_api.registerType(schema);
    });

    config.es.default_index = server.config().get('kibana.index');
    config.es.type = 'sentinl-watcher';
    config.settings.authentication.user_index = server.config().get('kibana.index');
    config.settings.authentication.user_type = 'sentinl-user';
    helpers.putMapping(server, config, config.es.default_index, config.es.type, coreIndexMappings);

    const middleware = new SavedObjectsAPIMiddleware(server);
    server.plugins.saved_objects_api.registerMiddleware(middleware);
  } else { // Kibana.
    helpers.createIndex(server, config, config.es.default_index, config.es.type, coreIndexMappings);
  }
  helpers.putMapping(server, config, config.es.default_index, config.es.script_type, templateMappings);
  helpers.createIndex(server, config, config.es.alarm_index, config.es.alarm_type, alarmIndexMappings, 'alarm');

  if (!server.plugins.kibi_access_control && config.settings.authentication.enabled) {
    helpers.createIndex(server, config, config.settings.authentication.user_index,
      config.settings.authentication.user_type, userIndexMappings);
  }

  // Schedule watchers execution.
  const sched = later.parse.recur().on(25,55).second();
  const handleWatchers = later.setInterval(() => scheduler.doalert(server), sched);
});

export default function (server, options) {

  let status = server.plugins.elasticsearch.status;
  if (status && status.state === 'green') {
    init(server);
  } else {
    status.on('change', () => {
      if (server.plugins.elasticsearch.status.state === 'green') {
        init(server);
      }
    });
  }

};
<commit_msg>Create sentinl mappings only if the saved objects API is not in use to avoid mapping conflicts<commit_after>/*
 * Copyright 2016, Lorenzo Mangani (lorenzo.mangani@gmail.com)
 * Copyright 2015, Rao Chenlin (rao.chenlin@gmail.com)
 *
 * This file is part of Sentinl (http://github.com/sirensolutions/sentinl)
 *
 * 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.
 */

import later from 'later';
import _ from 'lodash';
import masterRoute from './server/routes/routes';
import getScheduler from './server/lib/scheduler';
import helpers from './server/lib/helpers';
import getElasticsearchClient from './server/lib/get_elasticsearch_client';
import getConfiguration from './server/lib/get_configuration';
import fs from 'fs';
import phantom from './server/lib/phantom';

import userIndexMappings from './server/mappings/user_index';
import coreIndexMappings from './server/mappings/core_index';
import alarmIndexMappings from './server/mappings/alarm_index';
import templateMappings from './server/mappings/template';

import watchConfiguration from './server/lib/saved_objects/watch';
import scriptConfiguration from './server/lib/saved_objects/script';
import userConfiguration from './server/lib/saved_objects/user';
import SavedObjectsAPIMiddleware from './server/lib/saved_objects_api';

/**
* Initializes Sentinl app.
*
* @param {object} server - Kibana server.
*/
const init = _.once((server) => {
  const config = getConfiguration(server);
  const scheduler = getScheduler(server);

  if (fs.existsSync('/etc/sentinl.json')) {
    server.plugins.sentinl.status.red('Setting configuration values in /etc/sentinl.json is not supported anymore, please copy ' +
                                      'your Sentinl configuration values to config/kibi.yml or config/kibana.yml, ' +
                                      'remove /etc/sentinl.json and restart.');
    return;
  }

  server.log(['status', 'info', 'Sentinl'], 'Sentinl Initializing');

  // Object to hold different runtime values.
  server.sentinlStore = {
    schedule: {}
  };

  // Install PhantomJS lib. The lib is needed to take screenshots by report action.
  const phantomPath = _.has(config, 'settings.report.phantomjs_path') ? config.settings.report.phantomjs_path : undefined;
  phantom.install(phantomPath)
  .then((phantomPackage) => {
    server.log(['status', 'info', 'Sentinl', 'report'], `Phantom installed at ${phantomPackage.binary}`);
    server.expose('phantomjs_path', phantomPackage.binary);
  })
  .catch((err) => server.log(['status', 'error', 'Sentinl', 'report'], `Failed to install phantomjs: ${err}`));

  // Load Sentinl routes.
  masterRoute(server);

  // Create indexes and doc types with mappings.
  if (server.plugins.saved_objects_api) { // Kibi: savedObjectsAPI.
    _.forEach([watchConfiguration, scriptConfiguration, userConfiguration], (schema) => {
      server.plugins.saved_objects_api.registerType(schema);
    });

    config.es.default_index = server.config().get('kibana.index');
    config.es.type = 'sentinl-watcher';
    config.settings.authentication.user_index = server.config().get('kibana.index');
    config.settings.authentication.user_type = 'sentinl-user';

    const middleware = new SavedObjectsAPIMiddleware(server);
    server.plugins.saved_objects_api.registerMiddleware(middleware);
  } else { // Kibana.
    helpers.createIndex(server, config, config.es.default_index, config.es.type, coreIndexMappings);
    helpers.putMapping(server, config, config.es.default_index, config.es.script_type, templateMappings);
  }
  helpers.createIndex(server, config, config.es.alarm_index, config.es.alarm_type, alarmIndexMappings, 'alarm');

  if (!server.plugins.kibi_access_control && config.settings.authentication.enabled) {
    helpers.createIndex(server, config, config.settings.authentication.user_index,
      config.settings.authentication.user_type, userIndexMappings);
  }

  // Schedule watchers execution.
  const sched = later.parse.recur().on(25,55).second();
  const handleWatchers = later.setInterval(() => scheduler.doalert(server), sched);
});

export default function (server, options) {

  let status = server.plugins.elasticsearch.status;
  if (status && status.state === 'green') {
    init(server);
  } else {
    status.on('change', () => {
      if (server.plugins.elasticsearch.status.state === 'green') {
        init(server);
      }
    });
  }

};
<|endoftext|>


<commit_before>/**
 * Base Initialization Module
 *
 * This module sets up the application definitions, and loads all required
 * core modules.
 *
 * If any error is encountered, this module should terminate the application.
 */
module.exports = function(app, express) {
  var dir = __dirname + '/core/',
      fs = require('fs');

  /**
   * Set up site globals - these are based off of Environmental variables.
   */
  var env = (process.env.NODE_ENV || 'dev').toUpperCase();
  app.set('NODE ENVIRONMENT', env);
  app.set('NODE PORT', process.env[env + '_NODE_PORT'] || 3000);
  app.set('NODE HOST', process.env[env + '_NODE_HOST'] || '0.0.0.0');
  app.set('ROOT PATH', process.env[env + '_ROOT_PATH']);
  app.set('ROOT URL', process.env[env + '_ROOT_URL']);
  app.set('COOKIE SECRET', process.env[env + '_COOKIE_SECRET']);
  app.set('REDIS SECRET', process.env[env + '_REDIS_SECRET']);
  app.set('SITE OWNERS', process.env.SITE_OWNERS);

  /**
   * Load all required core files.
   */
  var modules = fs.readdirSync(dir);
  modules.forEach(function(module) {
    require(dir + '/' + module)(app);
  });

  /**
   * Extract environmental variables.
   */
  var root = app.get('ROOT PATH'),
      env = app.get('NODE ENVIRONMENT');

  /**
   * Load application-specific config files (routes, etc).
   */
  var confs = fs.readdirSync(root + 'config');
  confs.forEach(function(conf) {
    var path = root + 'config/' + conf;
    if (fs.lstatSync(path).isFile() && conf !== 'routes.js') {
      require(path)(app);
    }
  });

  /**
   * (Optional)
   * Setup environment-specific settings.
   * For example, if you are adding a custom logger to Dev, but you don't want
   * to use it in Prod, then you can create a `dev` file for dev-specific
   * settings.
   */
  var conf = root + 'config/environment/' + env.toLowerCase() + '.js';
  if (fs.existsSync(conf) && fs.lstatSync(conf).isFile()) {
    require(conf)(app, express);
  }

  /**
   * Always load the Routes last.
   */
  require(root + 'config/routes.js')(app);
};
<commit_msg>Re-adding MySQL globals, and added functionality to add multiple Owners.<commit_after>/**
 * Base Initialization Module
 *
 * This module sets up the application definitions, and loads all required
 * core modules.
 *
 * If any error is encountered, this module should terminate the application.
 */
module.exports = function(app, express) {
  var dir = __dirname + '/core/',
      fs = require('fs');

  /**
   * Set up site globals - these are based off of Environmental variables.
   */
  var env = (process.env.NODE_ENV || 'dev').toUpperCase();
  app.set('NODE ENVIRONMENT', env);
  app.set('NODE PORT', process.env[env + '_NODE_PORT'] || 3000);
  app.set('NODE HOST', process.env[env + '_NODE_HOST'] || '0.0.0.0');
  app.set('ROOT PATH', process.env[env + '_ROOT_PATH']);
  app.set('ROOT URL', process.env[env + '_ROOT_URL']);
  app.set('MYSQL DB', process.env[env + '_MYSQL_DB']);
  app.set('MYSQL HOST', process.env[env + '_MYSQL_HOST']);
  app.set('MYSQL USER', process.env[env + '_MYSQL_USER']);
  app.set('MYSQL PASS', process.env[env + '_MYSQL_PASS']);
  app.set('MYSQL MAX CONN', process.env[env + '_MYSQL_MAX_CONN']);
  app.set('COOKIE SECRET', process.env[env + '_COOKIE_SECRET']);
  app.set('REDIS SECRET', process.env[env + '_REDIS_SECRET']);

  /**
   * Extract the Site Owners and store as global.
   */
  var owners = process.env[env + '_SITE_OWNERS'];
  var ownersList = owners ? owners.split(',') : [];
  var siteOwners = ownersList.map(function(owner) {
    // TODO: Maybe also verify if this is an email address or not.
    return owner.trim();
  });
  app.set('SITE OWNERS', siteOwners);

  /**
   * Load all required core files.
   */
  var modules = fs.readdirSync(dir);
  modules.forEach(function(module) {
    require(dir + '/' + module)(app);
  });

  /**
   * Extract environmental variables.
   */
  var root = app.get('ROOT PATH'),
      env = app.get('NODE ENVIRONMENT');

  /**
   * Load application-specific config files (routes, etc).
   */
  var confs = fs.readdirSync(root + 'config');
  confs.forEach(function(conf) {
    var path = root + 'config/' + conf;
    if (fs.lstatSync(path).isFile() && conf !== 'routes.js') {
      require(path)(app);
    }
  });

  /**
   * (Optional)
   * Setup environment-specific settings.
   * For example, if you are adding a custom logger to Dev, but you don't want
   * to use it in Prod, then you can create a `dev` file for dev-specific
   * settings.
   */
  var conf = root + 'config/environment/' + env.toLowerCase() + '.js';
  if (fs.existsSync(conf) && fs.lstatSync(conf).isFile()) {
    require(conf)(app, express);
  }

  /**
   * Always load the Routes last.
   */
  require(root + 'config/routes.js')(app);
};
<|endoftext|>


<commit_before>this.models = {}

Date.new = function(x) {
  if (x === undefined) { return Date.new(+new Date) }
  return new Date(x)
}

Date.prototype.add_days = function(x) {
  var result = new Date(+this)
  result.setDate(result.getDate() + x)
  return result
}

Date.prototype.dayStart = function() {
  var result = new Date(+this)
  result.setHours(0)
  result.setMinutes(0)
  result.setSeconds(0)
  result.setMilliseconds(0)
  return result
}
<commit_msg>Add Date.Timecop<commit_after>this.models = {}

Date.Timecop = function() {
  this.daysOffset = 0
}

Date.timecop = new Date.Timecop

Date.Timecop.prototype.travelDays = function(newOffset) {
  this.daysOffset = newOffset
}

Date.Timecop.prototype.now = function() {
  return (new Date).add_days(this.daysOffset)
}

Date.new = function(x) {
  if (x === undefined) { return Date.new(+Date.timecop.now()) }
  return new Date(x)
}

Date.prototype.add_days = function(x) {
  var result = new Date(+this)
  result.setDate(result.getDate() + x)
  return result
}

Date.prototype.dayStart = function() {
  var result = new Date(+this)
  result.setHours(0)
  result.setMinutes(0)
  result.setSeconds(0)
  result.setMilliseconds(0)
  return result
}
<|endoftext|>


<commit_before>/**
\file ipv6.js
Plugin to measure various ipv6 related metrics.
This plugin tries to do a few things:
- Check if the client can connect to an ipv6 address
- Check if the client can resolve DNS that points to an ipv6 address
- Check latency of connecting to an ipv6 address
- Check avg latency of doing dns lookup to an ipv6 address (not worstcase)

You'll need a server that has an ipv6 address, and a DNS name to point to it.
Additionally, this server needs to be configured to serve content requested
from the IPv6 address and should not require a virtual host name.  This means
that you probably cannot use shared hosting that puts multiple hosts on the
same IP address.

All beacon parameters are prefixed with ipv6_

Beacon parameters:
- ipv6_latency: Latency in milliseconds of getting data from an ipv6 host when
		connecting to the IP.  Set to NA if the client cannot connect
		to the ipv6 host.
- ipv6_lookup:  Latency of getting data from a hostname that resolves to an
		ipv6 address.  Set to NA if the client cannot resolve or connect
		to the ipv6 host.
*/

(function(w) {

BOOMR = BOOMR || {};
BOOMR.plugins = BOOMR.plugins || {};

/*
Algorithm:

1. Try to load a sizeless image from an IPv6 host
   - onerror, flag no IPv6 connect support and end
   - onload, measure load time
2. Try to load a sizeless image from a hostname that resolves to an IPv6 address
   - onerror, flag no IPv6 DNS resolver and end
   - onload, measure load time
*/
var impl = {
	complete: false,
	ipv6_url: "",
	host_url: "",
	timeout: 1200,

	timers: {
		ipv6: { start: null, end: null },
		host: { start: null, end: null }
	},

	start: function() {
		this.load_img('ipv6', 'host');
	},

	load_img: function(which) {
		var img,
			rnd = "?t=" + (new Date().getTime()) + Math.random(),
			timer=0, error = null,
			that = this, a;

		// Terminate if we've reached end of test list
		if(!which || !(which in this.timers)) {
			this.done();
			return false;
		}

		Array.prototype.shift.call(arguments);
		a = arguments;

		// Skip if URL wasn't set for this test
		if(!this[which + '_url']) {
			return this.load_img.apply(this, a);
		}

		img = new Image();

		img.onload = function() {
			that.timers[which].end = new Date().getTime();
			clearTimeout(timer);
			img.onload = img.onerror = null;
			img = null;

			that.load_img.apply(that, a);
			that = a = null;
		};

		error = function() {
			that.timers[which].supported = false;
			clearTimeout(timer);
			img.onload = img.onerror = null;
			img = null;

			that.done();
			that = a = null;
		};

		img.onerror = error;
		timer = setTimeout(error, this.timeout);
		this.timers[which].start = new Date().getTime();
		img.src = this[which + '_url'] + rnd;

		return true;
	},

	done: function() {
		BOOMR.removeVar('ipv6_latency', 'ipv6_lookup');
		if(this.timers.ipv6.end !== null) {
			BOOMR.addVar('ipv6_latency', this.timers.ipv6.end - this.timers.ipv6.start);
		}
		else {
			BOOMR.addVar('ipv6_latency', 'NA');
		}

		if(this.timers.host.end !== null) {
			BOOMR.addVar('ipv6_lookup', this.timers.host.end - this.timers.host.start);
		}
		else {
			BOOMR.addVar('ipv6_lookup', 'NA');
		}

		this.complete = true;
		BOOMR.sendBeacon();
	}
};

BOOMR.plugins.IPv6 = {
	init: function(config) {
		BOOMR.utils.pluginConfig(impl, config, "IPv6", ["ipv6_url", "host_url", "timeout"]);

		if(!impl.ipv6_url) {
			BOOMR.warn("IPv6.ipv6_url is not set.  Cannot run IPv6 test.", "ipv6");
			impl.complete = true;	// set to true so that is_complete doesn't
						// block other plugins
			return this;
		}

		if(!impl.host_url) {
			BOOMR.warn("IPv6.host_url is not set.  Will skip hostname test.", "ipv6");
		}

		// make sure that test images use the same protocol as the host page
		if(w.location.protocol === 'https:') {
			impl.ipv6_url = impl.ipv6_url.replace(/^http:/, 'https:');
			impl.host_url = impl.host_url.replace(/^http:/, 'https:');
		}
		else {
			impl.ipv6_url = impl.ipv6_url.replace(/^https:/, 'http:');
			impl.host_url = impl.host_url.replace(/^https:/, 'http:');
		}

		BOOMR.subscribe("page_ready", impl.start, null, this);

		return this;
	},

	is_complete: function() {
		return impl.complete;
	}
};

}(window));

<commit_msg>fix scope for ipv6 test<commit_after>/**
\file ipv6.js
Plugin to measure various ipv6 related metrics.
This plugin tries to do a few things:
- Check if the client can connect to an ipv6 address
- Check if the client can resolve DNS that points to an ipv6 address
- Check latency of connecting to an ipv6 address
- Check avg latency of doing dns lookup to an ipv6 address (not worstcase)

You'll need a server that has an ipv6 address, and a DNS name to point to it.
Additionally, this server needs to be configured to serve content requested
from the IPv6 address and should not require a virtual host name.  This means
that you probably cannot use shared hosting that puts multiple hosts on the
same IP address.

All beacon parameters are prefixed with ipv6_

Beacon parameters:
- ipv6_latency: Latency in milliseconds of getting data from an ipv6 host when
		connecting to the IP.  Set to NA if the client cannot connect
		to the ipv6 host.
- ipv6_lookup:  Latency of getting data from a hostname that resolves to an
		ipv6 address.  Set to NA if the client cannot resolve or connect
		to the ipv6 host.
*/

(function(w) {

BOOMR = BOOMR || {};
BOOMR.plugins = BOOMR.plugins || {};

/*
Algorithm:

1. Try to load a sizeless image from an IPv6 host
   - onerror, flag no IPv6 connect support and end
   - onload, measure load time
2. Try to load a sizeless image from a hostname that resolves to an IPv6 address
   - onerror, flag no IPv6 DNS resolver and end
   - onload, measure load time
*/
var impl = {
	complete: false,
	ipv6_url: "",
	host_url: "",
	timeout: 1200,

	timers: {
		ipv6: { start: null, end: null },
		host: { start: null, end: null }
	},

	start: function() {
		this.load_img('ipv6', 'host');
	},

	load_img: function(which) {
		var img,
			rnd = "?t=" + (new Date().getTime()) + Math.random(),
			timer=0, error = null,
			that = this, a;

		// Terminate if we've reached end of test list
		if(!which || !(which in this.timers)) {
			this.done();
			return false;
		}

		Array.prototype.shift.call(arguments);
		a = arguments;

		// Skip if URL wasn't set for this test
		if(!this[which + '_url']) {
			return this.load_img.apply(this, a);
		}

		img = new Image();

		img.onload = function() {
			that.timers[which].end = new Date().getTime();
			clearTimeout(timer);
			img.onload = img.onerror = null;
			img = null;

			that.load_img.apply(that, a);
			that = a = null;
		};

		error = function() {
			that.timers[which].supported = false;
			clearTimeout(timer);
			img.onload = img.onerror = null;
			img = null;

			that.done();
			that = a = null;
		};

		img.onerror = error;
		timer = setTimeout(error, this.timeout);
		this.timers[which].start = new Date().getTime();
		img.src = this[which + '_url'] + rnd;

		return true;
	},

	done: function() {
		BOOMR.removeVar('ipv6_latency', 'ipv6_lookup');
		if(this.timers.ipv6.end !== null) {
			BOOMR.addVar('ipv6_latency', this.timers.ipv6.end - this.timers.ipv6.start);
		}
		else {
			BOOMR.addVar('ipv6_latency', 'NA');
		}

		if(this.timers.host.end !== null) {
			BOOMR.addVar('ipv6_lookup', this.timers.host.end - this.timers.host.start);
		}
		else {
			BOOMR.addVar('ipv6_lookup', 'NA');
		}

		this.complete = true;
		BOOMR.sendBeacon();
	}
};

BOOMR.plugins.IPv6 = {
	init: function(config) {
		BOOMR.utils.pluginConfig(impl, config, "IPv6", ["ipv6_url", "host_url", "timeout"]);

		if(!impl.ipv6_url) {
			BOOMR.warn("IPv6.ipv6_url is not set.  Cannot run IPv6 test.", "ipv6");
			impl.complete = true;	// set to true so that is_complete doesn't
						// block other plugins
			return this;
		}

		if(!impl.host_url) {
			BOOMR.warn("IPv6.host_url is not set.  Will skip hostname test.", "ipv6");
		}

		// make sure that test images use the same protocol as the host page
		if(w.location.protocol === 'https:') {
			impl.ipv6_url = impl.ipv6_url.replace(/^http:/, 'https:');
			impl.host_url = impl.host_url.replace(/^http:/, 'https:');
		}
		else {
			impl.ipv6_url = impl.ipv6_url.replace(/^https:/, 'http:');
			impl.host_url = impl.host_url.replace(/^https:/, 'http:');
		}

		BOOMR.subscribe("page_ready", impl.start, null, impl);

		return this;
	},

	is_complete: function() {
		return impl.complete;
	}
};

}(window));

<|endoftext|>


<commit_before>const xTime = require('x-time')
const net = require('net')
const fs = require('fs')
const cp = require('child_process')
const path = require('path')
const promisify = require('smart-promisify')
const StringDecoder = require('string_decoder').StringDecoder

/**
 * A class representing a set of commands to control z1.
 * @class
 */
class Remote {
  /**
   * Create a new Remote instance.
   * @param {string} socketFile - Path to the socket file of the z1 daemon.
   */
  constructor(socketFile) {
    /** @type {string} */
    this.socketFile = socketFile
  }

  /**
   * Sends the "ready" signal to the z1 daemon.
   * @returns {Promise.<void>}
   */
  async ready() {
    if (typeof process.send !== 'function') {
      throw new Error('Can not send the "ready" signal to z1 because process.send() is not defined.')
    }

    console.log('ready signal sent')
    const send = promisify(process.send, process)
    await send('ready')
  }

  /**
   * @typedef {Object} resurrectResult
   * @property {number} started - Number of started workers.
   */

  /**
   * Start the apps that were started before exit.
   * @param {boolean} immediate -- Resolve the returned promise immediately after the command has been transmitted.
   * @param {Promise.<resurrectResult>}
   */
  async resurrect(immediate = false) {
    this._impossibleInZ1()

    return this._connectAndSend({
      name: 'resurrect',
      immediate
    })
  }

  /**
   * @typedef {Object} appOptions
   * @property {string} [name] - The name of the app.
   * @property {number[]} [ports] - The prots that yoru app listens to.
   * @property {number} [workers] - The number of workers to start for your app. (default: number of CPUs)
   * @property {string} [output] - A directory for the log files. (default: ~/.z1/<appname>)
   */

  /**
   * @typedef {Object} startResult
   * @property {string} app - The name of the app.
   * @property {string} dir - The directory of the app.
   * @property {number} started - The number of started workers.
   * @property {number[]} ports - The ports that your app listens to.
   */

  /**
   * Start the app in the given directory.
   * @param {string} dir - Directory of the app.
   * @param {string[]} [args] - Arguments for the app.
   * @param {appOptions} [opt] - Options that overwrite the ones from the package.json.
   * @param {{string: string}} [env] - Environment variables for the app.
   * @param {boolean} [immediate] - Resolve the returned promise immediately after the command has been transmitted.
   * @returns {Promise.<startResult>}
   */
  async start(dir, args = [], opt = {}, env = {}, immediate = false) {
    const envi = Object.assign({}, process.env, env)
    return this._connectAndSend({
      name: 'start',
      dir: path.resolve(dir || ''),
      args,
      opt,
      env: envi,
      immediate
    })
  }

  /**
   * @typedef {Object} killOptions
   * @property {string} [signal] - The kill signal for the workers.
   * @property {number} [timeout] - The time (in ms) until the workers get force-killed.
   */

  /**
   * @typedef {Object} stopResult
   * @property {string} app - The name of the app.
   * @property {number} killed - The number of killed workers.
   */

  /**
   * Stop all workers of an app.
   * @param {string} app - The name of th app.
   * @param {killOptions} [opt] - Options for the command.
   * @param {boolean} [immediateResolve] - Resolve the returned promise immediately after the command has been transmitted.
   * @returns {Promise.<stopResult>}
   */
  async stop(app, opt = {}, immediate = false) {
    opt.timeout = translateInfinity(opt.timeout)
    return this._connectAndSend({
      name: 'stop',
      app,
      opt,
      immediate
    })
  }

  /**
   * @typedef {Object} restartResult
   * @property {string} app - The name of the app.
   * @property {string} dir - The directory of the app.
   * @property {number} started - The number of started workers.
   * @property {number} killed - The number of killed workers
   * @property {number[]} ports - The ports that your app listens to.
   */

  /**
   * Restart an app.
   * @param {string} app - The name of the app.
   * @param {killOptions} [opt] - Options for the command.
   * @param {boolean} [immediate] - Resolve the returned promise immediately after the command has been transmitted.
   * @returns {Promise.<restartResult>}
   */
  async restart(app, opt = {}, immediate = false) {
    opt.timeout = translateInfinity(opt.timeout)
    return this._connectAndSend({
      name: 'restart',
      app,
      opt,
      immediate
    })
  }

  /**
   * @typedef {Object} restartAllResult
   * @property {number} started - The number of started workers.
   * @property {number} killed - The number of killed workers
   */

  /**
   * Restart all apps.
   * @param {killOptions} [opt] - Options for the command.
   * @param {boolean} [immediate] - Resolve the returned promise immediately after the command has been transmitted.
   * @returns {Promise.<restartAllResult>}
   */
  async restartAll(opt = {}, immediate = false) {
    opt.timeout = translateInfinity(opt.timeout)
    return this._connectAndSend({
      name: 'restart-all',
      opt,
      immediate
    })
  }

  /**
   * @typedef {Object} infoResult
   * @property {string} name - The name of the app.
   * @property {string} dir - Directory of the app.
   * @property {number[]} ports - Ports that the app uses.
   * @property {number} pending - Number of pending workers.
   * @property {number} available - Number of available workers.
   * @property {number} killed - Number of killed workers.
   * @property {number} reviveCount - Shows how often the app has been revived.
   */

  /**
   * Get detailed information about an app.
   * @param {string} app - The name of the app.
   * @returns {Promise.<infoResult>}
   */
  async info(app) {
    return this._connectAndSend({
      name: 'info',
      app
    })
  }

  /**
   * @typedef {Object} listAppStats
   * @property {string} dir - Directory of the app.
   * @property {number[]} ports - Ports that the app uses.
   * @property {number} pending - Number of pending workers.
   * @property {number} available - Number of available workers.
   * @property {number} killed - Number of killed workers.
   */

  /**
   * @typedef {Object} listResult
   * @property {boolean} isResurrectable - Is true if the resurrect command can be used.
   * @property {{string: listAppStats}} stats - Statistics for each app.
   */

  /**
   * Get a list of all running apps.
   * @returns {Promise.<listResult>}
   */
  async list() {
    return this._connectAndSend({
      name: 'list'
    })
  }

  /**
   * Stop the z1 daemon.
   * @returns {Promise.<void>}
   */
  async exit() {
    await this._connectAndSend({
      name: 'exit'
    })

    await this._waitForDisconnect()
  }

  /**
   * Upgrade the z1 daemon to a new version. Do not call this in a child process of z1!
   * @returns {Promise.<void>}
   */
  async upgrade() {
    this._impossibleInZ1()

    await this.exit()
    await this.resurrect()
  }

  /**
   * Throws an error if called within a subprocess/worker of z1.
   * @returns {void}
   */
  _impossibleInZ1() {
    if (process.env.APPNAME && this.ready) {
      throw new Error('It is impossible to use this operation within apps that are managed with z1')
    }
  }

  /**
   * Returns a promise that resolves when the ping command was successful.
   * @returns {Promise.<void>}
   */
  async _ping() {
    await this._send({
      name: 'ping'
    })
  }

  /**
   * Returns a promise that resolves when the daemon is not available anymore.
   * @returns {Promise.<void>}
   */
  async _waitForDisconnect() {
    while (1) {
      try {
        await this._ping()
        await xTime(100)
      } catch (err) {
        if (err.code === 'ECONNREFUSED' || err.code === 'ENOENT') {
          break
        }
        throw err
      }
    }
  }

  /**
   * Returns a promise that resolves as soon as the daemon is available.
   * @returns {Promise.<void>}
   */
  async _waitForConnection() {
    while (1) {
      try {
        await this._ping()
        return
      } catch (err) {
        if (err.code === 'ECONNREFUSED' || err.code === 'ENOENT') {
          await xTime(100)
          continue
        }
        throw err
      }
    }
  }

  /**
   * Sends a command to the server.
   * @param {Object} object - An object representing the command.
   * @returns {Promise.<*>} - The result of the command.
   */
  async _send(object) {
    return new Promise((resolve, reject) => {
      const socket = net.connect(this.socketFile, () => {
        socket.end(JSON.stringify(object))

        const decoder = new StringDecoder()
        const message = []

        socket.once('data', chunk => {
          message.push(decoder.write(chunk))
        })

        socket.once('end', () => {
          message.push(decoder.end())

          try {
            let obj = JSON.parse(message.join(''))
            if (obj.error) {
              const err = new Error(obj.error.message)
              err.stack = obj.error.stack
              if (obj.error.code) {
                err.code = obj.error.code
              }
              reject(err)
            } else {
              resolve(obj.data)
            }
          } catch (err) {
            reject(err)
          }
        })
      })

      socket.on('error', reject)
    })
  }

  /**
   * Sends a command to the daemon. It starts the daemon if it is not running.
   * @param {Object} object - An object representing the command.
   * @returns {Promise.<*>} - The result of the command.
   */
  async _connectAndSend(object) {
    await this._connect()
    return this._send(object)
  }

  /**
   * Tries to connect to the daemon. It starts the daemon if it is not running.
   * @returns {Promise.<void>}
   */
  async _connect() {
    try {
      await this._ping()
      return
    } catch (err) {
      if (err.code !== 'ECONNREFUSED' && err.code !== 'ENOENT') {
        throw err
      }
    }

    try {
      fs.unlinkSync(this.socketFile)
    } catch (err) {
      if (err.code !== 'ENOENT') {
        throw err
      }
    }

    await this._startDaemon()
  }

  /**
   * Start the daemon.
   * @returns {Promise.<void>} - Returns a promise that resolves after the daemon is started.
   */
  async _startDaemon() {
    const start = new Promise((resolve, reject) => {
      const z1Path = path.join(__dirname, '..', '..')
      const file = path.join(z1Path, 'daemon', 'main.js')
      const node = process.argv[0]

      const p = cp.spawn(node, [file], {
        stdio: 'ignore',
        detached: true
      })

      p.once('error', reject)

      p.once('exit', code => {
        reject(new Error('daemon exited with code:', code))
      })

      p.unref()
    })

    await Promise.race([start, this._waitForConnection()])
  }
}

/**
 * If the value equals infinity then "infinity" (string) is returned.
 * @param {string|number} value
 * @returns {string|number}
 */
function translateInfinity(value) {
  if (value && !isFinite(+value)) {
    return 'infinity'
  }
  return value
}

module.exports = Remote
<commit_msg>fix JSDoc @returns of Remote#resurrect()<commit_after>const xTime = require('x-time')
const net = require('net')
const fs = require('fs')
const cp = require('child_process')
const path = require('path')
const promisify = require('smart-promisify')
const StringDecoder = require('string_decoder').StringDecoder

/**
 * A class representing a set of commands to control z1.
 * @class
 */
class Remote {
  /**
   * Create a new Remote instance.
   * @param {string} socketFile - Path to the socket file of the z1 daemon.
   */
  constructor(socketFile) {
    /** @type {string} */
    this.socketFile = socketFile
  }

  /**
   * Sends the "ready" signal to the z1 daemon.
   * @returns {Promise.<void>}
   */
  async ready() {
    if (typeof process.send !== 'function') {
      throw new Error('Can not send the "ready" signal to z1 because process.send() is not defined.')
    }

    console.log('ready signal sent')
    const send = promisify(process.send, process)
    await send('ready')
  }

  /**
   * @typedef {Object} resurrectResult
   * @property {number} started - Number of started workers.
   */

  /**
   * Start the apps that were started before exit.
   * @param {boolean} [immediate] -- Resolve the returned promise immediately after the command has been transmitted.
   * @returns {Promise.<resurrectResult>}
   */
  async resurrect(immediate = false) {
    this._impossibleInZ1()

    return this._connectAndSend({
      name: 'resurrect',
      immediate
    })
  }

  /**
   * @typedef {Object} appOptions
   * @property {string} [name] - The name of the app.
   * @property {number[]} [ports] - The prots that yoru app listens to.
   * @property {number} [workers] - The number of workers to start for your app. (default: number of CPUs)
   * @property {string} [output] - A directory for the log files. (default: ~/.z1/<appname>)
   */

  /**
   * @typedef {Object} startResult
   * @property {string} app - The name of the app.
   * @property {string} dir - The directory of the app.
   * @property {number} started - The number of started workers.
   * @property {number[]} ports - The ports that your app listens to.
   */

  /**
   * Start the app in the given directory.
   * @param {string} dir - Directory of the app.
   * @param {string[]} [args] - Arguments for the app.
   * @param {appOptions} [opt] - Options that overwrite the ones from the package.json.
   * @param {{string: string}} [env] - Environment variables for the app.
   * @param {boolean} [immediate] - Resolve the returned promise immediately after the command has been transmitted.
   * @returns {Promise.<startResult>}
   */
  async start(dir, args = [], opt = {}, env = {}, immediate = false) {
    const envi = Object.assign({}, process.env, env)
    return this._connectAndSend({
      name: 'start',
      dir: path.resolve(dir || ''),
      args,
      opt,
      env: envi,
      immediate
    })
  }

  /**
   * @typedef {Object} killOptions
   * @property {string} [signal] - The kill signal for the workers.
   * @property {number} [timeout] - The time (in ms) until the workers get force-killed.
   */

  /**
   * @typedef {Object} stopResult
   * @property {string} app - The name of the app.
   * @property {number} killed - The number of killed workers.
   */

  /**
   * Stop all workers of an app.
   * @param {string} app - The name of th app.
   * @param {killOptions} [opt] - Options for the command.
   * @param {boolean} [immediateResolve] - Resolve the returned promise immediately after the command has been transmitted.
   * @returns {Promise.<stopResult>}
   */
  async stop(app, opt = {}, immediate = false) {
    opt.timeout = translateInfinity(opt.timeout)
    return this._connectAndSend({
      name: 'stop',
      app,
      opt,
      immediate
    })
  }

  /**
   * @typedef {Object} restartResult
   * @property {string} app - The name of the app.
   * @property {string} dir - The directory of the app.
   * @property {number} started - The number of started workers.
   * @property {number} killed - The number of killed workers
   * @property {number[]} ports - The ports that your app listens to.
   */

  /**
   * Restart an app.
   * @param {string} app - The name of the app.
   * @param {killOptions} [opt] - Options for the command.
   * @param {boolean} [immediate] - Resolve the returned promise immediately after the command has been transmitted.
   * @returns {Promise.<restartResult>}
   */
  async restart(app, opt = {}, immediate = false) {
    opt.timeout = translateInfinity(opt.timeout)
    return this._connectAndSend({
      name: 'restart',
      app,
      opt,
      immediate
    })
  }

  /**
   * @typedef {Object} restartAllResult
   * @property {number} started - The number of started workers.
   * @property {number} killed - The number of killed workers
   */

  /**
   * Restart all apps.
   * @param {killOptions} [opt] - Options for the command.
   * @param {boolean} [immediate] - Resolve the returned promise immediately after the command has been transmitted.
   * @returns {Promise.<restartAllResult>}
   */
  async restartAll(opt = {}, immediate = false) {
    opt.timeout = translateInfinity(opt.timeout)
    return this._connectAndSend({
      name: 'restart-all',
      opt,
      immediate
    })
  }

  /**
   * @typedef {Object} infoResult
   * @property {string} name - The name of the app.
   * @property {string} dir - Directory of the app.
   * @property {number[]} ports - Ports that the app uses.
   * @property {number} pending - Number of pending workers.
   * @property {number} available - Number of available workers.
   * @property {number} killed - Number of killed workers.
   * @property {number} reviveCount - Shows how often the app has been revived.
   */

  /**
   * Get detailed information about an app.
   * @param {string} app - The name of the app.
   * @returns {Promise.<infoResult>}
   */
  async info(app) {
    return this._connectAndSend({
      name: 'info',
      app
    })
  }

  /**
   * @typedef {Object} listAppStats
   * @property {string} dir - Directory of the app.
   * @property {number[]} ports - Ports that the app uses.
   * @property {number} pending - Number of pending workers.
   * @property {number} available - Number of available workers.
   * @property {number} killed - Number of killed workers.
   */

  /**
   * @typedef {Object} listResult
   * @property {boolean} isResurrectable - Is true if the resurrect command can be used.
   * @property {{string: listAppStats}} stats - Statistics for each app.
   */

  /**
   * Get a list of all running apps.
   * @returns {Promise.<listResult>}
   */
  async list() {
    return this._connectAndSend({
      name: 'list'
    })
  }

  /**
   * Stop the z1 daemon.
   * @returns {Promise.<void>}
   */
  async exit() {
    await this._connectAndSend({
      name: 'exit'
    })

    await this._waitForDisconnect()
  }

  /**
   * Upgrade the z1 daemon to a new version. Do not call this in a child process of z1!
   * @returns {Promise.<void>}
   */
  async upgrade() {
    this._impossibleInZ1()

    await this.exit()
    await this.resurrect()
  }

  /**
   * Throws an error if called within a subprocess/worker of z1.
   * @returns {void}
   */
  _impossibleInZ1() {
    if (process.env.APPNAME && this.ready) {
      throw new Error('It is impossible to use this operation within apps that are managed with z1')
    }
  }

  /**
   * Returns a promise that resolves when the ping command was successful.
   * @returns {Promise.<void>}
   */
  async _ping() {
    await this._send({
      name: 'ping'
    })
  }

  /**
   * Returns a promise that resolves when the daemon is not available anymore.
   * @returns {Promise.<void>}
   */
  async _waitForDisconnect() {
    while (1) {
      try {
        await this._ping()
        await xTime(100)
      } catch (err) {
        if (err.code === 'ECONNREFUSED' || err.code === 'ENOENT') {
          break
        }
        throw err
      }
    }
  }

  /**
   * Returns a promise that resolves as soon as the daemon is available.
   * @returns {Promise.<void>}
   */
  async _waitForConnection() {
    while (1) {
      try {
        await this._ping()
        return
      } catch (err) {
        if (err.code === 'ECONNREFUSED' || err.code === 'ENOENT') {
          await xTime(100)
          continue
        }
        throw err
      }
    }
  }

  /**
   * Sends a command to the server.
   * @param {Object} object - An object representing the command.
   * @returns {Promise.<*>} - The result of the command.
   */
  async _send(object) {
    return new Promise((resolve, reject) => {
      const socket = net.connect(this.socketFile, () => {
        socket.end(JSON.stringify(object))

        const decoder = new StringDecoder()
        const message = []

        socket.once('data', chunk => {
          message.push(decoder.write(chunk))
        })

        socket.once('end', () => {
          message.push(decoder.end())

          try {
            let obj = JSON.parse(message.join(''))
            if (obj.error) {
              const err = new Error(obj.error.message)
              err.stack = obj.error.stack
              if (obj.error.code) {
                err.code = obj.error.code
              }
              reject(err)
            } else {
              resolve(obj.data)
            }
          } catch (err) {
            reject(err)
          }
        })
      })

      socket.on('error', reject)
    })
  }

  /**
   * Sends a command to the daemon. It starts the daemon if it is not running.
   * @param {Object} object - An object representing the command.
   * @returns {Promise.<*>} - The result of the command.
   */
  async _connectAndSend(object) {
    await this._connect()
    return this._send(object)
  }

  /**
   * Tries to connect to the daemon. It starts the daemon if it is not running.
   * @returns {Promise.<void>}
   */
  async _connect() {
    try {
      await this._ping()
      return
    } catch (err) {
      if (err.code !== 'ECONNREFUSED' && err.code !== 'ENOENT') {
        throw err
      }
    }

    try {
      fs.unlinkSync(this.socketFile)
    } catch (err) {
      if (err.code !== 'ENOENT') {
        throw err
      }
    }

    await this._startDaemon()
  }

  /**
   * Start the daemon.
   * @returns {Promise.<void>} - Returns a promise that resolves after the daemon is started.
   */
  async _startDaemon() {
    const start = new Promise((resolve, reject) => {
      const z1Path = path.join(__dirname, '..', '..')
      const file = path.join(z1Path, 'daemon', 'main.js')
      const node = process.argv[0]

      const p = cp.spawn(node, [file], {
        stdio: 'ignore',
        detached: true
      })

      p.once('error', reject)

      p.once('exit', code => {
        reject(new Error('daemon exited with code:', code))
      })

      p.unref()
    })

    await Promise.race([start, this._waitForConnection()])
  }
}

/**
 * If the value equals infinity then "infinity" (string) is returned.
 * @param {string|number} value
 * @returns {string|number}
 */
function translateInfinity(value) {
  if (value && !isFinite(+value)) {
    return 'infinity'
  }
  return value
}

module.exports = Remote
<|endoftext|>


<commit_before>
//
// wrap a function with setTimeout but let it be called like normal.
//

var delay = exports.delay = function (laters, time) {
  time = time || 0
  return function () {
    var args = [].slice.call(arguments)
    return setTimeout(function () {
      laters.apply(null, args)
    }, time)
  }
}

//
// recursively compose async function.
// the next function becomes the callback of the first
// otherwise, the next function is called with the args of the first callback
//
// nothing special is done to the error parameter
//

exports.compose = compose

function compose () {
  var funx = [].slice.call(arguments)
  if(funx.length <= 1)
    return funx[0]
  var f1 = funx.shift()
  var f2 = funx.shift()

  funx.unshift(function () {
    var args = [].slice.call(arguments)
    var callback = args.pop()
    args.push(function () {
      var args = [].slice.call(arguments)
      args.push(callback)
      f2.apply(this, args)
    })
    f1.apply(this, args)
  })
  return compose.apply(null, funx)
}

exports.fallthrough = fallthrough

function fallthrough () {
  var args = [].slice.call(arguments)
    , callback = args.pop()
  callback.apply(this, args)
}

exports.tryCatchPass = tryCatchPass

function tryCatchPass (_try,_catch,_pass) {
  //make _try safe
  return compose(safe(_try), function () {
    var args = [].slice.call(arguments)
      , next = args.pop()
      , err  = args.shift()
    if(err && _catch)
      safe(_catch).call(this, err, next)
    else if (!err && _pass)
      safe(_pass).apply(null, args.concat(next))
    else
      next.apply(this, [err].concat(args))
  })

}

exports.safe = safe

function safe (funx) {
  return function () {
    var _callback = arguments[arguments.length - 1]
      , n = 0
      , callback =
    arguments[arguments.length - 1] = function () {
      var args = [].slice.call(arguments)
      if(!n++)
        _callback.apply(this,args)
      else
        console.log('callback function ' + _callback.name + ' called:' + n + ' times')
    }
    try {
      funx.apply(null, arguments)
    } catch (err) {
      callback(err)
    }
  }
}

exports.toAsync = toAsync

function toAsync (func, a, b) {
  return function () {
    var args = [].slice.call(arguments)
      , callback = args.pop()
      , r
    try {
      r = func.apply(this, args)
    } catch (err) {
      return callback (err)
    }
    callback (null, r)
  }
}
<commit_msg>async.fallthrough now adds a null error parameter<commit_after>
//
// wrap a function with setTimeout but let it be called like normal.
//

var delay = exports.delay = function (laters, time) {
  time = time || 0
  return function () {
    var args = [].slice.call(arguments)
    return setTimeout(function () {
      laters.apply(null, args)
    }, time)
  }
}

//
// recursively compose async function.
// the next function becomes the callback of the first
// otherwise, the next function is called with the args of the first callback
//
// nothing special is done to the error parameter
//

exports.compose = compose

function compose () {
  var funx = [].slice.call(arguments)
  if(funx.length <= 1)
    return funx[0]
  var f1 = funx.shift()
  var f2 = funx.shift()

  funx.unshift(function () {
    var args = [].slice.call(arguments)
    var callback = args.pop()
    args.push(function () {
      var args = [].slice.call(arguments)
      args.push(callback)
      f2.apply(this, args)
    })
    f1.apply(this, args)
  })
  return compose.apply(null, funx)
}

exports.fallthrough = fallthrough

function fallthrough () {
  var args = [].slice.call(arguments)
    , callback = args.pop()
  args.unshift(null)
  callback.apply(this, args)
}

exports.tryCatchPass = tryCatchPass

function tryCatchPass (_try,_catch,_pass) {
  //make _try safe
  return compose(safe(_try), function () {
    var args = [].slice.call(arguments)
      , next = args.pop()
      , err  = args.shift()
    if(err && _catch)
      safe(_catch).call(this, err, next)
    else if (!err && _pass)
      safe(_pass).apply(null, args.concat(next))
    else
      next.apply(this, [err].concat(args))
  })

}

exports.safe = safe

function safe (funx) {
  return function () {
    var _callback = arguments[arguments.length - 1]
      , n = 0
      , callback =
    arguments[arguments.length - 1] = function () {
      var args = [].slice.call(arguments)
      if(!n++)
        _callback.apply(this,args)
      else
        console.log('callback function ' + _callback.name + ' called:' + n + ' times')
    }
    try {
      funx.apply(null, arguments)
    } catch (err) {
      callback(err)
    }
  }
}

exports.toAsync = toAsync

function toAsync (func, a, b) {
  return function () {
    var args = [].slice.call(arguments)
      , callback = args.pop()
      , r
    try {
      r = func.apply(this, args)
    } catch (err) {
      return callback (err)
    }
    callback (null, r)
  }
}
<|endoftext|>


<commit_before>//---------------------------
//  Simple Async performance
//---------------------------

// function now(){
//   return 4;
// }
// function later(){
//   answer = answer * 2
//   console.log("the meaning of life:", answer)
// }
// var answer = now();
// setTimeout(later,1000)

// // unit test
// var Bob = require('./bob.js');
// describe("Bob", function() {
//   var bob = new Bob();
//   it("stating something", function() {
//     var result = bob.hey('Tom-ay-to, tom-aaaah-to.');
//     expect(result).toEqual('Whatever.');
//   });
// });

//---------------------------
//  Simple callback
//---------------------------

// var simpleOne = function(cb){
//   console.log("here")

//   setTimeout(function(){
//     cb();
//   }, 1000)
// }

// simpleOne(function(){
//   console.log("your simple cb!")
// })

//---------------------------
//  Simple Async performance 2
//---------------------------

var doSomething = function(callback){
  console.log("1");

  setTimeout(function(){
    callback();
  }, Math.floor((Math.random() *10 ) + 1) * 1000);
};

var doSomething2 = function(callback){
  console.log("2");

  setTimeout(function(){
    callback();
  }, Math.floor((Math.random() *10 ) + 1) * 1000);
};

var doSomething3 = function(){
  console.log("3");
};

// in ruby world we would do this
// doSomething();
// doSomething2();
// doSomething3();

// one way to solve this is callback hell

doSomething(function(){
  doSomething2(function(){
   doSomething3();
  });
});

// to solve this we will get into the deferred
// consits of two constructs deferred and promise
// deferred manages the ability to resolve/reject a step

//promise will manage our array of calllbacks
// allows to chain methods together (using.then)

<commit_msg>add more examples to my js ninja practice<commit_after>//---------------------------
//  Simple Async performance
//---------------------------

// function now(){
//   return 4;
// }
// function later(){
//   answer = answer * 2
//   console.log("the meaning of life:", answer)
// }
// var answer = now();
// setTimeout(later,1000)

//---------------------------
//  Simple unit test
//---------------------------
var Bob = require('./bob.js');
describe("Bob", function() {
  var bob = new Bob();
  it("stating something", function() {
    var result = bob.hey('Tom-ay-to, tom-aaaah-to.');
    expect(result).toEqual('Whatever.');
  });
});

//---------------------------
//  Simple callback
//---------------------------

var simpleOne = function(cb){
  console.log("here")

  setTimeout(function(){
    cb();
  }, 1000)
}

simpleOne(function(){
  console.log("your simple cb!")
})

//---------------------------
//  Simple Async performance 2
//---------------------------

var doSomething = function(callback){
  console.log("1");

  setTimeout(function(){
    callback();
  }, Math.floor((Math.random() *10 ) + 1) * 1000);
};

var doSomething2 = function(callback){
  console.log("2");

  setTimeout(function(){
    callback();
  }, Math.floor((Math.random() *10 ) + 1) * 1000);
};

var doSomething3 = function(){
  console.log("3");
};

// // in ruby world we would do this
// // doSomething();
// // doSomething2();
// // doSomething3();

// // one way to solve this is callback hell

doSomething(function(){
  doSomething2(function(){
   doSomething3();
  });
});

// to solve this we will get into the deferred
// consits of two constructs deferred and promise
// deferred manages the ability to resolve/reject a step

//promise will manage our array of calllbacks
// allows to chain methods together (using.then)

//---------------------------
//  Promises 2 as of es6
//---------------------------

function getData(d){
  return new Promise(function(resolve,reject){
    setTimeout(function(){resolve(d); },1000)
  });
}

var x;

getData(10)
.then(function(num1){
  x = 1 + num1;
  return getData(30);
})
.then(function(num2){
  var y = 1 + num2;
  return getData("meaning of life" + (x+y));
})
.then(function(answer){
  console.log(answer)
});<|endoftext|>


<commit_before>var _ = require('underscore');

/********************************************************************************/
/* Static state of task                                                         */
/********************************************************************************/
var WAITING = 0;
var WAITING_FOR_DEPENDENCY = 1;
var RUNNING = 2;
var DONE = 3;
var FAIL = 4;

/********************************************************************************/
/* Task                                                                         */
/********************************************************************************/

var Task = function(parentStack, id, fct) {
    var self = this;
    this.parentStack = parentStack;
    this.id = id;
    this.alias = null;
    this.fct = fct;
    this.args = [];
    this.dependencies = [];
    this.status = WAITING;
};

Task.prototype.setCallback = function(callback) {
    this.callback = callback;
};

Task.prototype.execute = function() {
    var self = this;
    if (!this.checkDependencies()) {
        this.status = WAITING_FOR_DEPENDENCY;
        return;
    }
    this.status = RUNNING;

    this.args.forEach(function(arg, index) {
        if (arg instanceof DefArg) {
            self.args[index] = arg.resolve(self);
        }
    });
    if (this.status === RUNNING) {
        this.fct.apply(null, this.args);
    }
};

Task.prototype.fail = function(err) {
    this.status = FAIL;
    this.fct.apply(null, [err, null]);
};

Task.prototype.checkDependencies = function() {
    for (key in this.dependencies) {
        var id = this.dependencies[key];

        if (_.isString(id)) {
            id = this.parentStack.aliasMap[id];
        }

        if (_.isUndefined(this.parentStack.results[id])) {
            return false;
        }
    }
    return true;
};

/********************************************************************************/
/* Deferred Argument                                                            */
/********************************************************************************/

var DefArg = function(type, val) {
    this.type = type;
    this.value = val;
};

DefArg.prototype.resolve = function(task) {
    switch (this.type) {
        case 'order':
            if (this.value >= 0) {
                if (_.isUndefined(task.parentStack.results[this.value])) {
                    task.status = WAITING_FOR_DEPENDENCY;
                    task.dependencies.push(this.value);
                    return this;
                }
                else {
                    return task.parentStack.results[this.value];
                }
            }
            else if (this.value < 0) {
                if (_.isUndefined(task.parentStack.results[task.id + this.value])) {
                    task.status = WAITING_FOR_DEPENDENCY;
                    task.dependencies.push(task.id + this.value);
                    return this;
                }
                else {
                    return task.parentStack.results[task.id + this.value];
                }
            }
            break;

        case 'alias':
            if (this.value === 'all') {
                return task.parentStack.results;
            }
            else {
                return task.parentStack.results[task.parentStack.aliasMap[this.value]];
            }
            break;

        case 'callback':
            return task.callback;
            break;

        case 'item':
            return task.item;
            break;
    }
};

/********************************************************************************/
/* progressive                                                                  */
/********************************************************************************/
var Progressive = function(start, step) {
    this.step = step || 1;
    this.last = (_.isUndefined(start) ? 1 : start) - this.step;
    this.stack = [];
};

Progressive.prototype.push = function(order, fct) {
    var self = this;
    var task = {order: order, fct: fct};
    this.stack.push(task);

    return function(){
        task.args = _.toArray(arguments);
        var reCheck = true;
        while (reCheck) {
            reCheck = false;
            for(i in self.stack){
                var queued = self.stack[i];
                if (queued.order === (self.last + self.step)) {
                    if (!_.isUndefined(queued.args)) {
                        queued.fct.apply(null, queued.args);
                        self.stack.slice(i, 1);
                        self.last += self.step;
                        reCheck = true;
                    }
                    else {
                        reCheck = false;
                        break;
                    }
                }
            }
        }
    };
};

/********************************************************************************/
/* Fifo                                                                         */
/********************************************************************************/
var Fifo = function() {
    this.stack = [];
};
Fifo.prototype.push = function(fct) {
    var self = this;
    var task = {};
    task.fct = fct;
    this.stack.push(task);
    return function() {
        task.args = _.toArray(arguments);
        if (self.stack[0] === task) {
            while (self.stack.length && !_.isUndefined(self.stack[0].args)) {
                var callback = self.stack.shift();
                callback.fct.apply(null, callback.args);
            }
        }
    };
};

/********************************************************************************/
/* Asynk                                                                        */
/********************************************************************************/

var Asynk = function() {
    var self = this;
    this.tasks = [];
    this.aliasMap = [];
    this.results = [];
    this.currentTasks = [];
};

Asynk.prototype.add = function(fct) {
    var newId = this.tasks.length;
    this.tasks[newId] = new Task(this, newId, fct);
    this.currentTasks = [newId];
    return this;
};

Asynk.prototype.each = function(datas, fct) {
    var self = this;
    datas.forEach(function(data) {
        var newId = self.tasks.length;
        self.tasks[newId] = new Task(self, newId, fct);
        self.tasks[newId].item = data;
        self.currentTasks.push(newId);
    });
    return this;
};

Asynk.prototype.args = function() {
    args = _.toArray(arguments);
    var self = this;
    this.currentTasks.forEach(function(currentTask) {
        self.tasks[currentTask].args = _.clone(args);
    });
    return this;
};

Asynk.prototype.require = function(dependency) {
    var self = this;
    this.currentTasks.forEach(function(currentTask) {
        var current = self.tasks[currentTask];
        current.dependencies.push(dependency);
    });
    return this;
};

Asynk.prototype.alias = function(alias) {
    if (_.isString(alias)) {
        var self = this;
        this.currentTasks.forEach(function(currentTask, index) {
            if (self.currentTasks.length > 1) {
                alias += index;
            }
            self.tasks[currentTask].alias = alias;
            self.aliasMap[alias] = currentTask;
        });
    }
    return this;
};

Asynk.prototype.serie = function(endcall, endcallArgs) {
    var self = this;
    var endTask = new Task(this, 'end', endcall);
    endTask.args = endcallArgs || this.results;
    var cb = function(err, data) {
        if (!err) {
            self.results.push(data);
            self.next();
        }
        else {
            endTask.fail(err);
        }
    };
    this.next = function() {
        var current = self.tasks.shift();
        if (current) {
            current.setCallback(cb);
            current.execute();
        }
        else {
            endTask.execute();
        }
    };
    this.next();
    return this;
};

Asynk.prototype.parallel = function(endcall, endcallArgs) {
    var self = this;
    var endTask = new Task(this, 'end', endcall);
    endTask.args = endcallArgs || this.results;

    var count = 0;
    var todo = self.tasks.length;
    var cb = function(task, err, data) {
        task.status = DONE;
        if (!err) {
            self.results[task.id] = data;
            count++;
            if (count >= todo) {
                endTask.execute();
            }
            else {
                self.tasks.forEach(function(task) {
                    if (task.status === WAITING_FOR_DEPENDENCY) {
                        task.execute();
                    }
                });
            }
        }
        else {
            endTask.fail(err);
        }
    };

    this.tasks.forEach(function(task) {
        task.setCallback(function(err, data) {
            cb(task, err, data);
        });
    });

    this.tasks.forEach(function(task) {
        task.execute();
    });

    return this;
};

Asynk.prototype.parallelLimited = function(limit, endcall, endcallArgs) {
    var self = this;
    var endTask = new Task(this, 'end', endcall);
    endTask.args = endcallArgs || this.results;

    var count = 0;
    var todo = self.tasks.length;
    var cb = function(task, err, data) {
        task.status = 'done';
        if (!err) {
            self.results[task.id] = data;
            count++;
            if (count >= todo) {
                endTask.execute();
            }
            else {
                self.tasks.forEach(function(task) {
                    var stats = _.countBy(self.tasks, function(task) {
                        return task.status;
                    });
                    var running = stats[RUNNING] || 0;
                    if ((running < limit) && (task.status < RUNNING)) {
                        task.execute();
                    }
                });
            }
        }
        else {
            endTask.fail(err);
        }
    };

    this.tasks.forEach(function(task) {
        task.setCallback(function(err, data) {
            cb(task, err, data);
        });
    });

    this.tasks.forEach(function(task) {
        var stats = _.countBy(self.tasks, function(task) {
            return task.status;
        });
        var running = stats[RUNNING] || 0;
        if ((running < limit) && (task.status < RUNNING)) {
            task.execute();
        }
    });

    return this;
};
/*
 Asynk.prototype.getTask = function(id){
 if (_.isString(id)) {
 if (_.) {
 id = this.aliasMap[id];
 }
 }
 return this.tasks[id];
 }*/

module.exports = {
    add: function(fct) { return new Asynk().add(fct); },
    each: function(datas, fct) { return new Asynk().each(datas, fct); },
    callback: new DefArg('callback'),
    data: function(val) {
        if (_.isString(val)) {
            return new DefArg('alias', val);
        }
        else {
            return new DefArg('order', val);
        }
    },
    item: new DefArg('item'),
    fifo: function(){ return new Fifo(); },
    progressive: function(start,step){ return new Progressive(start,step); }
};

<commit_msg>correct each parallel with 0 task never finnish<commit_after>var _ = require('underscore');

/********************************************************************************/
/* Static state of task                                                         */
/********************************************************************************/
var WAITING = 0;
var WAITING_FOR_DEPENDENCY = 1;
var RUNNING = 2;
var DONE = 3;
var FAIL = 4;

/********************************************************************************/
/* Task                                                                         */
/********************************************************************************/

var Task = function(parentStack, id, fct) {
    var self = this;
    this.parentStack = parentStack;
    this.id = id;
    this.alias = null;
    this.fct = fct;
    this.args = [];
    this.dependencies = [];
    this.status = WAITING;
};

Task.prototype.setCallback = function(callback) {
    this.callback = callback;
};

Task.prototype.execute = function() {
    var self = this;
    if (!this.checkDependencies()) {
        this.status = WAITING_FOR_DEPENDENCY;
        return;
    }
    this.status = RUNNING;

    this.args.forEach(function(arg, index) {
        if (arg instanceof DefArg) {
            self.args[index] = arg.resolve(self);
        }
    });
    if (this.status === RUNNING) {
        this.fct.apply(null, this.args);
    }
};

Task.prototype.fail = function(err) {
    this.status = FAIL;
    this.fct.apply(null, [err, null]);
};

Task.prototype.checkDependencies = function() {
    for (key in this.dependencies) {
        var id = this.dependencies[key];

        if (_.isString(id)) {
            id = this.parentStack.aliasMap[id];
        }

        if (_.isUndefined(this.parentStack.results[id])) {
            return false;
        }
    }
    return true;
};

/********************************************************************************/
/* Deferred Argument                                                            */
/********************************************************************************/

var DefArg = function(type, val) {
    this.type = type;
    this.value = val;
};

DefArg.prototype.resolve = function(task) {
    switch (this.type) {
        case 'order':
            if (this.value >= 0) {
                if (_.isUndefined(task.parentStack.results[this.value])) {
                    task.status = WAITING_FOR_DEPENDENCY;
                    task.dependencies.push(this.value);
                    return this;
                }
                else {
                    return task.parentStack.results[this.value];
                }
            }
            else if (this.value < 0) {
                if (_.isUndefined(task.parentStack.results[task.id + this.value])) {
                    task.status = WAITING_FOR_DEPENDENCY;
                    task.dependencies.push(task.id + this.value);
                    return this;
                }
                else {
                    return task.parentStack.results[task.id + this.value];
                }
            }
            break;

        case 'alias':
            if (this.value === 'all') {
                return task.parentStack.results;
            }
            else {
                return task.parentStack.results[task.parentStack.aliasMap[this.value]];
            }
            break;

        case 'callback':
            return task.callback;
            break;

        case 'item':
            return task.item;
            break;
    }
};

/********************************************************************************/
/* progressive                                                                  */
/********************************************************************************/
var Progressive = function(start, step) {
    this.step = step || 1;
    this.last = (_.isUndefined(start) ? 1 : start) - this.step;
    this.stack = [];
};

Progressive.prototype.push = function(order, fct) {
    var self = this;
    var task = {order: order, fct: fct};
    this.stack.push(task);

    return function(){
        task.args = _.toArray(arguments);
        var reCheck = true;
        while (reCheck) {
            reCheck = false;
            for(i in self.stack){
                var queued = self.stack[i];
                if (queued.order === (self.last + self.step)) {
                    if (!_.isUndefined(queued.args)) {
                        queued.fct.apply(null, queued.args);
                        self.stack.slice(i, 1);
                        self.last += self.step;
                        reCheck = true;
                    }
                    else {
                        reCheck = false;
                        break;
                    }
                }
            }
        }
    };
};

/********************************************************************************/
/* Fifo                                                                         */
/********************************************************************************/
var Fifo = function() {
    this.stack = [];
};
Fifo.prototype.push = function(fct) {
    var self = this;
    var task = {};
    task.fct = fct;
    this.stack.push(task);
    return function() {
        task.args = _.toArray(arguments);
        if (self.stack[0] === task) {
            while (self.stack.length && !_.isUndefined(self.stack[0].args)) {
                var callback = self.stack.shift();
                callback.fct.apply(null, callback.args);
            }
        }
    };
};

/********************************************************************************/
/* Asynk                                                                        */
/********************************************************************************/

var Asynk = function() {
    var self = this;
    this.tasks = [];
    this.aliasMap = [];
    this.results = [];
    this.currentTasks = [];
};

Asynk.prototype.add = function(fct) {
    var newId = this.tasks.length;
    this.tasks[newId] = new Task(this, newId, fct);
    this.currentTasks = [newId];
    return this;
};

Asynk.prototype.each = function(datas, fct) {
    var self = this;
    datas.forEach(function(data) {
        var newId = self.tasks.length;
        self.tasks[newId] = new Task(self, newId, fct);
        self.tasks[newId].item = data;
        self.currentTasks.push(newId);
    });
    return this;
};

Asynk.prototype.args = function() {
    args = _.toArray(arguments);
    var self = this;
    this.currentTasks.forEach(function(currentTask) {
        self.tasks[currentTask].args = _.clone(args);
    });
    return this;
};

Asynk.prototype.require = function(dependency) {
    var self = this;
    this.currentTasks.forEach(function(currentTask) {
        var current = self.tasks[currentTask];
        current.dependencies.push(dependency);
    });
    return this;
};

Asynk.prototype.alias = function(alias) {
    if (_.isString(alias)) {
        var self = this;
        this.currentTasks.forEach(function(currentTask, index) {
            if (self.currentTasks.length > 1) {
                alias += index;
            }
            self.tasks[currentTask].alias = alias;
            self.aliasMap[alias] = currentTask;
        });
    }
    return this;
};

Asynk.prototype.serie = function(endcall, endcallArgs) {
    var self = this;
    var endTask = new Task(this, 'end', endcall);
    endTask.args = endcallArgs || this.results;
    var cb = function(err, data) {
        if (!err) {
            self.results.push(data);
            self.next();
        }
        else {
            endTask.fail(err);
        }
    };
    this.next = function() {
        var current = self.tasks.shift();
        if (current) {
            current.setCallback(cb);
            current.execute();
        }
        else {
            endTask.execute();
        }
    };
    this.next();
    return this;
};

Asynk.prototype.parallel = function(endcall, endcallArgs) {
    var self = this;
    var endTask = new Task(this, 'end', endcall);
    endTask.args = endcallArgs || this.results;

    var count = 0;
    var todo = self.tasks.length;
    var cb = function(task, err, data) {
        task.status = DONE;
        if (!err) {
            self.results[task.id] = data;
            count++;
            if (count >= todo) {
                endTask.execute();
            }
            else {
                self.tasks.forEach(function(task) {
                    if (task.status === WAITING_FOR_DEPENDENCY) {
                        task.execute();
                    }
                });
            }
        }
        else {
            endTask.fail(err);
        }
    };

    if (this.tasks.length === 0){
        endTask.execute();
        return this;
    }

    this.tasks.forEach(function(task) {
        task.setCallback(function(err, data) {
            cb(task, err, data);
        });
    });

    this.tasks.forEach(function(task) {
        task.execute();
    });

    return this;
};

Asynk.prototype.parallelLimited = function(limit, endcall, endcallArgs) {
    var self = this;
    var endTask = new Task(this, 'end', endcall);
    endTask.args = endcallArgs || this.results;

    var count = 0;
    var todo = self.tasks.length;
    var cb = function(task, err, data) {
        task.status = 'done';
        if (!err) {
            self.results[task.id] = data;
            count++;
            if (count >= todo) {
                endTask.execute();
            }
            else {
                self.tasks.forEach(function(task) {
                    var stats = _.countBy(self.tasks, function(task) {
                        return task.status;
                    });
                    var running = stats[RUNNING] || 0;
                    if ((running < limit) && (task.status < RUNNING)) {
                        task.execute();
                    }
                });
            }
        }
        else {
            endTask.fail(err);
        }
    };

    if (this.tasks.length === 0){
        endTask.execute();
        return this;
    }

    this.tasks.forEach(function(task) {
        task.setCallback(function(err, data) {
            cb(task, err, data);
        });
    });

    this.tasks.forEach(function(task) {
        var stats = _.countBy(self.tasks, function(task) {
            return task.status;
        });
        var running = stats[RUNNING] || 0;
        if ((running < limit) && (task.status < RUNNING)) {
            task.execute();
        }
    });

    return this;
};
/*
 Asynk.prototype.getTask = function(id){
 if (_.isString(id)) {
 if (_.) {
 id = this.aliasMap[id];
 }
 }
 return this.tasks[id];
 }*/

module.exports = {
    add: function(fct) { return new Asynk().add(fct); },
    each: function(datas, fct) { return new Asynk().each(datas, fct); },
    callback: new DefArg('callback'),
    data: function(val) {
        if (_.isString(val)) {
            return new DefArg('alias', val);
        }
        else {
            return new DefArg('order', val);
        }
    },
    item: new DefArg('item'),
    fifo: function(){ return new Fifo(); },
    progressive: function(start,step){ return new Progressive(start,step); }
};

<|endoftext|>


<commit_before>'use strict';

(function() {

  angular.module('ncsaas')
    .directive('visible', ['ENV', visible]);

  function visible(ENV) {
    return {
      restrict: 'A',
      scope: {
        excludeMode: "@"
      },
      link: function(scope, element, attrs) {
        var doRemove = false,
          features = attrs.visible.split(',');
        for (var i = 0; i < features.length; i++) {
          if ((ENV.toBeFeatures.indexOf(features[i].trim()) !== -1
              || (ENV.toBeFeatures.indexOf('resources') !== -1 && features[i].trim()) in ENV.resourcesTypes)
              && ENV.modeName !== attrs.excludeMode) {
            doRemove = true;
            break;
          }
        }
        if (!ENV.featuresVisible && doRemove) {
          element.remove();
        }
      }
    };
  }

})();
<commit_msg>Add deprecation notice for visible directive (WAL-91)<commit_after>'use strict';

(function() {

  angular.module('ncsaas')
    .directive('visible', ['ENV', visible]);

  // This directive is deprecated. Please use visible-if directive instead which parses expression.
  // For example:  becomes
  function visible(ENV) {
    return {
      restrict: 'A',
      scope: {
        excludeMode: "@"
      },
      link: function(scope, element, attrs) {
        var doRemove = false,
          features = attrs.visible.split(',');
        for (var i = 0; i < features.length; i++) {
          if ((ENV.toBeFeatures.indexOf(features[i].trim()) !== -1
              || (ENV.toBeFeatures.indexOf('resources') !== -1 && features[i].trim()) in ENV.resourcesTypes)
              && ENV.modeName !== attrs.excludeMode) {
            doRemove = true;
            break;
          }
        }
        if (!ENV.featuresVisible && doRemove) {
          element.remove();
        }
      }
    };
  }

})();
<|endoftext|>


<commit_before>(function () {
    'use strict';

    /**
     * Create an object witch the initial needed information from the UI5 availability check.
     * @returns {Object}
     */
    function createResponseToContentScript() {
        var responseToContentScript = Object.create(null);
        responseToContentScript.detail = Object.create(null);

        var responseToContentScriptBody = responseToContentScript.detail;

        if (window.sap) {

            responseToContentScriptBody.action = 'on-ui5-detected';
            responseToContentScriptBody.framework = Object.create(null);

            // Get minimal framework information
            try {
                responseToContentScriptBody.framework.version = sap.ui.getVersionInfo().version;
            } catch (e) {
                responseToContentScriptBody.framework.version = '';
            }
            try {
                responseToContentScriptBody.framework.name = sap.ui.getVersionInfo().gav.indexOf('openui5') !== -1 ? 'OpenUI5' : 'SAPUI5';
            } catch (e) {
                responseToContentScriptBody.framework.name = '';
            }

            // Check if the version is supported
            if (sap.ui.require) {
                responseToContentScriptBody.isVersionSupported = true;
            } else {
                responseToContentScriptBody.isVersionSupported = false;
            }

        } else {
            responseToContentScriptBody.action = 'on-ui5-not-detected';
        }

        return responseToContentScript;
    }

    // Send information to content script
    document.dispatchEvent(new CustomEvent('detect-ui5-content', createResponseToContentScript()));

    // Listens for event from injected script
    document.addEventListener('do-ui5-detection-injected', function () {
        document.dispatchEvent(new CustomEvent('detect-ui5-content', createResponseToContentScript()));
    }, false);
}());
<commit_msg>Update detectUI5.js<commit_after>(function () {
    'use strict';

    /**
     * Create an object witch the initial needed information from the UI5 availability check.
     * @returns {Object}
     */
    function createResponseToContentScript() {
        var responseToContentScript = Object.create(null);
        responseToContentScript.detail = Object.create(null);

        var responseToContentScriptBody = responseToContentScript.detail;

        if (window.sap && window.sap.ui) {

            responseToContentScriptBody.action = 'on-ui5-detected';
            responseToContentScriptBody.framework = Object.create(null);

            // Get minimal framework information
            try {
                responseToContentScriptBody.framework.version = sap.ui.getVersionInfo().version;
            } catch (e) {
                responseToContentScriptBody.framework.version = '';
            }
            try {
                responseToContentScriptBody.framework.name = sap.ui.getVersionInfo().gav.indexOf('openui5') !== -1 ? 'OpenUI5' : 'SAPUI5';
            } catch (e) {
                responseToContentScriptBody.framework.name = '';
            }

            // Check if the version is supported
            if (sap.ui.require) {
                responseToContentScriptBody.isVersionSupported = true;
            } else {
                responseToContentScriptBody.isVersionSupported = false;
            }

        } else {
            responseToContentScriptBody.action = 'on-ui5-not-detected';
        }

        return responseToContentScript;
    }

    // Send information to content script
    document.dispatchEvent(new CustomEvent('detect-ui5-content', createResponseToContentScript()));

    // Listens for event from injected script
    document.addEventListener('do-ui5-detection-injected', function () {
        document.dispatchEvent(new CustomEvent('detect-ui5-content', createResponseToContentScript()));
    }, false);
}());
<|endoftext|>