<commit_before>const sfw = require('../lib')

const path = require('path')
const fs = require('mz/fs')

describe('entry point', function () {
  let mainLogFile, workerLogFile

  beforeEach(function () {
    mainLogFile = path.join(__dirname, '..', 'main.log')
    workerLogFile = path.join(__dirname, '..', 'worker.log')
  })

  afterEach(async function () {
    await Promise.all(
      [mainLogFile, workerLogFile].map(fname => fs.unlink(fname).catch(() => {}))
    )
  })

  describe('configuration', function () {
    it('validates its arguments', async function () {
      await assert.isRejected(sfw.configure(), /requires an option object/)
    })

    it('configures the main thread logger', async function () {
      await sfw.configure({mainLogFile})

      const contents = await fs.readFile(mainLogFile)
      assert.match(contents, /FileLogger opened/)
    })

    it('configures the worker thread logger', async function () {
      await sfw.configure({workerLogFile})

      const contents = await fs.readFile(workerLogFile)
      assert.match(contents, /FileLogger opened/)
    })
  })
})
<commit_msg>Dump log file contents on test failures<commit_after>const sfw = require('../lib')

const path = require('path')
const fs = require('mz/fs')

describe('entry point', function () {
  let mainLogFile, workerLogFile

  beforeEach(function () {
    mainLogFile = path.join(__dirname, '..', 'main.test.log')
    workerLogFile = path.join(__dirname, '..', 'worker.test.log')
  })

  afterEach(async function () {
    if (this.currentTest.state === 'failed') {
      const [mainLog, workerLog] = await Promise.all(
        [mainLogFile, workerLogFile].map(fname => fs.readFile(fname, {encoding: 'utf8'}).catch(() => ''))
      )

      console.log(`main log:\n${mainLog}`)
      console.log(`worker log:\n${workerLog}`)
    }

    await Promise.all(
      [mainLogFile, workerLogFile].map(fname => fs.unlink(fname).catch(() => {}))
    )
  })

  describe('configuration', function () {
    it('validates its arguments', async function () {
      await assert.isRejected(sfw.configure(), /requires an option object/)
    })

    it('configures the main thread logger', async function () {
      await sfw.configure({mainLogFile})

      const contents = await fs.readFile(mainLogFile)
      assert.match(contents, /FileLogger opened/)
    })

    it('configures the worker thread logger', async function () {
      await sfw.configure({workerLogFile})

      const contents = await fs.readFile(workerLogFile)
      assert.match(contents, /FileLogger opened/)
    })
  })
})
<|endoftext|>


<commit_before>'use strict';

/*
function toFloatHex(args, argIdx, fd) {
    return parseFloat(args[argIdx]).toString(16);
}
*/

exports.convertArgToStr = function(arg, fd) {

    if (typeof fd !== 'object' || fd.conversion === undefined || arg === undefined)
        return '';

    // Get the target format of the conversion character, so we can work with it.
    var convResult;

    switch (fd.conversion) {
    case '%':       // A % followed by another % character will write a single %
        return '%';
    case 'a':       // hexadecimal floating point, lowercase
    case 'A':       // hexadecimal floating point, uppercase
    case 'e':       // Scientific notation (mantissa/exponent), lowercase  3.9265e+2
    case 'E':       // Scientific notation (mantissa/exponent), uppercase  3.9265E+2
    case 'f':       // Decimal floating point, lowercase   392.65
    case 'F':       // Decimal floating point, uppercase   392.65
    case 'g':       // Use the shortest representation: %e or %f
    case 'G':       // Use the shortest representation: %E or %F
        convResult = parseFloat(arg);
        fd.sign = (convResult >= 0) ? '+' : '-';
        fd.sign2 = (convResult >= 0) ? ' ' : '-';
        break;
    case 'c':       // character
        if (typeof arg === 'number')
            convResult = String.fromCharCode(parseInt(arg, 10));
        else
            convResult = String(arg.substring(0,1));
        break;
    case 'b':       // Unsigned hexadecimal integer (uppercase)
    case 'B':       // Unsigned hexadecimal integer (uppercase)
    case 'd':       // Signed decimal integer
    case 'i':       // signed decimal
    case 'o':       // Unsigned octal
    case 'u':       // Unsigned decimal integer
    case 'x':       // Unsigned hexadecimal integer lowercase
    case 'X':       // Unsigned hexadecimal integer (uppercase)
        convResult = parseInt(arg, 10);
        fd.sign = (convResult >= 0) ? '+' : '-';
        fd.sign2 = (convResult >= 0) ? ' ' : '-';
        break;
    case 'n':       // do nothing
    case 'p':       // do nothing
        return '';
    case 's':       // string
    case 'S':       // string
        convResult = String(arg);
        break;
    default:        // error case
        break;
    }

    // create the field by width, if specified
    switch (fd.conversion) {
    case 'f':       // Decimal floating point, lowercase   392.65
    case 'F':       // Decimal floating point, uppercase   392.65
    case 'a':       // hexadecimal floating point, lowercase
    case 'A':       // hexadecimal floating point, uppercase
    case 'e':       // Scientific notation (mantissa/exponent), lowercase  3.9265e+2
    case 'E':       // Scientific notation (mantissa/exponent), uppercase  3.9265E+2
    case 'g':       // Use the shortest representation: %e or %f
    case 'G':       // Use the shortest representation: %E or %F
        convResult = toFloat(convResult, fd);
        break;
    case 'c':       // character
    case 'C':       // character
    case 's':       // string
    case 'S':       // string
        convResult = toStr(convResult, fd);
        break;
    case 'd':       // Signed decimal integer
    case 'i':       // signed decimal
    case 'o':       // Unsigned octal
    case 'u':       // Unsigned decimal integer
    case 'x':       // Unsigned hexadecimal integer lowercase
    case 'X':       // Unsigned hexadecimal integer (uppercase)
    case 'b':       // Unsigned hexadecimal integer (uppercase)
    case 'B':       // Unsigned hexadecimal integer (uppercase)
        convResult = toInt(convResult, fd);
        break;
    case 'n':       // do nothing
    case 'p':       // do nothing
        return '';
    default:        // error case
        return '';
    }

    return convResult;
};

function toStr(convResult, fd) {

    var i;
    var pad;

    // if a charcter, we only take the first character
    if (fd.conversion === 'c' && convResult.length > 1)
        convResult = convResult.substring(0);
    // precision means how mny characters from the string we display
    else if (typeof fd.precision === 'number' && fd.precision < convResult.length)
        convResult = convResult.substring(0, fd.precision);

    // do we need to pad due to field with?
    if (fd.fieldWidth && fd.fieldWidth > convResult.length) {
        pad = fd.fieldWidth - convResult.length;
        if (fd.flags.leftJustified) {
            for (i=0; i<pad; i++) convResult += ' ';
        } else {
            for (i=0; i<pad; i++) convResult = ' ' + convResult;
        }
    }

    if (fd.conversion === 'S' || fd.conversion === 'C')
        convResult = convResult.toUpperCase();
    else if (fd.conversion === 't')
        convResult = convResult.toLowerCase();

    return convResult;
}

function toInt(arg, fd) {

    var isNeg = arg < 0 && fd.conversion.toLowerCase() !== 'u' ? true : false;

    // remove fractional part of value, if any - we don't need it
    // and remove the sign, we'll add it back later, if needed
    arg = Math.abs(Math.floor(arg));

    var i;
    var radix = 10;
    switch (fd.conversion.toLowerCase()) {
    case 'x':
        radix = 16;
        break;
    case 'o':
        radix = 8;
        break;
    case 'b':
        radix = 2;
        break;
    }
    var convResult = arg.toString(radix);

    // do we need to pad due to field with?
    if (fd.fieldWidth && fd.fieldWidth > convResult.length) {
        var pad = fd.fieldWidth - convResult.length;
        if (fd.flags.leftJustified) {
            pad = fd.precision - convResult.length;
            for (i=0; i<pad; i++) convResult = '0' + convResult;
            pad = fd.fieldWidth - convResult.length;
            if (fd.flags.forceSign || fd.flags.showNegSign) pad--;
            for (i=0; i<pad; i++) convResult += ' ';
            // handle cases where we need to add a sign
            if (fd.flags.forceSign || isNeg)
                convResult = fd.sign + convResult;
            else if (fd.flags.showNegSign)
                convResult = fd.sign2 + convResult;
        } else if (fd.flags.leadingZeros) {
            pad = fd.fieldWidth - convResult.length;
            if (fd.flags.forceSign || fd.flags.showNegSign) pad--;
            for (i=0; i<pad; i++) convResult = '0' + convResult;
            // handle cases where we need to add a sign
            if (fd.flags.forceSign || isNeg)
                convResult = fd.sign + convResult;
            else if (fd.flags.showNegSign)
                convResult = fd.sign2 + convResult;
        } else if (fd.precision > convResult.length) {
            pad = fd.precision - convResult.length;
            for (i=0; i<pad; i++) convResult = '0' + convResult;
            // handle cases where we need to add a sign
            if (fd.flags.forceSign || isNeg)
                convResult = fd.sign + convResult;
            else if (fd.flags.showNegSign)
                convResult = fd.sign2 + convResult;
            pad = fd.fieldWidth - convResult.length;
            for (i=0; i<pad; i++) convResult = ' ' + convResult;
        } else {
            for (i=0; i<pad; i++) convResult = ' ' + convResult;
        }
    } else if (isNeg) {
        convResult = fd.sign + convResult;
    }

    if (fd.conversion === 'X' || fd.conversion === 'D' || fd.conversion === 'O' ||
        fd.conversion === 'I' || fd.conversion === 'U')
        convResult = convResult.toUpperCase();

    return convResult;
}

