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

  var sass = require('node-sass'),
      each = require('async/each'),
      path = require('path'),

      // from https://gist.github.com/stevenschobert/ca76531b46f2ac00cbd8
      extend = function extend() {
        var args = [].slice.call(arguments);
        args[0] = (typeof args[0] === 'object') ? args[0] : {};

        for (var i=1; i<args.length; i++) {
          if (typeof args[i] === 'object') {
            for (var key in args[i]) {
              if (args[i].hasOwnProperty(key)) {
                args[0][key] = args[i][key];
              }
            }
          }
        }

        return args[0];
      },

      isAnySassFile = function isAnySassFile(filename) {
        return (/^[^_.].*\.s[ac]ss/).test(path.basename(filename));
      },

      isSassFile = function isSassFile(filename) {
        return (/^[^_.].*\.sass/).test(path.basename(filename));
      },

      isPartial = function isPartial(filename) {
        return (/^_.*\.s[ac]ss/).test(path.basename(filename));
      },

      compile = function(config, basePath, files, filename, done) {
        var file = files[filename],
            filePath = path.join(basePath, filename),
            opts = extend({
              includePaths: [],
              outputStyle: 'compressed',
              imagePath: '/',
              outputDir: path.dirname(filename),
              indentedSyntax: isSassFile(filename)
            }, config, {
              // Use the file's content stream buffer rather than the file path.
              data: file.contents.toString(),
              file: filePath
            }),
            fileDir = path.dirname(filePath),
            computedOutputDir = (typeof opts.outputDir === 'function') ? opts.outputDir(path.dirname(filename)) : opts.outputDir,
            dest = path.join(computedOutputDir, path.basename(filename).replace(/\.s[ca]ss/, '.css'));

        if (opts.sourceMap) {
          opts.outFile = filePath.replace(/\.s[ca]ss/, '.css');
        }

        if (isAnySassFile(filename) === true) {
          // Append the file's base path to the available include paths.
          opts.includePaths.push(fileDir);

          // Compile the file using SASS.
          sass.render(opts, function (err, result) {
            var error = null;

            if (err && err instanceof Error) {
              error = new Error([
                '[metalsmith-sass] Error: ',
                err.message, ' -> ',
                err.file,
                ':',
                err.line, ':', err.column
              ].join(''));
            } else if (err) {
              error = new Error(err);
            }

            if (error) {
              done(error);
              return;
            }

            // add soure map
            if (result.map) {
              files[dest+'.map'] = {
                contents: result.map,
                mode: file.mode
              };
            }

            // replace contents
            file.contents = result.css;

            // rename file extension
            files[dest] = file;

            delete files[filename];
            done();
          });
        } else if (isPartial(filename) === true) {
          delete files[filename];
          done();
        } else {
          done();
        }
      },

      compileSass = function compileSass(config, files, metalsmith, done) {
        /**
         * Looks up different key names on `metalsmith` to support
         * old versions (< v1) of Metalsmith. At some point, I will remove
         * support for < v1 and remove the key lookups
         */
        var directory = metalsmith.dir || metalsmith._directory,
            source = metalsmith._src || metalsmith._source,
            basePath = path.isAbsolute(source) ? source : path.join(directory, source);
        each(Object.keys(files), compile.bind(null, config, basePath, files), done);
      },

      plugin = function plugin(options) {
        var config = options || {};
        return compileSass.bind(null, config);
      };

  // exposing node-sass types for custom functions. see:
  // https://github.com/stevenschobert/metalsmith-sass/pull#21
  plugin.types = sass.types;
  module.exports = plugin;
}());
<commit_msg>Only call .toString() on sass files<commit_after>(function() {
  'use strict';

  var sass = require('node-sass'),
      each = require('async/each'),
      path = require('path'),

      // from https://gist.github.com/stevenschobert/ca76531b46f2ac00cbd8
      extend = function extend() {
        var args = [].slice.call(arguments);
        args[0] = (typeof args[0] === 'object') ? args[0] : {};

        for (var i=1; i<args.length; i++) {
          if (typeof args[i] === 'object') {
            for (var key in args[i]) {
              if (args[i].hasOwnProperty(key)) {
                args[0][key] = args[i][key];
              }
            }
          }
        }

        return args[0];
      },

      isAnySassFile = function isAnySassFile(filename) {
        return (/^[^_.].*\.s[ac]ss/).test(path.basename(filename));
      },

      isSassFile = function isSassFile(filename) {
        return (/^[^_.].*\.sass/).test(path.basename(filename));
      },

      isPartial = function isPartial(filename) {
        return (/^_.*\.s[ac]ss/).test(path.basename(filename));
      },

      compile = function(config, basePath, files, filename, done) {
        if (isPartial(filename)) {
          delete files[filename];
          done();
          return;
        }

        if (!isAnySassFile(filename)) {
          done();
          return;
        }

        var file = files[filename],
            filePath = path.join(basePath, filename),
            opts = extend({
              includePaths: [],
              outputStyle: 'compressed',
              imagePath: '/',
              outputDir: path.dirname(filename),
              indentedSyntax: isSassFile(filename)
            }, config, {
              // Use the file's content stream buffer rather than the file path.
              data: file.contents.toString(),
              file: filePath
            }),
            fileDir = path.dirname(filePath),
            computedOutputDir = (typeof opts.outputDir === 'function') ? opts.outputDir(path.dirname(filename)) : opts.outputDir,
            dest = path.join(computedOutputDir, path.basename(filename).replace(/\.s[ca]ss/, '.css'));

        if (opts.sourceMap) {
          opts.outFile = filePath.replace(/\.s[ca]ss/, '.css');
        }

        // Append the file's base path to the available include paths.
        opts.includePaths.push(fileDir);

        // Compile the file using SASS.
        sass.render(opts, function (err, result) {
          var error = null;

          if (err && err instanceof Error) {
            error = new Error([
              '[metalsmith-sass] Error: ',
              err.message, ' -> ',
              err.file,
              ':',
              err.line, ':', err.column
            ].join(''));
          } else if (err) {
            error = new Error(err);
          }

          if (error) {
            done(error);
            return;
          }

          // add soure map
          if (result.map) {
            files[dest+'.map'] = {
              contents: result.map,
              mode: file.mode
            };
          }

          // replace contents
          file.contents = result.css;

          // rename file extension
          files[dest] = file;

          delete files[filename];
          done();
        });
      },

      compileSass = function compileSass(config, files, metalsmith, done) {
        /**
         * Looks up different key names on `metalsmith` to support
         * old versions (< v1) of Metalsmith. At some point, I will remove
         * support for < v1 and remove the key lookups
         */
        var directory = metalsmith.dir || metalsmith._directory,
            source = metalsmith._src || metalsmith._source,
            basePath = path.isAbsolute(source) ? source : path.join(directory, source);
        each(Object.keys(files), compile.bind(null, config, basePath, files), done);
      },

      plugin = function plugin(options) {
        var config = options || {};
        return compileSass.bind(null, config);
      };

  // exposing node-sass types for custom functions. see:
  // https://github.com/stevenschobert/metalsmith-sass/pull#21
  plugin.types = sass.types;
  module.exports = plugin;
}());
<|endoftext|>


<commit_before>"use strict";

var conversions = {};
module.exports = conversions;

function sign(x) {
    return x < 0 ? -1 : 1;
}

function evenRound(x) {
    // Round x to the nearest integer, choosing the even integer if it lies halfway between two.
    if ((x % 1) === 0.5 && (x & 1) === 0) { // [even number].5; round down (i.e. floor)
        return Math.floor(x);
    } else {
        return Math.round(x);
    }
}

function createNumberConversion(bitLength, opts) {
    if (!opts.isUnsigned) {
        --bitLength;
    }
    const lowerBound = opts.isUnsigned ? 0 : -Math.pow(2, bitLength);
    const upperBound = Math.pow(2, bitLength) - 1;

    const moduloVal = opts.moduloBitLength ? Math.pow(2, opts.moduloBitLength) : Math.pow(2, bitLength);
    const moduloBound = opts.moduloBitLength ? Math.pow(2, opts.moduloBitLength - 1) : Math.pow(2, bitLength - 1);

    return function(V, opts) {
        let x = +V;

        if (opts.enforceRange) {
            if (!Number.isFinite(x)) {
                throw new TypeError("Argument is not a finite number");
            }

            x = sign(x) * Math.floor(Math.abs(x));
            if (x < lowerBound || x > upperBound) {
                throw new TypeError("Argument is not in byte range");
            }

            return x;
        }

        if (!isNaN(x) && opts.clamp) {
            x = evenRound(x);

            if (x < lowerBound) x = lowerBound;
            if (x > upperBound) x = upperBound;
            return x;
        }

        if (!Number.isFinite(x) || x === 0) {
            return 0;
        }

        x = sign(x) * Math.floor(Math.abs(x));
        x = x % moduloVal;

        if (!opts.isUnsigned && x >= moduloBound) {
            return x - moduloVal;
        }

        return x;
    }
}

conversions["void"] = function () {
    return undefined;
};

conversions["boolean"] = function (val) {
    return !!val;
};

conversions["byte"] = createNumberConversion(8, { unsigned: false });
conversions["octet"] = createNumberConversion(8, { unsigned: true });

conversions["short"] = createNumberConversion(16, { unsigned: false });
conversions["unsigned short"] = createNumberConversion(16, { unsigned: true });

conversions["long"] = createNumberConversion(32, { unsigned: false });
conversions["unsigned long"] = createNumberConversion(32, { unsigned: true });

conversions["long long"] = createNumberConversion(32, { unsigned: false, moduloBitLength: 64 });
conversions["unsigned long long"] = createNumberConversion(32, { unsigned: true, moduloBitLength: 64 });

conversions["double"] = function (V) {
    const x = +V;

    if (!Number.isFinite(x)) {
        throw new TypeError("Argument is not a finite floating-point value");
    }

    return x;
};

conversions["unrestricted double"] = function (V) {
    const x = +V;

    if (isNaN(x)) {
        throw new TypeError("Argument is NaN");
    }

    return x;
};

// not quite valid, but good enough for JS
conversions["float"] = conversions["double"];
conversions["unrestricted float"] = conversions["unrestricted double"];

conversions["DOMString"] = function (V, opts) {
    if (opts.treatNullAsEmptyString && V === null) {
        return "";
    }

    return String(V);
};

conversions["ByteString"] = function (V, opts) {
    const x = String(V);
    let c = undefined;
    for (let i = 0; (c = x.codePointAt(i)) !== undefined; ++i) {
        if (c > 255) {
            throw new TypeError("Argument is not a valid bytestring");
        }
    }

    return x;
};

conversions["USVString"] = function (V) {
    return String(V);
};

conversions["Date"] = function (V, opts) {
    if (!(V instanceof Date)) {
        throw new TypeError("Argument is not a Date object");
    }
    if (isNaN(V)) {
        return undefined;
    }

    return V;
};

conversions["RegExp"] = function (V, opts) {
    if (!(V instanceof RegExp)) {
        V = new RegExp(V);
    }

    return V;
};
<commit_msg>Fix USVString conversion<commit_after>"use strict";

var conversions = {};
module.exports = conversions;

function sign(x) {
    return x < 0 ? -1 : 1;
}

