<commit_before>/**
 * koa-body - index.js
 * Copyright(c) 2014
 * MIT Licensed
 *
 * @author  Daryl Lau (@dlau)
 * @author  Charlike Mike Reagent (@tunnckoCore)
 * @api private
 */

'use strict';

/**
 * Module dependencies.
 */

var buddy = require('co-body');
var forms = require('formidable');

/**
 * Expose `requestbody()`.
 */

module.exports = requestbody;

/**
 *
 * @param {Object} options
 * @see https://github.com/dlau/koa-body
 * @api public
 */
function requestbody(opts) {
  opts = opts || {};
  opts.onError = 'onError' in opts ? opts.onError : false;
  opts.patchNode = 'patchNode' in opts ? opts.patchNode : false;
  opts.patchKoa = 'patchKoa' in opts ? opts.patchKoa : true;
  opts.multipart = 'multipart' in opts ? opts.multipart : false;
  opts.urlencoded = 'urlencoded' in opts ? opts.urlencoded : true;
  opts.json = 'json' in opts ? opts.json : true;
  opts.text = 'text' in opts ? opts.text : true;
  opts.encoding = 'encoding' in opts ? opts.encoding : 'utf-8';
  opts.jsonLimit = 'jsonLimit' in opts ? opts.jsonLimit : '1mb';
  opts.jsonStrict = 'jsonStrict' in opts ? opts.jsonStrict : true;
  opts.formLimit = 'formLimit' in opts ? opts.formLimit : '56kb';
  opts.queryString = 'queryString' in opts ? opts.queryString : null;
  opts.formidable = 'formidable' in opts ? opts.formidable : {};
  opts.includeUnparsed = 'includeUnparsed' in opts ? opts.includeUnparsed : false
  opts.textLimit = 'textLimit' in opts ? opts.textLimit : '56kb';
  opts.strict = 'strict' in opts ? opts.strict : true;

  if (opts.includeUnparsed) {
    // Only load the symbol if includeUnparsed is truthy
    const symbolUnparsed = require('./unparsed.js');
  }

  return function (ctx, next) {
    var bodyPromise;
    // so don't parse the body in strict mode
    if (!opts.strict || ["GET", "HEAD", "DELETE"].indexOf(ctx.method.toUpperCase()) === -1) {
      try {
        if (opts.json && ctx.is('json')) {
          bodyPromise = buddy.json(ctx, {
            encoding: opts.encoding,
            limit: opts.jsonLimit,
            strict: opts.jsonStrict,
            returnRawBody: opts.includeUnparsed
          });
        } else if (opts.urlencoded && ctx.is('urlencoded')) {
          bodyPromise = buddy.form(ctx, {
            encoding: opts.encoding,
            limit: opts.formLimit,
            queryString: opts.queryString,
            returnRawBody: opts.includeUnparsed
          });
        } else if (opts.text && ctx.is('text')) {
          bodyPromise = buddy.text(ctx, {
            encoding: opts.encoding,
            limit: opts.textLimit,
            returnRawBody: opts.includeUnparsed
          });
        } else if (opts.multipart && ctx.is('multipart')) {
          bodyPromise = formy(ctx, opts.formidable);
        }
      } catch (parsingError) {
        if (typeof opts.onError === 'function') {
          opts.onError(parsingError, ctx);
        } else {
          throw parsingError;
        }
      }
    }

    bodyPromise = bodyPromise || Promise.resolve({});
    return bodyPromise.catch(function(parsingError) {
      if (typeof opts.onError === 'function') {
        opts.onError(parsingError, ctx);
      } else {
        throw parsingError;
      }
      return next();
    })
    .then(function(body) {
      if (opts.patchNode) {
        if (isMultiPart(ctx, opts)) {
          ctx.req.body = body.fields;
          ctx.req.files = body.files;
        } else if (opts.includeUnparsed) {
          ctx.req.body = body.parsed;
          if (! ctx.is('text')) {
            ctx.request.body[symbolUnparsed] = body.raw;
          }
        } else {
          ctx.req.body = body;
        }
      }
      if (opts.patchKoa) {
        if (isMultiPart(ctx, opts)) {
          ctx.request.body = body.fields;
          ctx.request.files = body.files;
        } else if (opts.includeUnparsed) {
          ctx.request.body = body.parsed;
          if (! ctx.is('text')) {
            ctx.request.body[symbolUnparsed] = body.raw;
          }
        } else {
          ctx.request.body = body;
        }
      }
      return next();
    })
  };
}

/**
 * Check if multipart handling is enabled and that this is a multipart request
 *
 * @param  {Object} ctx
 * @param  {Object} opts
 * @return {Boolean} true if request is multipart and being treated as so
 * @api private
 */
function isMultiPart(ctx, opts) {
  return opts.multipart && ctx.is('multipart');
}

/**
 * Donable formidable
 *
 * @param  {Stream} ctx
 * @param  {Object} opts
 * @return {Promise}
 * @api private
 */
function formy(ctx, opts) {
  return new Promise(function (resolve, reject) {
    var fields = {};
    var files = {};
    var form = new forms.IncomingForm(opts);
    form.on('end', function () {
      return resolve({
        fields: fields,
        files: files
      });
    }).on('error', function (err) {
      return reject(err);
    }).on('field', function (field, value) {
      if (fields[field]) {
        if (Array.isArray(fields[field])) {
          fields[field].push(value);
        } else {
          fields[field] = [fields[field], value];
        }
      } else {
        fields[field] = value;
      }
    }).on('file', function (field, file) {
      if (files[field]) {
        if (Array.isArray(files[field])) {
          files[field].push(file);
        } else {
          files[field] = [files[field], file];
        }
      } else {
        files[field] = file;
      }
    });
    if (opts.onFileBegin) {
      form.on('fileBegin', opts.onFileBegin);
    }
    form.parse(ctx.req);
  });
}
<commit_msg>make requires const<commit_after>/**
 * koa-body - index.js
 * Copyright(c) 2014
 * MIT Licensed
 *
 * @author  Daryl Lau (@dlau)
 * @author  Charlike Mike Reagent (@tunnckoCore)
 * @api private
 */

'use strict';

/**
 * Module dependencies.
 */

const buddy = require('co-body');
const forms = require('formidable');
const symbolUnparsed = require('./unparsed.js');

/**
 * Expose `requestbody()`.
 */

module.exports = requestbody;

/**
 *
 * @param {Object} options
 * @see https://github.com/dlau/koa-body
 * @api public
 */
function requestbody(opts) {
  opts = opts || {};
  opts.onError = 'onError' in opts ? opts.onError : false;
  opts.patchNode = 'patchNode' in opts ? opts.patchNode : false;
  opts.patchKoa = 'patchKoa' in opts ? opts.patchKoa : true;
  opts.multipart = 'multipart' in opts ? opts.multipart : false;
  opts.urlencoded = 'urlencoded' in opts ? opts.urlencoded : true;
  opts.json = 'json' in opts ? opts.json : true;
  opts.text = 'text' in opts ? opts.text : true;
  opts.encoding = 'encoding' in opts ? opts.encoding : 'utf-8';
  opts.jsonLimit = 'jsonLimit' in opts ? opts.jsonLimit : '1mb';
  opts.jsonStrict = 'jsonStrict' in opts ? opts.jsonStrict : true;
  opts.formLimit = 'formLimit' in opts ? opts.formLimit : '56kb';
  opts.queryString = 'queryString' in opts ? opts.queryString : null;
  opts.formidable = 'formidable' in opts ? opts.formidable : {};
  opts.includeUnparsed = 'includeUnparsed' in opts ? opts.includeUnparsed : false
  opts.textLimit = 'textLimit' in opts ? opts.textLimit : '56kb';
  opts.strict = 'strict' in opts ? opts.strict : true;

  return function (ctx, next) {
    var bodyPromise;
    // so don't parse the body in strict mode
    if (!opts.strict || ["GET", "HEAD", "DELETE"].indexOf(ctx.method.toUpperCase()) === -1) {
      try {
        if (opts.json && ctx.is('json')) {
          bodyPromise = buddy.json(ctx, {
            encoding: opts.encoding,
            limit: opts.jsonLimit,
            strict: opts.jsonStrict,
            returnRawBody: opts.includeUnparsed
          });
        } else if (opts.urlencoded && ctx.is('urlencoded')) {
          bodyPromise = buddy.form(ctx, {
            encoding: opts.encoding,
            limit: opts.formLimit,
            queryString: opts.queryString,
            returnRawBody: opts.includeUnparsed
          });
        } else if (opts.text && ctx.is('text')) {
          bodyPromise = buddy.text(ctx, {
            encoding: opts.encoding,
            limit: opts.textLimit,
            returnRawBody: opts.includeUnparsed
          });
        } else if (opts.multipart && ctx.is('multipart')) {
          bodyPromise = formy(ctx, opts.formidable);
        }
      } catch (parsingError) {
        if (typeof opts.onError === 'function') {
          opts.onError(parsingError, ctx);
        } else {
          throw parsingError;
        }
      }
    }

    bodyPromise = bodyPromise || Promise.resolve({});
    return bodyPromise.catch(function(parsingError) {
      if (typeof opts.onError === 'function') {
        opts.onError(parsingError, ctx);
      } else {
        throw parsingError;
      }
      return next();
    })
    .then(function(body) {
      if (opts.patchNode) {
        if (isMultiPart(ctx, opts)) {
          ctx.req.body = body.fields;
          ctx.req.files = body.files;
        } else if (opts.includeUnparsed) {
          ctx.req.body = body.parsed;
          if (! ctx.is('text')) {
            ctx.request.body[symbolUnparsed] = body.raw;
          }
        } else {
          ctx.req.body = body;
        }
      }
      if (opts.patchKoa) {
        if (isMultiPart(ctx, opts)) {
          ctx.request.body = body.fields;
          ctx.request.files = body.files;
        } else if (opts.includeUnparsed) {
          ctx.request.body = body.parsed;
          if (! ctx.is('text')) {
            ctx.request.body[symbolUnparsed] = body.raw;
          }
        } else {
          ctx.request.body = body;
        }
      }
      return next();
    })
  };
}

/**
 * Check if multipart handling is enabled and that this is a multipart request
 *
 * @param  {Object} ctx
 * @param  {Object} opts
 * @return {Boolean} true if request is multipart and being treated as so
 * @api private
 */
function isMultiPart(ctx, opts) {
  return opts.multipart && ctx.is('multipart');
}

/**
 * Donable formidable
 *
 * @param  {Stream} ctx
 * @param  {Object} opts
 * @return {Promise}
 * @api private
 */