function toFloat(arg, fd) {
    if (fd.flags.altNumeric && !fd.precision)
        fd.precision = 6;

    var i;
    var radix = fd.conversion.toLowerCase() === 'a' ? 16 : 10;

    if (fd.precision !== undefined) {
        var round = radix === 16 ? 0.8 : 0.5;
        for (i=0; i<fd.precision; i++) {
            round /= radix;
        }
        arg += round;
    }

    var convResult = arg.toString(radix);

    if (fd.precision > 0) {
        var p = convResult.indexOf('.');
        if (p === -1) {
            convResult += '.';
            for (i=0; i<fd.precision; ++i) convResult += '0';
        } else {
            ++p;    // skip past the '.'
            var start = 0;
            var per = fd.precision+1;
            if (per > 0) {
                while (--per && p < convResult.length && isValidDigit(convResult[p], radix))
                    p++;
            }
            convResult = convResult.substring(start, p);
        }
    }

    // handle cases where we need to add a sign
    if (fd.flags.forceSign)
        convResult = fd.sign + convResult;
    else if (fd.flags.showNegSign)
        convResult = fd.sign2 + convResult;

    // do we need to pad due to field with?
    if (fd.fieldWidth && fd.fieldWidth > convResult.length) {
        var pad = fd.fieldWidth - convResult.length;
        if (fd.flags.leftJustified)
            for (i=0; i<pad; i++) convResult += ' ';
        else if (fd.flags.leadingZeros)
            for (i=0; i<pad; i++) convResult = '0' + convResult;
        else
            for (i=0; i<pad; i++) convResult = ' ' + convResult;
    }

    if (fd.conversion === 'A' || fd.conversion === 'F' || fd.conversion === 'G')
        convResult = convResult.toUpperCase();

    return convResult;
}

function isValidDigit(digit, radix) {
    if (typeof digit !== 'string' && digit.length !== 1)
        return false;

    if (typeof radix !== 'number' && (radix === 16 || radix === 10 ||
        radix === 8 || radix === 2))
        return false;

    var ldigit = digit.toLowerCase();

    if (radix === 16 && ((ldigit >= '0' && ldigit <= '9') ||
        (ldigit >= 'a' && ldigit <= 'f')))
        return true;

    if (radix === 10 && ldigit >= '0' && ldigit <= '9')
        return true;

    if (radix === 8 && ldigit >= '0' && ldigit <= '7')
        return true;

    if (radix === 2 && (ldigit === '0' || ldigit === '1'))
        return true;

    return false;
}
<commit_msg>Fixed a bug with %C not being recognized. Removed uneccessary switch()<commit_after>'use strict';

/*
function toFloatHex(args, argIdx, fd) {
    return parseFloat(args[argIdx]).toString(16);
}
*/

exports.convertArgToStr = function(arg, fd) {

    if (typeof fd !== 'object' || fd.conversion === undefined || arg === undefined)
        return '';

    // Get the target format of the conversion character, so we can work with it.
    var convResult;

    // create the field by width, if specified
    switch (fd.conversion) {
    case '%':
        convResult = '%';
        break;
    case 'f':       // Decimal floating point, lowercase   392.65
    case 'F':       // Decimal floating point, uppercase   392.65
    case 'a':       // hexadecimal floating point, lowercase
    case 'A':       // hexadecimal floating point, uppercase
    case 'e':       // Scientific notation (mantissa/exponent), lowercase  3.9265e+2
    case 'E':       // Scientific notation (mantissa/exponent), uppercase  3.9265E+2
    case 'g':       // Use the shortest representation: %e or %f
    case 'G':       // Use the shortest representation: %E or %F
        convResult = parseFloat(arg);
        fd.sign = (convResult >= 0) ? '+' : '-';
        fd.sign2 = (convResult >= 0) ? ' ' : '-';
        convResult = toFloat(convResult, fd);
        break;
    case 'c':       // character
    case 'C':       // character
        if (typeof arg === 'number')
            convResult = String.fromCharCode(parseInt(arg, 10));
        else
            convResult = String(arg.substring(0,1));
        convResult = toStr(convResult, fd);
        break;
    case 's':       // string
    case 'S':       // string
        convResult = String(arg);
        convResult = toStr(convResult, fd);
        break;
    case 'd':       // Signed decimal integer
    case 'i':       // signed decimal
    case 'o':       // Unsigned octal
    case 'O':       // Unsigned octal
    case 'u':       // Unsigned decimal integer
    case 'x':       // Unsigned hexadecimal integer lowercase
    case 'X':       // Unsigned hexadecimal integer (uppercase)
    case 'b':       // Unsigned hexadecimal integer (uppercase)
    case 'B':       // Unsigned hexadecimal integer (uppercase)
        convResult = parseInt(arg, 10);
        fd.sign = (convResult >= 0) ? '+' : '-';
        fd.sign2 = (convResult >= 0) ? ' ' : '-';
        convResult = toInt(convResult, fd);
        break;
    case 'n':       // do nothing
    case 'p':       // do nothing
        convResult = '';
        break;
    default:        // error case
        convResult = '';
        break;
    }

    return convResult;
};

function toStr(convResult, fd) {

    var i;
    var pad;

    // if a charcter, we only take the first character
    if (fd.conversion === 'c' && convResult.length > 1)
        convResult = convResult.substring(0);
    // precision means how mny characters from the string we display
    else if (typeof fd.precision === 'number' && fd.precision < convResult.length)
        convResult = convResult.substring(0, fd.precision);

    // do we need to pad due to field with?
    if (fd.fieldWidth && fd.fieldWidth > convResult.length) {
        pad = fd.fieldWidth - convResult.length;
        if (fd.flags.leftJustified) {
            for (i=0; i<pad; i++) convResult += ' ';
        } else {
            for (i=0; i<pad; i++) convResult = ' ' + convResult;
        }
    }

    if (fd.conversion === 'S' || fd.conversion === 'C')
        convResult = convResult.toUpperCase();
    else if (fd.conversion === 't')
        convResult = convResult.toLowerCase();

    return convResult;
}

function toInt(arg, fd) {

    var isNeg = arg < 0 && fd.conversion.toLowerCase() !== 'u' ? true : false;

    // remove fractional part of value, if any - we don't need it
    // and remove the sign, we'll add it back later, if needed
    arg = Math.abs(Math.floor(arg));

    var i;
    var radix = 10;
    switch (fd.conversion.toLowerCase()) {
    case 'x':
        radix = 16;
        break;
    case 'o':
        radix = 8;
        break;
    case 'b':
        radix = 2;
        break;
    }
    var convResult = arg.toString(radix);

    // do we need to pad due to field with?
    if (fd.fieldWidth && fd.fieldWidth > convResult.length) {
        var pad = fd.fieldWidth - convResult.length;
        if (fd.flags.leftJustified) {
            pad = fd.precision - convResult.length;
            for (i=0; i<pad; i++) convResult = '0' + convResult;
            pad = fd.fieldWidth - convResult.length;
            if (fd.flags.forceSign || fd.flags.showNegSign) pad--;
            for (i=0; i<pad; i++) convResult += ' ';
            // handle cases where we need to add a sign
            if (fd.flags.forceSign || isNeg)
                convResult = fd.sign + convResult;
            else if (fd.flags.showNegSign)
                convResult = fd.sign2 + convResult;
        } else if (fd.flags.leadingZeros) {
            pad = fd.fieldWidth - convResult.length;
            if (fd.flags.forceSign || fd.flags.showNegSign) pad--;
            for (i=0; i<pad; i++) convResult = '0' + convResult;
            // handle cases where we need to add a sign
            if (fd.flags.forceSign || isNeg)
                convResult = fd.sign + convResult;
            else if (fd.flags.showNegSign)
                convResult = fd.sign2 + convResult;
        } else if (fd.precision > convResult.length) {
            pad = fd.precision - convResult.length;
            for (i=0; i<pad; i++) convResult = '0' + convResult;
            // handle cases where we need to add a sign
            if (fd.flags.forceSign || isNeg)
                convResult = fd.sign + convResult;
            else if (fd.flags.showNegSign)
                convResult = fd.sign2 + convResult;
            pad = fd.fieldWidth - convResult.length;
            for (i=0; i<pad; i++) convResult = ' ' + convResult;
        } else {
            for (i=0; i<pad; i++) convResult = ' ' + convResult;
        }
    } else if (isNeg) {
        convResult = fd.sign + convResult;
    }

    if (fd.conversion === 'X' || fd.conversion === 'D' || fd.conversion === 'O' ||
        fd.conversion === 'I' || fd.conversion === 'U')
        convResult = convResult.toUpperCase();

    return convResult;
}