function evenRound(x) {
    // Round x to the nearest integer, choosing the even integer if it lies halfway between two.
    if ((x % 1) === 0.5 && (x & 1) === 0) { // [even number].5; round down (i.e. floor)
        return Math.floor(x);
    } else {
        return Math.round(x);
    }
}

function createNumberConversion(bitLength, opts) {
    if (!opts.isUnsigned) {
        --bitLength;
    }
    const lowerBound = opts.isUnsigned ? 0 : -Math.pow(2, bitLength);
    const upperBound = Math.pow(2, bitLength) - 1;

    const moduloVal = opts.moduloBitLength ? Math.pow(2, opts.moduloBitLength) : Math.pow(2, bitLength);
    const moduloBound = opts.moduloBitLength ? Math.pow(2, opts.moduloBitLength - 1) : Math.pow(2, bitLength - 1);

    return function(V, opts) {
        let x = +V;

        if (opts.enforceRange) {
            if (!Number.isFinite(x)) {
                throw new TypeError("Argument is not a finite number");
            }

            x = sign(x) * Math.floor(Math.abs(x));
            if (x < lowerBound || x > upperBound) {
                throw new TypeError("Argument is not in byte range");
            }

            return x;
        }

        if (!isNaN(x) && opts.clamp) {
            x = evenRound(x);

            if (x < lowerBound) x = lowerBound;
            if (x > upperBound) x = upperBound;
            return x;
        }

        if (!Number.isFinite(x) || x === 0) {
            return 0;
        }

        x = sign(x) * Math.floor(Math.abs(x));
        x = x % moduloVal;

        if (!opts.isUnsigned && x >= moduloBound) {
            return x - moduloVal;
        }

        return x;
    }
}

conversions["void"] = function () {
    return undefined;
};

conversions["boolean"] = function (val) {
    return !!val;
};

conversions["byte"] = createNumberConversion(8, { unsigned: false });
conversions["octet"] = createNumberConversion(8, { unsigned: true });

conversions["short"] = createNumberConversion(16, { unsigned: false });
conversions["unsigned short"] = createNumberConversion(16, { unsigned: true });

conversions["long"] = createNumberConversion(32, { unsigned: false });
conversions["unsigned long"] = createNumberConversion(32, { unsigned: true });

conversions["long long"] = createNumberConversion(32, { unsigned: false, moduloBitLength: 64 });
conversions["unsigned long long"] = createNumberConversion(32, { unsigned: true, moduloBitLength: 64 });

conversions["double"] = function (V) {
    const x = +V;

    if (!Number.isFinite(x)) {
        throw new TypeError("Argument is not a finite floating-point value");
    }

    return x;
};

conversions["unrestricted double"] = function (V) {
    const x = +V;

    if (isNaN(x)) {
        throw new TypeError("Argument is NaN");
    }

    return x;
};

// not quite valid, but good enough for JS
conversions["float"] = conversions["double"];
conversions["unrestricted float"] = conversions["unrestricted double"];

conversions["DOMString"] = function (V, opts) {
    if (opts.treatNullAsEmptyString && V === null) {
        return "";
    }

    return String(V);
};

conversions["ByteString"] = function (V, opts) {
    const x = String(V);
    let c = undefined;
    for (let i = 0; (c = x.codePointAt(i)) !== undefined; ++i) {
        if (c > 255) {
            throw new TypeError("Argument is not a valid bytestring");
        }
    }

    return x;
};

conversions["USVString"] = function (V) {
    const S = String(V);
    const n = S.length;
    const U = [];
    for (let i = 0; i < n; ++i) {
        const c = S.charCodeAt(i);
        if (c < 0xD800 || c > 0xDFFF) {
            U.push(String.fromCodePoint(c));
        } else if (0xDC00 <= c && c <= 0xDFFF) {
            U.push(String.fromCodePoint(0xFFFD));
        } else {
            if (i === n - 1) {
                U.push(String.fromCodePoint(0xFFFD));
            } else {
                const d = S.charCodeAt(i + 1);
                if (0xDC00 <= d && d <= 0xDFFF) {
                    const a = c & 0x3FF;
                    const b = d & 0x3FF;
                    U.push(String.fromCodePoint((2 << 15) + (2 << 9) * a + b));
                    ++i;
                } else {
                    U.push(String.fromCodePoint(0xFFFD));
                }
            }
        }
    }

    return U;
};

conversions["Date"] = function (V, opts) {
    if (!(V instanceof Date)) {
        throw new TypeError("Argument is not a Date object");
    }
    if (isNaN(V)) {
        return undefined;
    }

    return V;
};

conversions["RegExp"] = function (V, opts) {
    if (!(V instanceof RegExp)) {
        V = new RegExp(V);
    }

    return V;
};
<|endoftext|>


<commit_before>(function () {
  "use strict";
  var jwt = require("jwt-simple");
  var rp = require("request-promise");
  var InputDataValidator = require("./validators");
  var apiKey;
  var secret;
  var payment;
  var consumer;
  var delivery;
  var callbacks;
  var order;
  var paymentToken;
  var authenticationToken;
  var returningConsumer;
  var enriched;

  module.exports = function PayapiClient(params) {

    function print(key, value) {
      console.log(key + ":" + JSON.stringify(value, null, 2));
    }

    if(params) {
      this.apiKey = params.apiKey;
      this.secret = params.secret;
      this.payment = params.payment;
      this.consumer = params.consumer;
      this.products = params.products;
      this.order = params.order;
      this.callbacks = params.callbacks;
      this.authenticationToken = params.authenticationToken;
      this.paymentToken = params.paymentToken;
      this.enriched = params.enriched;
      this.returningConsumer = params.returningConsumer || false;
    }

    function validateApiKey(params) {
      return new Promise(function(resolve, reject) {
        if(!apiKey) {
          reject("apiKey must not be empty");
        } else {
          resolve(params);
        }
      });
    }

    function validateSecret(params) {
      return new Promise(function(resolve, reject) {
        if(!secret) {
          reject("secret must not be empty");
        } else {
          resolve(params);
        }
      });
    }

    function validatePayload(params) {
      return new Promise(function(resolve, reject) {
        var payload = {
          payment: params.payment,
          consumer: params.consumer,
          order: params.order,
          products: params.products,
          callbacks: params.callbacks,
          enriched: params.enriched,
          returningConsumer: params.returningConsumer || false
        };
        var validationErrors = new InputDataValidator(payload).validate();
        if(validationErrors.length > 0) {
          for(var i = 0; i < validationErrors.length; i++) {
            console.log("Validation error:" + JSON.stringify(validationErrors[0]));
          }
          reject(validationErrors);
        } else {
          console.log("no validation errors validatePayload() params:" + params);
          params.payload = payload;
          resolve(params);
        }
      });
    }

    function createToken(params) {
      return new Promise(function(resolve, reject) {
        if(params.paymentToken) {
          resolve(params);
        } else {
          params.paymentToken = jwt.encode(params.payload, params.secret, "HS512");
          resolve(params);
        }
      });
    }

    function doRestCall(params) {
      return new Promise(function(resolve, reject) {
        console.log("doRestCall");
        var uri;
        switch(process.env.NODE_ENV) {
          case "production":
            uri = "https://input.payapi.io/v1/api/authorized/payments";
            break;
          case "staging":
            uri = "https://staging-input.payapi.io/v1/api/authorized/payments";
            break;
          default:
            uri = "http://localhost:3000/v1/api/authorized/payments";
        }
        rp({
          method: "POST",
          uri: uri,
          body: {
            authenticationToken: params.authenticationToken,
            paymentToken: params.paymentToken
          },
          json: true
        }).then(function(params) {
          resolve(params);
        }).catch(function(err) {
          reject(err);
        });
      });
    }

    function handleError(err) {
      return new Promise(function(resolve, reject) {
        console.log("Error:" + JSON.stringify(err, null, 2));
        reject(err);
      });
    }

    return {
      call: function(params) {
        if(params) {
          return doRestCall(params).catch(handleError);
        } else {
          return validateApiKey(params)
            .then(validateSecret)
            .then(validatePayload)
            .then(createToken)
            .then(doRestCall)
            .catch(handleError);
        }
      },
      paymentToken: function() {
        return validatePayload(params)
          .then(createToken)
          .then(function(params) {
            return new Promise(function(resolve, reject) {
              resolve(params.paymentToken);
            });
          })
          .catch(function(err) {
            throw err;
          });
      },
      validate: function() {
        return validatePayload(params);
      }
    };
  };
}());

<commit_msg>Removed console.logs<commit_after>(function () {
  "use strict";
  var jwt = require("jwt-simple");
  var rp = require("request-promise");
  var InputDataValidator = require("./validators");
  var apiKey;
  var secret;
  var payment;
  var consumer;
  var delivery;
  var callbacks;
  var order;
  var paymentToken;
  var authenticationToken;
  var returningConsumer;
  var enriched;

  module.exports = function PayapiClient(params) {

    function print(key, value) {
      console.log(key + ":" + JSON.stringify(value, null, 2));
    }

    if(params) {
      this.apiKey = params.apiKey;
      this.secret = params.secret;
      this.payment = params.payment;
      this.consumer = params.consumer;
      this.products = params.products;
      this.order = params.order;
      this.callbacks = params.callbacks;
      this.authenticationToken = params.authenticationToken;
      this.paymentToken = params.paymentToken;
      this.enriched = params.enriched;
      this.returningConsumer = params.returningConsumer || false;
    }

    function validateApiKey(params) {
      return new Promise(function(resolve, reject) {
        if(!apiKey) {
          reject("apiKey must not be empty");
        } else {
          resolve(params);
        }
      });
    }

    function validateSecret(params) {
      return new Promise(function(resolve, reject) {
        if(!secret) {
          reject("secret must not be empty");
        } else {
          resolve(params);
        }
      });
    }

    function validatePayload(params) {
      return new Promise(function(resolve, reject) {
        var payload = {
          payment: params.payment,
          consumer: params.consumer,
          order: params.order,
          products: params.products,
          callbacks: params.callbacks,
          enriched: params.enriched,
          returningConsumer: params.returningConsumer || false
        };
        var validationErrors = new InputDataValidator(payload).validate();
        if(validationErrors.length > 0) {
          reject(validationErrors);
        } else {
          params.payload = payload;
          resolve(params);
        }
      });
    }

    function createToken(params) {
      return new Promise(function(resolve, reject) {
        if(params.paymentToken) {
          resolve(params);
        } else {
          params.paymentToken = jwt.encode(params.payload, params.secret, "HS512");
          resolve(params);
        }
      });
    }

    function doRestCall(params) {
      return new Promise(function(resolve, reject) {
        var uri;
        switch(process.env.NODE_ENV) {
          case "production":
            uri = "https://input.payapi.io/v1/api/authorized/payments";
            break;
          case "staging":
            uri = "https://staging-input.payapi.io/v1/api/authorized/payments";
            break;
          default:
            uri = "http://localhost:3000/v1/api/authorized/payments";
        }
        rp({
          method: "POST",
          uri: uri,
          body: {
            authenticationToken: params.authenticationToken,
            paymentToken: params.paymentToken
          },
          json: true
        }).then(function(params) {
          resolve(params);
        }).catch(function(err) {
          reject(err);
        });
      });
    }

    function handleError(err) {
      return new Promise(function(resolve, reject) {
        console.log("Payapi Client Error:" + JSON.stringify(err, null, 2));
        reject(err);
      });
    }

    return {
      call: function(params) {
        if(params) {
          return doRestCall(params).catch(handleError);
        } else {
          return validateApiKey(params)
            .then(validateSecret)
            .then(validatePayload)
            .then(createToken)
            .then(doRestCall)
            .catch(handleError);
        }
      },
      paymentToken: function() {
        return validatePayload(params)
          .then(createToken)
          .then(function(params) {
            return new Promise(function(resolve, reject) {
              resolve(params.paymentToken);
            });
          })
          .catch(function(err) {
            throw err;
          });
      },
      validate: function() {
        return validatePayload(params);
      }
    };
  };
}());

