<commit_before>'use strict';

/** Load Node.js modules */
var fs = require('fs');

/** Load other modules */
var _ = require('lodash/lodash.js');

/** The minimal license/copyright template */
var licenseTemplate = [
  '/**',
  ' * @license',
  ' * Lo-Dash <%= lodash.VERSION %> lodash.com/license | Underscore.js <%= underscore.VERSION %> underscorejs.org/LICENSE',
  ' */'
].join('\n');

/*----------------------------------------------------------------------------*/

/**
 * Post-process a given minified Lo-Dash `source`, preparing it for
 * deployment.
 *
 * @param {string} source The source to process.
 * @returns {string} Returns the processed source.
 */
function postprocess(source) {
  // correct overly aggressive Closure Compiler advanced optimization
  source = source
    .replace(/\b(prototype\s*=\s*\{\s*valueOf\s*:\s*1)(\s*})/, '$1,y:1$2')
    .replace(/"\t"/g, '"\\t"')
    .replace(/"[^"]*?\\f[^"]*?"/g,
      '" \\t\\x0B\\f\\xa0\\ufeff' +
      '\\n\\r\\u2028\\u2029' +
      '\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000"'
    )
    .replace(/\bsupport\s*=\s*\{\s*\}\s*;\s*[!(]\s*function\s*\((?=\s*\))/, function(match) {
      return match + 'x_';
    })
    .replace(/(try\s*\{\s*[$\w]+\s*\.\s*nodeClass\s*=\s*)(?:true|!0)\b/, function(match, prelude, index, source) {
      var documentVar = _.result(/([$\w]+)\s*=\s*([$\w]+)\s*&&\s*\2\s*\.\s*document\b/.exec(source), 1),
          objectClassVar = _.result(/([$\w]+)\s*=\s*"\[object Object\]"/.exec(source), 1),
          toStringVar = _.result(/([$\w]+)\s*=\s*[$\w]+\s*\.\s*toString\b/.exec(source), 1);

      return prelude + '!(' + toStringVar + '.call(' + documentVar + ')==' + objectClassVar + '&&!({toString:0}+""))';
    });

  // replace `!0` and `!1` with `true` and `false`
  source = source.replace(/(.)(\![01])\b/g, function(match, chr, exp) {
    return chr + (/[$\w]/.test(chr) ? ' ' : '') + (exp == '!0');
  });

  // flip `typeof` expressions to help optimize Safari and
  // correct the AMD module definition for AMD build optimizers
  // (e.g. from `"number" == typeof x` to `typeof x == "number")
  source = source.replace(/([$\w])?("[^"]+")\s*([!=]=)\s*(typeof(?:\s*\([^)]+\)|\s+[.$\w]+(?!\[)))/g, function(match, other, type, equality, exp) {
    return (other ? other + ' ' : '') + exp + equality + type;
  });

  // add a space so `define` is detected by the Dojo builder
  source = source.replace(/(.)(define\()/, function(match, prelude, define) {
    return prelude + (/^\S/.test(prelude) ? ' ' : '') +  define;
  });

  // add trailing semicolon
  if (source) {
    source = source.replace(/[\s;]*?(\s*\/\/.*\s*|\s*\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/\s*)*$/, ';$1');
  }
  // remove copyright header
  var header = _.result(/^\/\**[\s\S]+?\*\/\n/.exec(source), 0, '');
  source = source.replace(header, '');

  // add new copyright header
  source = _.template(licenseTemplate, {
    'lodash': _,
    'underscore': { 'VERSION': _.result(/Underscore\.js ([\d.]+)/i.exec(header), 1, '') }
  }) + '\n;' + source;

  return source;
}

/*----------------------------------------------------------------------------*/

// export `postprocess`
if (module != require.main) {
  module.exports = postprocess;
}
// read the Lo-Dash source file from the first argument if the script
// was invoked directly (e.g. `node post-compile.js source.js`) and write to
// the same file
else if (_.size(process.argv) > 2) {
  (function() {
    var filePath = path.normalize(_.last(process.argv)),
        source = fs.readFileSync(filePath, 'utf8');

    fs.writeFileSync(filePath, postprocess(source), 'utf8');
  }());
}
<commit_msg>Fix new Closure Compiler advanced mode mung.<commit_after>'use strict';

/** Load Node.js modules */
var fs = require('fs');

/** Load other modules */
var _ = require('lodash/lodash.js');

/** The minimal license/copyright template */
var licenseTemplate = [
  '/**',
  ' * @license',
  ' * Lo-Dash <%= lodash.VERSION %> lodash.com/license | Underscore.js <%= underscore.VERSION %> underscorejs.org/LICENSE',
  ' */'
].join('\n');

/*----------------------------------------------------------------------------*/

/**
 * Post-process a given minified Lo-Dash `source`, preparing it for
 * deployment.
 *
 * @param {string} source The source to process.
 * @returns {string} Returns the processed source.
 */
function postprocess(source) {
  // correct overly aggressive Closure Compiler advanced optimization
  source = source
    .replace(/\b(prototype\s*=\s*\{\s*valueOf\s*:\s*1)(\s*})/, '$1,y:1$2')
    .replace(/"\t"/g, '"\\t"')
    .replace(/"[^"]*?\\f[^"]*?"/g,
      '" \\t\\x0B\\f\\xa0\\ufeff' +
      '\\n\\r\\u2028\\u2029' +
      '\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000"'
    )
    .replace(/\bsupport\s*=\s*\{\s*\}\s*;\s*[!(]\s*function\s*\((?=\s*\))/, function(match) {
      return match + 'x_';
    })
    .replace(/(try\s*\{\s*[$\w]+\s*\.\s*nodeClass\s*=\s*)[\s\S]+?(?=\s*}\s*catch\b)/, function(match, prelude, index, source) {
      var documentVar = _.result(/([$\w]+)\s*=\s*([$\w]+)\s*&&\s*\2\s*\.\s*document\b/.exec(source), 1),
          objectClassVar = _.result(/([$\w]+)\s*=\s*"\[object Object\]"/.exec(source), 1),
          toStringVar = _.result(/([$\w]+)\s*=\s*[$\w]+\s*\.\s*toString\b/.exec(source), 1);

      return prelude + '!(' + toStringVar + '.call(' + documentVar + ')==' + objectClassVar + '&&!({toString:0}+""))';
    });

  // replace `!0` and `!1` with `true` and `false`
  source = source.replace(/(.)(\![01])\b/g, function(match, chr, exp) {
    return chr + (/[$\w]/.test(chr) ? ' ' : '') + (exp == '!0');
  });

  // flip `typeof` expressions to help optimize Safari and
  // correct the AMD module definition for AMD build optimizers
  // (e.g. from `"number" == typeof x` to `typeof x == "number")
  source = source.replace(/([$\w])?("[^"]+")\s*([!=]=)\s*(typeof(?:\s*\([^)]+\)|\s+[.$\w]+(?!\[)))/g, function(match, other, type, equality, exp) {
    return (other ? other + ' ' : '') + exp + equality + type;
  });

  // add a space so `define` is detected by the Dojo builder
  source = source.replace(/(.)(define\()/, function(match, prelude, define) {
    return prelude + (/^\S/.test(prelude) ? ' ' : '') +  define;
  });

  // add trailing semicolon
  if (source) {
    source = source.replace(/[\s;]*?(\s*\/\/.*\s*|\s*\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/\s*)*$/, ';$1');
  }
  // remove copyright header
  var header = _.result(/^\/\**[\s\S]+?\*\/\n/.exec(source), 0, '');
  source = source.replace(header, '');

  // add new copyright header
  source = _.template(licenseTemplate, {
    'lodash': _,
    'underscore': { 'VERSION': _.result(/Underscore\.js ([\d.]+)/i.exec(header), 1, '') }
  }) + '\n;' + source;

  return source;
}

/*----------------------------------------------------------------------------*/

// export `postprocess`
if (module != require.main) {
  module.exports = postprocess;
}
// read the Lo-Dash source file from the first argument if the script
// was invoked directly (e.g. `node post-compile.js source.js`) and write to
// the same file
else if (_.size(process.argv) > 2) {
  (function() {
    var filePath = path.normalize(_.last(process.argv)),
        source = fs.readFileSync(filePath, 'utf8');

    fs.writeFileSync(filePath, postprocess(source), 'utf8');
  }());
}
<|endoftext|>


<commit_before>var Chalk = require('chalk');
var Pad = require('pad');

module.exports = printCronJob;

function printCronJob(job) {
    var WIDTH = 12;

    console.log(Chalk.blue(Pad('Name:', WIDTH)), Chalk.green(job.name));
    console.log(Chalk.blue(Pad('State:', WIDTH)), job.state);
    console.log(Chalk.blue(Pad('Container:', WIDTH)), job.container);
    console.log(Chalk.blue(Pad('Schedule:', WIDTH)), job.schedule);

    if (job.results.length) {
        console.log(Chalk.blue(Pad('Last result:', WIDTH)), job.results[0].type);
        console.log(Chalk.blue(Pad('Last run:', WIDTH)), new Date(job.results[0].completed_at).toLocaleString());
    }

    var intervalOptions = {
        currentDate: new Date(job.next_available_at),
    };

    if (job.expires_at) {
        intervalOptions.endDate = new Date(job.expires_at);
    }

    console.log(Chalk.blue(Pad('Next run:', WIDTH)), new Date(job.next_available_at).toLocaleString());

    if (job.expires_at) {
        console.log(Chalk.blue(Pad('Expires:', WIDTH)), new Date(job.expires_at).toLocaleString());
    }
}
<commit_msg>wt cron *: Fix error when printing cron job without results<commit_after>var Chalk = require('chalk');
var Pad = require('pad');

module.exports = printCronJob;

function printCronJob(job) {
    var WIDTH = 12;

    console.log(Chalk.blue(Pad('Name:', WIDTH)), Chalk.green(job.name));
    console.log(Chalk.blue(Pad('State:', WIDTH)), job.state);
    console.log(Chalk.blue(Pad('Container:', WIDTH)), job.container);
    console.log(Chalk.blue(Pad('Schedule:', WIDTH)), job.schedule);

    if (job.results && job.results.length) {
        console.log(Chalk.blue(Pad('Last result:', WIDTH)), job.results[0].type);
        console.log(Chalk.blue(Pad('Last run:', WIDTH)), new Date(job.results[0].completed_at).toLocaleString());
    }

    var intervalOptions = {
        currentDate: new Date(job.next_available_at),
    };

    if (job.expires_at) {
        intervalOptions.endDate = new Date(job.expires_at);
    }

    console.log(Chalk.blue(Pad('Next run:', WIDTH)), new Date(job.next_available_at).toLocaleString());

    if (job.expires_at) {
        console.log(Chalk.blue(Pad('Expires:', WIDTH)), new Date(job.expires_at).toLocaleString());
    }
}
<|endoftext|>


<commit_before>import chalk from 'chalk';
import execa from 'execa';
import inquirer from 'inquirer';
import getConfig from './getConfig';

const promptConfig = {
  config: () => getConfig(),

  choices: (configuration) => {
    const choicesList = [];

    configuration.types.forEach((type) => {
      const emoji = `${type.emoji} ` || '';
      const configType = type.type;
      const description = type.description || '';

      choicesList.push({
        value: emoji + configType,
        name: `${chalk.bold(configType)} ${description}`,
      });
    });

    return choicesList;
  },

  answerTypes: (configuration) => {
    const configTypeList = [];
    configuration.types.forEach((type) => {
      const configType = type.type;

      configTypeList.push(configType);
    });
    return configTypeList;
  },

  questions: (choices) => {
    const questionsList = [
      {
        type: 'list',
        name: 'type',
        message: 'Select the type of your commit:',
        choices,
      },
      {
        type: 'input',
        name: 'description',
        message: 'Enter your commit message:',
        validate: /* istanbul ignore next */ input => (input ? true : 'A commit message is mandatory!'),
      },
      {
        type: 'confirm',
        name: 'moreInfo',
        message: 'Do you want to add more information to your commit?',
        default: false,
      },
      {
        type: 'editor',
        name: 'editor',
        message: 'This will let you add more information',
        when: /* istanbul ignore next */ answers => answers.moreInfo,
        default: /* istanbul ignore next */ answers => `${answers.type} ${answers.description}\n\n\n`,
      },
    ];
    return questionsList;
  },

  prompt: (questions) => {
    const config = promptConfig.config();
    const types = promptConfig.answerTypes(config);
    const cli = inquirer.prompt(questions).then((answers) => {
      const message = answers.moreInfo ? `${answers.editor}` : `${answers.type} ${answers.description}`;
      /* istanbul ignore if */
      if (types.indexOf(answers.type.split(' ')[1]) !== -1) {
        return execa('git', ['commit', '-m', message])
          .then(result => console.log(result.stdout))
          .catch((err) => {
            console.error(chalk.red("Have you thought about 'git add' some files? Add files and try run following again:\n"));
            console.error(chalk.green(err.cmd));
          });
      }
      return answers.type;
    });
    return cli;
  },
};

export default promptConfig;
<commit_msg>:hammer: Refactor: change promptConfig from export default to named exports<commit_after>import chalk from 'chalk';
import getConfig from './getConfig';

const config = () => getConfig();

const choices = (configuration) => {
  const choicesList = [];

  configuration.types.forEach((type) => {
    const emoji = `${type.emoji} ` || '';
    const configType = type.type;
    const description = type.description || '';

    choicesList.push({
      value: emoji + configType,
      name: `${chalk.bold(configType)} ${description}`,
    });
  });

  return choicesList;
};

const questions = (choicesList) => {
  const questionsList = [
    {
      type: 'list',
      name: 'type',
      message: 'Select the type of your commit:',
      choicesList,
    },
    {
      type: 'input',
      name: 'description',
      message: 'Enter your commit message:',
      validate: input => (input ? true : 'A commit message is mandatory!'),
    },
    {
      type: 'confirm',
      name: 'moreInfo',
      message: 'Do you want to add more information to your commit?',
      default: false,
    },
    {
      type: 'editor',
      name: 'editor',
      message: 'This will let you add more information',
      when: answers => answers.moreInfo,
      default: answers => `${answers.type} ${answers.description}\n\n\n`,
    },
  ];

  return questionsList;
};

export { config, choices, questions };
<|endoftext|>


<commit_before>'use strict'
var Property = require('./')
var render = function (self, event) {
  let element = self.parent
  let node = element.getNode()
  if (node) {
    element._csscache = null
    self.render(node, event, element)
  }
}
var remove = function (val, event) {
  var removed
  this.each(function () {}, function (property) {
    if (property instanceof Property) {
      if (property.parseValue() === val) {
        property.remove()
        removed = true
      }
    }
  })
  if (this.parseValue() === val) {
    this.set('', event)
    removed = true
  }
  return removed
}

exports.properties = {
  css: new Property({
    ChildConstructor: new Property({
      render (node, event, css) {
        css._parent._csscache = null
      }
    }),
    render (node, event, element) {
      if (element._csscache) {
        node.className = element._csscache
      } else {
        let key = element.key
        let val = this.parseValue()
        let str = typeof val === 'string' ? val : ''
        if (key) {
          str = key + ' ' + str
        }
        this.each(function () {}, function (property) {
          if (property instanceof Property) {
            let val = property.parseValue()
            if (typeof val === 'string') {
              str += ' ' + val
            }
          }
        })
        node.className = str
        element._csscache = str
      }
    },
    properties: {
      add (val, event) {
        var exists = this.each(function () {}, function (property) {
          if (property instanceof Property) {
            if (property.parseValue() === val) {
              return true
            }
          }
        })
        if (!exists) {
          let cnt = 0
          while (this[cnt]) {
            cnt += 1
          }
          this.setKey(cnt, val)
          render(this, event)
        }
      },
      remove (node, event) {
        if (remove.apply(this, arguments)) {
          render(this, event)
        }
      },
      toggle (val, event) {
        if (!remove.call(this, val, event)) {
          let cnt = 0
          while (this[cnt]) {
            cnt += 1
          }
          this.setKey(cnt, val, event)
        }
        render(this, event)
      }
    }
  }).Constructor
}
<commit_msg>css cache<commit_after>'use strict'
var Property = require('./')
var render = function (self, event) {
  let element = self.parent
  let node = element.getNode()
  element._csscache = null
  if (node) {
    self.render(node, event, element)
  }
}
var remove = function (val, event) {
  var removed
  this.each(function () {}, function (property) {
    if (property instanceof Property) {
      if (property.parseValue() === val) {
        property.remove()
        removed = true
      }
    }
  })
  if (this.parseValue() === val) {
    this.set('', event)
    removed = true
  }
  return removed
}

exports.properties = {
  css: new Property({
    ChildConstructor: new Property({
      render (node, event, css) {
        css._parent._csscache = null
      }
    }),
    render (node, event, element) {
      if (element._csscache) {
        node.className = element._csscache
      } else {
        let key = element.key
        let val = this.parseValue()
        let str = typeof val === 'string' ? val : ''
        if (key) {
          str = key + ' ' + str
        }
        this.each(function () {}, function (property) {
          if (property instanceof Property) {
            let val = property.parseValue()
            if (typeof val === 'string') {
              str += ' ' + val
            }
          }
        })
        node.className = str
        element._csscache = str
      }
    },
    properties: {
      add (val, event) {
        var exists = this.each(function () {}, function (property) {
          if (property instanceof Property) {
            if (property.parseValue() === val) {
              return true
            }
          }
        })
        if (!exists) {
          let cnt = 0
          while (this[cnt]) {
            cnt += 1
          }
          this.setKey(cnt, val)
          render(this, event)
        }
      },
      remove (node, event) {
        if (remove.apply(this, arguments)) {
          render(this, event)
        }
      },
      toggle (val, event) {
        if (!remove.call(this, val, event)) {
          let cnt = 0
          while (this[cnt]) {
            cnt += 1
          }
          this.setKey(cnt, val, event)
        }
        render(this, event)
      }
    }
  }).Constructor
}
<|endoftext|>


<commit_before>"use strict";
/*global alert: true, console: true, ODSA */

(function ($) {
  var settings = ODSA.SETTINGS,
      odsaUtils = ODSA.UTILS;

  // Set the book ID (SHA1 hash of the book URL)
  settings.BOOK_ID = odsaUtils.getBookID();
  //function that displays config page

  var b_json = (function () {
    var b_json = null;
    $.ajax({
        'async': false,
        'global': false,
        'url': '_static/' + settings.BOOK_NAME + '.json',
        'dataType': "json",
        'success': function (data) {
          b_json = data;
        }
      });
    return b_json;
  })();

  //prepare data to send to the backend
  var jsonBook = {};

  jsonBook.key = odsaUtils.getSessionKey();
  jsonBook.book =  settings.BOOK_ID;
  // Calculate the URL of the book, relative to the current module page
  jsonBook.url = location.href.substring(0, location.href.lastIndexOf('/') + 1);
  jsonBook.b_json = JSON.stringify(b_json);

  function sendConfig() {
    //Add book build date
    jsonBook.build_date = settings.BUILD_DATE;
    $('#bookjson').html("Sending data ...");
    // Send the data to the server
    jQuery.ajax({
      url:   settings.SCORE_SERVER + "/api/v1/module/loadbook/",
      type:  "POST",
      data: jsonBook,
      contentType: "application/json; charset=utf-8",
      datatype: "json",
      xhrFields: {withCredentials: true},
      success: function (data) {
        alert("SUCCESS:\nAll chapters and exercises of book instance " + settings.BOOK_NAME + " have been saved on the data server.");
        $('#bookjson').html("SUCCESS");
        console.log("success: " + data);
      },
      error: function (data) {
        alert("ERROR:\nSomething went wrong when storing chapters and exercises of book instance " + settings.BOOK_NAME + ".\nRefresh the page, the try again. If the problem persists, contact the administrator.");
        $('#bookjson').html("FAILED");
        console.log("error: " + data);
      }
    });
  }

  //*****************************************************************************
  //***********            Runs When Page Finishes Loading            ***********
  //*****************************************************************************
  $(document).ready(function () {
    $('#bookname').val(settings.BOOK_NAME);
    $('#bookid').val(settings.BOOK_ID);
    //$('#bookjson').html(JSON.stringify(b_json));
    $('#registerbook').click(function () {
      sendConfig();
    });
  });

}(jQuery));
<commit_msg>Updated book instance registration error message. To reflect the fact that now, only "staff" users can register a book instance.<commit_after>"use strict";
/*global alert: true, console: true, ODSA */

(function ($) {
  var settings = ODSA.SETTINGS,
      odsaUtils = ODSA.UTILS;

  // Set the book ID (SHA1 hash of the book URL)
  settings.BOOK_ID = odsaUtils.getBookID();
  //function that displays config page

  var b_json = (function () {
    var b_json = null;
    $.ajax({
        'async': false,
        'global': false,
        'url': '_static/' + settings.BOOK_NAME + '.json',
        'dataType': "json",
        'success': function (data) {
          b_json = data;
        }
      });
    return b_json;
  })();

  //prepare data to send to the backend
  var jsonBook = {};

  jsonBook.key = odsaUtils.getSessionKey();
  jsonBook.book =  settings.BOOK_ID;
  // Calculate the URL of the book, relative to the current module page
  jsonBook.url = location.href.substring(0, location.href.lastIndexOf('/') + 1);
  jsonBook.b_json = JSON.stringify(b_json);

  function sendConfig() {
    //Add book build date
    jsonBook.build_date = settings.BUILD_DATE;
    $('#bookjson').html("Sending data ...");
    // Send the data to the server
    jQuery.ajax({
      url:   settings.SCORE_SERVER + "/api/v1/module/loadbook/",
      type:  "POST",
      data: jsonBook,
      contentType: "application/json; charset=utf-8",
      datatype: "json",
      xhrFields: {withCredentials: true},
      success: function (data) {
        alert("SUCCESS:\nAll chapters and exercises of book instance " + settings.BOOK_NAME + " have been saved on the data server.");
        $('#bookjson').html("SUCCESS");
        console.log("success: " + data);
      },
      error: function (data) {
        alert("ERROR:\nSomething went wrong when storing chapters and exercises of book instance " + settings.BOOK_NAME + ".\nYou might not have the right to complete this action. Refresh the page, the try again. If the problem persists, contact the administrator.");
        $('#bookjson').html("FAILED");
        console.log("error: " + data);
      }
    });
  }

  //*****************************************************************************
  //***********            Runs When Page Finishes Loading            ***********
  //*****************************************************************************
  $(document).ready(function () {
    $('#bookname').val(settings.BOOK_NAME);
    $('#bookid').val(settings.BOOK_ID);
    //$('#bookjson').html(JSON.stringify(b_json));
    $('#registerbook').click(function () {
      sendConfig();
    });
  });

}(jQuery));
<|endoftext|>


<commit_before>/*
* Module to convert to/from Roman Numerals and numbers
* Author: Christos Koumenides
*/

(function() {
  'use strict';

  module.exports = function(value) {

    if (value === 10000) throw new Error('invalid range');

    // some optimisation - will only compute these once per function call/init
    // and return them on consecutive calls to "toInt" and toString"
    var intValue, stringValue = null;

    var app = {
      toInt: function() {
        return intValue;
      },
      toString: function() {
        return stringValue;
      }
    }

    return app;
  }

})();<commit_msg>value validity checks<commit_after>/*
* Module to convert to/from Roman Numerals and numbers
* Author: Christos Koumenides
*/

(function() {
  'use strict';

  module.exports = function(value) {

    // some optimisation - will only compute these once per function call/init
    // and return them on consecutive calls to "toInt" and toString"
    var intValue, stringValue = null;

    var app = {
      toInt: function() {
        return intValue;
      },
      toString: function() {
        return stringValue;
      }
    };

    // if null or empty
    if (value === null || typeof value === 'undefined' || value === '') {
      throw new Error('value required');
    }

    // if integer and within range
    else if ((typeof value === 'number') && (value % 1 === 0)) {
      if (value >= 1 && value <= 3999) {
        return app;
      } else {
        throw new Error('invalid range');
      }
    }

    // if string and valid characters only
    else if (typeof value === 'string') {
      return app;
    }

    // anything else fails
    throw new Error('invalid value');
  }

  function toInt(value) {
    return value;
  }

  function toString(value) {
    return value;
  }

})();<|endoftext|>


<commit_before>'use strict';
var ngram = require('../util/ngram'),
    redis = require("redis"),
    client = redis.createClient();

var search = {};

search.basic = function(query, n, callback) {
  var grams = ngram(query, n),
      results = [];

  client.sinter(grams, function(err, documentNumbers){
    if (documentNumbers.length == 0) {
      client.end();
      callback(null, results);
    }

    documentNumbers.forEach(function(docNo) {
      var positions = grams.map(function(gram){
        return gram + "-" + docNo
      });

      client.mget(positions, function(err, res){
        var firstPos = parseInt(res[0]);
        var checkVal = res.reduce(function(a,b) { return parseInt(a) + parseInt(b)});
        var checkSum = res.length * (firstPos + (firstPos + res.length - 1)) / 2;

        if (checkVal == checkSum) {
          results.push({no:docNo, pos:res[0]});
        }

        if (docNo == documentNumbers[documentNumbers.length - 1]) {
          client.end();
          callback(null, results);
        }
      });
    });
  });
}

module.exports = search;

<commit_msg>同一文書中に複数語句が入った場合の対応<commit_after>'use strict';
var ngram = require('../util/ngram'),
    _ = require('underscore'),
    redis = require("redis"),
    client = redis.createClient();

var search = {};

search.basic = function(query, n, callback) {
  var grams = ngram(query, n),
      results = [];

  client.sinter(grams, function(err, documentNumbers){
    if (documentNumbers.length == 0) {
      client.end();
      callback(null, results);
    }

    documentNumbers.forEach(function(docNo) {
      var positions = grams.map(function(gram){
        return gram + "-" + docNo
      });

      client.mget(positions, function(err, res){
        var charPositions = res.map(function(pos){
          return pos.split(",").filter(function(e){return e !== ""}).map(function(e){return parseInt(e)});
        });

        for(var i=1; i<charPositions.length; i++) {
          charPositions[i] = charPositions[i].map(function(v) {return v-i});
        }

        charPositions.reduce(function(a,b) {return _.intersection(a,b)}).forEach(function(position) {
          results.push({no:docNo, pos:position});
        });

        if (docNo == documentNumbers[documentNumbers.length - 1]) {
          client.end();
          callback(null, results);
        }
      });
    });
  });
}

module.exports = search;

<|endoftext|>


<commit_before>'use strict';
var Agent = require('./agent');
var async = require('async');
var EventEmitter = require('events').EventEmitter;
var path = require('path');
var processor = require('./processor');
var request = require('./request');
var shared = require('../shared');
var utilities = require('./utilities');

/**
 * Runs the tasks in a queue and returns an event emitter.
 * @param {!Array.<!{address: string, options: !IOptions}>} tasks
 * @param {number=} workers
 * @return {!IEmitter}
 */
module.exports = function(tasks, workers) {
  var beginTimeInMs = Date.now();
  var emitter = new EventEmitter();
  var queue = async.queue(function(task, done) {
    done = createTaskCallback(emitter, queue, done);
    if (task.alias) return taskChapter(emitter, task, done);
    taskSeries(emitter, queue, task, done);
  }, workers);
  emitter.push = function(tasks) {
    queue.push(tasks);
  };
  process.nextTick(function() {
    queue.drain = function() {
      emitter.emit('end', {timeInMs: Date.now() - beginTimeInMs});
    };
    queue.push(tasks);
  });
  return emitter;
};

/**
 * Creates an agent.
 * @param {!IOptions} options
 * @param {!ISeries} series
 * @param {!IChapter} chapter
 * @param {string} alias
 * @param {function(Error, Agent)} done
 */
function createAgent(options, series, chapter, alias, done) {
  var filePath = path.join(options.output || '', alias);
  processor(options, series, chapter, function(err, processors) {
    if (err) return done(err);
    var Meta = shared.publisher.Meta;
    done(undefined, options.meta ?
      new Agent(filePath, processors) :
      new Agent(filePath, processors, new Meta(series, chapter)));
  });
}

/**
 * Creates a task callback, which emits and kills the queue on an error.
 * @param {!EventEmitter} emitter
 * @param {!{kill: function(), push: function(!Object)}} queue
 * @param {function()} done
 */
function createTaskCallback(emitter, queue, done) {
  return function(err) {
    if (!err) return done();
    emitter.emit('error', err);
    queue.kill();
  };
}

/**
 * Enqueues the chapter.
 * @param {!{kill: function(), push: function(!Object)}} queue
 * @param {!IOptions} options
 * @param {!ISeries} series The populated series.
 * @param {!IChapter} chapter
 * @param {function(Error)} done
 */
function enqueueChapter(queue, options, series, chapter, done) {
  if (utilities.excluded(options, chapter)) return process.nextTick(done);
  var alias = shared.common.alias(series, chapter, options.extension);
  if (!alias) return process.nextTick(done);
  utilities.duplicate(options, alias, function(err, duplicate) {
    if (!duplicate) {
      queue.push({
        alias: alias,
        options: options,
        series: series,
        chapter: chapter
      });
    }
    done();
  });
}

/**
 * Enqueues the series.
 * @param {!{kill: function(), push: function(!Object)}} queue
 * @param {!IOptions} options
 * @param {!ISeries} series
 * @param {function(Error)} done
 */
function enqueueSeries(queue, options, series, done) {
  request(series, 'utf8', function(err) {
    if (err) return done(err);
    async.eachSeries(series.children, function(chapter, next) {
      if (!chapter) return next();
      enqueueChapter(queue, options, series, chapter, next);
    }, done);
  });
}

/**
 * Runs a chapter task.
 * @param {!EventEmitter} emitter
 * @param {!Object} task
 * @param {function(Error)} done
 */
function taskChapter(emitter, task, done) {
  var alias = task.alias;
  var basename = path.basename(alias);
  var begin = Date.now();
  var chapter = task.chapter;
  var options = task.options;
  var series = task.series;
  emitter.emit('data', {item: basename, type: 'fetching'});
  request(chapter, 'utf8', function(err) {
    if (err) return done(err);
    createAgent(options, series, chapter, alias, function(err, agent) {
      if (err) return done(err);
      shared.publisher.mirror(agent, series, chapter, function(err) {
        if (err) return done(err);
        agent.publish(function(err) {
          if (err) return emitter.emit('error', err);
          emitter.emit('data', {
            item: basename,
            timeInMs: Date.now() - begin,
            type: 'finished'
          });
          done();
        });
      });
    });
  });
}

/**
 * Runs a series task.
 * @param {!EventEmitter} emitter
 * @param {!{kill: function(), push: function(!Object)}} queue
 * @param {!Object} task
 * @param {function(Error)} done
 */
function taskSeries(emitter, queue, task, done) {
  var series = shared.provider(task.address);
  if (series) return enqueueSeries(queue, task.options, series, done);
  emitter.emit('data', {item: task.address, type: 'obscured'});
  process.nextTick(done);
}
<commit_msg>Clean up the taskChapter function<commit_after>'use strict';
var Agent = require('./agent');
var async = require('async');
var EventEmitter = require('events').EventEmitter;
var path = require('path');
var processor = require('./processor');
var request = require('./request');
var shared = require('../shared');
var utilities = require('./utilities');

/**
 * Runs the tasks in a queue and returns an event emitter.
 * @param {!Array.<!{address: string, options: !IOptions}>} tasks
 * @param {number=} workers
 * @return {!IEmitter}
 */
module.exports = function(tasks, workers) {
  var beginTimeInMs = Date.now();
  var emitter = new EventEmitter();
  var queue = async.queue(function(task, done) {
    done = createTaskCallback(emitter, queue, done);
    if (task.alias) return taskChapter(emitter, task, done);
    taskSeries(emitter, queue, task, done);
  }, workers);
  emitter.push = function(tasks) {
    queue.push(tasks);
  };
  process.nextTick(function() {
    queue.drain = function() {
      emitter.emit('end', {timeInMs: Date.now() - beginTimeInMs});
    };
    queue.push(tasks);
  });
  return emitter;
};

/**
 * Creates an agent.
 * @param {!IOptions} options
 * @param {!ISeries} series
 * @param {!IChapter} chapter
 * @param {string} alias
 * @param {function(Error, Agent)} done
 */
function createAgent(options, series, chapter, alias, done) {
  var filePath = path.join(options.output || '', alias);
  processor(options, series, chapter, function(err, processors) {
    if (err) return done(err);
    var Meta = shared.publisher.Meta;
    done(undefined, options.meta ?
      new Agent(filePath, processors) :
      new Agent(filePath, processors, new Meta(series, chapter)));
  });
}

/**
 * Creates a task callback, which emits and kills the queue on an error.
 * @param {!EventEmitter} emitter
 * @param {!{kill: function(), push: function(!Object)}} queue
 * @param {function()} done
 */
function createTaskCallback(emitter, queue, done) {
  return function(err) {
    if (!err) return done();
    emitter.emit('error', err);
    queue.kill();
  };
}

/**
 * Enqueues the chapter.
 * @param {!{kill: function(), push: function(!Object)}} queue
 * @param {!IOptions} options
 * @param {!ISeries} series The populated series.
 * @param {!IChapter} chapter
 * @param {function(Error)} done
 */
function enqueueChapter(queue, options, series, chapter, done) {
  if (utilities.excluded(options, chapter)) return process.nextTick(done);
  var alias = shared.common.alias(series, chapter, options.extension);
  if (!alias) return process.nextTick(done);
  utilities.duplicate(options, alias, function(err, duplicate) {
    if (!duplicate) {
      queue.push({
        alias: alias,
        options: options,
        series: series,
        chapter: chapter
      });
    }
    done();
  });
}

/**
 * Enqueues the series.
 * @param {!{kill: function(), push: function(!Object)}} queue
 * @param {!IOptions} options
 * @param {!ISeries} series
 * @param {function(Error)} done
 */
function enqueueSeries(queue, options, series, done) {
  request(series, 'utf8', function(err) {
    if (err) return done(err);
    async.eachSeries(series.children, function(chapter, next) {
      if (!chapter) return next();
      enqueueChapter(queue, options, series, chapter, next);
    }, done);
  });
}

/**
 * Runs a chapter task.
 * @param {!EventEmitter} emitter
 * @param {!Object} task
 * @param {function(Error)} done
 */
function taskChapter(emitter, task, done) {
  var basename = path.basename(task.alias);
  var begin = Date.now();
  var chapter = task.chapter;
  var options = task.options;
  var series = task.series;
  emitter.emit('data', {item: basename, type: 'fetching'});
  request(chapter, 'utf8', function(err) {
    if (err) return done(err);
    createAgent(options, series, chapter, task.alias, function(err, agent) {
      if (err) return done(err);
      shared.publisher.mirror(agent, series, chapter, function(err) {
        if (err) return done(err);
        agent.publish(function(err) {
          if (err) return emitter.emit('error', err);
          emitter.emit('data', {
            item: basename,
            timeInMs: Date.now() - begin,
            type: 'finished'
          });
          done();
        });
      });
    });
  });
}

/**
 * Runs a series task.
 * @param {!EventEmitter} emitter
 * @param {!{kill: function(), push: function(!Object)}} queue
 * @param {!Object} task
 * @param {function(Error)} done
 */
function taskSeries(emitter, queue, task, done) {
  var series = shared.provider(task.address);
  if (series) return enqueueSeries(queue, task.options, series, done);
  emitter.emit('data', {item: task.address, type: 'obscured'});
  process.nextTick(done);
}
<|endoftext|>


<commit_before>const http = require('http');
const https = require('https');
const parseurl = require('url').parse;

var routeTree = {};

exports.app = function(isHTTPS, req, res) {
	Promise.resolve()
		.then(() => {
			var search = '';
			var path = req.url.replace(/\?.*?$/, m => {
				search = m[0];
				return '';
			}).split(/\/+/).filter(v => v);
			var domainName = req.headers.host.replace(/\:[0-9]+/, '');
			var host = domainName.split('.');
			var obj = routeTree;
			for (var i = host.length - 1; i >= 0; i--) {
				if (obj[host[i]]) {
					obj = obj[host[i]];
				} else {
					break;
				}
			}
			if (!obj['#'])
				throw 'No matching host';
			obj = obj['#'];
			for (var i = 0; i < path.length; i++) {
				if (obj[path[i]]) {
					obj = obj[path[i]];
				} else {
					break;
				}
			}
			path = path.slice(i).join('/') + search;
			if (!obj['#'])
				throw 'No matching path';
			obj = obj['#'];
			if (obj.forceSecure && !isHTTPS) {
				var port = '';
				if (CFG.server.https_port != 443) {
					port = ':' + CFG.server.https_port;
				}
				throw {redirect:'https://' + domainName + port + req.url};
			} else if (!path && !req.url.match(/\/$/)) {
				var port = '';
				if (isHTTPS) {
					if (CFG.server.https_port != 443)
						port = ':' + CFG.server.https_port;
				} else if (CFG.server.http_port != 80) {
					port = ':' + CFG.server.http_port;
				}
				throw {redirect:(isHTTPS ? 'https://' : 'http://') + domainName + port + req.url + '/'};
			} else {
                var targetUrl;
                obj = obj.app;
                if (!obj.url)
                    throw 'Application not ready';
                if (Array.isArray(obj.url)) {
                    if (!obj.cookie) {
                        targetUrl = obj.robin - 0 || 0;
                        obj.robin = (targetUrl + 1) % obj.url;
                        targetUrl = obj.url[targetUrl];
                    } else {
                        // TODO cookie based forwarding
                    }
                } else {
                    targetUrl = obj.url;
                }
                var resolvedUrl = targetUrl + path;
				targetUrl = parseurl(resolvedUrl);
				var protocol = targetUrl.protocol == 'https:' ? https : http;
				targetUrl.hostname = targetUrl.host = obj.host || domainName;
				targetUrl.method = req.method;
				targetUrl.headers = req.headers;
				targetUrl.rejectUnauthorized = false;
				return new Promise((resolve, reject) => {
					var targetReq = protocol.request(targetUrl, targetRes => {
                        try {
                            res.statusCode = targetRes.statusCode;
                            res.statusMessage = targetRes.statusMessage;
                            for (var k in targetRes.headers) {
                                res.setHeader(k, targetRes.headers[k]);
                            }
                            targetRes.pipe(res);
                            resolve();
                        } catch(err) {
                            reject(err);
                        }
					});
                    targetReq.setTimeout(15000, evt => {
                    	console.error('Timeout: ' + resolvedUrl);
                        reject('Backend host timeout');
                    });
                    targetReq.on('error', err => {
                    	console.error('Err: ' + resolvedUrl);
                        console.error(err.stack || err.message || err);
                        reject('Unable to reach backend host');
                    });
					req.pipe(targetReq);
				});
			}
		}).catch(err => {
			if (typeof err == 'string') {
				res.statusCode = 401;
				res.statusMessage = 'Bad Gateway';
				res.end(err);
			} else if (err.redirect) {
				res.statusCode = 302;
				res.statusMessage = 'Must Use HTTPS';
				res.setHeader('location', err.redirect);
				res.end();
			} else {
				res.statusCode = 500;
				res.statusMessage = 'Gateway Internal Error';
				res.end(err.stack || err.message || err);
			}
		}).catch(err => {
            console.error(err.stack || err.message || err);
		})
}

exports.set = function(newRouteTree) {
	if (newRouteTree && typeof newRouteTree == 'object') {
		routeTree = newRouteTree;
	}
}<commit_msg>fix host bug<commit_after>const http = require('http');
const https = require('https');
const parseurl = require('url').parse;

var routeTree = {};

exports.app = function(isHTTPS, req, res) {
	Promise.resolve()
		.then(() => {
			var search = '';
			var path = req.url.replace(/\?.*?$/, m => {
				search = m[0];
				return '';
			}).split(/\/+/).filter(v => v);
			var domainName = req.headers.host.replace(/\:[0-9]+/, '');
			var host = domainName.split('.');
			var obj = routeTree;
			for (var i = host.length - 1; i >= 0; i--) {
				if (obj[host[i]]) {
					obj = obj[host[i]];
				} else {
					break;
				}
			}
			if (!obj['#'])
				throw 'No matching host';
			obj = obj['#'];
			for (var i = 0; i < path.length; i++) {
				if (obj[path[i]]) {
					obj = obj[path[i]];
				} else {
					break;
				}
			}
			path = path.slice(i).join('/') + search;
			if (!obj['#'])
				throw 'No matching path';
			obj = obj['#'];
			if (obj.forceSecure && !isHTTPS) {
				var port = '';
				if (CFG.server.https_port != 443) {
					port = ':' + CFG.server.https_port;
				}
				throw {redirect:'https://' + domainName + port + req.url};
			} else if (!path && !req.url.match(/\/$/)) {
				var port = '';
				if (isHTTPS) {
					if (CFG.server.https_port != 443)
						port = ':' + CFG.server.https_port;
				} else if (CFG.server.http_port != 80) {
					port = ':' + CFG.server.http_port;
				}
				throw {redirect:(isHTTPS ? 'https://' : 'http://') + domainName + port + req.url + '/'};
			} else {
                var targetUrl;
                obj = obj.app;
                if (!obj.url)
                    throw 'Application not ready';
                if (Array.isArray(obj.url)) {
                    if (!obj.cookie) {
                        targetUrl = obj.robin - 0 || 0;
                        obj.robin = (targetUrl + 1) % obj.url;
                        targetUrl = obj.url[targetUrl];
                    } else {
                        // TODO cookie based forwarding
                    }
                } else {
                    targetUrl = obj.url;
                }
                var resolvedUrl = targetUrl + path;
				targetUrl = parseurl(resolvedUrl);
				var protocol = targetUrl.protocol == 'https:' ? https : http;
				targetUrl.method = req.method;
				targetUrl.headers = req.headers || {};
				if (obj.host) {
					if (targetUrl.headers.host) {
						targetUrl.headers.x_original_host = targetUrl.headers.host;
					}
					targetUrl.headers.host = obj.host;
				}
				targetUrl.rejectUnauthorized = false;
				return new Promise((resolve, reject) => {
					var targetReq = protocol.request(targetUrl, targetRes => {
                        try {
                            res.statusCode = targetRes.statusCode;
                            res.statusMessage = targetRes.statusMessage;
                            for (var k in targetRes.headers) {
                                res.setHeader(k, targetRes.headers[k]);
                            }
                            targetRes.pipe(res);
                            resolve();
                        } catch(err) {
                            reject(err);
                        }
					});
                    targetReq.setTimeout(15000, evt => {
                    	console.error('Timeout: ' + resolvedUrl);
                        reject('Backend host timeout');
                    });
                    targetReq.on('error', err => {
                    	console.error('Err: ' + resolvedUrl);
                        console.error(err.stack || err.message || err);
                        reject('Unable to reach backend host');
                    });
					req.pipe(targetReq);
				});
			}
		}).catch(err => {
			if (typeof err == 'string') {
				res.statusCode = 401;
				res.statusMessage = 'Bad Gateway';
				res.end(err);
			} else if (err.redirect) {
				res.statusCode = 302;
				res.statusMessage = 'Must Use HTTPS';
				res.setHeader('location', err.redirect);
				res.end();
			} else {
				res.statusCode = 500;
				res.statusMessage = 'Gateway Internal Error';
				res.end(err.stack || err.message || err);
			}
		}).catch(err => {
            console.error(err.stack || err.message || err);
		})
}

exports.set = function(newRouteTree) {
	if (newRouteTree && typeof newRouteTree == 'object') {
		routeTree = newRouteTree;
	}
}<|endoftext|>


<commit_before>// stack layers function (where the magic happens)
'use strict'

var viewbox = require('viewbox')

var gatherLayers = require('./_gather-layers')

var findLayerId = function(layers, type) {
  var layer
  var i

  for (i = 0; i < layers.length; i++) {
    layer = layers[i]
    if (layer.type === type) {
      return layer.id
    }
  }
}

var useLayer = function(element, id, className, mask) {
  var attr = {'xlink:href': '#' + id}

  if (className) {
    attr.fill = 'currentColor'
    attr.stroke = 'currentColor'
    attr.class = className
  }

  if (mask) {
    attr.mask = 'url(#' + mask + ')'
  }

  return element('use', attr)
}

var createRect = function(element, box, fill, className) {
  var attr = viewbox.rect(box)

  if (fill) {
    attr.fill = fill
  }

  if (className) {
    attr.class = className
  }

  return element('rect', attr)
}

var mechMask = function(element, id, box, drills) {
  var maskAttr = {id: id}
  var children = drills.map(function(layer) {
    return useLayer(element, layer.id)
  })

  children.unshift(createRect(element, box, '#fff'))

  var group = [element('g', {fill: '#000', stroke: '#000'}, children)]

  return element('mask', maskAttr, group)
}

module.exports = function(element, id, side, layers, drills, outline, useOutline) {
  var classPrefix = id + '_'
  var idPrefix = id + '_' + side + '_'
  var mechMaskId = idPrefix + 'mech-mask'

  var layerProps = gatherLayers(element, idPrefix, layers, drills, outline, useOutline)
  var defs = layerProps.defs
  var box = layerProps.box
  var units = layerProps.units

  layers = layerProps.layerIds
  drills = layerProps.drillIds

  defs.push(mechMask(element, mechMaskId, box, drills))

  // build the layer starting with an fr4 rectangle the size of the viewbox
  var layer = [createRect(element, box, 'currentColor', classPrefix + 'fr4')]
  var cuLayerId = findLayerId(layers, 'cu')
  var smLayerId = findLayerId(layers, 'sm')
  var ssLayerId = findLayerId(layers, 'ss')
  var spLayerId = findLayerId(layers, 'sp')
  var outLayerId = layerProps.outlineId

  // add copper and copper finish
  if (cuLayerId) {
    var cfMaskId = idPrefix + 'cf-mask'
    var cfMaskAttr = {id: cfMaskId}
    var cfMaskShape = smLayerId
      ? [element('use', {'xlink:href': '#' + smLayerId})]
      : [createRect(element, box)]
    var cfMaskGroup = [element('g', {fill: '#fff', stroke: '#fff'}, cfMaskShape)]

    defs.push(element('mask', cfMaskAttr, cfMaskGroup))
    layer.push(useLayer(element, cuLayerId, classPrefix + 'cu'))
    layer.push(useLayer(element, cuLayerId, classPrefix + 'cf', cfMaskId))
  }

  // add soldermask and silkscreen
  // silkscreen will not be added if no soldermask, because that's how it works in RL
  if (smLayerId) {
    // solder mask is... a mask, so mask it
    var smMaskId = idPrefix + 'sm-mask'
    var smMaskAttr = {id: smMaskId}
    var smMaskShape = [
      createRect(element, box, '#fff'),
      element('use', {'xlink:href': '#' + smLayerId})
    ]
    var smMaskGroup = [element('g', {fill: '#000', stroke: '#000'}, smMaskShape)]

    defs.push(element('mask', smMaskAttr, smMaskGroup))

    // add the layer that gets masked
    var smGroupAttr = {mask: 'url(#' + smMaskId + ')'}
    var smGroupShape = [createRect(element, box, 'currentColor', classPrefix + 'sm')]

    if (ssLayerId) {
      smGroupShape.push(useLayer(element, ssLayerId, classPrefix + 'ss'))
    }

    layer.push(element('g', smGroupAttr, smGroupShape))
  }

  // add solderpaste
  if (spLayerId) {
    layer.push(useLayer(element, spLayerId, classPrefix + 'sp'))
  }

  // add board outline if necessary
  if (outLayerId && !useOutline) {
    layer.push(useLayer(element, outLayerId, classPrefix + 'out'))
  }

  return {
    defs: defs,
    layer: layer,
    mechMaskId: mechMaskId,
    outClipId: (outLayerId && useOutline) ? outLayerId : null,
    box: box,
    units: units
  }
}
<commit_msg>Refactor attribute variables in stack-layers<commit_after>// stack layers function (where the magic happens)
'use strict'

var viewbox = require('viewbox')

var gatherLayers = require('./_gather-layers')

var findLayerId = function(layers, type) {
  var layer
  var i

  for (i = 0; i < layers.length; i++) {
    layer = layers[i]
    if (layer.type === type) {
      return layer.id
    }
  }
}

var useLayer = function(element, id, className, mask) {
  var attr = {'xlink:href': '#' + id}

  if (className) {
    attr.fill = 'currentColor'
    attr.stroke = 'currentColor'
    attr.class = className
  }

  if (mask) {
    attr.mask = 'url(#' + mask + ')'
  }

  return element('use', attr)
}

var createRect = function(element, box, fill, className) {
  var attr = viewbox.rect(box)

  if (fill) {
    attr.fill = fill
  }

  if (className) {
    attr.class = className
  }

  return element('rect', attr)
}

var mechMask = function(element, id, box, drills) {
  var children = drills.map(function(layer) {
    return useLayer(element, layer.id)
  })

  children.unshift(createRect(element, box, '#fff'))

  var groupAttr = {fill: '#000', stroke: '#000'}
  var group = [element('g', groupAttr, children)]

  return element('mask', {id: id}, group)
}

module.exports = function(element, id, side, layers, drills, outline, useOutline) {
  var classPrefix = id + '_'
  var idPrefix = id + '_' + side + '_'
  var mechMaskId = idPrefix + 'mech-mask'

  var layerProps = gatherLayers(element, idPrefix, layers, drills, outline, useOutline)
  var defs = layerProps.defs
  var box = layerProps.box
  var units = layerProps.units

  layers = layerProps.layerIds
  drills = layerProps.drillIds

  defs.push(mechMask(element, mechMaskId, box, drills))

  // build the layer starting with an fr4 rectangle the size of the viewbox
  var layer = [createRect(element, box, 'currentColor', classPrefix + 'fr4')]
  var cuLayerId = findLayerId(layers, 'cu')
  var smLayerId = findLayerId(layers, 'sm')
  var ssLayerId = findLayerId(layers, 'ss')
  var spLayerId = findLayerId(layers, 'sp')
  var outLayerId = layerProps.outlineId

  // add copper and copper finish
  if (cuLayerId) {
    var cfMaskId = idPrefix + 'cf-mask'
    var cfMaskShape = smLayerId
      ? [element('use', {'xlink:href': '#' + smLayerId})]
      : [createRect(element, box)]
    var cfMaskGroupAttr =  {fill: '#fff', stroke: '#fff'}
    var cfMaskGroup = [element('g', cfMaskGroupAttr, cfMaskShape)]

    defs.push(element('mask', {id: cfMaskId}, cfMaskGroup))
    layer.push(useLayer(element, cuLayerId, classPrefix + 'cu'))
    layer.push(useLayer(element, cuLayerId, classPrefix + 'cf', cfMaskId))
  }

  // add soldermask and silkscreen
  // silkscreen will not be added if no soldermask, because that's how it works in RL
  if (smLayerId) {
    // solder mask is... a mask, so mask it
    var smMaskId = idPrefix + 'sm-mask'
    var smMaskShape = [
      createRect(element, box, '#fff'),
      element('use', {'xlink:href': '#' + smLayerId})
    ]
    var smMaskGroupAtrr = {fill: '#000', stroke: '#000'}
    var smMaskGroup = [element('g', smMaskGroupAtrr, smMaskShape)]

    defs.push(element('mask', {id: smMaskId}, smMaskGroup))

    // add the layer that gets masked
    var smGroupAttr = {mask: 'url(#' + smMaskId + ')'}
    var smGroupShape = [createRect(element, box, 'currentColor', classPrefix + 'sm')]

    if (ssLayerId) {
      smGroupShape.push(useLayer(element, ssLayerId, classPrefix + 'ss'))
    }

    layer.push(element('g', smGroupAttr, smGroupShape))
  }

  // add solderpaste
  if (spLayerId) {
    layer.push(useLayer(element, spLayerId, classPrefix + 'sp'))
  }

  // add board outline if necessary
  if (outLayerId && !useOutline) {
    layer.push(useLayer(element, outLayerId, classPrefix + 'out'))
  }

  return {
    defs: defs,
    layer: layer,
    mechMaskId: mechMaskId,
    outClipId: (outLayerId && useOutline) ? outLayerId : null,
    box: box,
    units: units
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2016 Teppo Kurki <teppo.kurki@iki.fi>
 *
 * 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.
 */

var Bacon = require('baconjs')
const _ = require('lodash')

function StreamBundle (selfId) {
  this.selfContext = 'vessels.' + selfId
  this.buses = {}
  this.selfBuses = {}
  this.streams = {}
  this.keys = new Bacon.Bus()
  this.availableSelfPaths = []
}

StreamBundle.prototype.pushDelta = function (delta) {
  try {
    if (delta.updates) {
      delta.updates.forEach(update => {
        if (update.values) {
          update.values.forEach(pathValue => {
            var paths =
              pathValue.path === ''
                ? getPathsFromObjectValue(pathValue.value)
                : [pathValue.path]
            /*
            For values with empty path and object value we enumerate all the paths in the object
            and push the original delta's value to all those buses, so that subscriptionmanager
            can track hits also for paths of naked values (no path, just object value) and when
            regenerating the outgoing delta will use the unmodified, original delta pathvalue.
          */
            paths.forEach(path => {
              this.push(path, {
                path: pathValue.path,
                value: pathValue.value,
                context: delta.context,
                source: update.source,
                $source: update.$source,
                timestamp: update.timestamp
              })
            })
          }, this)
        }
      }, this)
    }
  } catch (e) {
    console.error(e)
  }
}

function getPathsFromObjectValue (objectValue) {
  return Object.keys(objectValue).reduce((acc, propName) => {
    const propValue = objectValue[propName]
    if (_.isObject(propValue)) {
      accumulatePathsFromValues(acc, propName + '.', propValue)
    } else {
      acc.push(propName)
    }
    return acc
  }, [])
}

function accumulatePathsFromValues (acc, prefix, objectValue) {
  Object.keys(objectValue).forEach(propName => {
    const propValue = objectValue[propName]
    if (_.isObject(propValue)) {
      accumulatePathsFromValues(acc, `${prefix}.${propName}`, propValue)
    }
  })
}

StreamBundle.prototype.push = function (path, pathValueWithSourceAndContext) {
  if (this.availableSelfPaths.indexOf(path) == -1) {
    this.availableSelfPaths.push(path)
  }
  this.getBus(path).push(pathValueWithSourceAndContext)
  if (pathValueWithSourceAndContext.context === this.selfContext) {
    this.getSelfBus(path).push(pathValueWithSourceAndContext)
    this.getSelfStream(path).push(pathValueWithSourceAndContext.value)
  }
}

StreamBundle.prototype.getBus = function (path) {
  var result = this.buses[path]
  if (!result) {
    result = this.buses[path] = new Bacon.Bus()
    this.keys.push(path)
  }
  return result
}

StreamBundle.prototype.getSelfStream = function (path) {
  var result = this.streams[path]
  if (!result) {
    result = this.streams[path] = new Bacon.Bus()
  }
  return result
}

StreamBundle.prototype.getSelfBus = function (path) {
  var result = this.selfBuses[path]
  if (!result) {
    result = this.selfBuses[path] = new Bacon.Bus()
  }
  return result
}

StreamBundle.prototype.getAvailablePaths = function () {
  return this.availableSelfPaths
}

function toDelta (normalizedDeltaData) {
  return {
    context: normalizedDeltaData.context,
    updates: [
      {
        source: normalizedDeltaData.source,
        $source: normalizedDeltaData['$source'],
        timestamp: normalizedDeltaData.timestamp,
        values: [
          {
            path: normalizedDeltaData.path,
            value: normalizedDeltaData.value
          }
        ]
      }
    ]
  }
}

module.exports = { StreamBundle, toDelta }
<commit_msg>feature: getSelfStream/Bus per sourceId (#648)<commit_after>/*
 * Copyright 2016 Teppo Kurki <teppo.kurki@iki.fi>
 *
 * 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.
 */

var Bacon = require('baconjs')
const _ = require('lodash')
const isUndefined = _.isUndefined

function StreamBundle (selfId) {
  this.selfContext = 'vessels.' + selfId
  this.buses = {}
  this.selfBuses = {}
  this.streams = {}
  this.keys = new Bacon.Bus()
  this.availableSelfPaths = []
}

StreamBundle.prototype.pushDelta = function (delta) {
  try {
    if (delta.updates) {
      delta.updates.forEach(update => {
        if (update.values) {
          update.values.forEach(pathValue => {
            var paths =
              pathValue.path === ''
                ? getPathsFromObjectValue(pathValue.value)
                : [pathValue.path]
            /*
            For values with empty path and object value we enumerate all the paths in the object
            and push the original delta's value to all those buses, so that subscriptionmanager
            can track hits also for paths of naked values (no path, just object value) and when
            regenerating the outgoing delta will use the unmodified, original delta pathvalue.
          */
            paths.forEach(path => {
              this.push(path, {
                path: pathValue.path,
                value: pathValue.value,
                context: delta.context,
                source: update.source,
                $source: update.$source,
                timestamp: update.timestamp,
                key: getPathWithSourceId(pathValue.path, update.$source)
              })
            })
          }, this)
        }
      }, this)
    }
  } catch (e) {
    console.error(e)
  }
}

function getPathsFromObjectValue (objectValue) {
  return Object.keys(objectValue).reduce((acc, propName) => {
    const propValue = objectValue[propName]
    if (_.isObject(propValue)) {
      accumulatePathsFromValues(acc, propName + '.', propValue)
    } else {
      acc.push(propName)
    }
    return acc
  }, [])
}

function accumulatePathsFromValues (acc, prefix, objectValue) {
  Object.keys(objectValue).forEach(propName => {
    const propValue = objectValue[propName]
    if (_.isObject(propValue)) {
      accumulatePathsFromValues(acc, `${prefix}.${propName}`, propValue)
    }
  })
}

StreamBundle.prototype.push = function (path, pathValueWithSourceAndContext) {
  if (this.availableSelfPaths.indexOf(path) == -1) {
    this.availableSelfPaths.push(path)
  }
  this.getBus(path).push(pathValueWithSourceAndContext)
  if (pathValueWithSourceAndContext.context === this.selfContext) {
    this.getSelfBusByKey(path).push(pathValueWithSourceAndContext)
    this.getSelfBusByKey(pathValueWithSourceAndContext.key).push(
      pathValueWithSourceAndContext
    )
    this.getSelfStreamByKey(path).push(pathValueWithSourceAndContext.value)
    this.getSelfStreamByKey(pathValueWithSourceAndContext.key).push(
      pathValueWithSourceAndContext.value
    )
  }
}

StreamBundle.prototype.getBus = function (path) {
  var result = this.buses[path]
  if (!result) {
    result = this.buses[path] = new Bacon.Bus()
    this.keys.push(path)
  }
  return result
}

StreamBundle.prototype.getSelfStream = function (path, sourceId = undefined) {
  return getSelfStreamByKey(getPathWithSourceId(path, sourceId))
}

StreamBundle.prototype.getSelfStreamByKey = function (pathWithSourceId) {
  return (
    this.streams[pathWithSourceId] ||
    (this.streams[pathWithSourceId] = new Bacon.Bus())
  )
}

StreamBundle.prototype.getSelfBus = function (path, sourceId = undefined) {
  return this.getSelfBusByKey(getPathWithSourceId(path, sourceId))
}

StreamBundle.prototype.getSelfBusByKey = function (pathWithSourceId) {
  return (
    this.selfBuses[pathWithSourceId] ||
    (this.selfBuses[pathWithSourceId] = new Bacon.Bus())
  )
}

StreamBundle.prototype.getAvailablePaths = function () {
  return this.availableSelfPaths
}

function toDelta (normalizedDeltaData) {
  return {
    context: normalizedDeltaData.context,
    updates: [
      {
        source: normalizedDeltaData.source,
        $source: normalizedDeltaData['$source'],
        timestamp: normalizedDeltaData.timestamp,
        values: [
          {
            path: normalizedDeltaData.path,
            value: normalizedDeltaData.value
          }
        ]
      }
    ]
  }
}

const getPathWithSourceId = (path, sourceId) =>
  path + (isUndefined(sourceId) ? '' : `.${sourceId}`)

module.exports = { StreamBundle, toDelta }
<|endoftext|>


<commit_before>import superagent from "superagent-es6";

// closure
var serviceHandler = function (service) {
  return function (data, params, fn) {
    /*
     * - data (object): request data payload
     * - params (object): use to replace the tokens in the url
     * - fn (function): callback to used, with a default which emits 'success' or 'error'
     *   event depending on res.ok value
     *
     * support these different format calls:
     *
     *  - function (data, fn)
     *  - function (data, params, fn)
     */
    // function (data, fn) used
    if ('function' === typeof params && !fn) {
      params = undefined;
      fn = params;
    }
    var req = this.request(service, data, params).end(fn ? fn : function (res) {
      req.emit(res.ok ? "success" : "error", res, data, params);
    });
    return req;
  };
};

function Api(config) {
  this.config = config;

  // create a hash-liked object where all the services handlers are registered
  this.api = Object.create(null);

  for (var name in config.services) {
    if (!Object.prototype.hasOwnProperty(this, name)) {
      // syntatic sugar: install a service handler available on
      // the api instance with service name
      this.api[name] = serviceHandler(name).bind(this);
    }
  }
}

Api.prototype = {
  paramsPattern: /:([^/]+)/g,

  service: function (id) {
    return this.config.services[id];
  },

  url: function (id) {
    var url = this.config.baseUrl;
    var resource = this.service(id);

    // from time being it"s a simple map
    if (resource) {
      var path;

      if (typeof resource === "string") {
        path = resource;
      }

      if (typeof resource === "object" && resource.path !== undefined) {
        path = resource.path;
      }

      if (!path) {
        throw new Error("path is not defined for route $" + id);
      }

      url += path[0] === "/" ? path : "/" + path;
    }

    return url;
  },

  buildUrl: function (url, params) {
    var tokens = url.match(this.paramsPattern);

    if (!tokens.length) {
      return url;
    }

    for (var i = 0, len = tokens.length; i < len; i += 1) {
      var token = tokens[i];
      var name = token.substring(1);
      if (params[name]) {
        url = url.replace(token, params[name]);
      }
    }
    return url;
  },

  request: function (id, data, params) {
    var service = this.service(id);
    var method = (typeof service === "string" ? "get" : service.method || "get").toLowerCase();
    // fix for delete being a reserved word
    if (method === "delete") {
      method = "del";
    }
    var request = superagent[method];
    if (!request) {
      throw new Error("Invalid method [" + service.method + "]");
    }

    var url = this.url(id);

    if (params) {
      url = this.buildUrl(url, params);
    }

    var _req = request(url, data);
    var header, opts;

    // add global headers
    for (header in this.config.headers) {
      _req.set(header, this.config.headers[header]);
    }

    // add global options to request headers
    for (opts in this.config.options) {
      _req[opts](this.config.options[opts]);
    }

    // add service options to request headers
    for (opts in service.options) {
      _req[opts](service.options[opts]);
    }

    // add service headers
    for (header in service.headers) {
      _req.set(header, service.headers[header]);
    }

    // set credentials
    if (this.config.withCredentials) {
      _req.withCredentials();
    }

    return _req;
  }
};

export default Api;
<commit_msg>feat(headers): add runtime headers<commit_after>import superagent from "superagent-es6";

// closure
var serviceHandler = function (service) {
  return function (data, params, fn) {
    /*
     * - data (object): request data payload
     * - params (object): use to replace the tokens in the url
     * - fn (function): callback to used, with a default which emits 'success' or 'error'
     *   event depending on res.ok value
     *
     * support these different format calls:
     *
     *  - function (data, fn)
     *  - function (data, params, fn)
     */
    // function (data, fn) used
    if ('function' === typeof params && !fn) {
      params = undefined;
      fn = params;
    }
    var req = this.request(service, data, params).end(fn ? fn : function (res) {
      req.emit(res.ok ? "success" : "error", res, data, params);
    });
    return req;
  };
};

function Api(config) {
  this.config = config;

  // create a hash-liked object where all the services handlers are registered
  this.api = Object.create(null);

  for (var name in config.services) {
    if (!Object.prototype.hasOwnProperty(this, name)) {
      // syntatic sugar: install a service handler available on
      // the api instance with service name
      this.api[name] = serviceHandler(name).bind(this);
    }
  }
}

Api.prototype = {
  paramsPattern: /:([^/]+)/g,

  service: function (id) {
    return this.config.services[id];
  },

  url: function (id) {
    var url = this.config.baseUrl;
    var resource = this.service(id);

    // from time being it"s a simple map
    if (resource) {
      var path;

      if (typeof resource === "string") {
        path = resource;
      }

      if (typeof resource === "object" && resource.path !== undefined) {
        path = resource.path;
      }

      if (!path) {
        throw new Error("path is not defined for route $" + id);
      }

      url += path[0] === "/" ? path : "/" + path;
    }

    return url;
  },

  buildUrl: function (url, params) {
    var tokens = url.match(this.paramsPattern);

    if (!tokens.length) {
      return url;
    }

    for (var i = 0, len = tokens.length; i < len; i += 1) {
      var token = tokens[i];
      var name = token.substring(1);
      if (params[name]) {
        url = url.replace(token, params[name]);
      }
    }
    return url;
  },

  request: function (id, data, params) {
    var service = this.service(id);
    var method = (typeof service === "string" ? "get" : service.method || "get").toLowerCase();
    // fix for delete being a reserved word
    if (method === "delete") {
      method = "del";
    }
    var request = superagent[method];
    if (!request) {
      throw new Error("Invalid method [" + service.method + "]");
    }

    var url = this.url(id);

    if (params) {
      url = this.buildUrl(url, params);
    }

    var _req = request(url, data);
    var header, opts;

    // add global headers
    for (header in this.config.headers) {
      _req.set(header, this.config.headers[header]);
    }

    // add global options to request headers
    for (opts in this.config.options) {
      _req[opts](this.config.options[opts]);
    }

    // add service options to request headers
    for (opts in service.options) {
      _req[opts](service.options[opts]);
    }

    // add service headers
    for (header in service.headers) {
      _req.set(header, service.headers[header]);
    }

    // add runtime headers
    for (header in this.headers) {
      _req.set(header, this.headers[header]);
    }

    // set credentials
    if (this.config.withCredentials) {
      _req.withCredentials();
    }

    return _req;
  },

  addHeader: function (name, value) {
    this.headers = this.headers || {};
    this.headers[name] = value;
  }
};

export default Api;
<|endoftext|>


<commit_before>import fs from 'fs'
import path from 'path'
import mkdirp from 'mkdirp'
import validator from 'validator'

import { COLORS, ERROR_CODES } from '../helpers/constants'
import sanitize from '../helpers/sanitize'

const BANNER = `
${COLORS.yellow}=======================================================================================${COLORS.reset}
Selenium 2.0 / webdriver protocol bindings implementation with helper commands in nodejs.
For a complete list of commands, visit ${COLORS.lime}http://webdriver.io/docs.html${COLORS.reset}.
${COLORS.yellow}=======================================================================================${COLORS.reset}
`

/**
 * Logger module
 *
 * A Logger helper with fancy colors
 */
class Logger {
    constructor (options, eventHandler) {
        /**
         * log level
         * silent : no logs
         * command : command only
         * result : result only
         * error : error only
         * verbose : command + data + result
         */
        this.logLevel = options.logLevel

        this.setupWriteStream(options)

        /**
         * disable colors if coloredLogs is set to false or if we pipe output into files
         */
        if (!JSON.parse(process.env.WEBDRIVERIO_COLORED_LOGS) || this.writeStream) {
            Object.keys(COLORS).forEach(colorName => COLORS[colorName] = '')
        }

        /**
         * print welcome message
         */
        if (this.logLevel !== 'silent' && !this.infoHasBeenShown) {
            this.write(BANNER)
            this.infoHasBeenShown = true
        }

        // register event handler to log command events
        eventHandler.on('command', (data) => {
            if (this.logLevel === 'command' || this.logLevel === 'verbose') {
                this.command(data.method, data.uri.path)
            }
            if (this.logLevel === 'data' || this.logLevel === 'verbose') {
                this.data(data.data)
            }
        })

        // register event handler to log result events
        eventHandler.on('result', (data) => {
            // only log result events if they got executed successfully
            if (data.body && data.body.status === 0 && (this.logLevel === 'result' || this.logLevel === 'verbose')) {
                this.result(typeof data.body.value ? data.body.value : data.body.orgStatusMessage)
            }
        })

        // register event handler to log error events
        eventHandler.on('error', (data) => {
            if (data.err && data.err.code === 'ECONNREFUSED') {
                this.error(`Couldn't find a running selenium server instance on ${data.requestOptions.uri}`)
            } else if (data.err && data.err.code === 'ENOTFOUND') {
                this.error(`Couldn't resolve hostname ${data.requestOptions.uri}`)
            } else if (data.err && data.err.code === 'NOSESSIONID') {
                this.error(`Couldn't get a session ID - ${data.err.message}`)
            } else if (this.logLevel === 'error' || this.logLevel === 'verbose') {
                if (data.body && ERROR_CODES[data.body.status]) {
                    this.error(ERROR_CODES[data.body.status].id + '\t' + ERROR_CODES[data.body.status].message + '\n\t\t\t' + data.body.value.message)
                } else if (typeof data.message === 'string') {
                    this.error('ServerError\t' + data.message)
                } else {
                    this.error(ERROR_CODES['-1'].id + '\t' + ERROR_CODES['-1'].message)
                }
            }
        })
    }

    /**
     * creates log file name and directories if not existing
     * @param  {Object} caps          capabilities (required to create filename)
     * @param  {String} logOutputPath specified log directory
     * @return {Buffer}               log file buffer stream
     */
    getLogfile (caps, logOutputPath) {
        logOutputPath = logOutputPath[0] === '/' ? logOutputPath : path.join(process.cwd(), logOutputPath)

        /**
         * create directory if not existing
         */
        try {
            fs.statSync(logOutputPath)
        } catch (e) {
            mkdirp.sync(logOutputPath)
        }

        let newDate = new Date()
        let dateString = newDate.toISOString().split(/\./)[0]
        let filename = sanitize.caps(caps) + '.' + dateString + '.' + process.pid + '.log'

        return fs.createWriteStream(path.join(logOutputPath, filename))
    }

    /**
     * create write stream if logOutput is a string
     */
    setupWriteStream (options) {
        if (typeof options.logOutput === 'string') {
            this.writeStream = this.getLogfile(options.desiredCapabilities, options.logOutput)
            this.logLevel = this.logLevel === 'silent' ? 'verbose' : this.logLevel
        } else if (typeof options.logOutput === 'object' && options.logOutput.writable) {
            this.writeStream = options.logOutput
            this.logLevel = this.logLevel === 'silent' ? 'verbose' : this.logLevel
        }
    }

    write (...messages) {
        let msgString = messages.join(' ')

        if (this.writeStream) {
            this.writeStream.write(msgString + '\n')
        } else {
            console.log(msgString)
        }
    }

    /**
     * main log function
     */
    log (message, content) {
        if (!this.logLevel || this.logLevel === 'silent') {
            return
        }

        let currentDate = new Date()
        let dateString = currentDate.toString().match(/\d\d:\d\d:\d\d/)[0]
        let preamble = `${COLORS.dkgray}[${dateString}] ${COLORS.reset}`

        if (!content) {
            this.write(preamble, message)
        } else {
            this.write(preamble, message, '\t', JSON.stringify(content))
        }
    }

    /**
     * logs command messages
     * @param  {String} method  method of command request
     * @param  {String} path    path of command request
     */
    command (method, path) {
        if (method && path) {
            this.log(`${COLORS.violet}COMMAND\t${COLORS.reset}${method}`, path)
        }
    }

    /**
     * debugger info message
     */
    debug () {
        this.write('\n')
        this.log(`${COLORS.yellow}DEBUG\t${COLORS.reset}queue has stopped, you can now go into the browser`)
        this.log(`${COLORS.yellow}DEBUG\t${COLORS.dkgray}continue by pressing the [ENTER] key ...${COLORS.reset}`)
    }

    /**
     * logs data messages
     * @param  {Object} data  data object
     */
    data (data) {
        data = JSON.stringify(data)

        if (data.length > 1000) {
            data = '[String Buffer]'
        }

        if (data && keySize(data) !== 0 && (this.logLevel === 'data' || this.logLevel === 'verbose')) {
            this.log(`${COLORS.brown}DATA\t\t${COLORS.reset}${data}`)
        }
    }

    /**
     * logs result messages
     * @param  {Object} result  result object
     */
    result (result) {
        if (typeof result === 'string' && validator.isBase64(result)) {
            result = '[base64] ' + result.length + ' bytes'
        } else if (typeof result === 'object') {
            result = JSON.stringify(result)
        }

        this.log(`${COLORS.teal}RESULT\t\t${COLORS.reset}${result}`)
    }

    /**
     * logs error messages
     * @param  {String} msg  error message
     */
    error (msg) {
        if (msg && typeof msg === 'string' && msg.indexOf('caused by Request') !== -1) {
            msg = msg.substr(0, msg.indexOf('caused by Request') - 2)
        }

        if (msg && typeof msg === 'string' && msg.indexOf('Command duration or timeout') !== -1) {
            msg = msg.substr(0, msg.indexOf('Command duration or timeout'))
        }

        if (msg && typeof msg === 'string' && msg.indexOf('ID does not correspond to an open view') !== -1) {
            msg = msg.substr(0, msg.indexOf('ID does not correspond to an open view'))
            msg += 'NOTE: you probably try to continue your tests after closing a tab/window. Please set the focus on a current opened tab/window to continue. Use the window protocol command to do so.'
        }

        if (msg) {
            this.log(COLORS.red + 'ERROR\t' + COLORS.reset + msg, null)
        }
    }

    /**
     * print exception if command fails
     * @param {String}   type        error type
     * @param {String}   message     error message
     * @param {String[]} stacktrace  error stacktrace
     */
    static printException (type, message, stacktrace) {
        stacktrace = stacktrace.map(trace => '    at ' + trace)
        this.write(COLORS.dkred + (type || 'Error') + ': ' + message + COLORS.reset, null)
        this.write(COLORS.dkgray + stacktrace.reverse().join('\n') + COLORS.reset, null)
    }
}

/**
 * helper method to check size of object
 * @param   {Object}   obj  object you like to check
 * @return  {Integer}       number of own properties
 */
let keySize = function (obj) {
    let size = 0

    for (let key in obj) {
        if (obj.hasOwnProperty(key)) size++
    }

    return size
}

export default Logger
<commit_msg>Limit very long results in the log output<commit_after>import fs from 'fs'
import path from 'path'
import mkdirp from 'mkdirp'
import validator from 'validator'

import { COLORS, ERROR_CODES } from '../helpers/constants'
import sanitize from '../helpers/sanitize'

const BANNER = `
${COLORS.yellow}=======================================================================================${COLORS.reset}
Selenium 2.0 / webdriver protocol bindings implementation with helper commands in nodejs.
For a complete list of commands, visit ${COLORS.lime}http://webdriver.io/docs.html${COLORS.reset}.
${COLORS.yellow}=======================================================================================${COLORS.reset}
`

const STRINGLIMIT = 1000

/**
 * Logger module
 *
 * A Logger helper with fancy colors
 */
class Logger {
    constructor (options, eventHandler) {
        /**
         * log level
         * silent : no logs
         * command : command only
         * result : result only
         * error : error only
         * verbose : command + data + result
         */
        this.logLevel = options.logLevel

        this.setupWriteStream(options)

        /**
         * disable colors if coloredLogs is set to false or if we pipe output into files
         */
        if (!JSON.parse(process.env.WEBDRIVERIO_COLORED_LOGS) || this.writeStream) {
            Object.keys(COLORS).forEach(colorName => COLORS[colorName] = '')
        }

        /**
         * print welcome message
         */
        if (this.logLevel !== 'silent' && !this.infoHasBeenShown) {
            this.write(BANNER)
            this.infoHasBeenShown = true
        }

        // register event handler to log command events
        eventHandler.on('command', (data) => {
            if (this.logLevel === 'command' || this.logLevel === 'verbose') {
                this.command(data.method, data.uri.path)
            }
            if (this.logLevel === 'data' || this.logLevel === 'verbose') {
                this.data(data.data)
            }
        })

        // register event handler to log result events
        eventHandler.on('result', (data) => {
            // only log result events if they got executed successfully
            if (data.body && data.body.status === 0 && (this.logLevel === 'result' || this.logLevel === 'verbose')) {
                this.result(typeof data.body.value ? data.body.value : data.body.orgStatusMessage)
            }
        })

        // register event handler to log error events
        eventHandler.on('error', (data) => {
            if (data.err && data.err.code === 'ECONNREFUSED') {
                this.error(`Couldn't find a running selenium server instance on ${data.requestOptions.uri}`)
            } else if (data.err && data.err.code === 'ENOTFOUND') {
                this.error(`Couldn't resolve hostname ${data.requestOptions.uri}`)
            } else if (data.err && data.err.code === 'NOSESSIONID') {
                this.error(`Couldn't get a session ID - ${data.err.message}`)
            } else if (this.logLevel === 'error' || this.logLevel === 'verbose') {
                if (data.body && ERROR_CODES[data.body.status]) {
                    this.error(ERROR_CODES[data.body.status].id + '\t' + ERROR_CODES[data.body.status].message + '\n\t\t\t' + data.body.value.message)
                } else if (typeof data.message === 'string') {
                    this.error('ServerError\t' + data.message)
                } else {
                    this.error(ERROR_CODES['-1'].id + '\t' + ERROR_CODES['-1'].message)
                }
            }
        })
    }

    /**
     * creates log file name and directories if not existing
     * @param  {Object} caps          capabilities (required to create filename)
     * @param  {String} logOutputPath specified log directory
     * @return {Buffer}               log file buffer stream
     */
    getLogfile (caps, logOutputPath) {
        logOutputPath = logOutputPath[0] === '/' ? logOutputPath : path.join(process.cwd(), logOutputPath)

        /**
         * create directory if not existing
         */
        try {
            fs.statSync(logOutputPath)
        } catch (e) {
            mkdirp.sync(logOutputPath)
        }

        let newDate = new Date()
        let dateString = newDate.toISOString().split(/\./)[0]
        let filename = sanitize.caps(caps) + '.' + dateString + '.' + process.pid + '.log'

        return fs.createWriteStream(path.join(logOutputPath, filename))
    }

    /**
     * create write stream if logOutput is a string
     */
    setupWriteStream (options) {
        if (typeof options.logOutput === 'string') {
            this.writeStream = this.getLogfile(options.desiredCapabilities, options.logOutput)
            this.logLevel = this.logLevel === 'silent' ? 'verbose' : this.logLevel
        } else if (typeof options.logOutput === 'object' && options.logOutput.writable) {
            this.writeStream = options.logOutput
            this.logLevel = this.logLevel === 'silent' ? 'verbose' : this.logLevel
        }
    }

    write (...messages) {
        let msgString = messages.join(' ')

        if (this.writeStream) {
            this.writeStream.write(msgString + '\n')
        } else {
            console.log(msgString)
        }
    }

    /**
     * main log function
     */
    log (message, content) {
        if (!this.logLevel || this.logLevel === 'silent') {
            return
        }

        let currentDate = new Date()
        let dateString = currentDate.toString().match(/\d\d:\d\d:\d\d/)[0]
        let preamble = `${COLORS.dkgray}[${dateString}] ${COLORS.reset}`

        if (!content) {
            this.write(preamble, message)
        } else {
            this.write(preamble, message, '\t', JSON.stringify(content))
        }
    }

    /**
     * logs command messages
     * @param  {String} method  method of command request
     * @param  {String} path    path of command request
     */
    command (method, path) {
        if (method && path) {
            this.log(`${COLORS.violet}COMMAND\t${COLORS.reset}${method}`, path)
        }
    }

    /**
     * debugger info message
     */
    debug () {
        this.write('\n')
        this.log(`${COLORS.yellow}DEBUG\t${COLORS.reset}queue has stopped, you can now go into the browser`)
        this.log(`${COLORS.yellow}DEBUG\t${COLORS.dkgray}continue by pressing the [ENTER] key ...${COLORS.reset}`)
    }

    /**
     * logs data messages
     * @param  {Object} data  data object
     */
    data (data) {
        data = JSON.stringify(data)

        if (data.length > STRINGLIMIT) {
            data = '[String Buffer]'
        }

        if (data && keySize(data) !== 0 && (this.logLevel === 'data' || this.logLevel === 'verbose')) {
            this.log(`${COLORS.brown}DATA\t\t${COLORS.reset}${data}`)
        }
    }

    /**
     * logs result messages
     * @param  {Object} result  result object
     */
    result (result) {
        if (typeof result === 'string' && validator.isBase64(result)) {
            result = '[base64] ' + result.length + ' bytes'
        } else if (typeof result === 'object') {
            result = JSON.stringify(result)
            if (result.length > STRINGLIMIT) result = `${result.substr(0, STRINGLIMIT)}... (${result.length - STRINGLIMIT} more bytes)`
        }

        this.log(`${COLORS.teal}RESULT\t\t${COLORS.reset}${result}`)
    }

    /**
     * logs error messages
     * @param  {String} msg  error message
     */
    error (msg) {
        if (msg && typeof msg === 'string' && msg.indexOf('caused by Request') !== -1) {
            msg = msg.substr(0, msg.indexOf('caused by Request') - 2)
        }

        if (msg && typeof msg === 'string' && msg.indexOf('Command duration or timeout') !== -1) {
            msg = msg.substr(0, msg.indexOf('Command duration or timeout'))
        }

        if (msg && typeof msg === 'string' && msg.indexOf('ID does not correspond to an open view') !== -1) {
            msg = msg.substr(0, msg.indexOf('ID does not correspond to an open view'))
            msg += 'NOTE: you probably try to continue your tests after closing a tab/window. Please set the focus on a current opened tab/window to continue. Use the window protocol command to do so.'
        }

        if (msg) {
            this.log(COLORS.red + 'ERROR\t' + COLORS.reset + msg, null)
        }
    }

    /**
     * print exception if command fails
     * @param {String}   type        error type
     * @param {String}   message     error message
     * @param {String[]} stacktrace  error stacktrace
     */
    static printException (type, message, stacktrace) {
        stacktrace = stacktrace.map(trace => '    at ' + trace)
        this.write(COLORS.dkred + (type || 'Error') + ': ' + message + COLORS.reset, null)
        this.write(COLORS.dkgray + stacktrace.reverse().join('\n') + COLORS.reset, null)
    }
}

/**
 * helper method to check size of object
 * @param   {Object}   obj  object you like to check
 * @return  {Integer}       number of own properties
 */
let keySize = function (obj) {
    let size = 0

    for (let key in obj) {
        if (obj.hasOwnProperty(key)) size++
    }

    return size
}

export default Logger
<|endoftext|>


<commit_before>'use strict';

var moment = require('moment');
var fs = require('fs');
var path = require('path');
var convict = require('convict');
var jobSchema = require('../../jobSchema');
var convictFormats = require('./convict_utils');

var insertAnalyzers = require('./analytics').insertAnalyzers;
var workerCount = require('os').cpus().length;
var processDone = 0;

var _context;

var argv = require('yargs')
    .alias('j', 'job')
    .argv;

function getJob() {
    var jobFile;
    jobFile = process.cwd() + '/job.json';

    if (argv.job) {
        jobFile = argv.job;
    }

    if (jobFile.indexOf('.') === 0) {
        jobFile = process.cwd() + '/' + jobFile;
    }

    if (!fs.existsSync(jobFile)) {
        throw new Error("Could not find a usable job.json at path: " + jobFile);
    }
    return require(jobFile);
}

function getPath(type, opconfig, opPath) {
    var firstPath = path.join(opPath, type, opconfig);
    firstPath += '.js';
    var nextPath = '../' + type + '/' + opconfig;

    try {
        if (fs.existsSync(firstPath)) {
            return require(firstPath);
        }
        else {

            return require(nextPath);
        }
    }
    catch (e) {
        throw new Error('Could not retrieve code for: ' + opconfig + '\n' + e);
    }

}

function validateOperation(schema, jobConfig) {
    var config = schema.load(jobConfig).validate(/*{strict: true}*/);
    return config.getProperties();
}

function initializeJob(context) {
    _context = context;
    var opPath;

    if (context.sysconfig.teraslice && context.sysconfig.teraslice.ops_directory) {
        opPath = context.sysconfig.teraslice.ops_directory;
    }

    var job = getJob();
    var reader;
    var sender;
    var readerConfig;
    var senderConfig;
    var queue = [];

    convictFormats.forEach(function(obj){
        convict.addFormat(obj)
    });

    //top level job validation occurs, but not operations
    var validJob = validateOperation(jobSchema, job);
    var validOpConfig = [];

    job.operations.forEach(function(jobConfig, i){
        //Reader
        if (i === 0) {
            reader = getPath('readers', jobConfig.op, opPath);
            readerConfig = validateOperation(reader.schema(), jobConfig);
            validOpConfig.push(readerConfig);
            queue.push(reader.newReader.bind(null, context, readerConfig));
        }
        //Sender
        else if (i === job.operations.length - 1) {
            sender = getPath('senders', jobConfig.op, opPath);
            senderConfig = validateOperation(sender.schema(), jobConfig);
            validOpConfig.push(senderConfig)
            queue.push(sender.newSender.bind(null,context, senderConfig));
        }
        //Processor
        else {
            var processor = getPath('processors', jobConfig.op, opPath);
           var processConfig = validateOperation(processor.schema(), jobConfig);
            validOpConfig.push(processConfig);
            queue.push(processor.newProcessor.bind(null, context, processConfig));
        }
    });

    //now the operations are correctly validated, the entire job is now properly validated
    validJob.operations = validOpConfig;

    //need to pass in fully validated job to function in queue
    var jobQueue = queue.map(function(fn){
        return fn(validJob);
    });

    //console.log('what is this',jobQueue[0])

    var scheduler = lifecycle(validJob);
    var max_retries = validJob.max_retries;

    if (job.analytics) {
        jobQueue = insertAnalyzers(queue);
    }

    return {
        analytics: validJob.analytics,
        reader: reader,
        sender: sender,
        jobs: validJob.operations,
        queue: jobQueue,
        readerConfig: readerConfig,
        scheduler: scheduler,
        jobConfig: validJob,
        max_retries: max_retries

    };
}

function sendMessage(cluster, id, message) {
    cluster.workers[id].send(message);
}

function lifecycle(job) {
    if (job.lifecycle === 'once') {
        return once;
    }
    if (job.lifecycle === 'periodic') {
        return periodic;
    }
    if (job.lifecycle === 'persistent') {
        return persistent;
    }
}

function periodic(msg) {

}

function persistent(reader, start) {
    var nextSlice = reader;
    var start = start;
    var logger = _context.logger;

    return function(msg) {
        if (msg.message === 'ready') {
            Promise.resolve(nextSlice(msg))
                .then(function(data) {
                    //not null or undefined
                    if (data != null) {
                        sendMessage(_context.cluster, msg.id, {message: 'data', data: data})
                    }

                })

        }
    }
}

function once(reader, start) {
    var nextSlice = reader;
    var start = start;
    var logger = _context.logger;

    return function(msg) {
        if (msg.message === 'ready') {
            Promise.resolve(nextSlice(msg))
                .then(function(data) {
                    //not null or undefined
                    if (data != null) {
                        sendMessage(_context.cluster, msg.id, {message: 'data', data: data})
                    }
                    else {
                        processDone++;
                        if (processDone === workerCount) {

                            var end = moment();
                            var time = (end - start ) / 1000;

                            logger.info('processing has finished in ' + time + ' seconds, will now exit');
                            process.exit()
                        }
                    }
                })
        }
    }
}

module.exports = {
    initializeJob: initializeJob,
    sendMessage: sendMessage
};<commit_msg>ops do not really on convict resolves #25<commit_after>'use strict';

var moment = require('moment');
var fs = require('fs');
var path = require('path');
var convict = require('convict');
var jobSchema = require('../../jobSchema');
var convictFormats = require('./convict_utils');
var convict = require('convict');

var insertAnalyzers = require('./analytics').insertAnalyzers;
var workerCount = require('os').cpus().length;
var processDone = 0;

var _context;

var argv = require('yargs')
    .alias('j', 'job')
    .argv;

function getJob() {
    var jobFile;
    jobFile = process.cwd() + '/job.json';

    if (argv.job) {
        jobFile = argv.job;
    }

    if (jobFile.indexOf('.') === 0) {
        jobFile = process.cwd() + '/' + jobFile;
    }

    if (!fs.existsSync(jobFile)) {
        throw new Error("Could not find a usable job.json at path: " + jobFile);
    }

    return require(jobFile);
}

function getPath(type, opconfig, opPath) {
    var firstPath = path.join(opPath, type, opconfig);
    firstPath += '.js';
    var nextPath = '../' + type + '/' + opconfig;

    try {
        if (fs.existsSync(firstPath)) {
            return require(firstPath);
        }
        else {

            return require(nextPath);
        }
    }
    catch (e) {
        throw new Error('Could not retrieve code for: ' + opconfig + '\n' + e);
    }

}

function validateOperation(schema, job) {
    var config = convict(schema);
    config.load(job).validate(/*{strict: true}*/);
    return config.getProperties();
}

function initializeJob(context) {
    _context = context;
    var opPath;

    if (context.sysconfig.teraslice && context.sysconfig.teraslice.ops_directory) {
        opPath = context.sysconfig.teraslice.ops_directory;
    }

    var job = getJob();
    var reader;
    var sender;
    var readerConfig;
    var senderConfig;
    var queue = [];

    convictFormats.forEach(function(obj){
        convict.addFormat(obj)
    });

    //top level job validation occurs, but not operations
    var validJob = validateOperation(jobSchema, job);
    var validOpConfig = [];

    job.operations.forEach(function(jobConfig, i){
        //Reader
        if (i === 0) {
            reader = getPath('readers', jobConfig.op, opPath);
            readerConfig = validateOperation(reader.schema(), jobConfig);
            validOpConfig.push(readerConfig);
            queue.push(reader.newReader.bind(null, context, readerConfig));
        }
        //Sender
        else if (i === job.operations.length - 1) {
            sender = getPath('senders', jobConfig.op, opPath);
            senderConfig = validateOperation(sender.schema(), jobConfig);
            validOpConfig.push(senderConfig)
            queue.push(sender.newSender.bind(null,context, senderConfig));
        }
        //Processor
        else {
            var processor = getPath('processors', jobConfig.op, opPath);
           var processConfig = validateOperation(processor.schema(), jobConfig);
            validOpConfig.push(processConfig);
            queue.push(processor.newProcessor.bind(null, context, processConfig));
        }
    });

    //now the operations are correctly validated, the entire job is now properly validated
    validJob.operations = validOpConfig;

    //need to pass in fully validated job to function in queue
    var jobQueue = queue.map(function(fn){
        return fn(validJob);
    });

    var scheduler = lifecycle(validJob);
    var max_retries = validJob.max_retries;

    if (job.analytics) {
        jobQueue = insertAnalyzers(queue);
    }

    return {
        analytics: validJob.analytics,
        reader: reader,
        sender: sender,
        jobs: validJob.operations,
        queue: jobQueue,
        readerConfig: readerConfig,
        scheduler: scheduler,
        jobConfig: validJob,
        max_retries: max_retries

    };
}

function sendMessage(cluster, id, message) {
    cluster.workers[id].send(message);
}

function lifecycle(job) {
    if (job.lifecycle === 'once') {
        return once;
    }
    if (job.lifecycle === 'periodic') {
        return periodic;
    }
    if (job.lifecycle === 'persistent') {
        return persistent;
    }
}

function periodic(msg) {

}

function persistent(reader, start) {
    var nextSlice = reader;
    var start = start;
    var logger = _context.logger;

    return function(msg) {
        if (msg.message === 'ready') {
            Promise.resolve(nextSlice(msg))
                .then(function(data) {
                    //not null or undefined
                    if (data != null) {
                        sendMessage(_context.cluster, msg.id, {message: 'data', data: data})
                    }

                })

        }
    }
}

function once(reader, start) {
    var nextSlice = reader;
    var start = start;
    var logger = _context.logger;

    return function(msg) {
        if (msg.message === 'ready') {
            Promise.resolve(nextSlice(msg))
                .then(function(data) {
                    //not null or undefined
                    if (data != null) {
                        sendMessage(_context.cluster, msg.id, {message: 'data', data: data})
                    }
                    else {
                        processDone++;
                        if (processDone === workerCount) {

                            var end = moment();
                            var time = (end - start ) / 1000;

                            logger.info('processing has finished in ' + time + ' seconds, will now exit');
                            process.exit()
                        }
                    }
                })
        }
    }
}

module.exports = {
    initializeJob: initializeJob,
    sendMessage: sendMessage
};<|endoftext|>