function formy(ctx, opts) {
  return new Promise(function (resolve, reject) {
    var fields = {};
    var files = {};
    var form = new forms.IncomingForm(opts);
    form.on('end', function () {
      return resolve({
        fields: fields,
        files: files
      });
    }).on('error', function (err) {
      return reject(err);
    }).on('field', function (field, value) {
      if (fields[field]) {
        if (Array.isArray(fields[field])) {
          fields[field].push(value);
        } else {
          fields[field] = [fields[field], value];
        }
      } else {
        fields[field] = value;
      }
    }).on('file', function (field, file) {
      if (files[field]) {
        if (Array.isArray(files[field])) {
          files[field].push(file);
        } else {
          files[field] = [files[field], file];
        }
      } else {
        files[field] = file;
      }
    });
    if (opts.onFileBegin) {
      form.on('fileBegin', opts.onFileBegin);
    }
    form.parse(ctx.req);
  });
}
<|endoftext|>


<commit_before>// String encode/decode helpers
'use strict';

var utils = require('./common');

// Quick check if we can use fast array to bin string conversion
var STR_APPLY_OK = true;
try { String.fromCharCode.apply(null, [0]); } catch(__) { STR_APPLY_OK = false; }

// Table with utf8 lengths
var utf8len = new utils.Buf8(256);
for (var i=0; i<256; i++) {
  utf8len[i] = (i >= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1);
}

// convert string to array (typed, when possible)
// src: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding
exports.string2buf = function (str) {
  var buf, c, str_len = str.length, buf_len = 0;

  /* mapping... */

  for (var m_pos = 0; m_pos < str_len; m_pos++) {
    c = str.charCodeAt(m_pos);
    buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : c < 0x200000 ? 4 : c < 0x4000000 ? 5 : 6;
  }

  buf = new utils.Buf8(buf_len);

  /* transcription... */

  for (var i = 0, c_pos = 0; i < buf_len; c_pos++) {
    c = str.charCodeAt(c_pos);
    if (c < 128) {
      /* one byte */
      buf[i++] = c;
    } else if (c < 0x800) {
      /* two bytes */
      buf[i++] = 192 + (c >>> 6);
      buf[i++] = 128 + (c & 63);
    } else if (c < 0x10000) {
      /* three bytes */
      buf[i++] = 224 + (c >>> 12);
      buf[i++] = 128 + (c >>> 6 & 63);
      buf[i++] = 128 + (c & 63);
    } else if (c < 0x200000) {
      /* four bytes */
      buf[i++] = 240 + (c >>> 18);
      buf[i++] = 128 + (c >>> 12 & 63);
      buf[i++] = 128 + (c >>> 6 & 63);
      buf[i++] = 128 + (c & 63);
    } else if (c < 0x4000000) {
      /* five bytes */
      buf[i++] = 248 + (c >>> 24);
      buf[i++] = 128 + (c >>> 18 & 63);
      buf[i++] = 128 + (c >>> 12 & 63);
      buf[i++] = 128 + (c >>> 6 & 63);
      buf[i++] = 128 + (c & 63);
    } else /* if (c <= 0x7fffffff) */ {
      /* six bytes */
      buf[i++] = 252 + /* (c >>> 32) is not possible in ECMAScript! So...: */ (c / 1073741824);
      buf[i++] = 128 + (c >>> 24 & 63);
      buf[i++] = 128 + (c >>> 18 & 63);
      buf[i++] = 128 + (c >>> 12 & 63);
      buf[i++] = 128 + (c >>> 6 & 63);
      buf[i++] = 128 + (c & 63);
    }
  }

  return buf;
};

// Convert byte array to binary string
exports.buf2binstring = function(buf) {
  // use fallback for big arrays to avoid stack overflow
  if (STR_APPLY_OK && buf.length < 65537) {
    return String.fromCharCode.apply(null, buf);
  }

  var result = '';
  for(var i=0, len=buf.length; i < len; i++) {
    result += String.fromCharCode(buf[i]);
  }
  return result;
};

// Convert binary string (typed, when possible)
exports.binstring2buf = function(str) {
  var buf = new utils.Buf8(str.length);
  for(var i=0, len=buf.length; i < len; i++) {
    buf[i] = str.charCodeAt(i);
  }
  return buf;
};

// convert array to string
// src: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding
exports.buf2string = function (buf, max) {
  /*jshint nonstandard:true*/
  // That's not as fast as via String.fromCharCode.appy
  /*return decodeURIComponent(escape(exports.buf2binstring(
    (buf.length === max) ?
      buf
    :
      buf.subarray ? buf.subarray(0, max) : buf.slice(0, max)
  )));*/

  var str = '', i, out, part, char_len;
  var len = max || buf.length;
  var out_len = 0;
  var utf16buf;

  // Calculate output length
  for (i=0; i < len;) {
    i += utf8len[buf[i]];
    out_len++;
  }

  utf16buf = new utils.Buf32(out_len);

  for (out=0, i=0; i<len; i++) {
    part = buf[i];
    char_len = utf8len[part];

    // edge case - broken sequence
    if (i + char_len > len) {
      utf16buf[out++] = 0x7f;
      break;
    }
    switch (char_len) {
      case 1:
        utf16buf[out++] = part;
        break;
      case 2:
        utf16buf[out++] = ((part & 0x1f) << 6) | (buf[++i] & 0x7f);
        break;
      case 3:
        utf16buf[out++] = ((part & 0x0f) << 12) | ((buf[++i] & 0x3f) << 6) | (buf[++i] & 0x3f);
        break;
      case 4:
        utf16buf[out++] = ((part & 0x07) << 18) | ((buf[++i] & 0x3f) << 12) | ((buf[++i] & 0x3f) << 6) + (buf[++i] & 0x3f);
        break;
      // 5 & 6 bytes uticodes not supported in UTF16 (JS), so fill with dummy symbol
      case 5:
        i += 4;
        utf16buf[out++] = 0x7f;
        //utf16buf[out++] = (part - 248 << 24) + (buf[++i] - 128 << 18) + (buf[++i] - 128 << 12) + (buf[++i] - 128 << 6) + buf[++i] - 128;
        break;
      case 6:
        i += 5;
        utf16buf[out++] = 0x7f;
                          // (part - 252 << 32) is not possible in ECMAScript! So...:
        //utf16buf[out++] = (part - 252) * 1073741824 + (buf[++i] - 128 << 24) + (buf[++i] - 128 << 18) + (buf[++i] - 128 << 12) + (buf[++i] - 128 << 6) + buf[++i] - 128;
        break;
    }
  }

  if (STR_APPLY_OK) {
    return String.fromCharCode.apply(null, utf16buf);
  }

  // Fallback, when String.fromCharCode.apply not available
  for (i=0, len=utf16buf.length; i<len; i++) {
    str += String.fromCharCode(utf16buf[i]);
  }
  return str;
};

// calculate tail size of utf8 char by current byte value
exports.utf8tail = function(code) {
  return utf8len[code];
};
<commit_msg>More utf8 decoder opts<commit_after>// String encode/decode helpers
'use strict';

var utils = require('./common');

// Quick check if we can use fast array to bin string conversion
var STR_APPLY_OK = true;
try { String.fromCharCode.apply(null, [0]); } catch(__) { STR_APPLY_OK = false; }

// Table with utf8 lengths
var utf8len = new utils.Buf8(256);
for (var i=0; i<256; i++) {
  utf8len[i] = (i >= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1);
}

// convert string to array (typed, when possible)
// src: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding
exports.string2buf = function (str) {
  var buf, c, str_len = str.length, buf_len = 0;

  /* mapping... */

  for (var m_pos = 0; m_pos < str_len; m_pos++) {
    c = str.charCodeAt(m_pos);
    buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : c < 0x200000 ? 4 : c < 0x4000000 ? 5 : 6;
  }

  buf = new utils.Buf8(buf_len);

  /* transcription... */

  for (var i = 0, c_pos = 0; i < buf_len; c_pos++) {
    c = str.charCodeAt(c_pos);
    if (c < 128) {
      /* one byte */
      buf[i++] = c;
    } else if (c < 0x800) {
      /* two bytes */
      buf[i++] = 192 + (c >>> 6);
      buf[i++] = 128 + (c & 63);
    } else if (c < 0x10000) {
      /* three bytes */
      buf[i++] = 224 + (c >>> 12);
      buf[i++] = 128 + (c >>> 6 & 63);
      buf[i++] = 128 + (c & 63);
    } else if (c < 0x200000) {
      /* four bytes */
      buf[i++] = 240 + (c >>> 18);
      buf[i++] = 128 + (c >>> 12 & 63);
      buf[i++] = 128 + (c >>> 6 & 63);
      buf[i++] = 128 + (c & 63);
    } else if (c < 0x4000000) {
      /* five bytes */
      buf[i++] = 248 + (c >>> 24);
      buf[i++] = 128 + (c >>> 18 & 63);
      buf[i++] = 128 + (c >>> 12 & 63);
      buf[i++] = 128 + (c >>> 6 & 63);
      buf[i++] = 128 + (c & 63);
    } else /* if (c <= 0x7fffffff) */ {
      /* six bytes */
      buf[i++] = 252 + /* (c >>> 32) is not possible in ECMAScript! So...: */ (c / 1073741824);
      buf[i++] = 128 + (c >>> 24 & 63);
      buf[i++] = 128 + (c >>> 18 & 63);
      buf[i++] = 128 + (c >>> 12 & 63);
      buf[i++] = 128 + (c >>> 6 & 63);
      buf[i++] = 128 + (c & 63);
    }
  }

  return buf;
};

// Convert byte array to binary string
exports.buf2binstring = function(buf) {
  // use fallback for big arrays to avoid stack overflow
  if (STR_APPLY_OK && buf.length < 65537) {
    return String.fromCharCode.apply(null, buf);
  }

  var result = '';
  for(var i=0, len=buf.length; i < len; i++) {
    result += String.fromCharCode(buf[i]);
  }
  return result;
};

// Convert binary string (typed, when possible)
exports.binstring2buf = function(str) {
  var buf = new utils.Buf8(str.length);
  for(var i=0, len=buf.length; i < len; i++) {
    buf[i] = str.charCodeAt(i);
  }
  return buf;
};