<|endoftext|>


<commit_before>// Copyright (c) 2014 Quildreen Motta
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation files
// (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/**
 * Beautiful assertion library.
 *
 * @module lib/index
 */

// -- Dependencies -----------------------------------------------------
var AssertionError = require('assertion-error')
var constant       = require('core.lambda').constant

// -- Helpers ----------------------------------------------------------

/**
 * Raises an exception.
 *
 * @summary Divergence → Void        :: partial, throws
 */
function raise(divergence) {
  throw new AssertionError( 'Expected ' + divergence.toString()
                          , divergence )
}

/**
 * Inverts a divergence.
 *
 * @summary Divergence → Divergence
 */
function invert(a) {
  return a.inverse()
}

// -- Assertion primitives ---------------------------------------------

/**
 * Verifies if a property is correct.
 *
 * @method
 * @summary Validation[α, β] → Boolean          :: partial, throws
 */
exports.verify = verify
function verify(validation) {
  return validation.fold(raise, constant(true))
}

/**
 * Inverts a Validation containing a divergence.
 *
 * @method
 * @summary Validation[Divergence, α] → Validation[Divergence, α]
 */
exports.not = not
function not(validation) {
  return validation.swap()
                   .bimap(invert, invert)
}<commit_msg>Exports validations and divergences.<commit_after>// Copyright (c) 2014 Quildreen Motta
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation files
// (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/**
 * Beautiful assertion library.
 *
 * @module lib/index
 */

// -- Dependencies -----------------------------------------------------
var AssertionError = require('assertion-error')
var constant       = require('core.lambda').constant
var extend         = require('boo').extend

// -- Helpers ----------------------------------------------------------

/**
 * Raises an exception.
 *
 * @summary Divergence → Void        :: partial, throws
 */
function raise(divergence) {
  throw new AssertionError( 'Expected ' + divergence.toString()
                          , divergence )
}

/**
 * Inverts a divergence.
 *
 * @summary Divergence → Divergence
 */
function invert(a) {
  return a.inverse()
}

// -- Assertion primitives ---------------------------------------------

/**
 * Verifies if a property is correct.
 *
 * @method
 * @summary Validation[α, β] → Boolean          :: partial, throws
 */
exports.verify = verify
function verify(validation) {
  return validation.fold(raise, constant(true))
}

/**
 * Inverts a Validation containing a divergence.
 *
 * @method
 * @summary Validation[Divergence, α] → Validation[Divergence, α]
 */
exports.not = not
function not(validation) {
  return validation.swap()
                   .bimap(invert, invert)
}

// -- Other exports ----------------------------------------------------
extend(exports, require('./validations'))
exports.divergence = require('./divergence')<|endoftext|>


<commit_before>'use strict';

const MySQL = require('mysql');
const Hoek = require('@hapi/hoek');

const internals = {
    pool: null
};

internals.attachConnection = async (request, h) => {

    await new Promise((resolve, reject) => {

        return internals.getConnection((err, conn) => {

            if (err) {
                return reject(err);
            }

            request.app.db = conn;

            return resolve();
        });
    });

    return h.continue;
};

exports.getConnection = internals.getConnection = (callback) => {

    Hoek.assert(internals.pool, 'No mysql pool found');

    return internals.pool.getConnection(callback);
};

internals.response = (request) => {

    if (request.app.db) {
        request.app.db.release();
    }
};

exports.stop = internals.stop = async () => {

    return new Promise((resolve, reject) => {

        return internals.pool.end((err) => {

            delete internals.pool;

            if (err) {
                return reject(err);
            }

            return resolve();
        });
    });
};

exports.init = internals.init = async (baseOptions) => {

    const hasOptions = Object.keys(baseOptions).length > 0;

    if (!internals.pool && !hasOptions) {
        throw new Error('No pool and no options to create one found, call `init` or `register` with options first');
    }

    if (internals.pool) {
        // Calling init and then register with no options should work
        if (!hasOptions) {
            return;
        }

        // Error on trying to init multiple times
        throw new Error('There is already a pool configured');
    }

    if (!baseOptions.hasOwnProperty('host')) {
       throw new Error('Options must include host property');
    }

    const options = Hoek.clone(baseOptions);
    internals.pool = MySQL.createPool(options);

    // test connection
    return new Promise((resolve, reject) => {

        return internals.pool.getConnection((err, connection) => {

            if (err) {
                delete internals.pool;
                return reject(err);
            }

            // release test connection
            connection.release();

            return resolve();
        });
    });
}

exports.plugin = {
    pkg: require('../package.json'),
    register: async function (server, baseOptions) {

        await internals.init(baseOptions);

        // add connection to request object
        server.ext('onPreAuth', internals.attachConnection);

        // end connection after request finishes
        server.events.on('response', internals.response);

        // try to close pool on server end
        server.ext('onPostStop', internals.stop);

        // add getDb() function to `server`
        server.decorate('server', 'getDb', internals.getConnection);

        server.log(['hapi-plugin-mysql', 'database'], 'Connection to the database successfull');

        return;
    }
}
<commit_msg>fix: typo<commit_after>'use strict';

const MySQL = require('mysql');
const Hoek = require('@hapi/hoek');

const internals = {
    pool: null
};

internals.attachConnection = async (request, h) => {

    await new Promise((resolve, reject) => {

        return internals.getConnection((err, conn) => {

            if (err) {
                return reject(err);
            }

            request.app.db = conn;

            return resolve();
        });
    });

    return h.continue;
};

exports.getConnection = internals.getConnection = (callback) => {

    Hoek.assert(internals.pool, 'No mysql pool found');

    return internals.pool.getConnection(callback);
};

internals.response = (request) => {

    if (request.app.db) {
        request.app.db.release();
    }
};

exports.stop = internals.stop = async () => {

    return new Promise((resolve, reject) => {

        return internals.pool.end((err) => {

            delete internals.pool;

            if (err) {
                return reject(err);
            }

            return resolve();
        });
    });
};

exports.init = internals.init = async (baseOptions) => {

    const hasOptions = Object.keys(baseOptions).length > 0;

    if (!internals.pool && !hasOptions) {
        throw new Error('No pool and no options to create one found, call `init` or `register` with options first');
    }

    if (internals.pool) {
        // Calling init and then register with no options should work
        if (!hasOptions) {
            return;
        }

        // Error on trying to init multiple times
        throw new Error('There is already a pool configured');
    }

    if (!baseOptions.hasOwnProperty('host')) {
       throw new Error('Options must include host property');
    }

    const options = Hoek.clone(baseOptions);
    internals.pool = MySQL.createPool(options);

    // test connection
    return new Promise((resolve, reject) => {

        return internals.pool.getConnection((err, connection) => {

            if (err) {
                delete internals.pool;
                return reject(err);
            }

            // release test connection
            connection.release();

            return resolve();
        });
    });
}

exports.plugin = {
    pkg: require('../package.json'),
    register: async function (server, baseOptions) {

        await internals.init(baseOptions);

        // add connection to request object
        server.ext('onPreAuth', internals.attachConnection);

        // end connection after request finishes
        server.events.on('response', internals.response);

        // try to close pool on server end
        server.ext('onPostStop', internals.stop);

        // add getDb() function to `server`
        server.decorate('server', 'getDb', internals.getConnection);

        server.log(['hapi-plugin-mysql', 'database'], 'Connection to the database successful');

        return;
    }
}
<|endoftext|>


<commit_before>require('colors');

module.exports = {
    error: function(str) {
        console.error(str.red);
    },
    log: function(str) {
        console.log(str.bold.blue);
    },
    status: function(json) {
        var str = (json.failed ? ':('.bold.red : ':)'.bold.green) +
            ' ' + ('[' + json.name + ']').bold.blue +
            ' Passed: ' + (json.passed ? (''+json.passed).green : json.passed) +
            ' Failed: ' + (json.failed ? (''+json.failed).red : json.failed) +
            ' Total: ' +  json.total +
            ' (ignored ' + json.ignored + ')';
        console.log(str);

        if (json.failed) {
            Object.keys(json).forEach(function(key) {
                if (typeof json[key] === 'object') {
                    for (var i in json[key]) {
                        if (json[key][i].result === 'fail') {
                            var res = json[key][i];
                            console.log('    ' + ('Failed! ' + res.name).red.bold);
                            console.log('    ' + res.message);
                        }
                    }
                }
            });
        }

    }
}
<commit_msg>Better pass/fail icons<commit_after>require('colors');

var good = ':)',
    bad = ':(';

good = "✔";
bad = "✖";

module.exports = {
    error: function(str) {
        console.error(str.red);
    },
    log: function(str) {
        console.log(str.bold.blue);
    },
    status: function(json) {
        var str = (json.failed ? bad.bold.red : good.bold.green) +
            ' ' + ('[' + json.name + ']').bold.blue +
            ' Passed: ' + (json.passed ? (''+json.passed).green : json.passed) +
            ' Failed: ' + (json.failed ? (''+json.failed).red : json.failed) +
            ' Total: ' +  json.total +
            ' (ignored ' + json.ignored + ')';
        console.log(str);

        if (json.failed) {
            Object.keys(json).forEach(function(key) {
                if (typeof json[key] === 'object') {
                    for (var i in json[key]) {
                        if (json[key][i].result === 'fail') {
                            var res = json[key][i];
                            console.log('    ' + ('Failed! ' + res.name).red.bold);
                            console.log('    ' + res.message);
                        }
                    }
                }
            });
        }

    }
}
<|endoftext|>


<commit_before>module.exports = Inliner;

var debug = require('debug')('inliner');
var events = require('events');
var path = require('path');
var util = require('util');
var fs = require('then-fs');
var assign = require('lodash.assign');
var forEach = require('lodash.foreach');
var Promise = require('es6-promise').Promise; // jshint ignore:line
var findAssets = require('./find-assets');
var iconv = require('iconv-lite');
var charset = require('charset');
var jschardet = require('jschardet');

// note: these tasks (excluding HTML), match up to files in lib/tasks/*.js
var tasks = {
  html: 'html', // this is abritrary since it's manually processed
  js: 'script',
  svg: 'svg',
  links: 'link[rel=stylesheet]',
  styles: 'style',
  'style-attrs': '[style]:not(svg *)',  // only style attrs in HTML, not SVG
  images: 'img',
  videos: 'video',
};
var taskRunner = Object.keys(tasks).reduce(function (acc, curr) {
  if (curr !== 'html') {
    acc[curr] = require('./tasks/' + curr);
  }
  return acc;
}, {});