function toFloat(arg, fd) {
    if (fd.flags.altNumeric && !fd.precision)
        fd.precision = 6;

    var i;
    var radix = fd.conversion.toLowerCase() === 'a' ? 16 : 10;

    if (fd.precision !== undefined) {
        var round = radix === 16 ? 0.8 : 0.5;
        for (i=0; i<fd.precision; i++) {
            round /= radix;
        }
        arg += round;
    }

    var convResult = arg.toString(radix);

    if (fd.precision > 0) {
        var p = convResult.indexOf('.');
        if (p === -1) {
            convResult += '.';
            for (i=0; i<fd.precision; ++i) convResult += '0';
        } else {
            ++p;    // skip past the '.'
            var start = 0;
            var per = fd.precision+1;
            if (per > 0) {
                while (--per && p < convResult.length && isValidDigit(convResult[p], radix))
                    p++;
            }
            convResult = convResult.substring(start, p);
        }
    }

    // handle cases where we need to add a sign
    if (fd.flags.forceSign)
        convResult = fd.sign + convResult;
    else if (fd.flags.showNegSign)
        convResult = fd.sign2 + convResult;

    // do we need to pad due to field with?
    if (fd.fieldWidth && fd.fieldWidth > convResult.length) {
        var pad = fd.fieldWidth - convResult.length;
        if (fd.flags.leftJustified)
            for (i=0; i<pad; i++) convResult += ' ';
        else if (fd.flags.leadingZeros)
            for (i=0; i<pad; i++) convResult = '0' + convResult;
        else
            for (i=0; i<pad; i++) convResult = ' ' + convResult;
    }

    if (fd.conversion === 'A' || fd.conversion === 'F' || fd.conversion === 'G')
        convResult = convResult.toUpperCase();

    return convResult;
}

function isValidDigit(digit, radix) {
    if (typeof digit !== 'string' && digit.length !== 1)
        return false;

    if (typeof radix !== 'number' && (radix === 16 || radix === 10 ||
        radix === 8 || radix === 2))
        return false;

    var ldigit = digit.toLowerCase();

    if (radix === 16 && ((ldigit >= '0' && ldigit <= '9') ||
        (ldigit >= 'a' && ldigit <= 'f')))
        return true;

    if (radix === 10 && ldigit >= '0' && ldigit <= '9')
        return true;

    if (radix === 8 && ldigit >= '0' && ldigit <= '7')
        return true;

    if (radix === 2 && (ldigit === '0' || ldigit === '1'))
        return true;

    return false;
}
<|endoftext|>


<commit_before>'use strict';

const tough = require('tough-cookie'),
      Store = tough.Store,
      fs = require('fs'),
      helpers = require('./helpers'),
      yaml = require('js-yaml');

class CookieFilestore extends Store {

    constructor() {

        super();

        this.synchronous = true;

        this.filePath = `${helpers.getConfigFilePath()}cookies.yml`;

        this.cookies = this._loadFromDisk();
    }