// convert array to string
// src: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding
exports.buf2string = function (buf, max) {
  /*jshint nonstandard:true*/
  // That's not as fast as via String.fromCharCode.appy
  /*return decodeURIComponent(escape(exports.buf2binstring(
    (buf.length === max) ?
      buf
    :
      buf.subarray ? buf.subarray(0, max) : buf.slice(0, max)
  )));*/

  var str, i, out, part, char_len;
  var len = max || buf.length;

  // Reserve max possibli length
  var utf16buf = new utils.Buf16(len*2);

  for (out=0, i=0; i<len; i++) {
    part = buf[i];
    char_len = utf8len[part];

    // edge case - broken sequence
    if (i + char_len > len) {
      utf16buf[out++] = 0xfffd;
      break;
    }
    switch (char_len) {
      case 1:
        utf16buf[out++] = part;
        break;
      case 2:
        utf16buf[out++] = ((part & 0x1f) << 6) | (buf[++i] & 0x7f);
        break;
      case 3:
        utf16buf[out++] = ((part & 0x0f) << 12) | ((buf[++i] & 0x3f) << 6) | (buf[++i] & 0x3f);
        break;
      case 4:
        // surrogate pair
        part = ((part & 0x07) << 18) | ((buf[++i] & 0x3f) << 12) | ((buf[++i] & 0x3f) << 6) + (buf[++i] & 0x3f);
        part -= 0x10000;
        utf16buf[out++] = 0xd800 | ((part >> 10) & 0x3ff);
        utf16buf[out++] = 0xdc00 | (part & 0x3ff);
        break;
      // 5 & 6 bytes uticodes not supported in UTF16 (JS), so fill with dummy symbol
      case 5:
        i += 4;
        utf16buf[out++] = 0xfffd;
        //utf16buf[out++] = (part - 248 << 24) + (buf[++i] - 128 << 18) + (buf[++i] - 128 << 12) + (buf[++i] - 128 << 6) + buf[++i] - 128;
        break;
      case 6:
        i += 5;
        utf16buf[out++] = 0xfffd;
                          // (part - 252 << 32) is not possible in ECMAScript! So...:
        //utf16buf[out++] = (part - 252) * 1073741824 + (buf[++i] - 128 << 24) + (buf[++i] - 128 << 18) + (buf[++i] - 128 << 12) + (buf[++i] - 128 << 6) + buf[++i] - 128;
        break;
    }
  }

  if (STR_APPLY_OK) {
    return String.fromCharCode.apply(null, utils.shrinkBuf(utf16buf, out));
  }

  // Fallback, when String.fromCharCode.apply not available
  str = '';
  for (i=0, len=out; i<len; i++) {
    str += String.fromCharCode(utf16buf[i]);
  }
  return str;
};

// calculate tail size of utf8 char by current byte value
exports.utf8tail = function(code) {
  return utf8len[code];
};
<|endoftext|>


<commit_before>var through = require('through2')

module.exports = prependify

function prependify (b, text) {
  if (typeof(text) === 'object') {
    text = text[Object.keys(text)[0]].join(' ');
  }

  b.on('bundle', function () {
    var first = true
    b.pipeline.get('wrap').push(
      through.obj(function (buf, _, next) {
        if (first) {
          this.push(text)
          first = false
        }
        this.push(buf)
        next()
      })
    )
  })
}
<commit_msg>style fix<commit_after>var through = require('through2')

module.exports = prependify

function prependify (b, text) {
  if (typeof (text) === 'object') {
    text = text[Object.keys(text)[0]].join(' ')
  }

  b.on('bundle', function () {
    var first = true
    b.pipeline.get('wrap').push(
      through.obj(function (buf, _, next) {
        if (first) {
          this.push(text)
          first = false
        }
        this.push(buf)
        next()
      })
    )
  })
}
<|endoftext|>


<commit_before>const Evaluator = require('./evaluator');
const FilterManager = require('./filter-manager');
const Hash = require('./data.hash');
const QueueHash = require('./data.queueHash');
const parser = require('./parser');

class AstCache {
  /**
   * @param {Evaluator} evaluator
   */
  constructor(evaluator) {
    this._parser = parser.init();
    this._evaluator = evaluator;
    this._cache = new Hash();
  }

  /**
   * @param {string} source
   * @param {string} content
   */
  save(source, content) {
    if (!this._cache.has(source)) {
      this._cache.add(source, this._parser.parse(content, source));
    }
  }

  /**
   * @param {string} source
   * @return {boolean}
   */
  has(source) {
    return this._cache.has(source);
  }

  /**
   * @param {string} source
   * @param {Object} param
   * @return {string}
   * @throws {Error}
   */
  evaluate(source, param) {
    try {
      return this._evaluator.evaluate(this._cache.get(source), [param]);
    } catch (e) {
      throw new Error('template - ' + e.message + ' in source ' + source);
    }
  }

  clear() {
    this._cache.clear();
  }
}

class RemoteQueue {
  /**
   * @param {AstCache} astCache
   */
  constructor(astCache) {
    this._astCache = astCache;
    this._queueHash = new QueueHash();
  }

  /**
   * @param {string} source
   * @param {{param: Object, callback: function}} data
   */
  push(source, data) {
    this._queueHash.addTo(source, {
      param: data.param,
      callback: data.callback,
    });
  }

  /**
   * @param {string} source
   * @throws {Error}
   */
  consume(source) {
    let queue;

    while (this._queueHash.sizeOf(source) > 0) {
      queue = this._queueHash.getFrom(source);
      queue.callback(this._astCache.evaluate(source, queue.param));
    }
  }
}

class PrefetchManager {
  /**
   * @param {AstCache} astCache
   */
  constructor(astCache) {
    this._jobList = [];
    this._astCache = astCache;
  }

  /**
   * @param {string[]} sourceList
   * @param {function} callback
   */
  add(sourceList, callback) {
    this._jobList.push({
      sourceList: sourceList,
      callback: callback,
    });
  }

  notifyFetched() {
    const undone = [];
    const finished = [];

    this._jobList.forEach((job) => {
      const unacquired = job.sourceList.filter((source) => {
        return !this._astCache.has(source);
      });

      if (unacquired.length > 0) {
        undone.push(job);
      } else {
        finished.push(job);
      }
    });

    this._jobList = undone;

    finished.forEach((job) => {
      if (typeof job.callback === 'function') {
        job.callback();
      }
    });
  }
}

class RemoteManager {
  /**
   * @param {AstCache} astCache
   */
  constructor(astCache) {
    this._astCache = astCache;
    this._prefetchManager = new PrefetchManager(astCache);
    this._remoteQueue = new RemoteQueue(astCache);
    this._fetching = new Hash();
  }

  /**
   * @param {string} source
   * @param {Object} data
   */
  register(source, data) {
    if (data.render) {
      this._remoteQueue.push(source, data.render);
    }

    if (this._astCache.has(source)) {
      this._remoteQueue.consume(source);
    } else {
      if (this._fetching.has(source)) {
        return;
      }

      this._fetching.add(source, true);
      this._fetchRemoteSource(source, (content) => {
        if (data.check && typeof data.check.callback === 'function') {
          data.check.callback(source);
        }

        this._astCache.save(source, content);
        this._fetching.remove(source);
        this._prefetchManager.notifyFetched();
        this._remoteQueue.consume(source);
      });
    }
  }

  /**
   * @param {string[]} sourceList
   * @param {function} callback
   * @param {function} checkCallback
   */
  prefetch(sourceList, callback, checkCallback) {
    this._prefetchManager.add(sourceList, callback);

    sourceList.forEach((source) => {
      this.register(source, {
        check: {
          callback: checkCallback,
        },
      });
    });
  }

  /**
   * @param {string} source
   * @param {function} callback
   * @private
   */
  _fetchRemoteSource(source, callback) {
    const req = new XMLHttpRequest();

    req.open('GET', source, true);
    req.onreadystatechange = () => {
      if (req.readyState !== 4 || req.status !== 200) {
        return;
      }

      callback(req.responseText);
    };
    req.send();
  }
}

const template = () => {
  const that = {};

  const _filterManager = new FilterManager();

  const _astCache = new AstCache(new Evaluator(_filterManager));

  const _prefetchManager = new PrefetchManager(_astCache);

  const _remoteQueue = new RemoteQueue(_astCache);

  const _registerFromRemote = (() => {
    const _fetching = new Hash();

    const _fetchRemoteSource = (source, data, callback) => {
      const req = new XMLHttpRequest();

      req.open('GET', source, true);
      req.onreadystatechange = () => {
        if (req.readyState !== 4 || req.status !== 200) {
          return;
        }

        callback(req.responseText);
      };
      req.send();
    };

    return (source, data) => {
      if (data.render) {
        _remoteQueue.push(source, data.render);
      }

      if (_astCache.has(source)) {
        _remoteQueue.consume(source);
      } else {
        if (_fetching.has(source)) {
          return;
        }

        _fetching.add(source, true);
        _fetchRemoteSource(source, data, (content) => {
          if (data.check && typeof data.check.callback === 'function') {
            data.check.callback(source);
          }

          _astCache.save(source, content);
          _fetching.remove(source);
          _prefetchManager.notifyFetched();
          _remoteQueue.consume(source);
        });
      }
    };
  })();

  /**
   * @param {string} name
   * @param {function} func
   */
  that.addFilter = (name, func) => {
    _filterManager.register(name, func);
  };

  /**
   * @param {string} source
   * @param {Object} param
   * @return {string}
   * @throws {Error}
   */
  that.render = (source, param) => {
    _astCache.save(source, source);

    return _astCache.evaluate(source, param);
  };

  /**
   * @param {string} source
   * @param {Object} param
   * @param {function} callback
   */
  that.renderAsync = (source, param, callback) => {
    _registerFromRemote(source, {
      render: {
        param: param,
        callback: callback,
      },
    });
  };

  /**
   * @param {string|string[]} target
   * @param {function} callback Called once when all sources fetched.
   * @param {function} [checkCallback] Called every time when a source fetched.
   */
  that.prefetch = (target, callback, checkCallback) => {
    const sourceList = (typeof target === 'string') ? [].concat(target) : target;

    sourceList.forEach((source) => {
      _registerFromRemote(source, {
        check: {
          callback: checkCallback,
        },
      });
    });

    _prefetchManager.add(sourceList, callback);
  };

  that.clearTemplateCache = () => {
    _astCache.clear();
  };

  registerPredefinedFilters(_filterManager);

  return that;
};

/**
 * @param {FilterManager} filterManager
 */