// source is typicaly a URL, but can be a file location OR an HTML string
function Inliner(source, options, callback) {
  var inliner = this;
  events.EventEmitter.call(this);

  // allow for source to be optional
  if (typeof source !== 'string') {
    callback = options;
    options = source;
  }

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

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

  if (options.url) {
    this.url = options.url;
  }

  if (options.filename) {
    this.filename = options.filename;
  }

  if (options.source) {
    this.source = options.source;
  } else {
    this.source = source;
  }

  this.callback = function wrapper(error, res) {
    // noop the callback once it's fired
    inliner.callback = function noop() {
      inliner.emit('error', 'callback fired again');
    };

    callback(error, res);
  };
  this.options = assign({}, Inliner.defaults(), options);
  this.jobs = {
    total: 0,
    todo: 0,
    tasks: tasks,
    add: this.addJob.bind(this),
    breakdown: {},
    done: {},
  };

  Object.keys(this.jobs.tasks).forEach(function (key) {
    this.jobs.breakdown[key] = 0;
    this.jobs.done[key] = this.completeJob.bind(this, key);
  }.bind(this));

  this.isFile = false;

  this.on('error', function localErrorHandler(event) {
    inliner.callback(event);
  });

  // this allows the user code to get the object back before
  // it starts firing events
  if (this.source) {
    if (typeof setImmediate === 'undefined') {
      global.setImmediate = function setImmediatePolyfill(fn) {
        // :-/
        setTimeout(fn, 0);
      };
    }
    global.setImmediate(this.main.bind(this));
  }

  return this;
}

util.inherits(Inliner, events.EventEmitter);
Inliner.prototype.updateTodo = updateTodo;
Inliner.prototype.addJob = addJob;
Inliner.prototype.completeJob = completeJob;
Inliner.prototype.cssImages = require('./css').getImages;
Inliner.prototype.cssImports = require('./css').getImports;
Inliner.prototype.image = require('./image');
Inliner.prototype.uglify = require('./javascript');
Inliner.prototype.resolve = resolve;
Inliner.prototype.removeComments = removeComments;
Inliner.prototype.get = require('./get');
Inliner.prototype.main = main;
Inliner.prototype.findAssets = findAssets;

// static properties and methods
Inliner.errors = require('./errors');
Inliner.defaults = require('./defaults');

// main thread of functionality that does all the inlining
function main() {
  var inliner = this;
  var url = this.source;

  fs.exists(this.filename || url)
  .then(function exists(isFile) {
    if (!isFile) {
      throw new Error();
    }

    debug('inlining file');

    inliner.isFile = true;
    inliner.url = url; // this is a hack for the `resolve` function later on
    return inliner.get(this.filename || url, { encoding: 'binary' });
  })
  .catch(function isUrl() {
    // make the best guess as to whether we're working with a url
    if (inliner.url || url.indexOf('<') === -1) {
      url = inliner.url || inliner.source;
      // check for protocol on URL
      if (url.indexOf('http') !== 0) {
        url = 'http://' + url;
      }

      inliner.url = url;

      debug('inlining url');
      return inliner.get(url, { encoding: 'binary' });
    }

    // otherwise we're dealing with an inline string
    debug('inlining by string: ', inliner.source);
    inliner.url = '.';
    var res = {
      body: new Buffer(inliner.source),
      headers: {
        'content-type': 'text/html',
      },
    };
    return res;
  })
  .then(inliner.jobs.add('html'))
  .then(function processHTML(res) {
    inliner.jobs.done.html();
    debug('processing HTML');

    debug(inliner.options);

    var body;
    var cheerioLoadOptions = {};
    var enc = inliner.options.encoding;

    // try to determine the encoding from the headers and the body
    if (!enc) {
      enc = charset(res.headers, res.body);
      enc = enc || jschardet.detect(res.body).encoding.toLowerCase();
    }

    // normalise to avoid any mistakes
    if (enc === 'utf-8' || enc === 'utf8') {
      enc = 'utf-8';
    }

    if (enc !== 'utf-8') {
      debug('decoding from: %s', enc);
      cheerioLoadOptions.decodeEntities = false;
      body = iconv.encode(iconv.decode(res.body, enc), 'utf-8');
    } else {
      body = res.body;
    }

    body = body.toString();

    // if we spot some SVG elements in the source,
    // then we'll parse as XML to correctly get the SVG
    if (body.indexOf('<svg') !== -1 || body.indexOf('<SVG') !== -1) {
      cheerioLoadOptions.xmlMode = true;
    }

    var todo = inliner.findAssets(body, cheerioLoadOptions);
    var $ = todo.$;
    delete todo.$;

    if (enc !== 'utf-8') {
      // when transcoding remove any meta tags setting the charset
      $('meta').each(function charMeta() {
        var content = $(this).attr('content') || '';
        if (content.toLowerCase().indexOf('charset=')) {
          $(this).remove();
        }
      });
    }

    var promises = [];

    forEach(todo, function forEach(todo, key) {
      if (key === 'images' && !inliner.options.images) {
        // skip images if the user doesn't want them
        delete todo.images;
        debug('skipping images');
        return;
      }

      if (key === 'videos' && !inliner.options.videos) {
        // skip videos if the user doesn't want them
        delete todo.videos;
        debug('skipping videos');
        return;
      }

      if (!todo.length) {
        return;
      }

      inliner.jobs.add(key, todo.length);

      var tasks = taskRunner[key](inliner, todo.get(), $);
      // console.log(key, typeof tasks);
      // console.log('----------------');
      promises = promises.concat(tasks);
    });

    return Promise.all(promises).then(function then() {
      var html = '';
      inliner.removeComments($(':root')[0], $);
      // collapse the white space
      if (inliner.options.collapseWhitespace) {
        $('pre, textarea').each(function () {
          $(this).html($(this).html()
              .replace(/\n/g, '~~nl~~')
              .replace(/\s/g, '~~s~~'));
        });

        html = $.html()
          .replace(/\s+/g, ' ')
          .replace(/~~nl~~/g, '\n')
          .replace(/~~s~~/g, ' ');
      } else {
        html = $.html();
      }

      debug('completed: %s bytes', html.length);

      return html;
    });

  })
  .then(function then(html) {
    inliner.callback(null, html);
  })
  .catch(function errHandler(error) {
    debug('fail', error.stack);
    inliner.callback(error);
    inliner.emit('error', error);
  });
}

function removeComments(element, $) {
  if (!element || !element.childNodes) {
    return;
  }

  var nodes = element.childNodes;
  var i = nodes.length;

  while (i--) {
    if (nodes[i].type === 'comment' && nodes[i].nodeValue.indexOf('[') !== 0) {
      $(nodes[i]).remove();
    }
    removeComments(nodes[i], $);
  }
}

function resolve(from, to) {
  if (!to) {
    to = from;
    from = this.url;
  }

  // don't resolve data urls (already inlined)
  if (to.indexOf('data:') === 0) {
    return to;
  }

  // don't resolve http(s) urls (no need to resolve)
  if (to.indexOf('http:') === 0 || to.indexOf('https:') === 0) {
    return to;
  }

  if (!this.isFile || from.indexOf('http') === 0) {
    return require('url').resolve(from, to);
  }

  var base = path.dirname(from);
  return path.resolve(base, to);
}

function updateTodo() {
  var jobs = this.jobs;
  jobs.todo = Object.keys(jobs.breakdown).reduce(function (acc, key) {
    return acc + jobs.breakdown[key];
  }, 0);

  this.emit('jobs', (jobs.total - jobs.todo) + '/' + jobs.total);
}

function addJob(type) {
  var n = typeof arguments[1] === 'number' ? arguments[1] : 1;
  this.jobs.breakdown[type] += n;
  this.jobs.total += n;
  this.updateTodo();

  debug('%s: %s', type, n);

  // this allows me to include addJob as part of a promise chain
  return arguments[1];
}

function completeJob(type) {
  this.jobs.breakdown[type]--;
  this.updateTodo();

  // this allows me to include addJob as part of a promise chain
  return arguments[1];
}
<commit_msg>fix: metatags being removed on non-utf8<commit_after>module.exports = Inliner;

var debug = require('debug')('inliner');
var events = require('events');
var path = require('path');
var util = require('util');
var fs = require('then-fs');
var assign = require('lodash.assign');
var forEach = require('lodash.foreach');
var Promise = require('es6-promise').Promise; // jshint ignore:line
var findAssets = require('./find-assets');
var iconv = require('iconv-lite');
var charset = require('charset');
var jschardet = require('jschardet');

// note: these tasks (excluding HTML), match up to files in lib/tasks/*.js
var tasks = {
  html: 'html', // this is abritrary since it's manually processed
  js: 'script',
  svg: 'svg',
  links: 'link[rel=stylesheet]',
  styles: 'style',
  'style-attrs': '[style]:not(svg *)',  // only style attrs in HTML, not SVG
  images: 'img',
  videos: 'video',
};
var taskRunner = Object.keys(tasks).reduce(function (acc, curr) {
  if (curr !== 'html') {
    acc[curr] = require('./tasks/' + curr);
  }
  return acc;
}, {});

// source is typicaly a URL, but can be a file location OR an HTML string
function Inliner(source, options, callback) {
  var inliner = this;
  events.EventEmitter.call(this);

  // allow for source to be optional
  if (typeof source !== 'string') {
    callback = options;
    options = source;
  }

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

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

  if (options.url) {
    this.url = options.url;
  }

  if (options.filename) {
    this.filename = options.filename;
  }

  if (options.source) {
    this.source = options.source;
  } else {
    this.source = source;
  }

  this.callback = function wrapper(error, res) {
    // noop the callback once it's fired
    inliner.callback = function noop() {
      inliner.emit('error', 'callback fired again');
    };

    callback(error, res);
  };
  this.options = assign({}, Inliner.defaults(), options);
  this.jobs = {
    total: 0,
    todo: 0,
    tasks: tasks,
    add: this.addJob.bind(this),
    breakdown: {},
    done: {},
  };

  Object.keys(this.jobs.tasks).forEach(function (key) {
    this.jobs.breakdown[key] = 0;
    this.jobs.done[key] = this.completeJob.bind(this, key);
  }.bind(this));

  this.isFile = false;

  this.on('error', function localErrorHandler(event) {
    inliner.callback(event);
  });

  // this allows the user code to get the object back before
  // it starts firing events
  if (this.source) {
    if (typeof setImmediate === 'undefined') {
      global.setImmediate = function setImmediatePolyfill(fn) {
        // :-/
        setTimeout(fn, 0);
      };
    }
    global.setImmediate(this.main.bind(this));
  }

  return this;
}

util.inherits(Inliner, events.EventEmitter);
Inliner.prototype.updateTodo = updateTodo;
Inliner.prototype.addJob = addJob;
Inliner.prototype.completeJob = completeJob;
Inliner.prototype.cssImages = require('./css').getImages;
Inliner.prototype.cssImports = require('./css').getImports;
Inliner.prototype.image = require('./image');
Inliner.prototype.uglify = require('./javascript');
Inliner.prototype.resolve = resolve;
Inliner.prototype.removeComments = removeComments;
Inliner.prototype.get = require('./get');
Inliner.prototype.main = main;
Inliner.prototype.findAssets = findAssets;

// static properties and methods
Inliner.errors = require('./errors');
Inliner.defaults = require('./defaults');