    findCookie(domain, path, key, cb) {

        if (!this.cookies[domain]) return cb(null, undefined);

        if (!this.cookies[domain][path] return cb(null, undefined);

        return cb(null, this.cookies[domain][path][key] || null);
    }

    findCookies() {

    }

    putCookie(cookie, cb) {

        const { domain, path, key } = cookie;

        if (!this.cookies[domain]) this.cookies[domain] = {};

        if (!this.cookies[domain][path] this.cookies[domain][path] = {};

        this.cookies[domain][path][key] = cookie;

        this._saveToDisk();

        return cb(null);
    }

    updateCookie(oldCookie, newCookie, cb) {
        this.putCookie(newCookie, cb);
    }

    removeCookie(domain, path, key, cb) {

        if (this.cookies[domain] &&
            this.cookies[domain][path] &&
            this.cookies[domain][path][key]) {
            delete this.cookies[domain][path][key];
        }

        this._saveToDisk();

        return cb(null);
    }

    removeCookies(domain, path, cb) {

        if (this.cookies[domain]) {

            if (path) {

                delete this.cookies[domain][path];

            }

        } else {

            delete this.cookies[domain];

        }

        this._saveToDisk();

        return cb(null);
    }

    getAllCookies() {

    }

    _loadFromDisk() {

        const data = fs.readFileSync(this.filePath),
              dataJson = data ? JSON.parse(data) : null;

        for (let domainName in dataJson) {
            for (let pathName in dataJson[domainName]) {
                for (let cookieName in dataJson[domainName][pathName]) {
                    this.cookies[domainName][pathName][cookieName] = tough.fromJSON(JSON.stringify(dataJson[domainName][pathName][cookieName]));
                }
            }
        }
    }

    _saveToDisk() {
        fs.writeFileSync(this.filePath. JSON.stringify(this.cookies));
    }
}
<commit_msg>remove unneeded dep<commit_after>'use strict';

const tough = require('tough-cookie'),
      Store = tough.Store,
      fs = require('fs'),
      helpers = require('./helpers');

class CookieFilestore extends Store {

    constructor() {

        super();

        this.synchronous = true;

        this.filePath = `${helpers.getConfigFilePath()}cookies.yml`;

        this.cookies = this._loadFromDisk();
    }

    findCookie(domain, path, key, cb) {

        if (!this.cookies[domain]) return cb(null, undefined);

        if (!this.cookies[domain][path] return cb(null, undefined);

        return cb(null, this.cookies[domain][path][key] || null);
    }

    findCookies() {

    }

    putCookie(cookie, cb) {

        const { domain, path, key } = cookie;

        if (!this.cookies[domain]) this.cookies[domain] = {};

        if (!this.cookies[domain][path] this.cookies[domain][path] = {};

        this.cookies[domain][path][key] = cookie;

        this._saveToDisk();

        return cb(null);
    }

    updateCookie(oldCookie, newCookie, cb) {
        this.putCookie(newCookie, cb);
    }

    removeCookie(domain, path, key, cb) {

        if (this.cookies[domain] &&
            this.cookies[domain][path] &&
            this.cookies[domain][path][key]) {
            delete this.cookies[domain][path][key];
        }

        this._saveToDisk();

        return cb(null);
    }

    removeCookies(domain, path, cb) {

        if (this.cookies[domain]) {

            if (path) {

                delete this.cookies[domain][path];

            }

        } else {

            delete this.cookies[domain];

        }

        this._saveToDisk();

        return cb(null);
    }

    getAllCookies() {

    }

    _loadFromDisk() {

        const data = fs.readFileSync(this.filePath),
              dataJson = data ? JSON.parse(data) : null;

        for (let domainName in dataJson) {
            for (let pathName in dataJson[domainName]) {
                for (let cookieName in dataJson[domainName][pathName]) {
                    this.cookies[domainName][pathName][cookieName] = tough.fromJSON(JSON.stringify(dataJson[domainName][pathName][cookieName]));
                }
            }
        }
    }

    _saveToDisk() {
        fs.writeFileSync(this.filePath. JSON.stringify(this.cookies));
    }
}
<|endoftext|>


<commit_before>const ANONYMOUS = '<<anonymous>>';
const DEFAULT_MESSAGE = '';

// Pulled from: https://github.com/facebook/react/blob/master/src/isomorphic/classic/types/ReactPropTypes.js#L108
function createChainableTypeChecker(validate) {
  function checkType(
    isRequired,
    props,
    propName,
    componentName = ANONYMOUS
  ) {
    if (props[propName] == null) {
      if (isRequired) {
        if (props[propName] === null) {
          return new Error(
            `The \`${propName}\` is marked as required ` +
            `in \`${componentName}\`, but its value is \`null\`.`
          );
        }

        return new Error(
          `The \`${propName}\` is marked as required in ` +
          `\`${componentName}\`, but its value is \`undefined\`.`
        );
      }

      return null;
    }

    return validate(
      props,
      propName,
      componentName
    );
  }

  // Use of .bind for creating the chainable `.isRequired` interface
  const chainedCheckType = checkType.bind(null, false);
  chainedCheckType.isRequired = checkType.bind(null, true);

  return chainedCheckType;
}

function createCustomTypeChecker(
  callback,
  message = DEFAULT_MESSAGE
) {
  // See customProp: https://facebook.github.io/react/docs/reusable-components.html#prop-validation
  // Ideally, propTypes should be validated only in development:
  // https://facebook.github.io/react/warnings/dont-call-proptypes.html
  return function validate(
    props,
    propName,
    componentName
  ) {
    const prop = props[propName];

    if (typeof callback(prop) !== 'boolean') {
      return new Error(
        'Error message for the callback to evaluate to a boolean value'
      );
    }
    if (typeof message !== 'string') {
      return new Error(
        'Error message for the string param to be of type string'
      );
    }

  };
}

function createPropType(callback, message) {
  return createChainableTypeChecker(
    createCustomTypeChecker(callback, message)
  );
}

export default createPropType;
<commit_msg>Implement logic for createCustomTypeChecker<commit_after>const ANONYMOUS = '<<anonymous>>';

// Pulled from: https://github.com/facebook/react/blob/master/src/isomorphic/classic/types/ReactPropTypes.js#L108
function createChainableTypeChecker(validate) {
  function checkType(
    isRequired,
    props,
    propName,
    componentName = ANONYMOUS
  ) {
    if (props[propName] == null) {
      if (isRequired) {
        if (props[propName] === null) {
          return new Error(
            `The \`${propName}\` is marked as required ` +
            `in \`${componentName}\`, but its value is \`null\`.`
          );
        }

        return new Error(
          `The \`${propName}\` is marked as required in ` +
          `\`${componentName}\`, but its value is \`undefined\`.`
        );
      }

      return null;
    }

    return validate(
      props,
      propName,
      componentName
    );
  }

  // Use of .bind for creating the chainable `.isRequired` interface
  const chainedCheckType = checkType.bind(null, false);
  chainedCheckType.isRequired = checkType.bind(null, true);

  return chainedCheckType;
}

function createCustomTypeChecker(
  callback,
  message
) {
  // See customProp: https://facebook.github.io/react/docs/reusable-components.html#prop-validation
  // Ideally, propTypes should be validated only in development:
  // https://facebook.github.io/react/warnings/dont-call-proptypes.html
  return function validate(
    props,
    propName,
    componentName
  ) {
    const prop = props[propName];

    if (typeof callback(prop) !== 'boolean') {
      return new Error(
        'ERROR MESSAGE for the callback to evaluate to a boolean value'
      );
    }
    if (!!message && typeof message !== 'string') {
      return new Error(
        'ERROR MESSAGE for the string param to be of type string'
      );
    }

    /* eslint-disable no-param-reassign */
    message = message || 'DEFAULT MESSAGE';
    /* eslint-enable no-param-reassign */

    if (!callback(prop)) {
      return new Error(message);
    }

    return null;
  };
}

function createPropType(callback, message) {
  return createChainableTypeChecker(
    createCustomTypeChecker(callback, message)
  );
}

export default createPropType;
<|endoftext|>


<commit_before>var nativeNroonga = require('nroonga');
var nroonga = require('../wrapped-nroonga');
var IndexField = require('./index-field').IndexField;

exports.MINIMUM_DOMAIN_NAME_LENGTH = 3;
exports.MAXIMUM_DOMAIN_NAME_LENGTH = 28;
exports.INVALID_DOMAIN_NAME_CHARACTER_PATTERN = /[^\-a-z0-9]/g;
exports.INVALID_TABLE_NAME_CHARACTER_PATTERN = /[^_a-z0-9]/g;

var DEFAULT_DOMAIN_ID =
      exports.DEFAULT_DOMAIN_ID =
      Domain.DEFAULT_DOMAIN_ID = '00000000000000000000000000';

function assertValidDomainName(domain) {
  if (typeof domain != 'string')
    throw new Error('domain name must be a string');

  if (domain.length < exports.MINIMUM_DOMAIN_NAME_LENGTH)
    throw new Error('too short domain name (minimum length = ' +
                    exports.MINIMUM_DOMAIN_NAME_LENGTH + ')');

  if (domain.length > exports.MAXIMUM_DOMAIN_NAME_LENGTH)
    throw new Error('too long domain name (max length = ' +
                   exports.MAXIMUM_DOMAIN_NAME_LENGTH + ')');

  var invalidCharacter = domain.match(exports.INVALID_DOMAIN_NAME_CHARACTER_PATTERN) ||
                         domain.match(exports.INVALID_TABLE_NAME_CHARACTER_PATTERN);
  if (invalidCharacter) {
    var characters = Array.prototype.map.call(invalidCharacter, function(aCharacter) {
                       return '"' + aCharacter + '"';
                     });
    throw new Error(characters.join(', ') + ' cannot appear in a domain name');
  }
}

// Accepts two arguments: source and context.
// You can give them in the reversed order, like:
// new Domain("source", context) or new Domain(context, "source")
function Domain() {
  var source, context;
  for (var i = 0, maxi = arguments.length, argument; i < maxi; i++) {
    argument = arguments[i];
    if (!argument) continue;
    if (argument instanceof nroonga.Context ||
        argument instanceof nativeNroonga.Database) {
      context = argument;
    } else if (argument) {
      source = argument;
    }
  }

  if (source instanceof Domain)
    return source;

  this.initialize(source, context);
}
Domain.prototype = {
  initialize: function(source, context) {
    this.cachedIndexFields = {};

    this.context = context && new nroonga.Context(context);
    this.initializeNameAndId(source);

    // for validation
    this.tableName;
    this.termsTableName;
  },
  initializeNameAndId: function(source) {
    if (typeof source == 'string') {
      this.name = source;
      this.id = this.getIdForTable(this.toTableNamePart(this.name));
      return;
    }

    if (source.query && source.query.DomainName) {
      this.name = source.query.DomainName;
      this.id = this.getIdForTable(this.toTableNamePart(this.name));
      return;
    }

    if (source.headers && source.headers.host) {
      var host = source.headers.host;
      var nameAndIdFromHost = Domain.getNameAndIdFromHost(host);
      if (nameAndIdFromHost.name) {
        this.name = nameAndIdFromHost.name;
        this.id = nameAndIdFromHost.id;
        return;
      }
    }

    if (source.url) {
      var nameAndIdFromPath = Domain.getNameAndIdFromPath(source.url);
      if (nameAndIdFromPath.name) {
        this.name = nameAndIdFromPath.name;
        this.id = nameAndIdFromPath.id;
        return;
      }
    }

    throw new Error('no domain name');
  },
  getIdForTable: function(tableName) {
    if (this.context) {
      var tables = this.context.tableListSync();
      var tableIdMatcher = new RegExp('^' + tableName + '_([^_]+)$');
      var id;
      if (tables.some(function(table) {
            var match = table.name.match(tableIdMatcher);
            if (match) {
              id = match[1];
              return true;
            }
            return false;
          }, this))
        return id;
    }
    return this.createNewId();
  },
  createNewId: function() {
    // we must calculate it!
  },

  get tableName() {
    if (!this._tableName) {
      assertValidDomainName(this.name);
      this._tableName = this.toTableNamePart(this.name) + '_' + this.id;
    }
    return this._tableName;
  },
  toTableNamePart: function(string) {
    return string;
  },

  get termsTableName() {
    if (!this._termsTableName)
      this._termsTableName = this.tableName + '_BigramTerms';
    return this._termsTableName;
  },

  getIndexField: function(field) {
    return this.cachedIndexFields[field] ||
           (this.cachedIndexFields[field] = new IndexField(field, this));
  },
  get indexFields() {
    if (!this.context)
      throw new Error('no context');
    var columns = this.context.ordinalColumnsSync(this.tableName);
    var fields = columns.map(function(column) {
                   // XXX The "name" must be the field name given by the user,
                   // not normalized. Because there is no such information in the
                   // context and currently the column name is luckily equals to the
                   // given field name, we can use the column name.
                   var name = column.name;
                   return this.getIndexField(name);
                 }, this);
    return fields;
  },

  get synonymTableName() {
    if (!this._synonymTableName)
      this._synonymTableName = this.tableName + '_synonyms';
    return this._synonymTableName;
  },

  get id() {
    return this._id === undefined ? DEFAULT_DOMAIN_ID : this._id ;
  },
  set id(value) {
    return this._id = value;
  },

  get domainId() {
    return this.id + '/' + this.name;
  },

  get searchableDocumentsCount() {
    return 0;
  },
  get requiresIndexDocuments() {
    return false;
  },
  get searchInstanceCount() {
    return 0;
  },
  get searchPartitionCount() {
    return 0;
  },

  getDocumentsEndpoint: function(hostname) {
    return 'doc-' + this.name + '-' + this.id + hostname;
  },
  getSearchEndpoint: function(hostname) {
    return 'search-' + this.name + '-' + this.id + hostname;
  },

  createSync: function() {
    if (!this.context)
      throw new Error('no context');

    this.context.commandSync('table_create', {
      name: this.tableName,
      flags: nroonga.TABLE_HASH_KEY,
      key_type: nroonga.ShortText
    });
    this.context.commandSync('table_create', {
      name: this.termsTableName,
      flags: nroonga.TABLE_PAT_KEY + '|' + nroonga.KEY_NORMALIZE,
      key_type: nroonga.ShortText,
      default_tokenizer: nroonga.TokenBigram
    });
  },
  deleteSync: function() {
    if (!this.context)
      throw new Error('no context');

    this.context.commandSync('table_remove', {
      name: this.tableName
    });
    this.context.commandSync('table_remove', {
      name: this.termsTableName
    });
  },
  reindexSync: function() {
    this.indexFields.forEach(function(field) {
      field.reindexSync();
    });
  },
  updateSynonymsSync: function(synonymOptions) {
    if (!this.context)
      throw new Error('no context');
    var synonyms = synonymOptions.synonyms;

    try {
      this.context.commandSync('table_remove', {
        table: this.synonymTableName
      });
    } catch (error) {
      // The synonym table should be inexistent. Do nothing.
    }

    this.context.commandSync('table_create', {
      name: this.synonymTableName,
      flags: nroonga.TABLE_HASH_KEY,
      key_type: nroonga.ShortText,
      flags: nroonga.KEY_NORMALIZE
    });
    this.context.commandSync('column_create', {
      table: this.synonymTableName,
      name: 'synonyms',
      type: nroonga.ShortText,
      flags: nroonga.COLUMN_VECTOR
    });

    var load = Object.keys(synonyms).map(function(key) {
      return {_key: key, synonyms: synonyms[key]};
    });
    this.context.commandSync('load', {
      table: this.synonymTableName,
      values: JSON.stringify(load)
    });
  },
  isSynonymTableAvailableSync: function() {
    var results = this.context.commandSync('table_list');
    var tables = nroonga.formatResults(results);
    var self = this;
    return tables.some(function(table) {
      return table.name === self.synonymTableName;
    });
  }
};

exports.Domain = Domain;

Domain.getNameAndIdFromHost = function(host) {
  var domainMatcher = /^(?:doc|search)-([^\.]+)-([^\.\-]+)\./;
  var match = host.match(domainMatcher);
  if (match)
    return { name: match[1], id: match[2] };

  return { name: '', id: '' };
};

Domain.getNameAndIdFromPath = function(path) {
  var domainMatcher = /^\/gcs\/([^\/]+)-([^\/\-]+)/;

  var match = path.match(domainMatcher);
  if (match)
    return { name: match[1], id: match[2] };

  return { name: '', id: '' };
};
<commit_msg>Generate random ID<commit_after>var nativeNroonga = require('nroonga');
var nroonga = require('../wrapped-nroonga');
var IndexField = require('./index-field').IndexField;

exports.MINIMUM_DOMAIN_NAME_LENGTH = 3;
exports.MAXIMUM_DOMAIN_NAME_LENGTH = 28;
exports.INVALID_DOMAIN_NAME_CHARACTER_PATTERN = /[^\-a-z0-9]/g;
exports.INVALID_TABLE_NAME_CHARACTER_PATTERN = /[^_a-z0-9]/g;

var DEFAULT_DOMAIN_ID =
      exports.DEFAULT_DOMAIN_ID =
      Domain.DEFAULT_DOMAIN_ID = '00000000000000000000000000';

function assertValidDomainName(domain) {
  if (typeof domain != 'string')
    throw new Error('domain name must be a string');

  if (domain.length < exports.MINIMUM_DOMAIN_NAME_LENGTH)
    throw new Error('too short domain name (minimum length = ' +
                    exports.MINIMUM_DOMAIN_NAME_LENGTH + ')');

  if (domain.length > exports.MAXIMUM_DOMAIN_NAME_LENGTH)
    throw new Error('too long domain name (max length = ' +
                   exports.MAXIMUM_DOMAIN_NAME_LENGTH + ')');

  var invalidCharacter = domain.match(exports.INVALID_DOMAIN_NAME_CHARACTER_PATTERN) ||
                         domain.match(exports.INVALID_TABLE_NAME_CHARACTER_PATTERN);
  if (invalidCharacter) {
    var characters = Array.prototype.map.call(invalidCharacter, function(aCharacter) {
                       return '"' + aCharacter + '"';
                     });
    throw new Error(characters.join(', ') + ' cannot appear in a domain name');
  }
}

// Accepts two arguments: source and context.
// You can give them in the reversed order, like:
// new Domain("source", context) or new Domain(context, "source")
function Domain() {
  var source, context;
  for (var i = 0, maxi = arguments.length, argument; i < maxi; i++) {
    argument = arguments[i];
    if (!argument) continue;
    if (argument instanceof nroonga.Context ||
        argument instanceof nativeNroonga.Database) {
      context = argument;
    } else if (argument) {
      source = argument;
    }
  }

  if (source instanceof Domain)
    return source;

  this.initialize(source, context);
}
Domain.prototype = {
  initialize: function(source, context) {
    this.cachedIndexFields = {};

    this.context = context && new nroonga.Context(context);
    this.initializeNameAndId(source);

    // for validation
    this.tableName;
    this.termsTableName;
  },
  initializeNameAndId: function(source) {
    if (typeof source == 'string') {
      this.name = source;
      this.id = this.getIdForTable(this.toTableNamePart(this.name));
      return;
    }

    if (source.query && source.query.DomainName) {
      this.name = source.query.DomainName;
      this.id = this.getIdForTable(this.toTableNamePart(this.name));
      return;
    }

    if (source.headers && source.headers.host) {
      var host = source.headers.host;
      var nameAndIdFromHost = Domain.getNameAndIdFromHost(host);
      if (nameAndIdFromHost.name) {
        this.name = nameAndIdFromHost.name;
        this.id = nameAndIdFromHost.id;
        return;
      }
    }

    if (source.url) {
      var nameAndIdFromPath = Domain.getNameAndIdFromPath(source.url);
      if (nameAndIdFromPath.name) {
        this.name = nameAndIdFromPath.name;
        this.id = nameAndIdFromPath.id;
        return;
      }
    }

    throw new Error('no domain name');
  },
  getIdForTable: function(tableName) {
    if (this.context) {
      var tables = this.context.tableListSync();
      var tableIdMatcher = new RegExp('^' + tableName + '_([^_]+)$');
      var id;
      if (tables.some(function(table) {
            var match = table.name.match(tableIdMatcher);
            if (match) {
              id = match[1];
              return true;
            }
            return false;
          }, this))
        return id;
    }
    return this.createNewId();
  },
  createNewId: function() {
    var size = 26;
    var characters = '0123456789abcdefghijklmnopqrstuvwxyz'.split('');
    var lastIndex = characters.length;
    var id = '';
    while (id.length < size) {
      id += characters[Math.round(Math.random() * lastIndex)];
    }
    return id;
  },

  get tableName() {
    if (!this._tableName) {
      assertValidDomainName(this.name);
      this._tableName = this.toTableNamePart(this.name) + '_' + this.id;
    }
    return this._tableName;
  },
  toTableNamePart: function(string) {
    return string;
  },

  get termsTableName() {
    if (!this._termsTableName)
      this._termsTableName = this.tableName + '_BigramTerms';
    return this._termsTableName;
  },

  getIndexField: function(field) {
    return this.cachedIndexFields[field] ||
           (this.cachedIndexFields[field] = new IndexField(field, this));
  },
  get indexFields() {
    if (!this.context)
      throw new Error('no context');
    var columns = this.context.ordinalColumnsSync(this.tableName);
    var fields = columns.map(function(column) {
                   // XXX The "name" must be the field name given by the user,
                   // not normalized. Because there is no such information in the
                   // context and currently the column name is luckily equals to the
                   // given field name, we can use the column name.
                   var name = column.name;
                   return this.getIndexField(name);
                 }, this);
    return fields;
  },

  get synonymTableName() {
    if (!this._synonymTableName)
      this._synonymTableName = this.tableName + '_synonyms';
    return this._synonymTableName;
  },

  get id() {
    return this._id === undefined ? DEFAULT_DOMAIN_ID : this._id ;
  },
  set id(value) {
    return this._id = value;
  },

  get domainId() {
    return this.id + '/' + this.name;
  },

  get searchableDocumentsCount() {
    return 0;
  },
  get requiresIndexDocuments() {
    return false;
  },
  get searchInstanceCount() {
    return 0;
  },
  get searchPartitionCount() {
    return 0;
  },

  getDocumentsEndpoint: function(hostname) {
    return 'doc-' + this.name + '-' + this.id + hostname;
  },
  getSearchEndpoint: function(hostname) {
    return 'search-' + this.name + '-' + this.id + hostname;
  },

  createSync: function() {
    if (!this.context)
      throw new Error('no context');

    this.context.commandSync('table_create', {
      name: this.tableName,
      flags: nroonga.TABLE_HASH_KEY,
      key_type: nroonga.ShortText
    });
    this.context.commandSync('table_create', {
      name: this.termsTableName,
      flags: nroonga.TABLE_PAT_KEY + '|' + nroonga.KEY_NORMALIZE,
      key_type: nroonga.ShortText,
      default_tokenizer: nroonga.TokenBigram
    });
  },
  deleteSync: function() {
    if (!this.context)
      throw new Error('no context');

    this.context.commandSync('table_remove', {
      name: this.tableName
    });
    this.context.commandSync('table_remove', {
      name: this.termsTableName
    });
  },
  reindexSync: function() {
    this.indexFields.forEach(function(field) {
      field.reindexSync();
    });
  },
  updateSynonymsSync: function(synonymOptions) {
    if (!this.context)
      throw new Error('no context');
    var synonyms = synonymOptions.synonyms;

    try {
      this.context.commandSync('table_remove', {
        table: this.synonymTableName
      });
    } catch (error) {
      // The synonym table should be inexistent. Do nothing.
    }

    this.context.commandSync('table_create', {
      name: this.synonymTableName,
      flags: nroonga.TABLE_HASH_KEY,
      key_type: nroonga.ShortText,
      flags: nroonga.KEY_NORMALIZE
    });
    this.context.commandSync('column_create', {
      table: this.synonymTableName,
      name: 'synonyms',
      type: nroonga.ShortText,
      flags: nroonga.COLUMN_VECTOR
    });

    var load = Object.keys(synonyms).map(function(key) {
      return {_key: key, synonyms: synonyms[key]};
    });
    this.context.commandSync('load', {
      table: this.synonymTableName,
      values: JSON.stringify(load)
    });
  },
  isSynonymTableAvailableSync: function() {
    var results = this.context.commandSync('table_list');
    var tables = nroonga.formatResults(results);
    var self = this;
    return tables.some(function(table) {
      return table.name === self.synonymTableName;
    });
  }
};

exports.Domain = Domain;

Domain.getNameAndIdFromHost = function(host) {
  var domainMatcher = /^(?:doc|search)-([^\.]+)-([^\.\-]+)\./;
  var match = host.match(domainMatcher);
  if (match)
    return { name: match[1], id: match[2] };

  return { name: '', id: '' };
};

Domain.getNameAndIdFromPath = function(path) {
  var domainMatcher = /^\/gcs\/([^\/]+)-([^\/\-]+)/;

  var match = path.match(domainMatcher);
  if (match)
    return { name: match[1], id: match[2] };

  return { name: '', id: '' };
};
<|endoftext|>


<commit_before>var path = require('path')
var debug = require('debug')('micromono:discovery')
var assign = require('lodash.assign')
var Router = require('../web/router')
var spawnSync = require('child_process').spawnSync
var RemotePipe = require('../service/remote')

exports.require = function(serviceName, serviceDir) {
  var service
  var servicePath = serviceName
  serviceDir = serviceDir || this.serviceDir

  var ServiceClass = exports.localRequire(serviceName, serviceDir, this.services)

  if (false === ServiceClass) {
    debug('Failed to locate service [%s] locally, try to discover from network.', serviceName)
    ServiceClass = exports.remoteRequire(this, serviceName, serviceDir)
  }

  if ('function' === typeof ServiceClass)
    service = new ServiceClass()
  else
    service = ServiceClass

  service.name = serviceName
  if (servicePath)
    service.packagePath = servicePath
  this.register(service, serviceName)

  return service
}

exports.localRequire = function(serviceName, serviceDir, services) {
  var ServiceClass
  var servicePath = serviceName

  try {
    if (serviceDir) {
      servicePath = path.resolve(serviceDir, serviceName)
      debug('Resolved service [%s] path "%s"', serviceName, servicePath)
    }
    if (services[serviceName]) {
      debug('Service [%s] already required', serviceName)
      return services[serviceName]
    } else {
      debug('Require service [%s] from path "%s"', serviceName, servicePath)
      ServiceClass = require(servicePath)
    }
  } catch (e) {
    var expectedMessage = new RegExp('Cannot find module \'' + servicePath + '\'')
    if ('MODULE_NOT_FOUND' !== e.code || !expectedMessage.test(e.message))
      // throw error if we found the module which contains error.
      throw e
    else
      return false
  }

  return ServiceClass
}

exports.remoteRequire = function(micromono, serviceName, serviceDir) {
  var proberPath
  var ServiceClass
  var proberCommand
  var discoveryOptions = exports.getDiscoveryOptions(micromono)

  var args = ['--discovery-target', serviceName]
  args = args.concat(process.argv.slice(2))

  if (discoveryOptions.MICROMONO_DISCOVERY_AGENT_PATH) {
    // Customized discovery agent.
    proberCommand = discoveryOptions.MICROMONO_DISCOVERY_AGENT_PATH
    // Tell the child process this suppose to be a discovery agent.
    args.push('--discovery-agent')
  } else {
    // Use default discovery agent.
    proberPath = require.resolve('./prober')
    proberCommand = 'node'
    args.unshift(proberPath)
  }

  debug('Probing service [%s] using command: "%s %s"', serviceName, proberCommand, args.join(' '))

  var probedResult = spawnSync(proberCommand, args, {
    env: assign({}, process.env, discoveryOptions),
    stdio: ['inherit', 'pipe', 'inherit']
  })

  if (255 === probedResult.status) {
    debug('Stopped discovering service [%s]\n', serviceName)
    process.exit(probedResult.status)
  } else if (0 !== probedResult.status) {
    debug('Service [%s] probing error %s:\n\t%s\n',
      serviceName, probedResult.status, probedResult.stdout)
    process.exit(probedResult.status)
  } else {
    try {
      var announcement = JSON.parse(probedResult.stdout)
      debug('Service [%s@%s] probed from network', announcement.name, announcement.version)
      ServiceClass = RemotePipe.buildServiceFromAnnouncement(announcement)
      if (ServiceClass.middleware)
        Router.rebuildRemoteMiddlewares(ServiceClass.middleware, ServiceClass)
    } catch (e) {
      debug('Service [%s] invalid announcement data:\n', serviceName, probedResult.stdout.toString())
      return exports.remoteRequire(micromono, serviceName, serviceDir)
    }
  }

  return ServiceClass
}

exports.register = function(serviceInstance, name) {
  debug('Register instance of service [%s]', name)
  this.services[name] = serviceInstance
  return serviceInstance
}

exports.getDiscoveryOptions = function(micromono) {
  var keys = [
    'MICROMONO_DISCOVERY_BACKEND',
    'MICROMONO_DISCOVERY_TIMEOUT',
    'MICROMONO_DISCOVERY_ANNOUNCE_INTERVAL',
    'MICROMONO_DISCOVERY_AGENT_PATH',
    'MICROMONO_DISCOVERY_UDP_MULTICAST',
    'MICROMONO_DISCOVERY_UDP_PORT',
    'MICROMONO_DISCOVERY_NATS_SERVERS'
  ]
  var options = {}

  keys.forEach(function(key) {
    var value = micromono.get(key)
    if (value)
      options[key] = value
  })

  return options
}
<commit_msg>Use new logger for discovery/index.js<commit_after>var path = require('path')
var logger = require('../logger')('micromono:discovery')
var assign = require('lodash.assign')
var Router = require('../web/router')
var spawnSync = require('child_process').spawnSync
var RemotePipe = require('../service/remote')

exports.require = function(serviceName, serviceDir) {
  var service
  var servicePath = serviceName
  serviceDir = serviceDir || this.serviceDir

  var ServiceClass = exports.localRequire(serviceName, serviceDir, this.services)

  if (false === ServiceClass) {
    logger.info('Failed to locate service locally, try to discover from network.', {
      service: serviceName
    })
    ServiceClass = exports.remoteRequire(this, serviceName, serviceDir)
  }

  if ('function' === typeof ServiceClass)
    service = new ServiceClass()
  else
    service = ServiceClass

  service.name = serviceName
  if (servicePath)
    service.packagePath = servicePath
  this.register(service, serviceName)

  return service
}

exports.localRequire = function(serviceName, serviceDir, services) {
  var ServiceClass
  var servicePath = serviceName

  try {
    if (serviceDir) {
      servicePath = path.resolve(serviceDir, serviceName)
      logger.debug('Resolved service path', {
        path: servicePath,
        service: serviceName
      })
    }
    if (services[serviceName]) {
      logger.debug('Service already required', {
        service: serviceName
      })
      return services[serviceName]
    } else {
      logger.info('Require service locally', {
        path: servicePath,
        service: serviceName
      })
      ServiceClass = require(servicePath)
    }
  } catch (e) {
    var expectedMessage = new RegExp('Cannot find module \'' + servicePath + '\'')
    if ('MODULE_NOT_FOUND' !== e.code || !expectedMessage.test(e.message))
      // throw error if we found the module which contains error.
      throw e
    else
      return false
  }

  return ServiceClass
}

exports.remoteRequire = function(micromono, serviceName, serviceDir) {
  var proberPath
  var ServiceClass
  var proberCommand
  var discoveryOptions = exports.getDiscoveryOptions(micromono)

  var args = ['--discovery-target', serviceName]
  args = args.concat(process.argv.slice(2))

  if (discoveryOptions.MICROMONO_DISCOVERY_AGENT_PATH) {
    // Customized discovery agent.
    proberCommand = discoveryOptions.MICROMONO_DISCOVERY_AGENT_PATH
    // Tell the child process this suppose to be a discovery agent.
    args.push('--discovery-agent')
  } else {
    // Use default discovery agent.
    proberPath = require.resolve('./prober')
    proberCommand = 'node'
    args.unshift(proberPath)
  }

  logger.debug('Probing remote service', {
    service: serviceName,
    proberCommand: proberCommand,
    args: args.join
  })

  var probedResult = spawnSync(proberCommand, args, {
    env: assign({}, process.env, discoveryOptions),
    stdio: ['inherit', 'pipe', 'inherit']
  })

  if (255 === probedResult.status) {
    logger.fatal('Stopped discovering service\n', {
      service: serviceName
    })
    process.exit(probedResult.status)
  } else if (0 !== probedResult.status) {
    logger.fatal('Service probing error', {
      service: serviceName,
      status: probedResult.status,
      stdout: probedResult.stdout.toString()
    })
    process.exit(probedResult.status)
  } else {
    try {
      var announcement = JSON.parse(probedResult.stdout)
      logger.info('Service probed from network', {
        service: announcement.name,
        version: announcement.version
      })
      ServiceClass = RemotePipe.buildServiceFromAnnouncement(announcement)
      if (ServiceClass.middleware)
        Router.rebuildRemoteMiddlewares(ServiceClass.middleware, ServiceClass)
    } catch (e) {
      logger.error('Invalid announcement data', {
        service: serviceName,
        stdout: probedResult.stdout.toString(),
        error: e
      })
      return exports.remoteRequire(micromono, serviceName, serviceDir)
    }
  }

  return ServiceClass
}

exports.register = function(serviceInstance, name) {
  logger.debug('Register service instance', {
    service: name
  })
  this.services[name] = serviceInstance
  return serviceInstance
}

exports.getDiscoveryOptions = function(micromono) {
  var keys = [
    'MICROMONO_DISCOVERY_BACKEND',
    'MICROMONO_DISCOVERY_TIMEOUT',
    'MICROMONO_DISCOVERY_ANNOUNCE_INTERVAL',
    'MICROMONO_DISCOVERY_AGENT_PATH',
    'MICROMONO_DISCOVERY_UDP_MULTICAST',
    'MICROMONO_DISCOVERY_UDP_PORT',
    'MICROMONO_DISCOVERY_NATS_SERVERS'
  ]
  var options = {}

  keys.forEach(function(key) {
    var value = micromono.get(key)
    if (value)
      options[key] = value
  })

  return options
}
<|endoftext|>


<commit_before>/*
 * jQuery UI ContextMenu
 *
 * Copyright 2011, Sebastian Sauer info@dynpages.de
 * Version 0.1.2
 *
 * Dual Licensed under GPL V.3 and CC BY-NC 3.0
 * GNU GENERAL PUBLIC LICENSE Version 3 http://www.gnu.org/licenses/gpl-3.0.html
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 *	jquery.ui.menu.js
 *
 *
 *	events:
 *		before
 *		open
 *		close
 */
;(function( $, undefined ) {

$.widget( "dyn.contextmenu", {
	/**
	 * @see jquery.ui.menu.js
	 */
    options : {
		menu : null,
		pageX : 0,
		pageY : 0
    },
	/**
	 * cache check for $.isWindow
	 * @var bool
	 */
	_isWindow : false,
	_useDocumentFallback : false,
    _create : function () {
		var o = this.options,
			menuOptions = $.extend( true, {}, this.options ),
			el = this.element;

		if( !$.isFunction ( $.ui.menu ) ) {
			throw( 'You need at least jQueryUi 1.9 || jquery.ui.menu.js' );
		}
		if( null === o.menu ) {
			return;
		}

		if( el[ 0 ] && $.isWindow( el[ 0 ] ) ) {
			this._isWindow = true;
			if( $.browser.msie ) {
				this._useDocumentFallback = true;
			}
		}
		delete( menuOptions.menu );

		this.menulayer = o.menu
			.addClass( this.widgetName )
			.hide();

		if( this.menulayer.data( 'menu' ) === undefined ) {
			this.menulayer.menu( menuOptions )
		}

		this._registerClick();

		this._registerMenuEvents();
    },
	_registerClick : function () {
		var o = this.options,
			el,
			that = this;

		el = ( this._useDocumentFallback )
			? $( document )
			: this.element;

		el.bind(
			'contextmenu.' + this.widgetName,
			function ( ev ) {
				var body = document.body,
					pageX = ev.pageX || this.clientX + ( this.scrollLeft || body.scrollLeft || 0 ),
					pageY = ev.pageY || this.clientY + ( this.scrollTop || body.scrollTop || 0 );

				$.extend( o, { pageX : pageX, pageY : pageY } );
				that.open( ev );
			}
		);
	},
	_registerMenuEvents : function () {
		var that = this,
			ns = '.' + this.widgetName,
			menu = this.menulayer;

		menu.bind( 'mouseleave' + ns, function ( ev ) {
			that.close( ev );
		});

		if( this._isWindow ) {
			// fix contextmenu closing on link click on chrome/chromium
			this.menulayer
				.find( 'a' )
				.bind( 'click' + ns, function ( ev ) {
					ev.stopImmediatePropagation();
				});
		} else {
			this.menulayer.delegate(
				'click' + ns,
				'a',
				function ( ev ) {
					ev.stopImmediatePropagation();
				}
			);
		}

		if( $( ':dyn-contextmenu' ).length > 0 && !$.mobile ) {
			return;
		}

		$( window ).bind( 'click' + ns , function ( ev ) {
			that.closeAll();
		});

	},
	_ui : function () {
		return {
			active : this.menulayer
		};
	},
	open : function ( ev ) {
		var o = this.options;
		if ( false === this._trigger( 'before', ev || null, this._ui() ) ) {
			return;
		}
		if( ev && ev.preventDefault ) {
			ev.preventDefault();
		}
		if( !$.browser.opera ) {
			$( ':dyn-contextmenu' ).contextmenu( 'closeAll' );
		}
		this.menulayer.css({
			left: '' + o.pageX + 'px',
			top: '' + o.pageY + 'px'
		}).show();

		this._trigger( 'open', ev || null, this._ui() );
	},
	closeAll : function () {
		$( ':dyn-contextmenu' ).contextmenu( 'close' );
	},
	close : function ( ev ) {
		this.menulayer.hide();
		if( ev && ev.type ) {
			ev.type = 'contextmenuclose';
		}
		this._trigger( 'close', ev || null, this._ui() );
	},
	destroy : function () {
		var ns = '.' + this.widgetName;

		this.menulayer
			.undelegate( ns )
			.unbind( ns )
			.removeClass( this.widgetName )
			.menu( 'destroy' );
		this.element.unbind( ns );
		this.element.removeData( this.widgetName );
		if( $( ':dyn-contextmenu' ).length < 1 ) {
			$( window ).unbind( ns );
		}
		if( !$.mobile ) {
			this._superApply( this, arguments );
		}
	}
});

})( jQuery );
<commit_msg>fu license stuff - sorted, just use gpl;fin.<commit_after>/*
 * jQuery UI ContextMenu
 *
 * Copyright 2011, Sebastian Sauer info@dynpages.de
 * Version 0.1.2
 *
 * Licensed under GPL V.3
 * GNU GENERAL PUBLIC LICENSE Version 3 http://www.gnu.org/licenses/gpl-3.0.html
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 *	jquery.ui.menu.js
 *
 *
 *	events:
 *		before
 *		open
 *		close
 */
;(function( $, undefined ) {

$.widget( "dyn.contextmenu", {
	/**
	 * @see jquery.ui.menu.js
	 */
    options : {
		menu : null,
		pageX : 0,
		pageY : 0
    },
	/**
	 * cache check for $.isWindow
	 * @var bool
	 */
	_isWindow : false,
	_useDocumentFallback : false,
    _create : function () {
		var o = this.options,
			menuOptions = $.extend( true, {}, this.options ),
			el = this.element;

		if( !$.isFunction ( $.ui.menu ) ) {
			throw( 'You need at least jQueryUi 1.9 || jquery.ui.menu.js' );
		}
		if( null === o.menu ) {
			return;
		}

		if( el[ 0 ] && $.isWindow( el[ 0 ] ) ) {
			this._isWindow = true;
			if( $.browser.msie ) {
				this._useDocumentFallback = true;
			}
		}
		delete( menuOptions.menu );

		this.menulayer = o.menu
			.addClass( this.widgetName )
			.hide();

		if( this.menulayer.data( 'menu' ) === undefined ) {
			this.menulayer.menu( menuOptions )
		}

		this._registerClick();

		this._registerMenuEvents();
    },
	_registerClick : function () {
		var o = this.options,
			el,
			that = this;

		el = ( this._useDocumentFallback )
			? $( document )
			: this.element;

		el.bind(
			'contextmenu.' + this.widgetName,
			function ( ev ) {
				var body = document.body,
					pageX = ev.pageX || this.clientX + ( this.scrollLeft || body.scrollLeft || 0 ),
					pageY = ev.pageY || this.clientY + ( this.scrollTop || body.scrollTop || 0 );

				$.extend( o, { pageX : pageX, pageY : pageY } );
				that.open( ev );
			}
		);
	},
	_registerMenuEvents : function () {
		var that = this,
			ns = '.' + this.widgetName,
			menu = this.menulayer;

		menu.bind( 'mouseleave' + ns, function ( ev ) {
			that.close( ev );
		});

		if( this._isWindow ) {
			// fix contextmenu closing on link click on chrome/chromium
			this.menulayer
				.find( 'a' )
				.bind( 'click' + ns, function ( ev ) {
					ev.stopImmediatePropagation();
				});
		} else {
			this.menulayer.delegate(
				'click' + ns,
				'a',
				function ( ev ) {
					ev.stopImmediatePropagation();
				}
			);
		}

		if( $( ':dyn-contextmenu' ).length > 0 && !$.mobile ) {
			return;
		}

		$( window ).bind( 'click' + ns , function ( ev ) {
			that.closeAll();
		});

	},
	_ui : function () {
		return {
			active : this.menulayer
		};
	},
	open : function ( ev ) {
		var o = this.options;
		if ( false === this._trigger( 'before', ev || null, this._ui() ) ) {
			return;
		}
		if( ev && ev.preventDefault ) {
			ev.preventDefault();
		}
		if( !$.browser.opera ) {
			$( ':dyn-contextmenu' ).contextmenu( 'closeAll' );
		}
		this.menulayer.css({
			left: '' + o.pageX + 'px',
			top: '' + o.pageY + 'px'
		}).show();

		this._trigger( 'open', ev || null, this._ui() );
	},
	closeAll : function () {
		$( ':dyn-contextmenu' ).contextmenu( 'close' );
	},
	close : function ( ev ) {
		this.menulayer.hide();
		if( ev && ev.type ) {
			ev.type = 'contextmenuclose';
		}
		this._trigger( 'close', ev || null, this._ui() );
	},
	destroy : function () {
		var ns = '.' + this.widgetName;

		this.menulayer
			.undelegate( ns )
			.unbind( ns )
			.removeClass( this.widgetName )
			.menu( 'destroy' );
		this.element.unbind( ns );
		this.element.removeData( this.widgetName );
		if( $( ':dyn-contextmenu' ).length < 1 ) {
			$( window ).unbind( ns );
		}
		if( !$.mobile ) {
			this._superApply( this, arguments );
		}
	}
});

})( jQuery );
<|endoftext|>


<commit_before>/**
 * The listener module is responsible for mapping event handlers to a set of criteria (filters). When the named
 * event is emitted we then look and see if there are filters that are listening for the event. If there are
 * then we call the event handler.
 */
module.exports = (function listener() {
    'use strict';

    var _ = require('underscore'),
        listeners = [],
        listener = {};

    /**
     * The register function maps a named event with a set of criteria and attach it's handler.
     *
     * @param name
     * @param filters
     * @param handler
     */
    listener.register = function(name, filters, handler) {
        var listenersWithSameName = _.filter(listeners, function(item){
            return item.name === name;
        });

        // No listeners exist for this name, just register it.
        if(_.isUndefined(listenersWithSameName)){
            listeners.push( { name: name, filters: filters, handlers: [ handler ] });
        }
        else {

        }
        console.log(listenersWithSameName);

        //listeners.push({name, filters, callback});
    };

    return listener;
})();
/*
var EventEmitter = require('events').EventEmitter,
    emitter = new EventEmitter(),
    util = require('util'),
    Emmitter = function() {
        this.trigger = function( target, payload ) {

            this.emit( target, payload );
        };
    };

util.inherits(Emmitter, events.EventEmitter);

module.exports = new Emmitter();

emitter.emit("someEvent");*/<commit_msg> Finished the register function for the listeners module<commit_after>/**
 * The listener module is responsible for mapping event handlers to a set of criteria (filters). When the named
 * event is emitted we then look and see if there are filters that are listening for the event. If there are
 * then we call the event handler.
 */
module.exports = (function listener() {
    'use strict';

    var _ = require('underscore'),
        listeners = [],
        listener = {};

    function arraysSame(arrays) {
        return _.all(arrays, function(array) {
            return array.length === arrays[0].length && _.difference(array, arrays[0]).length === 0;
        });
    }

    /**
     * The register function maps a named event with a set of criteria and attach it's handler.
     *
     * @param name
     * @param filters
     * @param handler
     */
    listener.register = function(name, filters, handler) {
        var listenersWithSameName = _.filter(listeners, function(item){
                return item.name === name;
            }),
            existingListener;

        // No listeners exist for this name, just register it.
        if( listenersWithSameName.length === 0 ){
            listeners.push( { name: name, filters: filters, handlers: [ handler ] });
        }
        else {
            _.each(listenersWithSameName, function(listener) {
                // If all of the filters are the same then we don't want to reregister the listener.
                if( arraysSame([listener.filters.nodes, filters.nodes] ) &&
                    arraysSame([listener.filters.types, filters.types] ) &&
                    arraysSame([listener.filters.contentids, filters.contentids] ) ) {

                    existingListener = listener;
                }
            });

            if(_.isUndefined(existingListener)){
                listeners.push( { name: name, filters: filters, handlers: [ handler ] });
            }
            else {
                existingListener.handlers.push(handler);
            }
        }
    };

    return listener;
})();<|endoftext|>


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

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

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

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

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

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

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

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

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

          var date = AWS.util.date.getDate();
          var SignerClass = req.service.getSignerClass(req);
          var signer = new SignerClass(req.httpRequest,
            req.service.api.signingName || req.service.api.endpointPrefix);

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

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

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

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

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

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

        httpResp.on('headers', function onHeaders(statusCode, headers) {
          resp.request.emitEvent('httpHeaders', [statusCode, headers, resp]);

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

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

      function progress(httpResp) {
        httpResp.on('sendProgress', function onSendProgress(progress) {
          resp.request.emitEvent('httpUploadProgress', [progress, resp]);
        });

        httpResp.on('receiveProgress', function onReceiveProgress(progress) {
          resp.request.emitEvent('httpDownloadProgress', [progress, resp]);
        });
      }

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

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

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

    add('HTTP_DATA', 'httpData', function HTTP_DATA(chunk, resp) {
      if (chunk) {
        if (AWS.util.isNode()) {
          resp.httpResponse.numBytes += chunk.length;

          var total = resp.httpResponse.headers['content-length'];
          var progress = { loaded: resp.httpResponse.numBytes, total: total };
          resp.request.emitEvent('httpDownloadProgress', [progress, resp]);
        }

        resp.httpResponse.buffers.push(new AWS.util.Buffer(chunk));
      }
    });

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

      this.completeRequest(resp);
    });

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

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

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

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

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

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

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

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

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

    });

  }),

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

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

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

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

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

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

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

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

  Query: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    var svc = AWS.ServiceInterface.Query;
    add('BUILD', 'build', svc.buildRequest);
    add('EXTRACT_DATA', 'extractData', svc.extractData);
    add('EXTRACT_ERROR', 'extractError', svc.extractError);
  })
};
<commit_msg>Don't clear error/data properties on retry.<commit_after>var AWS = require('./core');
require('./sequential_executor');
require('./service_interface/json');
require('./service_interface/query');
require('./service_interface/rest');
require('./service_interface/rest_json');
require('./service_interface/rest_xml');

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

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

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

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

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

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

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

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

          var date = AWS.util.date.getDate();
          var SignerClass = req.service.getSignerClass(req);
          var signer = new SignerClass(req.httpRequest,
            req.service.api.signingName || req.service.api.endpointPrefix);

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

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

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

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

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

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

        httpResp.on('headers', function onHeaders(statusCode, headers) {
          resp.request.emitEvent('httpHeaders', [statusCode, headers, resp]);

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

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

      function progress(httpResp) {
        httpResp.on('sendProgress', function onSendProgress(progress) {
          resp.request.emitEvent('httpUploadProgress', [progress, resp]);
        });

        httpResp.on('receiveProgress', function onReceiveProgress(progress) {
          resp.request.emitEvent('httpDownloadProgress', [progress, resp]);
        });
      }

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

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

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

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

    add('HTTP_DATA', 'httpData', function HTTP_DATA(chunk, resp) {
      if (chunk) {
        if (AWS.util.isNode()) {
          resp.httpResponse.numBytes += chunk.length;

          var total = resp.httpResponse.headers['content-length'];
          var progress = { loaded: resp.httpResponse.numBytes, total: total };
          resp.request.emitEvent('httpDownloadProgress', [progress, resp]);
        }

        resp.httpResponse.buffers.push(new AWS.util.Buffer(chunk));
      }
    });

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

      this.completeRequest(resp);
    });

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

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

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

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

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

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

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

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

    });

  }),

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

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

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

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

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

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

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

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

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