const registerPredefinedFilters = (filterManager) => {
  filterManager.register('h', (() => {
    const list = {
      '<': '<',
      '>': '>',
      '&': '&',
      '"': '"',
      "'": ''', // eslint-disable-line quotes
    };

    return (value) => {
      return value.replace(/[<>&"']/g, (matched) => {
        return list[matched];
      });
    };
  })());

  filterManager.register('default', (value, defaultValue) => {
    return value.length === 0 ? defaultValue : value;
  });

  filterManager.register('upper', (value) => {
    return value.toLocaleUpperCase();
  });

  filterManager.register('lower', (value) => {
    return value.toLocaleLowerCase();
  });

  filterManager.register('plus', (value, plus) => {
    if (isFinite(value) && typeof plus === 'number' && isFinite(plus)) {
      return (+(value) + plus).toString();
    } else {
      return value;
    }
  });
};

module.exports.init = () => {
  return template();
};
<commit_msg>Use RemoteManager<commit_after>const Evaluator = require('./evaluator');
const FilterManager = require('./filter-manager');
const Hash = require('./data.hash');
const QueueHash = require('./data.queueHash');
const parser = require('./parser');

class AstCache {
  /**
   * @param {Evaluator} evaluator
   */
  constructor(evaluator) {
    this._parser = parser.init();
    this._evaluator = evaluator;
    this._cache = new Hash();
  }

  /**
   * @param {string} source
   * @param {string} content
   */
  save(source, content) {
    if (!this._cache.has(source)) {
      this._cache.add(source, this._parser.parse(content, source));
    }
  }

  /**
   * @param {string} source
   * @return {boolean}
   */
  has(source) {
    return this._cache.has(source);
  }

  /**
   * @param {string} source
   * @param {Object} param
   * @return {string}
   * @throws {Error}
   */
  evaluate(source, param) {
    try {
      return this._evaluator.evaluate(this._cache.get(source), [param]);
    } catch (e) {
      throw new Error('template - ' + e.message + ' in source ' + source);
    }
  }

  clear() {
    this._cache.clear();
  }
}

class RemoteQueue {
  /**
   * @param {AstCache} astCache
   */
  constructor(astCache) {
    this._astCache = astCache;
    this._queueHash = new QueueHash();
  }

  /**
   * @param {string} source
   * @param {{param: Object, callback: function}} data
   */
  push(source, data) {
    this._queueHash.addTo(source, {
      param: data.param,
      callback: data.callback,
    });
  }

  /**
   * @param {string} source
   * @throws {Error}
   */
  consume(source) {
    let queue;

    while (this._queueHash.sizeOf(source) > 0) {
      queue = this._queueHash.getFrom(source);
      queue.callback(this._astCache.evaluate(source, queue.param));
    }
  }
}

class PrefetchManager {
  /**
   * @param {AstCache} astCache
   */
  constructor(astCache) {
    this._jobList = [];
    this._astCache = astCache;
  }

  /**
   * @param {string[]} sourceList
   * @param {function} callback
   */
  add(sourceList, callback) {
    this._jobList.push({
      sourceList: sourceList,
      callback: callback,
    });
  }

  notifyFetched() {
    const undone = [];
    const finished = [];

    this._jobList.forEach((job) => {
      const unacquired = job.sourceList.filter((source) => {
        return !this._astCache.has(source);
      });

      if (unacquired.length > 0) {
        undone.push(job);
      } else {
        finished.push(job);
      }
    });

    this._jobList = undone;

    finished.forEach((job) => {
      if (typeof job.callback === 'function') {
        job.callback();
      }
    });
  }
}

class RemoteManager {
  /**
   * @param {AstCache} astCache
   */
  constructor(astCache) {
    this._astCache = astCache;
    this._prefetchManager = new PrefetchManager(astCache);
    this._remoteQueue = new RemoteQueue(astCache);
    this._fetching = new Hash();
  }

  /**
   * @param {string} source
   * @param {Object} data
   */
  register(source, data) {
    if (data.render) {
      this._remoteQueue.push(source, data.render);
    }

    if (this._astCache.has(source)) {
      this._remoteQueue.consume(source);
    } else {
      if (this._fetching.has(source)) {
        return;
      }

      this._fetching.add(source, true);
      this._fetchRemoteSource(source, (content) => {
        if (data.check && typeof data.check.callback === 'function') {
          data.check.callback(source);
        }

        this._astCache.save(source, content);
        this._fetching.remove(source);
        this._prefetchManager.notifyFetched();
        this._remoteQueue.consume(source);
      });
    }
  }

  /**
   * @param {string[]} sourceList
   * @param {function} callback
   * @param {function} checkCallback
   */
  prefetch(sourceList, callback, checkCallback) {
    this._prefetchManager.add(sourceList, callback);

    sourceList.forEach((source) => {
      this.register(source, {
        check: {
          callback: checkCallback,
        },
      });
    });
  }

  /**
   * @param {string} source
   * @param {function} callback
   * @private
   */
  _fetchRemoteSource(source, callback) {
    const req = new XMLHttpRequest();

    req.open('GET', source, true);
    req.onreadystatechange = () => {
      if (req.readyState !== 4 || req.status !== 200) {
        return;
      }

      callback(req.responseText);
    };
    req.send();
  }
}

const template = () => {
  const that = {};

  const _filterManager = new FilterManager();

  const _astCache = new AstCache(new Evaluator(_filterManager));

  const _remoteManager = new RemoteManager(_astCache);

  /**
   * @param {string} name
   * @param {function} func
   */
  that.addFilter = (name, func) => {
    _filterManager.register(name, func);
  };

  /**
   * @param {string} source
   * @param {Object} param
   * @return {string}
   * @throws {Error}
   */
  that.render = (source, param) => {
    _astCache.save(source, source);

    return _astCache.evaluate(source, param);
  };

  /**
   * @param {string} source
   * @param {Object} param
   * @param {function} callback
   */
  that.renderAsync = (source, param, callback) => {
    _remoteManager.register(source, {
      render: {
        param: param,
        callback: callback,
      },
    });
  };

  /**
   * @param {string|string[]} target
   * @param {function} callback Called once when all sources fetched.
   * @param {function} [checkCallback] Called every time when a source fetched.
   */
  that.prefetch = (target, callback, checkCallback) => {
    const sourceList = (typeof target === 'string') ? [].concat(target) : target;

    _remoteManager.prefetch(sourceList, callback, checkCallback);
  };

  that.clearTemplateCache = () => {
    _astCache.clear();
  };

  registerPredefinedFilters(_filterManager);

  return that;
};

/**
 * @param {FilterManager} filterManager
 */
const registerPredefinedFilters = (filterManager) => {
  filterManager.register('h', (() => {
    const list = {
      '<': '<',
      '>': '>',
      '&': '&',
      '"': '"',
      "'": ''', // eslint-disable-line quotes
    };

    return (value) => {
      return value.replace(/[<>&"']/g, (matched) => {
        return list[matched];
      });
    };
  })());

  filterManager.register('default', (value, defaultValue) => {
    return value.length === 0 ? defaultValue : value;
  });

  filterManager.register('upper', (value) => {
    return value.toLocaleUpperCase();
  });

  filterManager.register('lower', (value) => {
    return value.toLocaleLowerCase();
  });

  filterManager.register('plus', (value, plus) => {
    if (isFinite(value) && typeof plus === 'number' && isFinite(plus)) {
      return (+(value) + plus).toString();
    } else {
      return value;
    }
  });
};

module.exports.init = () => {
  return template();
};
<|endoftext|>