// main thread of functionality that does all the inlining
function main() {
  var inliner = this;
  var url = this.source;

  fs.exists(this.filename || url)
  .then(function exists(isFile) {
    if (!isFile) {
      throw new Error();
    }

    debug('inlining file');

    inliner.isFile = true;
    inliner.url = url; // this is a hack for the `resolve` function later on
    return inliner.get(this.filename || url, { encoding: 'binary' });
  })
  .catch(function isUrl() {
    // make the best guess as to whether we're working with a url
    if (inliner.url || url.indexOf('<') === -1) {
      url = inliner.url || inliner.source;
      // check for protocol on URL
      if (url.indexOf('http') !== 0) {
        url = 'http://' + url;
      }

      inliner.url = url;

      debug('inlining url');
      return inliner.get(url, { encoding: 'binary' });
    }

    // otherwise we're dealing with an inline string
    debug('inlining by string: ', inliner.source);
    inliner.url = '.';
    var res = {
      body: new Buffer(inliner.source),
      headers: {
        'content-type': 'text/html',
      },
    };
    return res;
  })
  .then(inliner.jobs.add('html'))
  .then(function processHTML(res) {
    inliner.jobs.done.html();
    debug('processing HTML');

    debug(inliner.options);

    var body;
    var cheerioLoadOptions = {};
    var enc = inliner.options.encoding;

    // try to determine the encoding from the headers and the body
    if (!enc) {
      enc = charset(res.headers, res.body);
      enc = enc || jschardet.detect(res.body).encoding.toLowerCase();
    }

    // normalise to avoid any mistakes
    if (enc === 'utf-8' || enc === 'utf8') {
      enc = 'utf-8';
    }

    if (enc !== 'utf-8') {
      debug('decoding from: %s', enc);
      cheerioLoadOptions.decodeEntities = false;
      body = iconv.encode(iconv.decode(res.body, enc), 'utf-8');
    } else {
      body = res.body;
    }

    body = body.toString();

    // if we spot some SVG elements in the source,
    // then we'll parse as XML to correctly get the SVG
    if (body.indexOf('<svg') !== -1 || body.indexOf('<SVG') !== -1) {
      cheerioLoadOptions.xmlMode = true;
    }

    var todo = inliner.findAssets(body, cheerioLoadOptions);
    var $ = todo.$;
    delete todo.$;

    if (enc !== 'utf-8') {
      // when transcoding remove any meta tags setting the charset
      $('meta').each(function charMeta() {
        var attrs = $(this).attr();
        var content = attrs.content || '';
        if (attrs.charset || content.toLowerCase().indexOf('charset=') !== -1) {
          $(this).remove();
        }
      });
    }

    var promises = [];

    forEach(todo, function forEach(todo, key) {
      if (key === 'images' && !inliner.options.images) {
        // skip images if the user doesn't want them
        delete todo.images;
        debug('skipping images');
        return;
      }

      if (key === 'videos' && !inliner.options.videos) {
        // skip videos if the user doesn't want them
        delete todo.videos;
        debug('skipping videos');
        return;
      }

      if (!todo.length) {
        return;
      }

      inliner.jobs.add(key, todo.length);

      var tasks = taskRunner[key](inliner, todo.get(), $);
      // console.log(key, typeof tasks);
      // console.log('----------------');
      promises = promises.concat(tasks);
    });

    return Promise.all(promises).then(function then() {
      var html = '';
      inliner.removeComments($(':root')[0], $);
      // collapse the white space
      if (inliner.options.collapseWhitespace) {
        $('pre, textarea').each(function () {
          $(this).html($(this).html()
              .replace(/\n/g, '~~nl~~')
              .replace(/\s/g, '~~s~~'));
        });

        html = $.html()
          .replace(/\s+/g, ' ')
          .replace(/~~nl~~/g, '\n')
          .replace(/~~s~~/g, ' ');
      } else {
        html = $.html();
      }

      debug('completed: %s bytes', html.length);

      return html;
    });

  })
  .then(function then(html) {
    inliner.callback(null, html);
  })
  .catch(function errHandler(error) {
    debug('fail', error.stack);
    inliner.callback(error);
    inliner.emit('error', error);
  });
}

function removeComments(element, $) {
  if (!element || !element.childNodes) {
    return;
  }

  var nodes = element.childNodes;
  var i = nodes.length;

  while (i--) {
    if (nodes[i].type === 'comment' && nodes[i].nodeValue.indexOf('[') !== 0) {
      $(nodes[i]).remove();
    }
    removeComments(nodes[i], $);
  }
}

function resolve(from, to) {
  if (!to) {
    to = from;
    from = this.url;
  }

  // don't resolve data urls (already inlined)
  if (to.indexOf('data:') === 0) {
    return to;
  }

  // don't resolve http(s) urls (no need to resolve)
  if (to.indexOf('http:') === 0 || to.indexOf('https:') === 0) {
    return to;
  }

  if (!this.isFile || from.indexOf('http') === 0) {
    return require('url').resolve(from, to);
  }

  var base = path.dirname(from);
  return path.resolve(base, to);
}

function updateTodo() {
  var jobs = this.jobs;
  jobs.todo = Object.keys(jobs.breakdown).reduce(function (acc, key) {
    return acc + jobs.breakdown[key];
  }, 0);

  this.emit('jobs', (jobs.total - jobs.todo) + '/' + jobs.total);
}

function addJob(type) {
  var n = typeof arguments[1] === 'number' ? arguments[1] : 1;
  this.jobs.breakdown[type] += n;
  this.jobs.total += n;
  this.updateTodo();

  debug('%s: %s', type, n);

  // this allows me to include addJob as part of a promise chain
  return arguments[1];
}

function completeJob(type) {
  this.jobs.breakdown[type]--;
  this.updateTodo();

  // this allows me to include addJob as part of a promise chain
  return arguments[1];
}
<|endoftext|>


<commit_before>// Generated by CoffeeScript 1.7.1
'use strict';
var defaultSettings, each, fs, progenyConstructor, sysPath,
  __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

sysPath = require('path');

fs = require('fs-mode');

each = require('async-each');