<commit_before>;(function () {
  module.exports = parseGame
  var tenthPattern = new RegExp('^[XF0-9-]{1}[XF0-9-/]?[XF0-9-/]?$', 'i')
  var basicPattern = new RegExp('^[XF0-9-]{1}[F0-9-/]?$', 'i')
  var zeroEquiv = new RegExp('[F-]', 'g')

  function validateFrame (frame, isTenthFrame) {
    if (frame.length === 0) {
      throw new Error('frame must not be empty: ' + frame)
    } else if (frame.length > 3) {
      throw new Error('frame must be less than 4 chars: ' + frame)
    } else if (frame.length === 3 && !isTenthFrame) {
      throw new Error('frame length too long for frames 1-9: ' + frame)
    } else if (isTenthFrame && !tenthPattern.test(frame)) {
      throw new Error('failed tenth frame validation' + frame)
    } else if (!isTenthFrame && !basicPattern.test(frame)) {
      throw new Error('failed normal frame validation' + frame)
    }
  }

  function parseFrame (result) {
    if (typeof result !== 'string') result = result + ''

    result = result.replace(/0/g, '-')
    result = result.toUpperCase()
    return result
  }

  function isStrike (frame) { return frame === 'X' }

  function isSpare (frame) {
    return frame.length === 2 && frame.match(/\//)
  }

  function scoreFrame (frame) {
    var score

    if (isStrike(frame) || isSpare(frame)) {
      score = null
    } else {
      var addable = frame.replace(zeroEquiv, '0')
      score = 0
      for (var c = 0; c < addable.length; c++) {
        score += parseInt(addable[c], 10)
        if (score > 9) {
          throw new Error('invalid frame score: ' + frame + ' = ' + score)
        }
      }
    }
    return score
  }

  function getRollScores (frames) {
    var rollScores = []
    var rolls = frames.join('').replace(zeroEquiv, '0')

    for (var t = 0; t < rolls.length; t++) {
      var score

      if (rolls[t] === 'X') {
        score = 10
      } else if (rolls[t] === '/') {
        score = 10 - parseInt(rolls[t - 1], 10)
      } else {
        score = parseInt(rolls[t], 10)
      }

      rollScores.push(score)
    }

    return rollScores
  }

  function updateCumulatives (scoresheet) {
    var cumulative = 0
    for (var f = 0; f < scoresheet.length; f++) {
      if (scoresheet[f].score === null) break

      cumulative += scoresheet[f].score
      scoresheet[f].cumulative = cumulative
    }
    return scoresheet
  }

  function scoreTenthFrame (frame) {
    var score = 0
    var isFinal = false

    if (frame.length === 3) {
      isFinal = true
    } else if (frame.length === 2 && frame[1] !== 'X' && frame[1] !== '/') {
      isFinal = true
    }

    if (!isFinal) return null

    while (frame.length > 0) {
      if (isStrike(frame[0])) {
        score += 10
        frame = frame.slice(1)
      } else if (isSpare(frame.substr(0, 2))) {
        score += 10
        frame = frame.slice(2)
      } else {
        score += scoreFrame(frame[0])
        frame = frame.slice(1)
      }
    }
    return score
  }

  function attemptFrameFinalize (frame, leadingFrames) {
    var prevIsPending = frame.score === null
    var nextScores = getRollScores(leadingFrames)
    var bonus = 0

    if (prevIsPending) {
      if (isStrike(frame.outcome)) {
        if (nextScores.length >= 2) {
          bonus += nextScores[0]
          bonus += nextScores[1]
          frame.score = 10 + bonus
        }
      }
      if (isSpare(frame.outcome)) {
        bonus += nextScores[0]
        frame.score = 10 + bonus
      }
    }
  }

  function parseGame (game) {
    var scoresheet = []

    if (game.length > 10) throw new Error('too many frames')

    for (var i = 0; i < game.length; i++) {
      var isTenthFrame = i === 9
      var notFirstFrame = i > 0
      var notFirstTwoFrames = i > 1
      var cleanOutcome = parseFrame(game[i], isTenthFrame)

      validateFrame(cleanOutcome, isTenthFrame)

      scoresheet[i] = {
        outcome: cleanOutcome,
        cumulative: null,
        score: scoreFrame(cleanOutcome)
      }

      var prevFrame, leadingFrames

      if (notFirstFrame) {
        prevFrame = scoresheet[i - 1]
        leadingFrames = [scoresheet[i].outcome]

        attemptFrameFinalize(prevFrame, leadingFrames)
      }

      if (notFirstTwoFrames) {
        prevFrame = scoresheet[i - 2]
        leadingFrames = [scoresheet[i - 1].outcome, scoresheet[i].outcome]

        attemptFrameFinalize(prevFrame, leadingFrames)
      }

      if (isTenthFrame) {
        scoresheet[i].score = scoreTenthFrame(scoresheet[i].outcome)
      }
    }

    scoresheet = updateCumulatives(scoresheet)

    return scoresheet
  }
})(this)
<commit_msg>remove iife, add 'use strict'<commit_after>'use strict'

module.exports = parseGame

var tenthPattern = new RegExp('^[XF0-9-]{1}[XF0-9-/]?[XF0-9-/]?$', 'i')
var basicPattern = new RegExp('^[XF0-9-]{1}[F0-9-/]?$', 'i')
var zeroEquiv = new RegExp('[F-]', 'g')

function validateFrame (frame, isTenthFrame) {
  if (frame.length === 0) {
    throw new Error('frame must not be empty: ' + frame)
  } else if (frame.length > 3) {
    throw new Error('frame must be less than 4 chars: ' + frame)
  } else if (frame.length === 3 && !isTenthFrame) {
    throw new Error('frame length too long for frames 1-9: ' + frame)
  } else if (isTenthFrame && !tenthPattern.test(frame)) {
    throw new Error('failed tenth frame validation' + frame)
  } else if (!isTenthFrame && !basicPattern.test(frame)) {
    throw new Error('failed normal frame validation' + frame)
  }
}

function parseFrame (result) {
  if (typeof result !== 'string') result = result + ''

  result = result.replace(/0/g, '-')
  result = result.toUpperCase()
  return result
}

function isStrike (frame) { return frame === 'X' }

function isSpare (frame) {
  return frame.length === 2 && frame.match(/\//)
}

function scoreFrame (frame) {
  var score

  if (isStrike(frame) || isSpare(frame)) {
    score = null
  } else {
    var addable = frame.replace(zeroEquiv, '0')
    score = 0
    for (var c = 0; c < addable.length; c++) {
      score += parseInt(addable[c], 10)
      if (score > 9) {
        throw new Error('invalid frame score: ' + frame + ' = ' + score)
      }
    }
  }
  return score
}

function getRollScores (frames) {
  var rollScores = []
  var rolls = frames.join('').replace(zeroEquiv, '0')

  for (var t = 0; t < rolls.length; t++) {
    var score

    if (rolls[t] === 'X') {
      score = 10
    } else if (rolls[t] === '/') {
      score = 10 - parseInt(rolls[t - 1], 10)
    } else {
      score = parseInt(rolls[t], 10)
    }

    rollScores.push(score)
  }

  return rollScores
}

function updateCumulatives (scoresheet) {
  var cumulative = 0
  for (var f = 0; f < scoresheet.length; f++) {
    if (scoresheet[f].score === null) break

    cumulative += scoresheet[f].score
    scoresheet[f].cumulative = cumulative
  }
  return scoresheet
}

function scoreTenthFrame (frame) {
  var score = 0
  var isFinal = false

  if (frame.length === 3) {
    isFinal = true
  } else if (frame.length === 2 && frame[1] !== 'X' && frame[1] !== '/') {
    isFinal = true
  }

  if (!isFinal) return null

  while (frame.length > 0) {
    if (isStrike(frame[0])) {
      score += 10
      frame = frame.slice(1)
    } else if (isSpare(frame.substr(0, 2))) {
      score += 10
      frame = frame.slice(2)
    } else {
      score += scoreFrame(frame[0])
      frame = frame.slice(1)
    }
  }
  return score
}

function attemptFrameFinalize (frame, leadingFrames) {
  var prevIsPending = frame.score === null
  var nextScores = getRollScores(leadingFrames)
  var bonus = 0

  if (prevIsPending) {
    if (isStrike(frame.outcome)) {
      if (nextScores.length >= 2) {
        bonus += nextScores[0]
        bonus += nextScores[1]
        frame.score = 10 + bonus
      }
    }
    if (isSpare(frame.outcome)) {
      bonus += nextScores[0]
      frame.score = 10 + bonus
    }
  }
}

function parseGame (game) {
  var scoresheet = []

  if (game.length > 10) throw new Error('too many frames')

  for (var i = 0; i < game.length; i++) {
    var isTenthFrame = i === 9
    var notFirstFrame = i > 0
    var notFirstTwoFrames = i > 1
    var cleanOutcome = parseFrame(game[i], isTenthFrame)

    validateFrame(cleanOutcome, isTenthFrame)

    scoresheet[i] = {
      outcome: cleanOutcome,
      cumulative: null,
      score: scoreFrame(cleanOutcome)
    }

    var prevFrame, leadingFrames

    if (notFirstFrame) {
      prevFrame = scoresheet[i - 1]
      leadingFrames = [scoresheet[i].outcome]

      attemptFrameFinalize(prevFrame, leadingFrames)
    }

    if (notFirstTwoFrames) {
      prevFrame = scoresheet[i - 2]
      leadingFrames = [scoresheet[i - 1].outcome, scoresheet[i].outcome]

      attemptFrameFinalize(prevFrame, leadingFrames)
    }

    if (isTenthFrame) {
      scoresheet[i].score = scoreTenthFrame(scoresheet[i].outcome)
    }
  }

  scoresheet = updateCumulatives(scoresheet)

  return scoresheet
}
<|endoftext|>


<commit_before>var M = process.mono;
var fs = require('fs');
var Model = require(M.config.paths.MODELS + 'factory');
var viewCollection = "m_views";

function load (err, viewId) {
    var self = this;

    Model.factory({name: 'views'}, function (err, views) {

        if (err) {
            return self.emit('<view', err);
        }

        views.read({q: {_id: viewId}}, function (err, data) {

            if (err || !data || !data[0] || !data[0].client) {
                return self.emit('<view', err || 'no view found: ' + viewId);
            }

            self.emit('<view', null, data[0].client);
        });
    });
}

// get html snipptets (ws)
// TODO cache
function html (err, data) {
    var self = this;

    if (!data) {
        return self.emit('<html', 'No path given');
    }

    var file = M.config.paths.TEMPLATE_ROOT + data.replace(/[^a-z0-9\/\.\-_]|\.\.\//gi, "");
    fs.readFile(file, {encoding: 'utf8'}, function (err, data) {

        if (err) {
            return self.emit('<html', 'File not found');
        }

        self.emit('<html', null, data);
    });
}

function factory (config, callback) {

     // create cache key
    var cacheKey = (config.project || '') + config.name;

    // check cache
    var view = M.cache.views.get(cacheKey);
    if (view) {
        return callback(null, view);
    }

    // get system store to fetch models
    M.store(M.config.store.systemStoreName, config.project, function (err, systemStore) {

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

        // get view config
        // TODO check access
        systemStore.collection(viewCollection).findOne({name: config.name}, function (err, dbView) {

            if (err || !dbView) {
                return callback(err || 'View not found');
            }

            // TODO get here the html snipped
            M.store(dbView.store, config.project, function (err, store) {

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

                if (err || !adapters[store._adapter]) {
                    return callback(err || 'Store adapter "' + store._adapter + '" not available.');
                }

                // require adapter
                if (typeof adapters[store._adapter] === 'string') {
                    adapters[store._adapter] = require(adapters[store._adapter]);
                }

                // save view in cache
                view = adapters[store._adapter].model(store, dbModel);
                M.cache.views.save(cacheKey, view);

                callback(null, models[cacheKey]);
            });
        });
    });
}

function factoryService (err, message) {
    var self = this;

    // check message
    if (!message || !message[0]) {
        return self.emit('<model', 'Bad message');
    }

    // create factory config
    message = {
        name: message[0],
        project: message[1]
    };

    // create model
    factory(message, function (err, view) {

        if (err) {
            return self.emit('<view', err);
        }

        var clientView = {
            _id: view._id,
            name: view.name,
            config: view.config
        };

        self.emit('<view', null, clientView);
    });
}

function setup (instance) {

    // setup view
    instance.on('view>', factoryService);
    instance.on('html>', html);

    // return view factory
    return factory;
}

module.exports = setup;
<commit_msg>get html snippet with view config<commit_after>var M = process.mono;
var fs = require('fs');
var Model = require(M.config.paths.MODELS + 'factory');
var viewCollection = "m_views";

function load (err, viewId) {
    var self = this;

    Model.factory({name: 'views'}, function (err, views) {

        if (err) {
            return self.emit('<view', err);
        }

        views.read({q: {_id: viewId}}, function (err, data) {

            if (err || !data || !data[0] || !data[0].client) {
                return self.emit('<view', err || 'no view found: ' + viewId);
            }

            self.emit('<view', null, data[0].client);
        });
    });
}

// get html snipptets (ws)
// TODO cache
function getSnipped (err, data) {
    var self = this;

    if (!data) {
        return self.emit('<html', 'No path given');
    }

    var file = M.config.paths.TEMPLATE_ROOT + data.replace(/[^a-z0-9\/\.\-_]|\.\.\//gi, "");
    fs.readFile(file, {encoding: 'utf8'}, function (err, data) {

        if (err) {
            return self.emit('<html', 'File not found');
        }

        self.emit('<html', null, data);
    });
}

function factory (config, callback) {

     // create cache key
    var cacheKey = (config.project || '') + config.name;

    // check cache
    var view = M.cache.views.get(cacheKey);
    if (view) {
        return callback(null, view);
    }

    // get system store to fetch models
    M.store(M.config.store.systemStoreName, config.project, function (err, systemStore) {

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

        // get view config
        // TODO check access
        systemStore.collection(viewCollection).findOne({name: config.name}, function (err, view) {

            if (err || !dbView) {
                return callback(err || 'View not found');
            }

            // get here the html snipped
            getSnipped(dbView.client.template.html, function (err, snipped) {

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

                // add snipped to view
                if (snipped) {
                    view.client.template.html = snipped;
                }

                // save view in cache
                M.cache.views.save(cacheKey, view);

                callback(null, models[cacheKey]);
            });
        });
    });
}

function factoryService (err, message) {
    var self = this;

    // check message
    if (!message || !message[0]) {
        return self.emit('<model', 'Bad message');
    }

    // create factory config
    message = {
        name: message[0],
        project: message[1]
    };

    // create model
    factory(message, function (err, view) {

        if (err) {
            return self.emit('<view', err);
        }

        // create client view
        var clientView = view.client;
        clientView.name = view.name;

        self.emit('<view', null, clientView);
    });
}

function setup (instance) {

    // setup view
    instance.on('view>', factoryService);

    // return view factory
    return factory;
}

module.exports = setup;
<|endoftext|>


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

    function getExports($wnd) {

        var $doc = $wnd.document;
        var $gwt = {};
        var navigator = {
            userAgent: 'webkit'
        };

        function noop(){}

        var __gwtModuleFunction = noop;
        __gwtModuleFunction.__moduleStartupDone = noop;
        var $sendStats = noop;
        var $moduleName, $moduleBase;

        // Start GWT code <%= gwtContent %>
        // End GWT code

        var toReturn = $wnd<%= exportsName %>;

        toReturn.version = '<%= version %>';

        return toReturn;
    }

    var isBrowser, globalEnv, document;

    if (typeof window !== 'undefined') { // usual browser window
        isBrowser = true;
        globalEnv = window;
        document = window.document;
    } else if (typeof self !== 'undefined') { // Web Worker
        isBrowser = true;
        globalEnv = self;
        document = {};
    } else { // Node.js
        isBrowser = false;
        globalEnv = global;
        document = {};
    }

    var fakeWindow;
    if (isBrowser && !<%= useFake %>) {
        fakeWindow = globalEnv;
    } else {
        fakeWindow = {};
        fakeWindow.setTimeout = globalEnv.setTimeout.bind(globalEnv);
        fakeWindow.clearTimeout = globalEnv.clearTimeout.bind(globalEnv);
        fakeWindow.setInterval = globalEnv.setInterval.bind(globalEnv);
        fakeWindow.clearInterval = globalEnv.clearInterval.bind(globalEnv);
    }

    if (!fakeWindow.document) {
        fakeWindow.document = document;
    }

    if (typeof module !== 'undefined' && module.exports) { // NodeJS
        module.exports = getExports(fakeWindow);
    } else if (typeof define === 'function' && define.amd) { // AMD
        define(function () {
            return getExports(fakeWindow);
        });
    } else { // Global
        var path = <%= exportsPath %>;
        var l = path.length - 1;
        var obj = globalEnv;
        for (var i = 0; i < l; i++) {
            obj = obj[path[i]] || (obj[path[i]] = {});
        }
        obj[path[l]] = getExports(fakeWindow);
    }

})();
<commit_msg>fix: copy Error in fakeWindow<commit_after>(function () {
    'use strict';

    function getExports($wnd) {

        var $doc = $wnd.document;
        var $gwt = {};
        var navigator = {
            userAgent: 'webkit'
        };

        function noop(){}

        var __gwtModuleFunction = noop;
        __gwtModuleFunction.__moduleStartupDone = noop;
        var $sendStats = noop;
        var $moduleName, $moduleBase;

        // Start GWT code <%= gwtContent %>
        // End GWT code

        var toReturn = $wnd<%= exportsName %>;

        toReturn.version = '<%= version %>';

        return toReturn;
    }

    var isBrowser, globalEnv, document;

    if (typeof window !== 'undefined') { // usual browser window
        isBrowser = true;
        globalEnv = window;
        document = window.document;
    } else if (typeof self !== 'undefined') { // Web Worker
        isBrowser = true;
        globalEnv = self;
        document = {};
    } else { // Node.js
        isBrowser = false;
        globalEnv = global;
        document = {};
    }

    var fakeWindow;
    if (isBrowser && !<%= useFake %>) {
        fakeWindow = globalEnv;
    } else {
        fakeWindow = {};
        fakeWindow.setTimeout = globalEnv.setTimeout.bind(globalEnv);
        fakeWindow.clearTimeout = globalEnv.clearTimeout.bind(globalEnv);
        fakeWindow.setInterval = globalEnv.setInterval.bind(globalEnv);
        fakeWindow.clearInterval = globalEnv.clearInterval.bind(globalEnv);
        fakeWindow.Error = globalEnv.Error; // required since GWT 2.8.0
    }

    if (!fakeWindow.document) {
        fakeWindow.document = document;
    }

    if (typeof module !== 'undefined' && module.exports) { // NodeJS
        module.exports = getExports(fakeWindow);
    } else if (typeof define === 'function' && define.amd) { // AMD
        define(function () {
            return getExports(fakeWindow);
        });
    } else { // Global
        var path = <%= exportsPath %>;
        var l = path.length - 1;
        var obj = globalEnv;
        for (var i = 0; i < l; i++) {
            obj = obj[path[i]] || (obj[path[i]] = {});
        }
        obj[path[l]] = getExports(fakeWindow);
    }

})();
<|endoftext|>


<commit_before>/* jshint node: true */
'use strict';

var path = require('path'),
  util = require('util'),
  extend = util._extend,
  mergeTrees = require('broccoli-merge-trees'),
  Funnel = require('broccoli-funnel');

var defaultOptions = {
  importBootstrapTheme: false,
  importBootstrapCSS: true,
  importBootstrapFont: true
};

module.exports = {
  name: 'ember-bootstrap',

  included: function included(app) {
    // workaround for https://github.com/ember-cli/ember-cli/issues/3718
    if (typeof app.import !== 'function' && app.app) {
      app = app.app;
    }
    this.app = app;

    var options = extend(defaultOptions, app.options['ember-bootstrap']);
    var bootstrapPath = path.join(app.bowerDirectory, 'bootstrap/dist');

    // Import css from bootstrap
    if (options.importBootstrapCSS) {
      app.import(path.join(bootstrapPath, 'css/bootstrap.css'));
      app.import(path.join(bootstrapPath, 'css/bootstrap.css.map'), {destDir: 'assets'});
    }

    if (options.importBootstrapTheme) {
      app.import(path.join(bootstrapPath, 'css/bootstrap-theme.css'));
    }

    // Import glyphicons
    if (options.importBootstrapFont) {
      app.import(path.join(bootstrapPath, 'fonts/glyphicons-halflings-regular.eot'), {destDir: '/fonts'});
      app.import(path.join(bootstrapPath, 'fonts/glyphicons-halflings-regular.svg'), {destDir: '/fonts'});
      app.import(path.join(bootstrapPath, 'fonts/glyphicons-halflings-regular.ttf'), {destDir: '/fonts'});
      app.import(path.join(bootstrapPath, 'fonts/glyphicons-halflings-regular.woff'), {destDir: '/fonts'});
      app.import(path.join(bootstrapPath, 'fonts/glyphicons-halflings-regular.woff2'), {destDir: '/fonts'});
    }

    if (!process.env.EMBER_CLI_FASTBOOT) {
      app.import('vendor/transition.js');
    }
  },

  treeForStyles: function treeForStyles(tree) {
    var styleTrees = [];

    if (this.app.project.findAddonByName('ember-cli-less')) {
      var lessTree = new Funnel(path.join(this.app.bowerDirectory, 'bootstrap/less'), {
        destDir: 'ember-bootstrap'
      });
      styleTrees.push(lessTree);
    }

    if (tree) {
      styleTrees.push(tree);
    }

    return mergeTrees(styleTrees, { overwrite: true });
  }
};
<commit_msg>import map file along with bootstrap-theme.css<commit_after>/* jshint node: true */
'use strict';

var path = require('path'),
  util = require('util'),
  extend = util._extend,
  mergeTrees = require('broccoli-merge-trees'),
  Funnel = require('broccoli-funnel');

var defaultOptions = {
  importBootstrapTheme: false,
  importBootstrapCSS: true,
  importBootstrapFont: true
};

module.exports = {
  name: 'ember-bootstrap',

  included: function included(app) {
    // workaround for https://github.com/ember-cli/ember-cli/issues/3718
    if (typeof app.import !== 'function' && app.app) {
      app = app.app;
    }
    this.app = app;

    var options = extend(defaultOptions, app.options['ember-bootstrap']);
    var bootstrapPath = path.join(app.bowerDirectory, 'bootstrap/dist');

    // Import css from bootstrap
    if (options.importBootstrapCSS) {
      app.import(path.join(bootstrapPath, 'css/bootstrap.css'));
      app.import(path.join(bootstrapPath, 'css/bootstrap.css.map'), {destDir: 'assets'});
    }

    if (options.importBootstrapTheme) {
      app.import(path.join(bootstrapPath, 'css/bootstrap-theme.css'));
      app.import(path.join(bootstrapPath, 'css/bootstrap-theme.css.map'), {destDir: 'assets'});
    }

    // Import glyphicons
    if (options.importBootstrapFont) {
      app.import(path.join(bootstrapPath, 'fonts/glyphicons-halflings-regular.eot'), {destDir: '/fonts'});
      app.import(path.join(bootstrapPath, 'fonts/glyphicons-halflings-regular.svg'), {destDir: '/fonts'});
      app.import(path.join(bootstrapPath, 'fonts/glyphicons-halflings-regular.ttf'), {destDir: '/fonts'});
      app.import(path.join(bootstrapPath, 'fonts/glyphicons-halflings-regular.woff'), {destDir: '/fonts'});
      app.import(path.join(bootstrapPath, 'fonts/glyphicons-halflings-regular.woff2'), {destDir: '/fonts'});
    }

    if (!process.env.EMBER_CLI_FASTBOOT) {
      app.import('vendor/transition.js');
    }
  },

  treeForStyles: function treeForStyles(tree) {
    var styleTrees = [];

    if (this.app.project.findAddonByName('ember-cli-less')) {
      var lessTree = new Funnel(path.join(this.app.bowerDirectory, 'bootstrap/less'), {
        destDir: 'ember-bootstrap'
      });
      styleTrees.push(lessTree);
    }

    if (tree) {
      styleTrees.push(tree);
    }

    return mergeTrees(styleTrees, { overwrite: true });
  }
};
<|endoftext|>


<commit_before>// base-x encoding
// Forked from https://github.com/cryptocoinjs/bs58
// Originally written by Mike Hearn for BitcoinJ
// Copyright (c) 2011 Google Inc
// Ported to JavaScript by Stefan Thomas
// Merged Buffer refactorings from base58-native by Stephen Pair
// Copyright (c) 2013 BitPay Inc

module.exports = function base (ALPHABET) {
  var ALPHABET_MAP = {}
  var BASE = ALPHABET.length
  var LEADER = ALPHABET.charAt(0)

  // pre-compute lookup table
  for (var z = 0; z < ALPHABET.length; z++) {
    ALPHABET_MAP[ALPHABET.charAt(z)] = z
  }

  function encode (source) {
    if (source.length === 0) return ''

    var digits = [0]
    for (var i = 0; i < source.length; ++i) {
      for (var j = 0, carry = source[i]; j < digits.length; ++j) {
        carry += digits[j] << 8
        digits[j] = carry % BASE
        carry = (carry / BASE) | 0
      }

      while (carry > 0) {
        digits.push(carry % BASE)
        carry = (carry / BASE) | 0
      }
    }

    var string = ''

    // deal with leading zeros
    for (var k = 0; source[k] === 0 && k < source.length - 1; ++k) string += ALPHABET[0]
    // convert digits to a string
    for (var q = digits.length - 1; q >= 0; --q) string += ALPHABET[digits[q]]

    return string
  }

  function decodeUnsafe (string) {
    if (string.length === 0) return []

    var bytes = [0]
    for (var i = 0; i < string.length; i++) {
      var value = ALPHABET_MAP[string[i]]
      if (value === undefined) return

      for (var j = 0, carry = value; j < bytes.length; ++j) {
        carry += bytes[j] * BASE
        bytes[j] = carry & 0xff
        carry >>= 8
      }

      while (carry > 0) {
        bytes.push(carry & 0xff)
        carry >>= 8
      }
    }

    // deal with leading zeros
    for (var k = 0; string[k] === LEADER && k < string.length - 1; ++k) {
      bytes.push(0)
    }

    return bytes.reverse()
  }

  function decode (string) {
    var array = decodeUnsafe(string)
    if (array) return array

    throw new Error('Non-base' + BASE + ' character')
  }

  return {
    encode: encode,
    decodeUnsafe: decodeUnsafe,
    decode: decode
  }
}
<commit_msg>return Buffer<commit_after>// base-x encoding
// Forked from https://github.com/cryptocoinjs/bs58
// Originally written by Mike Hearn for BitcoinJ
// Copyright (c) 2011 Google Inc
// Ported to JavaScript by Stefan Thomas
// Merged Buffer refactorings from base58-native by Stephen Pair
// Copyright (c) 2013 BitPay Inc

module.exports = function base (ALPHABET) {
  var ALPHABET_MAP = {}
  var BASE = ALPHABET.length
  var LEADER = ALPHABET.charAt(0)

  // pre-compute lookup table
  for (var z = 0; z < ALPHABET.length; z++) {
    ALPHABET_MAP[ALPHABET.charAt(z)] = z
  }

  function encode (source) {
    if (source.length === 0) return ''

    var digits = [0]
    for (var i = 0; i < source.length; ++i) {
      for (var j = 0, carry = source[i]; j < digits.length; ++j) {
        carry += digits[j] << 8
        digits[j] = carry % BASE
        carry = (carry / BASE) | 0
      }

      while (carry > 0) {
        digits.push(carry % BASE)
        carry = (carry / BASE) | 0
      }
    }

    var string = ''

    // deal with leading zeros
    for (var k = 0; source[k] === 0 && k < source.length - 1; ++k) string += ALPHABET[0]
    // convert digits to a string
    for (var q = digits.length - 1; q >= 0; --q) string += ALPHABET[digits[q]]

    return string
  }

  function decodeUnsafe (string) {
    if (string.length === 0) return []

    var bytes = [0]
    for (var i = 0; i < string.length; i++) {
      var value = ALPHABET_MAP[string[i]]
      if (value === undefined) return

      for (var j = 0, carry = value; j < bytes.length; ++j) {
        carry += bytes[j] * BASE
        bytes[j] = carry & 0xff
        carry >>= 8
      }

      while (carry > 0) {
        bytes.push(carry & 0xff)
        carry >>= 8
      }
    }

    // deal with leading zeros
    for (var k = 0; string[k] === LEADER && k < string.length - 1; ++k) {
      bytes.push(0)
    }

    return new Buffer(bytes.reverse())
  }

  function decode (string) {
    var buffer = decodeUnsafe(string)
    if (buffer) return buffer

    throw new Error('Non-base' + BASE + ' character')
  }

  return {
    encode: encode,
    decodeUnsafe: decodeUnsafe,
    decode: decode
  }
}
<|endoftext|>


<commit_before>var async = require('async');

// MemcachedTransaction: a wrapper around 3rdEden's node-memcached module to provide transactional behavior.

// currently supported mutations: 'set', 'del', 'touch'

function MemcachedTransaction(client, options) {
	this.queue = {};    // { key: operation }  operation to be executed per key
	this.cache = {};    // guaranteed to be the latest version of a value, if it's in here
	this.client = client;
	this.options = options || {};

	this.debug = null;

	if (this.options.debug) {
		if (this.options.debug === true) {
			this.debug = console.info;
		} else if (typeof this.options.debug === 'function') {
			this.debug = this.options.debug;
		}
	}
}

module.exports = MemcachedTransaction;

MemcachedTransaction.prototype.get = function (key, cb) {
	var cache = this.cache;

	var op = this.queue[key];
	if (op && op.type === 'del') {
		// this value is scheduled to be deleted, so consider it non-existing and return undefined

		if (cb) {
			cb(null, undefined);
		}
		return;
	}

	var value = cache[key];

	if (value !== undefined) {
		// there is a known uptodate value for this key, so return it instantly

		if (cb) {
			cb(null, value);
		}
		return;
	}

	// get the value from memcached and cache it

	if (this.debug) {
		this.debug('MemcachedTransaction: getting key', key);
	}

	this.client.get(key, function (error, value) {
		if (error) {
			if (cb) {
				cb(error);
			}
		} else {
			cache[key] = value;

			if (cb) {
				cb(null, value);
			}
		}
	});
};

MemcachedTransaction.prototype.getMulti = function (keys, cb) {
	var cache = this.cache;
	var value, result = {};
	var lookup = [];

	// for each key, check if we really need to fetch it, or if there is a known state

	for (var i = 0, len = keys.length; i < len; i++) {
		var key = keys[i];
		var op = this.queue[key];

		if (op && op.type === 'del') {
			// this value is scheduled to be deleted, so consider it non-existing and return undefined

			result[key] = undefined;
		} else {
			value = cache[key];

			if (value === undefined) {
				// prepare for fetching from memcached

				lookup.push(key);
			} else {
				// there is a known uptodate value for this key, so return it instantly

				result[key] = value;
			}
		}
	}

	// if there is nothing to look up from memcached, return all known results

	if (lookup.length === 0) {
		if (cb) {
			cb(null, result);
		}
		return;
	}

	// get the unknown values from memcached and cache them

	if (this.debug) {
		this.debug('MemcachedTransaction: getting keys', lookup);
	}

	this.client.getMulti(lookup, function (error, values) {
		if (error) {
			if (cb) {
				cb(error);
			}
			return;
		}

		for (var key in values) {
			var value = values[key];

			result[key] = value;
			cache[key] = value;
		}

		if (cb) {
			cb(null, result);
		}
	});
};

MemcachedTransaction.prototype.set = function (key, value, ttl, cb) {
	this.queue[key] = { type: 'set', key: key, value: value, ttl: ttl };
	this.cache[key] = value;

	if (cb) {
		cb();
	}
};

MemcachedTransaction.prototype.del = function (key, cb) {
	this.queue[key] = { type: 'del', key: key };
	delete this.cache[key];

	if (cb) {
		cb();
	}
};

MemcachedTransaction.prototype.touch = function (key, ttl, cb) {
	var op = this.queue[key];

	if (op) {
		switch (op.type) {
		case 'set':
			op.ttl = ttl;
			break;
		case 'del':
			// noop
			break;
		}
	} else {
		this.queue[key] = { type: 'touch', key: key, ttl: ttl };
	}

	if (cb) {
		cb();
	}
};

MemcachedTransaction.prototype._exec = function (op, cb) {
	if (this.options.simulate) {
		console.info('Executing', op);
		if (cb) {
			cb();
		}
		return;
	}

	function callback(err) {
		if (err) {
			console.error(JSON.stringify(err));
		}

		return cb();
	}

	switch (op.type) {
	case 'set':
		if (this.debug) {
			this.debug('MemcachedTransaction: setting key', op.key, 'to value', op.value, 'with TTL', op.ttl || 0);
		}

		this.client.set(op.key, op.value, op.ttl || 0, callback);
		break;
	case 'del':
		if (this.debug) {
			this.debug('MemcachedTransaction: deleting key', op.key);
		}

		this.client.del(op.key, callback);
		break;
	case 'touch':
		if (this.debug) {
			this.debug('MemcachedTransaction: touching key', op.key, 'with TTL', op.ttl || 0);
		}

		this.client.command(function touch(noreply) {
			return {
				command: ['touch', op.key, op.ttl || 0].join(' '),
				key: op.key,
				type: 'touch',
				callback: callback
			};
		});
		break;
	default:
		if (cb) {
			callback('Unknown operation type: ' + op.type);
		}
		break;
	}
};

MemcachedTransaction.prototype.commit = function (cb) {
	var ops = [];
	for (var key in this.queue) {
		ops.push(this.queue[key]);
	}

	var len = ops.length;

	// hot code paths: length 0 and 1

	if (len === 0) {
		return cb ? cb() : null;
	}

	if (len === 1) {
		return this._exec(ops[0], cb);
	}

	// more than 1 operation

	var that = this;

	async.forEachSeries(
		ops,
		function (op, callback) {
			that._exec(op, callback);
		},
		function (error) {
			if (cb) {
				cb(error);
			}
		}
	);
};

MemcachedTransaction.prototype.rollBack = function (cb) {
	this.queue = {};
	this.cache = {};

	if (cb) {
		cb();
	}
};

<commit_msg>* Added increment and decrement<commit_after>var async = require('async');

// MemcachedTransaction: a wrapper around 3rdEden's node-memcached module to provide transactional behavior.

// currently supported mutations: 'set', 'del', 'touch'

function MemcachedTransaction(client, options) {
	this.queue = {};    // { key: operation }  operation to be executed per key
	this.cache = {};    // guaranteed to be the latest version of a value, if it's in here
	this.client = client;
	this.options = options || {};

	this.debug = null;

	if (this.options.debug) {
		if (this.options.debug === true) {
			this.debug = console.info;
		} else if (typeof this.options.debug === 'function') {
			this.debug = this.options.debug;
		}
	}
}

module.exports = MemcachedTransaction;

MemcachedTransaction.prototype.get = function (key, cb) {
	var cache = this.cache;

	var op = this.queue[key];
	if (op && op.type === 'del') {
		// this value is scheduled to be deleted, so consider it non-existing and return undefined

		if (cb) {
			cb(null, undefined);
		}
		return;
	}

	var value = cache[key];

	if (value !== undefined) {
		// there is a known uptodate value for this key, so return it instantly

		if (cb) {
			cb(null, value);
		}
		return;
	}

	// get the value from memcached and cache it

	if (this.debug) {
		this.debug('MemcachedTransaction: getting key', key);
	}

	this.client.get(key, function (error, value) {
		if (error) {
			if (cb) {
				cb(error);
			}
		} else {
			cache[key] = value;

			if (cb) {
				cb(null, value);
			}
		}
	});
};

MemcachedTransaction.prototype.getMulti = function (keys, cb) {
	var cache = this.cache;
	var value, result = {};
	var lookup = [];

	// for each key, check if we really need to fetch it, or if there is a known state

	for (var i = 0, len = keys.length; i < len; i++) {
		var key = keys[i];
		var op = this.queue[key];

		if (op && op.type === 'del') {
			// this value is scheduled to be deleted, so consider it non-existing and return undefined

			result[key] = undefined;
		} else {
			value = cache[key];

			if (value === undefined) {
				// prepare for fetching from memcached

				lookup.push(key);
			} else {
				// there is a known uptodate value for this key, so return it instantly

				result[key] = value;
			}
		}
	}

	// if there is nothing to look up from memcached, return all known results

	if (lookup.length === 0) {
		if (cb) {
			cb(null, result);
		}
		return;
	}

	// get the unknown values from memcached and cache them

	if (this.debug) {
		this.debug('MemcachedTransaction: getting keys', lookup);
	}

	this.client.getMulti(lookup, function (error, values) {
		if (error) {
			if (cb) {
				cb(error);
			}
			return;
		}

		for (var key in values) {
			var value = values[key];

			result[key] = value;
			cache[key] = value;
		}

		if (cb) {
			cb(null, result);
		}
	});
};

MemcachedTransaction.prototype.set = function (key, value, ttl, cb) {
	this.queue[key] = { type: 'set', key: key, value: value, ttl: ttl };
	this.cache[key] = value;

	if (cb) {
		cb();
	}
};

MemcachedTransaction.prototype.del = function (key, cb) {
	this.queue[key] = { type: 'del', key: key };
	delete this.cache[key];

	if (cb) {
		cb();
	}
};

MemcachedTransaction.prototype.increment = function (key, amount, cb) {
	return this.client.increment(key, amount, cb);
};

MemcachedTransaction.prototype.decrement = function (key, amount, cb) {
	return this.client.decrement(key, amount, cb);
};

MemcachedTransaction.prototype.touch = function (key, ttl, cb) {
	var op = this.queue[key];

	if (op) {
		switch (op.type) {
		case 'set':
			op.ttl = ttl;
			break;
		case 'del':
			// noop
			break;
		}
	} else {
		this.queue[key] = { type: 'touch', key: key, ttl: ttl };
	}

	if (cb) {
		cb();
	}
};

MemcachedTransaction.prototype._exec = function (op, cb) {
	if (this.options.simulate) {
		console.info('Executing', op);
		if (cb) {
			cb();
		}
		return;
	}

	function callback(err) {
		if (err) {
			console.error(JSON.stringify(err));
		}

		return cb();
	}

	switch (op.type) {
	case 'set':
		if (this.debug) {
			this.debug('MemcachedTransaction: setting key', op.key, 'to value', op.value, 'with TTL', op.ttl || 0);
		}

		this.client.set(op.key, op.value, op.ttl || 0, callback);
		break;
	case 'del':
		if (this.debug) {
			this.debug('MemcachedTransaction: deleting key', op.key);
		}

		this.client.del(op.key, callback);
		break;
	case 'touch':
		if (this.debug) {
			this.debug('MemcachedTransaction: touching key', op.key, 'with TTL', op.ttl || 0);
		}

		this.client.command(function touch(noreply) {
			return {
				command: ['touch', op.key, op.ttl || 0].join(' '),
				key: op.key,
				type: 'touch',
				callback: callback
			};
		});
		break;
	default:
		if (cb) {
			callback('Unknown operation type: ' + op.type);
		}
		break;
	}
};

MemcachedTransaction.prototype.commit = function (cb) {
	var ops = [];
	for (var key in this.queue) {
		ops.push(this.queue[key]);
	}

	var len = ops.length;

	// hot code paths: length 0 and 1

	if (len === 0) {
		return cb ? cb() : null;
	}

	if (len === 1) {
		return this._exec(ops[0], cb);
	}

	// more than 1 operation

	var that = this;

	async.forEachSeries(
		ops,
		function (op, callback) {
			that._exec(op, callback);
		},
		function (error) {
			if (cb) {
				cb(error);
			}
		}
	);
};

MemcachedTransaction.prototype.rollBack = function (cb) {
	this.queue = {};
	this.cache = {};

	if (cb) {
		cb();
	}
};

<|endoftext|>


<commit_before>/* globals describe it beforeEach afterEach */

require('should');
var Dictionary = require('../');

describe('Dictionary Unit Tests', function() {
    var dict;

    beforeEach(function () {
        dict = new Dictionary();
    });

    afterEach(function () {
        dict = null;
    });

    it('should have a working test environment', function() {
        true.should.equal(true);
    });

    it('should instantiate a dictionary instance', function () {
        dict.should.be.ok;
        dict.should.be.instanceof(Dictionary);
    });

    it('should be empty when first instantiated', function () {
        dict.isEmpty().should.equal(true);
        dict.size().should.equal(0);
    });
});
<commit_msg>add some unit tests<commit_after>/* globals describe it beforeEach afterEach */

require('should');
var Dictionary = require('../');

describe('Dictionary Unit Tests', function() {
    var dict;

    beforeEach(function () {
        dict = new Dictionary();
    });

    afterEach(function () {
        dict = null;
    });

    it('should have a working test environment', function() {
        true.should.equal(true);
    });

    it('should instantiate a dictionary instance', function () {
        dict.should.be.ok;
        dict.should.be.instanceof(Dictionary);
    });

    it('should be empty when first instantiated', function () {
        dict.isEmpty().should.equal(true);
        dict.size().should.equal(0);
    });

    it('should add items to the dictionary', function () {
        dict.set('dict', 'data structure');
        dict.set('set', 'another data structure');
        dict.size().should.equal(2);
    });

    it('should determine if the dictionary has a particular key', function () {
        dict.set('dict', 'data structure');
        dict.set('set', 'another data structure');
        dict.has('dict').should.equal(true);
        dict.has('set').should.equal(true);
    });

    it('should correctly remove an item', function () {
        dict.set('dict', 'data structure');
        dict.set('set', 'another data structure');
        dict.remove('dict').should.equal(true);
        dict.size().should.equal(1);
        dict.remove('nothing').should.equal(false);
    });

    it('should correctly get an item', function () {
        dict.set('dict', 'data structure');
        dict.set('set', 'another data structure');
        dict.get('dict').should.equal('data structure');
        dict.get('set').should.equal('another data structure');
        dict.get('nothing').should.equal(-1);
    });
});
<|endoftext|>


<commit_before>import test from 'ava';
import fetchMock from 'fetch-mock';

import Directory from '../src/directory';

test.afterEach(() => {
  fetchMock.restore();
});

test.serial('Calls directoryUrl', t => {
  const testDirectoryUrl = 'directory-test-url';

  fetchMock.mock(testDirectoryUrl, { });

  return new Directory()
    .getUsers(testDirectoryUrl)
    .then(() => {
      t.true(fetchMock.called(testDirectoryUrl));
    });
});

test.serial('Uses filterFunction when supplied', t => {
  const testDirectoryUrl = 'directory-test-url';
  const testFilterFunction = x => x.test === 'b';

  fetchMock.mock(testDirectoryUrl, [{ test: 'a' }, { test: 'b' }]);

  return new Directory()
    .getUsers(testDirectoryUrl, testFilterFunction)
    .then(users => {
      t.is(users.length, 1);
      t.is(users[0].test, 'b');
    });
});
<commit_msg>Add eslint ignore<commit_after>import test from 'ava';
import fetchMock from 'fetch-mock';

import Directory from '../src/directory';

test.afterEach(() => {
  fetchMock.restore();
});

test.serial('Calls directoryUrl', t => {
  const testDirectoryUrl = 'directory-test-url';

  fetchMock.mock(testDirectoryUrl, { });

  return new Directory()
    .getUsers(testDirectoryUrl)
    .then(() => {
      t.true(fetchMock.called(testDirectoryUrl));
    });
});

test.serial('Uses filterFunction when supplied', t => {
  const testDirectoryUrl = 'directory-test-url';
  const testFilterFunction = x => x.test === 'b';

  fetchMock.mock(testDirectoryUrl, [{ test: 'a' }, { test: 'b' }]);

  return new Directory()
    .getUsers(testDirectoryUrl, testFilterFunction)
    .then(users => {
      t.is(users.length, 1); // eslint-disable-line no-magic-numbers
      t.is(users[0].test, 'b');
    });
});
<|endoftext|>


<commit_before>// check for elements common across the uql looknfeel
module.exports = {
  commonChecks: function (browser, theurl) {
    browser
      .url(theurl)
      .assert.elementPresent('uq-minimal-header', 'uq header component is present')
      .assert.elementPresent('uq-minimal-header uql-global-links', 'uq global links header component is present')
      .assert.containsText('.library-title a', 'UQ Library')
      .assert.elementPresent('uql-askus-button', 'uql askus component is present')
      .assert.elementPresent('uq-minimal-footer', 'uq footer component is present')
      .assert.elementPresent('uq-minimal-footer uql-global-links', 'uq global links footer component is present')
      .assert.containsText('uq-minimal-footer .footer-uq-details li', 'Authorised by:')
      .assert.elementPresent('uq-minimal-footer .footer-legal-details a'
      , 'Emergency Phone footer component is present')
      .assert.containsText('uq-minimal-footer .footer-legal-details .h6', 'Emergency');
    return browser;
  }
};<commit_msg>update variable name [PT #129808567]<commit_after>// check for elements common across the uql looknfeel
module.exports = {
  commonChecks: function (browser, urlTest) {
    browser
      .url(urlTest)
      .assert.elementPresent('uq-minimal-header', 'uq header component is present')
      .assert.elementPresent('uq-minimal-header uql-global-links', 'uq global links header component is present')
      .assert.containsText('.library-title a', 'UQ Library')
      .assert.elementPresent('uql-askus-button', 'uql askus component is present')
      .assert.elementPresent('uq-minimal-footer', 'uq footer component is present')
      .assert.elementPresent('uq-minimal-footer uql-global-links', 'uq global links footer component is present')
      .assert.containsText('uq-minimal-footer .footer-uq-details li', 'Authorised by:')
      .assert.elementPresent('uq-minimal-footer .footer-legal-details a'
      , 'Emergency Phone footer component is present')
      .assert.containsText('uq-minimal-footer .footer-legal-details .h6', 'Emergency');
    return browser;
  }
};<|endoftext|>