defaultSettings = function(extname) {
  switch (extname) {
    case 'jade':
      return {
        regexp: /^\s*(?:include|extends)\s+(.+)/
      };
    case 'styl':
      return {
        regexp: /^\s*(?:@import|@require)\s*['"]?([^'"]+)['"]?/,
        exclusion: 'nib'
      };
    case 'less':
      return {
        regexp: /^\s*@import\s*(?:\(\w+\)\s*)?['"]([^'"]+)['"]/
      };
    case 'scss':
    case 'sass':
      return {
        regexp: /^\s*@import\s*['"]?([^'"]+)['"]?/,
        prefix: '_',
        exclusion: /^compass/,
        extensionsList: ['scss', 'sass'],
        multipass: [/@import[^;]+;/g, /\s*['"][^'"]+['"]\s*,?/g, /(?:['"])([^'"]+)/]
      };
  }
};

progenyConstructor = function(mode, settings) {
  var exclusion, extension, extensionsList, multipass, parseDeps, prefix, progeny, progenySync, regexp, rootPath;
  if (settings == null) {
    settings = {};
  }
  rootPath = settings.rootPath, extension = settings.extension, regexp = settings.regexp, prefix = settings.prefix, exclusion = settings.exclusion, extensionsList = settings.extensionsList, multipass = settings.multipass;
  parseDeps = function(path, source, depsList, callback) {
    var altExts, deps, mdeps, parent, prefixed, _ref;
    if (path) {
      parent = sysPath.dirname(path);
    }
    mdeps = multipass != null ? (_ref = multipass.slice(0, -1).reduce(function(vals, regex) {
      return vals != null ? vals.map(function(val) {
        return val.match(regex);
      }).reduce(function(flat, val) {
        return flat.concat(val, []);
      }) : void 0;
    }, [source])) != null ? _ref.map(function(val) {
      return (val.match(multipass[multipass.length - 1]))[1];
    }) : void 0 : void 0;
    deps = source.toString().split('\n').map(function(line) {
      return line.match(regexp);
    }).filter(function(match) {
      return (match != null ? match.length : void 0) > 0;
    }).map(function(match) {
      return match[1];
    }).concat(mdeps || []).filter(function(path) {
      if ('[object Array]' !== toString.call(exclusion)) {
        exclusion = [exclusion];
      }
      return !!path && !exclusion.some(function(_exclusion) {
        switch (false) {
          case !(_exclusion instanceof RegExp):
            return _exclusion.test(path);
          case '[object String]' !== toString.call(_exclusion):
            return _exclusion === path;
          default:
            return false;
        }
      });
    }).map(function(path) {
      if (extension && '' === sysPath.extname(path)) {
        return "" + path + "." + extension;
      } else {
        return path;
      }
    }).map(function(path) {
      if (path[0] === '/' || !parent) {
        return sysPath.join(rootPath, path.slice(1));
      } else {
        return sysPath.join(parent, path);
      }
    });
    if (extension) {
      deps.forEach(function(path) {
        if (("." + extension) !== sysPath.extname(path)) {
          return deps.push("" + path + "." + extension);
        }
      });
    }
    if (prefix != null) {
      prefixed = [];
      deps.forEach(function(path) {
        var dir, file;
        dir = sysPath.dirname(path);
        file = sysPath.basename(path);
        if (0 !== file.indexOf(prefix)) {
          return prefixed.push(sysPath.join(dir, "" + prefix + file));
        }
      });
      deps = deps.concat(prefixed);
    }
    if (extensionsList.length) {
      altExts = [];
      deps.forEach(function(path) {
        var dir;
        dir = sysPath.dirname(path);
        return extensionsList.forEach(function(ext) {
          var base;
          if (("." + ext) !== sysPath.extname(path)) {
            base = sysPath.basename(path, "." + extension);
            return altExts.push(sysPath.join(dir, "" + base + "." + ext));
          }
        });
      });
      deps = deps.concat(altExts);
    }
    if (deps.length) {
      return each(deps, function(path, callback) {
        if (__indexOf.call(depsList, path) >= 0) {
          return callback();
        } else {
          depsList.push(path);
          return fs[mode].readFile(path, {
            encoding: 'utf8'
          }, function(err, source) {
            if (err) {
              return callback();
            }
            return parseDeps(path, source, depsList, callback);
          });
        }
      }, callback);
    } else {
      return callback();
    }
  };
  progeny = function(path, source, callback) {
    var altExt, def, depsList, fileExt, run, tempPath, _ref, _ref1;
    if (typeof source === 'function') {
      callback = source;
      source = void 0;
    }
    fileExt = sysPath.extname(path).slice(1);
    if (path && source) {
      altExt = sysPath.extname(source);
      if (!((0 < (_ref = fileExt.length) && _ref < 5)) && (1 < (_ref1 = altExt.length) && _ref1 < 6)) {
        tempPath = source;
        source = path;
        path = tempPath;
        fileExt = altExt.slice(1);
      }
    }
    depsList = [];
    if (extension == null) {
      extension = fileExt;
    }
    def = defaultSettings(extension);
    if (regexp == null) {
      regexp = def.regexp;
    }
    if (prefix == null) {
      prefix = def.prefix;
    }
    if (exclusion == null) {
      exclusion = def.exclusion;
    }
    if (extensionsList == null) {
      extensionsList = def.extensionsList || [];
    }
    if (multipass == null) {
      multipass = def.multipass;
    }
    run = function() {
      return parseDeps(path, source, depsList, function() {
        return callback(null, depsList);
      });
    };
    if (source != null) {
      return run();
    } else {
      return fs[mode].readFile(path, {
        encoding: 'utf8'
      }, function(err, fileContents) {
        if (err) {
          return callback(err);
        }
        source = fileContents;
        return run();
      });
    }
  };
  progenySync = function(path, source) {
    var result;
    result = [];
    progeny(path, source, function(err, depsList) {
      if (err) {
        throw err;
      }
      return result = depsList;
    });
    return result;
  };
  if (mode === 'Sync') {
    return progenySync;
  } else {
    return progeny;
  }
};

module.exports = progenyConstructor.bind(null, 'Async');

module.exports.Sync = progenyConstructor.bind(null, 'Sync');
<commit_msg>compile<commit_after>// Generated by CoffeeScript 1.8.0
'use strict';
var defaultSettings, each, fs, progenyConstructor, sysPath,
  __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

sysPath = require('path');

fs = require('fs-mode');

each = require('async-each');

defaultSettings = function(extname) {
  switch (extname) {
    case 'jade':
      return {
        regexp: /^\s*(?:include|extends)\s+(.+)/
      };
    case 'styl':
      return {
        regexp: /^\s*(?:@import|@require)\s*['"]?([^'"]+)['"]?/,
        exclusion: 'nib'
      };
    case 'less':
      return {
        regexp: /^\s*@import\s*(?:\(\w+\)\s*)?['"]([^'"]+)['"]/
      };
    case 'scss':
    case 'sass':
      return {
        regexp: /^\s*@import\s*['"]?([^'"]+)['"]?/,
        prefix: '_',
        exclusion: /^compass/,
        extensionsList: ['scss', 'sass'],
        multipass: [/@import[^;]+;/g, /\s*['"][^'"]+['"]\s*,?/g, /(?:['"])([^'"]+)/]
      };
  }
};

progenyConstructor = function(mode, settings) {
  var exclusion, extension, extensionsList, multipass, parseDeps, prefix, progeny, progenySync, regexp, rootPath;
  if (settings == null) {
    settings = {};
  }
  rootPath = settings.rootPath, extension = settings.extension, regexp = settings.regexp, prefix = settings.prefix, exclusion = settings.exclusion, extensionsList = settings.extensionsList, multipass = settings.multipass;
  parseDeps = function(path, source, depsList, callback) {
    var altExts, deps, mdeps, parent, prefixed, _ref;
    if (path) {
      parent = sysPath.dirname(path);
    }
    mdeps = multipass != null ? (_ref = multipass.slice(0, -1).reduce(function(vals, regex) {
      return vals != null ? vals.map(function(val) {
        return val.match(regex);
      }).reduce(function(flat, val) {
        return flat.concat(val, []);
      }) : void 0;
    }, [source])) != null ? _ref.map(function(val) {
      return (val.match(multipass[multipass.length - 1]))[1];
    }) : void 0 : void 0;
    deps = source.toString().split('\n').map(function(line) {
      return line.match(regexp);
    }).filter(function(match) {
      return (match != null ? match.length : void 0) > 0;
    }).map(function(match) {
      return match[1];
    }).concat(mdeps || []).filter(function(path) {
      if ('[object Array]' !== toString.call(exclusion)) {
        exclusion = [exclusion];
      }
      return !!path && !exclusion.some(function(_exclusion) {
        switch (false) {
          case !(_exclusion instanceof RegExp):
            return _exclusion.test(path);
          case '[object String]' !== toString.call(_exclusion):
            return _exclusion === path;
          default:
            return false;
        }
      });
    }).map(function(path) {
      if (extension && '' === sysPath.extname(path)) {
        return "" + path + "." + extension;
      } else {
        return path;
      }
    }).map(function(path) {
      if (path[0] === '/' || !parent) {
        return sysPath.join(rootPath, path.slice(1));
      } else {
        return sysPath.join(parent, path);
      }
    });
    if (extension) {
      deps.forEach(function(path) {
        if (("." + extension) !== sysPath.extname(path)) {
          return deps.push("" + path + "." + extension);
        }
      });
    }
    if (prefix != null) {
      prefixed = [];
      deps.forEach(function(path) {
        var dir, file;
        dir = sysPath.dirname(path);
        file = sysPath.basename(path);
        if (0 !== file.indexOf(prefix)) {
          return prefixed.push(sysPath.join(dir, "" + prefix + file));
        }
      });
      deps = deps.concat(prefixed);
    }
    if (extensionsList.length) {
      altExts = [];
      deps.forEach(function(path) {
        var dir;
        dir = sysPath.dirname(path);
        return extensionsList.forEach(function(ext) {
          var base;
          if (("." + ext) !== sysPath.extname(path)) {
            base = sysPath.basename(path, "." + extension);
            return altExts.push(sysPath.join(dir, "" + base + "." + ext));
          }
        });
      });
      deps = deps.concat(altExts);
    }
    if (deps.length) {
      return each(deps, function(path, callback) {
        if (__indexOf.call(depsList, path) >= 0) {
          return callback();
        } else {
          depsList.push(path);
          return fs[mode].readFile(path, {
            encoding: 'utf8'
          }, function(err, source) {
            if (err) {
              return callback();
            }
            return parseDeps(path, source, depsList, callback);
          });
        }
      }, callback);
    } else {
      return callback();
    }
  };
  progeny = function(path, source, callback) {
    var altExt, def, depsList, fileExt, run, tempPath, _ref, _ref1;
    if (typeof source === 'function') {
      callback = source;
      source = void 0;
    }
    fileExt = sysPath.extname(path).slice(1);
    if (path && source) {
      altExt = sysPath.extname(source);
      if (!((0 < (_ref = fileExt.length) && _ref < 5)) && (1 < (_ref1 = altExt.length) && _ref1 < 6)) {
        tempPath = source;
        source = path;
        path = tempPath;
        fileExt = altExt.slice(1);
      }
    }
    depsList = [];
    if (extension == null) {
      extension = fileExt;
    }
    def = defaultSettings(extension);
    if (regexp == null) {
      regexp = def.regexp;
    }
    if (prefix == null) {
      prefix = def.prefix;
    }
    if (exclusion == null) {
      exclusion = def.exclusion;
    }
    if (extensionsList == null) {
      extensionsList = def.extensionsList || [];
    }
    if (multipass == null) {
      multipass = def.multipass;
    }
    run = function() {
      return parseDeps(path, source, depsList, function() {
        return callback(null, depsList);
      });
    };
    if (source != null) {
      return run();
    } else {
      return fs[mode].readFile(path, {
        encoding: 'utf8'
      }, function(err, fileContents) {
        if (err) {
          return callback(err);
        }
        source = fileContents;
        return run();
      });
    }
  };
  progenySync = function(path, source) {
    var result;
    result = [];
    progeny(path, source, function(err, depsList) {
      if (err) {
        throw err;
      }
      return result = depsList;
    });
    return result;
  };
  if (mode === 'Sync') {
    return progenySync;
  } else {
    return progeny;
  }
};

module.exports = progenyConstructor.bind(null, 'Async');

module.exports.Sync = progenyConstructor.bind(null, 'Sync');
<|endoftext|>


<commit_before>(function () {
  "use strict";
  var jwt = require("jwt-simple");
  var rp = require("request-promise");
  var InputDataValidator = require("./validators");

  module.exports = function PayapiClient(params) {

    function print(key, value) {
      console.log(key + ":" + JSON.stringify(value, null, 2));
    }

    function sanitizeAndExtractBinAndLast4(apiKeyAndToken) {
      var paymentObject = toPaymentObject();
      console.log('paymentObject below');
      console.log(params.optionalFields.indexOf('payment') < 0 && params.optionalFields.indexOf('payment.creditCardNumber') < 0);
      if(params.optionalFields.indexOf('payment') < 0 && params.optionalFields.indexOf('payment.creditCardNumber') < 0) {
        paymentObject.payment.creditCardNumber = paymentObject.payment.creditCardNumber.replace(/\s/g,"");
        paymentObject.payment.cardBin = paymentObject.payment.creditCardNumber
          .replace(/\s/g, "")
          .substring(0, 6);
      }
      return paymentObject;
    }

    if(params) {
      params.returningConsumer = params.returningConsumer || false;
      params.optionalFields = params.optionalFields || [];
      params.extra = params.extra || {};

      if(params.payment && params.payment.creditCardNumber) {
        params.payment.creditCardNumber = params.payment.creditCardNumber.replace(/\s/g, "");
        params.payment.cardBin = params.payment.creditCardNumber
          .replace(/\s/g, "")
          .substring(0, 6);
      }

      if(params.paymentToken) {
        // decode, sanitize and re-package
        params.payload = sanitizeAndExtractBinAndLast4();
        params.paymentToken = toPaymentToken();
      }
    }

    function toPaymentToken() {
      return jwt.encode(params.payload, params.apiKey, "HS512");
    }

    function toPaymentObject() {
      var jwtHeader64 = params.paymentToken.split(".")[0];
      var jwtHeader = JSON.parse(new Buffer(jwtHeader64, "base64").toString());
      var alg = jwtHeader.alg;
      if(alg === "HS512" ||
          alg === "HS384" ||
          alg === "HS256" ||
          alg === "RS256") {
        return jwt.decode(params.paymentToken, params.apiKey);
      } else {
        throw new Error("Only HS256, HS384, HS512 and RS256 algorithms are supported for JWT.");
      }
    }

    function validateApiKey(params) {
      return new Promise(function(resolve, reject) {
        if(!apiKey) {
          reject("apiKey must not be empty");
        } else {
          resolve(params);
        }
      });
    }

    // secret is unused in v1, but is here as a placeholder for v2
    function validateSecret(params) {
      return new Promise(function(resolve, reject) {
        if(!secret) {
          reject("secret must not be empty");
        } else {
          resolve(params);
        }
      });
    }

    function validatePayload(params) {
      return new Promise(function(resolve, reject) {
        var payload = {
          payment: params.payment,
          consumer: params.consumer,
          order: params.order,
          products: params.products,
          callbacks: params.callbacks,
          returningConsumer: params.returningConsumer || false,
          optionalFields: params.optionalFields || [],
          extra: params.extra || {}
        };
        var validationErrors = new InputDataValidator(payload).validate();
        if(validationErrors.length > 0) {
          reject(validationErrors);
        } else {
          params.payload = payload;
          resolve(params);
        }
      });
    }

    function createToken(params) {
      return new Promise(function(resolve, reject) {
        if(params.payload) {
          params.paymentToken = toPaymentToken(params.payload, params.apiKey, "HS512");
          resolve(params);
        } else if(params.paymentToken) {
          resolve(params);
        } else {
          reject(new Error("No payment token or payload to create a payment token from. Unable to continue."));
        }
      });
    }

    function doRestCall(params) {
      return new Promise(function(resolve, reject) {
        var uri;
        switch(process.env.NODE_ENV) {
          case "production":
            uri = "https://input.payapi.io/v1/api/authorized/payments";
            break;
          case "staging":
            uri = "https://staging-input.payapi.io/v1/api/authorized/payments";
            break;
          default:
            uri = "http://localhost:3000/v1/api/authorized/payments";
        }
        rp({
          method: "POST",
          uri: uri,
          body: {
            authenticationToken: params.authenticationToken,
            paymentToken: params.paymentToken
          },
          json: true
        }).then(function(params) {
          resolve(params);
        }).catch(function(err) {
          reject(err);
        });
      });
    }

    function handleError(err) {
      return new Promise(function(resolve, reject) {
        console.log("Payapi Client Error:" + JSON.stringify(err, null, 2));
        reject(err);
      });
    }

    function convertIntegersToInteger(params) {
      return new Promise(function(resolve, reject) {
        for(var i = 0; i < params.payload.products; i++) {
          params.payload.products[i].quantity = Number(params.payload.products[i].quantity);
          params.payload.products[i].priceInCentsIncVat = Number(params.payload.products[i].priceInCentsIncVat);
          params.payload.products[i].priceInCentsExcVat = Number(params.payload.products[i].priceInCentsExcVat);
          params.payload.products[i].vatPercentage = Number(params.payload.products[i].vatPercentage);
        }
        params.payload.order.sumInCentsIncVat = Number(params.payload.order.sumInCentsIncVat);
        params.payload.order.sumInCentsExcVat = Number(params.payload.order.sumInCentsExcVat);
        resolve(params);
      });
    }

    return {
      call: function(params) {
        if(params) {
          return doRestCall(params).catch(handleError);
        } else {
          return validateApiKey(params)
            .then(validateSecret)
            .then(validatePayload)
            .then(convertIntegersToInteger)
            .then(createToken)
            .then(doRestCall)
            .catch(handleError);
        }
      },
      paymentToken: function() {
        return validatePayload(params)
          .then(convertIntegersToInteger)
          .then(createToken)
          .then(function(params) {
            return new Promise(function(resolve, reject) {
              resolve(params.paymentToken);
            });
          })
          .catch(function(err) {
            throw err;
          });
      },
      validate: function() {
        return validatePayload(params);
      },
      encodePaymentToken: function() {
        return toPaymentToken();
      },
      decodePaymentToken: function() {
        return toPaymentObject();
      },
    };
  };
}());
<commit_msg>Fixed lint issues<commit_after>(function () {
  "use strict";
  var jwt = require("jwt-simple");
  var rp = require("request-promise");
  var InputDataValidator = require("./validators");

  module.exports = function PayapiClient(params) {

    function print(key, value) {
      console.log(key + ":" + JSON.stringify(value, null, 2));
    }

    function sanitizeAndExtractBinAndLast4(apiKeyAndToken) {
      var paymentObject = toPaymentObject();
      console.log("paymentObject below");
      console.log(params.optionalFields.indexOf("payment") < 0 &&
          params.optionalFields.indexOf("payment.creditCardNumber") < 0);
      if(params.optionalFields.indexOf("payment") < 0 &&
          params.optionalFields.indexOf("payment.creditCardNumber") < 0) {
        paymentObject.payment.creditCardNumber = paymentObject.payment.creditCardNumber.replace(/\s/g,"");
        paymentObject.payment.cardBin = paymentObject.payment.creditCardNumber
          .replace(/\s/g, "")
          .substring(0, 6);
      }
      return paymentObject;
    }

    if(params) {
      params.returningConsumer = params.returningConsumer || false;
      params.optionalFields = params.optionalFields || [];
      params.extra = params.extra || {};

      if(params.payment && params.payment.creditCardNumber) {
        params.payment.creditCardNumber = params.payment.creditCardNumber.replace(/\s/g, "");
        params.payment.cardBin = params.payment.creditCardNumber
          .replace(/\s/g, "")
          .substring(0, 6);
      }

      if(params.paymentToken) {
        // decode, sanitize and re-package
        params.payload = sanitizeAndExtractBinAndLast4();
        params.paymentToken = toPaymentToken();
      }
    }

    function toPaymentToken() {
      return jwt.encode(params.payload, params.apiKey, "HS512");
    }

    function toPaymentObject() {
      var jwtHeader64 = params.paymentToken.split(".")[0];
      var jwtHeader = JSON.parse(new Buffer(jwtHeader64, "base64").toString());
      var alg = jwtHeader.alg;
      if(alg === "HS512" ||
          alg === "HS384" ||
          alg === "HS256" ||
          alg === "RS256") {
        return jwt.decode(params.paymentToken, params.apiKey);
      } else {
        throw new Error("Only HS256, HS384, HS512 and RS256 algorithms are supported for JWT.");
      }
    }

    function validateApiKey(params) {
      return new Promise(function(resolve, reject) {
        if(!apiKey) {
          reject("apiKey must not be empty");
        } else {
          resolve(params);
        }
      });
    }

    // secret is unused in v1, but is here as a placeholder for v2
    function validateSecret(params) {
      return new Promise(function(resolve, reject) {
        if(!secret) {
          reject("secret must not be empty");
        } else {
          resolve(params);
        }
      });
    }

    function validatePayload(params) {
      return new Promise(function(resolve, reject) {
        var payload = {
          payment: params.payment,
          consumer: params.consumer,
          order: params.order,
          products: params.products,
          callbacks: params.callbacks,
          returningConsumer: params.returningConsumer || false,
          optionalFields: params.optionalFields || [],
          extra: params.extra || {}
        };
        var validationErrors = new InputDataValidator(payload).validate();
        if(validationErrors.length > 0) {
          reject(validationErrors);
        } else {
          params.payload = payload;
          resolve(params);
        }
      });
    }

    function createToken(params) {
      return new Promise(function(resolve, reject) {
        if(params.payload) {
          params.paymentToken = toPaymentToken(params.payload, params.apiKey, "HS512");
          resolve(params);
        } else if(params.paymentToken) {
          resolve(params);
        } else {
          reject(new Error("No payment token or payload to create a payment token from. Unable to continue."));
        }
      });
    }

    function doRestCall(params) {
      return new Promise(function(resolve, reject) {
        var uri;
        switch(process.env.NODE_ENV) {
          case "production":
            uri = "https://input.payapi.io/v1/api/authorized/payments";
            break;
          case "staging":
            uri = "https://staging-input.payapi.io/v1/api/authorized/payments";
            break;
          default:
            uri = "http://localhost:3000/v1/api/authorized/payments";
        }
        rp({
          method: "POST",
          uri: uri,
          body: {
            authenticationToken: params.authenticationToken,
            paymentToken: params.paymentToken
          },
          json: true
        }).then(function(params) {
          resolve(params);
        }).catch(function(err) {
          reject(err);
        });
      });
    }

    function handleError(err) {
      return new Promise(function(resolve, reject) {
        console.log("Payapi Client Error:" + JSON.stringify(err, null, 2));
        reject(err);
      });
    }

    function convertIntegersToInteger(params) {
      return new Promise(function(resolve, reject) {
        for(var i = 0; i < params.payload.products; i++) {
          params.payload.products[i].quantity = Number(params.payload.products[i].quantity);
          params.payload.products[i].priceInCentsIncVat = Number(params.payload.products[i].priceInCentsIncVat);
          params.payload.products[i].priceInCentsExcVat = Number(params.payload.products[i].priceInCentsExcVat);
          params.payload.products[i].vatPercentage = Number(params.payload.products[i].vatPercentage);
        }
        params.payload.order.sumInCentsIncVat = Number(params.payload.order.sumInCentsIncVat);
        params.payload.order.sumInCentsExcVat = Number(params.payload.order.sumInCentsExcVat);
        resolve(params);
      });
    }

    return {
      call: function(params) {
        if(params) {
          return doRestCall(params).catch(handleError);
        } else {
          return validateApiKey(params)
            .then(validateSecret)
            .then(validatePayload)
            .then(convertIntegersToInteger)
            .then(createToken)
            .then(doRestCall)
            .catch(handleError);
        }
      },
      paymentToken: function() {
        return validatePayload(params)
          .then(convertIntegersToInteger)
          .then(createToken)
          .then(function(params) {
            return new Promise(function(resolve, reject) {
              resolve(params.paymentToken);
            });
          })
          .catch(function(err) {
            throw err;
          });
      },
      validate: function() {
        return validatePayload(params);
      },
      encodePaymentToken: function() {
        return toPaymentToken();
      },
      decodePaymentToken: function() {
        return toPaymentObject();
      },
    };
  };
}());
<|endoftext|>


<commit_before>"use strict";

var P = require('bluebird');
var cass = require('cassandra-driver');
var loadBalancing = cass.policies.loadBalancing;
var reconnection = cass.policies.reconnection;
var DB = require('./db');

P.promisifyAll(cass, { suffix: '_p' });

function validateAndNormalizeDcConf (conf) {
    // Default to 'datacenter1'
    if (!conf.localDc) { conf.localDc = 'datacenter1'; }
    if (!conf.datacenters) { conf.datacenters = ['datacenter1']; }
    if (!(conf.datacenters instanceof Array)) {
        throw new Error('invalid datacenters configuration (not an array)');
    }
    if (conf.datacenters.indexOf(conf.localDc) < 0) {
        throw new Error('localDc not in configured datacenters');
    }
}

function makeClient (options) {
    var clientOpts = {};
    var conf = options.conf;
    validateAndNormalizeDcConf(conf);

    clientOpts.keyspace = conf.keyspace || 'system';
    clientOpts.contactPoints = conf.hosts;

    // See http://www.datastax.com/drivers/nodejs/2.0/module-policies_loadBalancing-DCAwareRoundRobinPolicy.html
    clientOpts.policies = {
        loadBalancing: new loadBalancing.TokenAwarePolicy(
            new loadBalancing.DCAwareRoundRobinPolicy(conf.localDc)
        ),
        // Also see
        // http://www.datastax.com/documentation/developer/nodejs-driver/2.0/common/drivers/reference/clientOptions.html
        // Retry immediately, then delay by 100ms, back off up to 2000ms
        reconnection: new reconnection.ExponentialReconnectionPolicy(100, 2000, true)
    };

    // Increase the schema agreement wait period from the default of 10s
    clientOpts.protocolOptions = {
        maxSchemaAgreementWaitSeconds: 30
    };

    if (conf.username && conf.password) {
        clientOpts.authProvider = new cass.auth.PlainTextAuthProvider(
                conf.username, conf.password);
    }

    // Up the maximum number of prepared statements. Driver default is 500.
    clientOpts.maxPrepared = conf.maxPrepared || 50000;

    var client = new cass.Client(clientOpts);

    client.on('log', function(level, message, info) {
        // Re-map levels
        switch (level) {
            case 'warning': level = 'warn'; break;
            case 'verbose': level = 'trace'; break;
            default: break; // other levels correspond to ours
        }

        level += '/table/cassandra/driver';
        options.log(level, {
            message: message,
            info: info
        });
    });

    return client.connect_p()
    .then(function() {
        return new DB(client, options);
    });
}

module.exports = makeClient;
<commit_msg>make TLS connections to Cassandra configurable<commit_after>"use strict";

var P = require('bluebird');
var cass = require('cassandra-driver');
var fs = require('fs');
var loadBalancing = cass.policies.loadBalancing;
var reconnection = cass.policies.reconnection;
var DB = require('./db');

P.promisifyAll(cass, { suffix: '_p' });

function validateAndNormalizeDcConf (conf) {
    // Default to 'datacenter1'
    if (!conf.localDc) { conf.localDc = 'datacenter1'; }
    if (!conf.datacenters) { conf.datacenters = ['datacenter1']; }
    if (!(conf.datacenters instanceof Array)) {
        throw new Error('invalid datacenters configuration (not an array)');
    }
    if (conf.datacenters.indexOf(conf.localDc) < 0) {
        throw new Error('localDc not in configured datacenters');
    }
}

// sync
function sslOptions(sslConf) {
    var sslOpts = {};

    if (sslConf.cert) { sslOpts.cert = fs.readFileSync(sslConf.cert); }
    if (sslConf.key)  { sslOpts.key  = fs.readFileSync(sslConf.key);  }

    if (sslConf.ca) {
        sslOpts.ca = [];
        if (sslConf.ca instanceof Array) {
            sslConf.ca.forEach(function(ca) {
                sslOpts.ca.push(fs.readFileSync(ca));
            });
        } else {
            sslOpts.ca.push(fs.readFileSync(sslConf.ca));
        }
    }

    return sslOpts;
}

function makeClient (options) {
    var clientOpts = {};
    var conf = options.conf;
    validateAndNormalizeDcConf(conf);

    clientOpts.keyspace = conf.keyspace || 'system';
    clientOpts.contactPoints = conf.hosts;

    // See http://www.datastax.com/drivers/nodejs/2.0/module-policies_loadBalancing-DCAwareRoundRobinPolicy.html
    clientOpts.policies = {
        loadBalancing: new loadBalancing.TokenAwarePolicy(
            new loadBalancing.DCAwareRoundRobinPolicy(conf.localDc)
        ),
        // Also see
        // http://www.datastax.com/documentation/developer/nodejs-driver/2.0/common/drivers/reference/clientOptions.html
        // Retry immediately, then delay by 100ms, back off up to 2000ms
        reconnection: new reconnection.ExponentialReconnectionPolicy(100, 2000, true)
    };

    if (conf.tls) { clientOpts.sslOptions = sslOptions(conf.tls); }

    // Increase the schema agreement wait period from the default of 10s
    clientOpts.protocolOptions = {
        maxSchemaAgreementWaitSeconds: 30
    };

    if (conf.username && conf.password) {
        clientOpts.authProvider = new cass.auth.PlainTextAuthProvider(
                conf.username, conf.password);
    }

    // Up the maximum number of prepared statements. Driver default is 500.
    clientOpts.maxPrepared = conf.maxPrepared || 50000;

    var client = new cass.Client(clientOpts);

    client.on('log', function(level, message, info) {
        // Re-map levels
        switch (level) {
            case 'warning': level = 'warn'; break;
            case 'verbose': level = 'trace'; break;
            default: break; // other levels correspond to ours
        }

        level += '/table/cassandra/driver';
        options.log(level, {
            message: message,
            info: info
        });
    });

    return client.connect_p()
    .then(function() {
        return new DB(client, options);
    });
}

module.exports = makeClient;
<|endoftext|>


<commit_before>var express = require('express');
var url = require('url');
var net = require('net');
var path = require('path');
var fs = require('fs');
var EventEmitter = require('events').EventEmitter;
var exnted = require('util')._extend;
var util = require('../util');
var EventEmitter = require('events').EventEmitter;
var rules = require('./rules');
var rulesUtil = require('./rules/util');
var connect = require('./proxy/connect');
var config = util.config;

function tunnelProxy(server, proxy) {

	server.on('connect', function(req, reqSocket, head) {//ws, wss, https proxy
		var tunnelUrl = req.url = util.setProtocol(req.url, true);
		var options = parseUrl();
		var resSocket;

		if (!options.hostname) {
			tunnelUrl = req.url = util.setProtocol(req.headers.host, true);
			parseUrl();
		}
		abortIfUnavailable(reqSocket);
		function emitError(err) {
			resSocket && resSocket.destroy();
			reqSocket.destroy();
		}

		function abortIfUnavailable(socket) {
			socket.on('error', emitError).on('close', emitError);
		}

		function parseUrl(_tunnelUrl, port) {
			_tunnelUrl = _tunnelUrl || tunnelUrl;
			options = req.options = url.parse(_tunnelUrl);
			options.port = options.port || port || 443;
			return options;
		}

		function tunnel() {
			rules.resolveHost(tunnelUrl, function(err, ip) {
				req.host = ip;
				if (!util.isLocalAddress(ip) || options.port != proxy.uisslport) {
					proxy.emit('tunnel', req);
				} else {
					options.port = proxy.uisslport;
				}

				if (err) {
					emitError(err);
					return;
				}

				resSocket = net.connect(options.port, ip || options.hostname, function() {
		            reqSocket.write('HTTP/1.1 200 Connection Established\r\nProxy-Agent: ' + config.name + '\r\n\r\n');
		            resSocket.pipe(reqSocket).pipe(resSocket);
		        });
				abortIfUnavailable(resSocket);
			});
		}

		var _rules = rules.resolveRules(tunnelUrl);
		var proxyUrl = _rules.proxy && _rules.proxy.matcher;
		if (proxyUrl) {
			var _tunnelUrl = 'https:' + util.removeProtocol(proxyUrl);
			rules.resolveHost(_tunnelUrl, function(err, ip) {
				req.host = ip;
				parseUrl(_tunnelUrl, config.port);
				if (!err && util.isLocalAddress(ip) && options.port == config.port) {
					parseUrl();
					return tunnel();
				}
				proxy.emit('tunnelProxy', req);
				if (err) {
					emitError(err);
					return;
				}
				options.host = ip;
				connect(req, function(err, proxySocket) {
					if (err) {
						return emitError();
					}
					abortIfUnavailable(proxySocket);
					reqSocket.pipe(proxySocket).pipe(reqSocket);
				});
			});
		} else {
			tunnel();
		}
    });

	return server;
}

process.on('uncaughtException', function(err){
	  fs.writeFileSync(path.join(process.cwd(), config.name + '-log.log'), err.stack + '\r\n', {flag: 'a'});
	  console.error(err);
	  process.exit(1);
});

function proxy(port, middlewares, _config) {
	if (Array.isArray(port)) {
		_config = middlewares;
		middlewares = port;
	} else if (!Array.isArray(middlewares)) {
		middlewares = [];
	}

	exnted(config, _config);
	var proxyEvents = new EventEmitter();
	var app = express();

	var server = app.listen(proxyEvents.port = port || config.port);
	server.on('clientError', util.noop); //ignore，防止keepalive的socket发生error时，出现crash
	middlewares = ['./init',
	               '../biz/webui']
				   .concat(require('./inspectors'))
				   .concat(middlewares)
	               .concat(['../biz/tianma'])
	               .concat(require('./handlers'));

	middlewares.forEach(function(mw) {
		app.use((typeof mw == 'string' ? require(mw) : mw).bind(proxyEvents));
	});
	exportInterfaces(proxyEvents);
	tunnelProxy(server, proxyEvents);
	require('./proxy');
	return proxyEvents;
}

function exportInterfaces(obj) {
	obj.rules = rules;
	obj.util = util;
	obj.rulesUtil = rulesUtil;
	return obj;
}

module.exports = exportInterfaces(proxy);<commit_msg>rules<commit_after>var express = require('express');
var url = require('url');
var net = require('net');
var path = require('path');
var fs = require('fs');
var EventEmitter = require('events').EventEmitter;
var exnted = require('util')._extend;
var util = require('../util');
var EventEmitter = require('events').EventEmitter;
var rules = require('./rules');
var rulesUtil = require('./rules/util');
var connect = require('./proxy/connect');
var config = util.config;

function tunnelProxy(server, proxy) {

	server.on('connect', function(req, reqSocket, head) {//ws, wss, https proxy
		var tunnelUrl = req.url = util.setProtocol(req.url, true);
		var options = parseUrl();
		var resSocket, proxySocket;

		if (!options.hostname) {
			tunnelUrl = req.url = util.setProtocol(req.headers.host, true);
			parseUrl();
		}
		abortIfUnavailable(reqSocket);
		function emitError(err) {
			resSocket && resSocket.destroy();
			proxySocket && proxySocket.destroy();
			reqSocket.destroy();
		}

		function abortIfUnavailable(socket) {
			socket.on('error', emitError).on('close', emitError);
		}

		function parseUrl(_tunnelUrl, port) {
			_tunnelUrl = _tunnelUrl || tunnelUrl;
			options = req.options = url.parse(_tunnelUrl);
			options.port = options.port || port || 443;
			return options;
		}

		function tunnel() {
			rules.resolveHost(tunnelUrl, function(err, ip) {
				req.host = ip;
				if (!util.isLocalAddress(ip) || options.port != proxy.uisslport) {
					proxy.emit('tunnel', req);
				} else {
					options.port = proxy.uisslport;
				}

				if (err) {
					emitError(err);
					return;
				}

				resSocket = net.connect(options.port, ip || options.hostname, function() {
		            reqSocket.write('HTTP/1.1 200 Connection Established\r\nProxy-Agent: ' + config.name + '\r\n\r\n');
		            resSocket.pipe(reqSocket).pipe(resSocket);
		        });
				abortIfUnavailable(resSocket);
			});
		}

		var _rules = rules.resolveRules(tunnelUrl);
		var proxyUrl = _rules.proxy && _rules.proxy.matcher;
		if (proxyUrl) {
			var _tunnelUrl = 'https:' + util.removeProtocol(proxyUrl);
			rules.resolveHost(_tunnelUrl, function(err, ip) {
				req.host = ip;
				parseUrl(_tunnelUrl, config.port);
				if (!err && util.isLocalAddress(ip) && options.port == config.port) {
					parseUrl();
					return tunnel();
				}
				proxy.emit('tunnelProxy', req);
				if (err) {
					emitError(err);
					return;
				}
				options.host = ip;
				connect(req, function(err, _proxySocket) {
					if (err) {
						return emitError();
					}
					proxySocket = _proxySocket;
					abortIfUnavailable(_proxySocket);
					reqSocket.pipe(_proxySocket).pipe(reqSocket);
				});
			});
		} else {
			tunnel();
		}
    });

	return server;
}

process.on('uncaughtException', function(err){
	  fs.writeFileSync(path.join(process.cwd(), config.name + '-log.log'), err.stack + '\r\n', {flag: 'a'});
	  console.error(err);
	  process.exit(1);
});

function proxy(port, middlewares, _config) {
	if (Array.isArray(port)) {
		_config = middlewares;
		middlewares = port;
	} else if (!Array.isArray(middlewares)) {
		middlewares = [];
	}

	exnted(config, _config);
	var proxyEvents = new EventEmitter();
	var app = express();

	var server = app.listen(proxyEvents.port = port || config.port);
	server.on('clientError', util.noop); //ignore，防止keepalive的socket发生error时，出现crash
	middlewares = ['./init',
	               '../biz/webui']
				   .concat(require('./inspectors'))
				   .concat(middlewares)
	               .concat(['../biz/tianma'])
	               .concat(require('./handlers'));

	middlewares.forEach(function(mw) {
		app.use((typeof mw == 'string' ? require(mw) : mw).bind(proxyEvents));
	});
	exportInterfaces(proxyEvents);
	tunnelProxy(server, proxyEvents);
	require('./proxy');
	return proxyEvents;
}

function exportInterfaces(obj) {
	obj.rules = rules;
	obj.util = util;
	obj.rulesUtil = rulesUtil;
	return obj;
}

module.exports = exportInterfaces(proxy);<|endoftext|>