<commit_before>var DecompressZip = require('decompress-zip');
var pathLib = require('path');
var request = require('request');
var mkdirp = require('mkdirp');
var fs = require('fs');
var log = require('./logger.js');
var config = require('./config.js');
var parseAndResolve = require('document-write-html').parseAndResolve;

var internals = {};

var RE_PREFIX = /^\.|^__/;
internals.validPrefix =  function (name) {
    return !(RE_PREFIX.test(name));
};

var VALID_EXTENTIONS = ['js', 'html', 'htm', 'css', 'json', 'jpeg', 'jpg', 'png', 'gif'];
internals.validExtention =  function (ext) {
    return VALID_EXTENTIONS.indexOf(ext.substring(1)) > -1;
};

internals.validateHTML = function(html, done){
    var options = {
        uri: 'http://validator.w3.org/nu/',
        headers: {
            'Content-Type': 'text/html; charset=utf-8',
            'User-Agent' : 'gardr-validator-web'
        },
        qs: {
            'out': 'json'
        },
        method: 'POST',
        body: html
    };

    request(options, function(error, response, result){

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

        var data;
        try{
            data = typeof result === 'string' ? JSON.parse(result) : result;
        } catch(e){
            error = e;
        }

        done(error, data);
    });
};

internals.runUnzip =  function (uploadedZipFile, data, done) {

    function cleanup() {
        fs.unlink(uploadedZipFile.path, function (err) {
            log.info('Deleted file ' + uploadedZipFile.path + ': ' + !err);
        });
    }

    var unzipper = new DecompressZip(uploadedZipFile.path);

    unzipper.on('error', function (err) {
        // console.log('Caught an error', err);
        data.error = {
            'message': 'An error occured with unzipping file.  Code 040. ' + err.message,
            'stack': err.stack + ''
        };
        cleanup();
        done();
    });

    unzipper.on('extract', function (ziplog) {
        if (config.get('env') === 'development'){
            require('colors');
            console.log('FINISHED EXTRACTING:\n'.yellow,
                uploadedZipFile.path, '\n',
                (JSON.stringify(ziplog, null, 4)+'').blue.bold,
                '\n->',
                data.output.zip.path
            );
        }

        data.output.zip.unzipSuccess = true;
        cleanup();

        if (!data.output.zip.indexFilePath) {
            var msg = 'Failed locating index.html file. Code 041';
            log.error(msg);
            data.error = {
                'message': msg
            };
            return done();
        }

        fs.readFile(data.output.zip.indexFilePath, function (err, fileBuffer) {
            if (err) {
                data.error = {
                    'message': 'Failed reading / locating index.html file. Code 042',
                    'err': err
                };
                return done();
            }

            var html = fileBuffer.toString('utf8');

            // validate against w3c
            internals.validateIndex(data, html, function(){

                // resolve relative paths
                var indexDir = pathLib.dirname(data.output.zip.indexFilePath);
                var host = data.runnerConfig && data.runnerConfig.resourceDomainBase ?  data.runnerConfig.resourceDomainBase : data.host;
                var base = host + '/zip/' + data.id + indexDir.replace(data.output.zip.path, '') + '/';
                //
                data.output.html = parseAndResolve(base, html);

                done();
            });

        });
    });

    unzipper.extract({
        path: data.output.zip.path,
        filter: internals.filterFn.bind(null, data)
    });
};

var allowedErrors =[
     'Bad value “X-UA-Compatible” for attribute “http-equiv” on element “meta”.',
     'Element “head” is missing a required instance of child element “title”.',
     'Almost standards mode doctype. Expected e.g. “<!DOCTYPE html>”.',
     'Bad value “” for attribute “src” on element “img”: Must be non-empty.',
     '“&” did not start a character reference. (“&” probably should have been escaped as “&”.)',
     'An “img” element must have an “alt” attribute, except under certain conditions. For details, consult guidance on providing text alternatives for images.'
];

function filterErrors(a){
    return a.type === 'error' && a.message && allowedErrors.indexOf(a.message) === -1;
}

internals.validateIndex = function(data, html, done){
    internals.validateHTML(html, function(error, validationResult){
        if (error){
            console.error('w3c validation failed, reason: ', error);
            return done();
        }

        if (!validationResult || !validationResult.messages || validationResult.messages.length <= 0){
            return done();
        }

        var errors = validationResult.messages.filter(filterErrors);

        if (errors.length === 0){
            return done();
        }

        data.error = {
            'message': 'Failed validating index.html file via w3c',
            'errors': errors
        };
        done();
    });
};

internals.filterFn = function (data, file) {
    var extention = pathLib.extname(file.filename).toLowerCase();
    var baseFileName = pathLib.basename(file.filename, extention);

    if (baseFileName === 'index' && (extention === '.html' || extention === '.htm')) {
        data.output.zip.indexFilePath = pathLib.join(data.output.zip.path, file.path);
    }

    if (file.type === "SymbolicLink"){
        return false;
    }

    var isValidFolder = file.type === 'Directory' && file.parent && (file.parent === '.' || internals.validPrefix(file.parent));
    if (isValidFolder){
        return true;
    }

    var isValidFile = file.type === 'File' && file.filename && internals.validPrefix(file.filename) && internals.validExtention(extention);
    if (isValidFile){
        return true;
    }

    return false;
};

var getTmpDir = require('./tmpDir.js');

module.exports = function (uploadedZipFile, data, done) {
    if (!data.output.zip || !data.output.zip.path){
        data.output.zip = {
            'path': pathLib.join(getTmpDir(data.id), 'zip')
        };
    }

    mkdirp(data.output.zip.path, function (err) {
        if (err) {
            var msg = 'Failed creating tmp zip output directory: ' + data.output.zip.path + '.  Code 043';
            log.error(msg);
            data.error = {
                'message': msg
            };
            return done();
        }
        internals.runUnzip(uploadedZipFile, data, done);
    });

};

module.exports._validateIndex = internals.validateIndex;
<commit_msg>closes #46<commit_after>var DecompressZip = require('decompress-zip');
var pathLib = require('path');
var request = require('request');
var mkdirp = require('mkdirp');
var fs = require('fs');
var log = require('./logger.js');
var config = require('./config.js');
var parseAndResolve = require('document-write-html').parseAndResolve;

var internals = {};

var RE_PREFIX = /^\.|^__/;
internals.validPrefix =  function (name) {
    return !(RE_PREFIX.test(name));
};

var VALID_EXTENTIONS = ['js', 'html', 'htm', 'css', 'json', 'jpeg', 'jpg', 'png', 'gif', 'svg', 'woff', 'woff2', 'eot', 'ttf'];
internals.validExtention =  function (ext) {
    return VALID_EXTENTIONS.indexOf(ext.substring(1)) > -1;
};

internals.validateHTML = function(html, done){
    var options = {
        uri: 'http://validator.w3.org/nu/',
        headers: {
            'Content-Type': 'text/html; charset=utf-8',
            'User-Agent' : 'gardr-validator-web'
        },
        qs: {
            'out': 'json'
        },
        method: 'POST',
        body: html
    };

    request(options, function(error, response, result){

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

        var data;
        try{
            data = typeof result === 'string' ? JSON.parse(result) : result;
        } catch(e){
            error = e;
        }

        done(error, data);
    });
};

internals.runUnzip =  function (uploadedZipFile, data, done) {

    function cleanup() {
        fs.unlink(uploadedZipFile.path, function (err) {
            log.info('Deleted file ' + uploadedZipFile.path + ': ' + !err);
        });
    }

    var unzipper = new DecompressZip(uploadedZipFile.path);

    unzipper.on('error', function (err) {
        // console.log('Caught an error', err);
        data.error = {
            'message': 'An error occured with unzipping file.  Code 040. ' + err.message,
            'stack': err.stack + ''
        };
        cleanup();
        done();
    });

    unzipper.on('extract', function (ziplog) {
        if (config.get('env') === 'development'){
            require('colors');
            console.log('FINISHED EXTRACTING:\n'.yellow,
                uploadedZipFile.path, '\n',
                (JSON.stringify(ziplog, null, 4)+'').blue.bold,
                '\n->',
                data.output.zip.path
            );
        }

        data.output.zip.unzipSuccess = true;
        cleanup();

        if (!data.output.zip.indexFilePath) {
            var msg = 'Failed locating index.html file. Code 041';
            log.error(msg);
            data.error = {
                'message': msg
            };
            return done();
        }

        fs.readFile(data.output.zip.indexFilePath, function (err, fileBuffer) {
            if (err) {
                data.error = {
                    'message': 'Failed reading / locating index.html file. Code 042',
                    'err': err
                };
                return done();
            }

            var html = fileBuffer.toString('utf8');

            // validate against w3c
            internals.validateIndex(data, html, function(){

                // resolve relative paths
                var indexDir = pathLib.dirname(data.output.zip.indexFilePath);
                var host = data.runnerConfig && data.runnerConfig.resourceDomainBase ?  data.runnerConfig.resourceDomainBase : data.host;
                var base = host + '/zip/' + data.id + indexDir.replace(data.output.zip.path, '') + '/';
                //
                data.output.html = parseAndResolve(base, html);

                done();
            });

        });
    });

    unzipper.extract({
        path: data.output.zip.path,
        filter: internals.filterFn.bind(null, data)
    });
};

var allowedErrors =[
     'Bad value “X-UA-Compatible” for attribute “http-equiv” on element “meta”.',
     'Element “head” is missing a required instance of child element “title”.',
     'Almost standards mode doctype. Expected e.g. “<!DOCTYPE html>”.',
     'Bad value “” for attribute “src” on element “img”: Must be non-empty.',
     '“&” did not start a character reference. (“&” probably should have been escaped as “&”.)',
     'An “img” element must have an “alt” attribute, except under certain conditions. For details, consult guidance on providing text alternatives for images.'
];

function filterErrors(a){
    return a.type === 'error' && a.message && allowedErrors.indexOf(a.message) === -1;
}

internals.validateIndex = function(data, html, done){
    internals.validateHTML(html, function(error, validationResult){
        if (error){
            console.error('w3c validation failed, reason: ', error);
            return done();
        }

        if (!validationResult || !validationResult.messages || validationResult.messages.length <= 0){
            return done();
        }

        var errors = validationResult.messages.filter(filterErrors);

        if (errors.length === 0){
            return done();
        }

        data.error = {
            'message': 'Failed validating index.html file via w3c',
            'errors': errors
        };
        done();
    });
};

internals.filterFn = function (data, file) {
    var extention = pathLib.extname(file.filename).toLowerCase();
    var baseFileName = pathLib.basename(file.filename, extention);

    if (baseFileName === 'index' && (extention === '.html' || extention === '.htm')) {
        data.output.zip.indexFilePath = pathLib.join(data.output.zip.path, file.path);
    }

    if (file.type === "SymbolicLink"){
        return false;
    }

    var isValidFolder = file.type === 'Directory' && file.parent && (file.parent === '.' || internals.validPrefix(file.parent));
    if (isValidFolder){
        return true;
    }

    var isValidFile = file.type === 'File' && file.filename && internals.validPrefix(file.filename) && internals.validExtention(extention);
    if (isValidFile){
        return true;
    }

    return false;
};

var getTmpDir = require('./tmpDir.js');

module.exports = function (uploadedZipFile, data, done) {
    if (!data.output.zip || !data.output.zip.path){
        data.output.zip = {
            'path': pathLib.join(getTmpDir(data.id), 'zip')
        };
    }

    mkdirp(data.output.zip.path, function (err) {
        if (err) {
            var msg = 'Failed creating tmp zip output directory: ' + data.output.zip.path + '.  Code 043';
            log.error(msg);
            data.error = {
                'message': msg
            };
            return done();
        }
        internals.runUnzip(uploadedZipFile, data, done);
    });

};

module.exports._validateIndex = internals.validateIndex;
<|endoftext|>


<commit_before>/*
 * Copyright 2013 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
'use strict';

var HeatGrid = function(el) {
  this.el = $(el);

  var rgb = function(r, g, b) {
    return 'rgb(' + parseInt(r) + ',' + parseInt(g) + ',' + parseInt(b) + ')';
  }

  var frac = function(minval, maxval, fraction) {
    return minval + fraction * (maxval - minval);
  }

  var gradient = function(mincolor, zerocolor, maxcolor,
                          ofs) {
    if (ofs == 0) {
      return zerocolor;
    } else if (ofs < 0) {
      return [frac(zerocolor[0], mincolor[0], -ofs/3),
              frac(zerocolor[1], mincolor[1], -ofs/3),
              frac(zerocolor[2], mincolor[2], -ofs/3)];
    } else if (ofs > 0) {
      return [frac(zerocolor[0], maxcolor[0], ofs/3),
              frac(zerocolor[1], maxcolor[1], ofs/3),
              frac(zerocolor[2], maxcolor[2], ofs/3)];
    }
  }

  this.draw = function(grid) {
    console.debug('heatgrid.draw', grid);
    this.el.html('
<canvas></canvas>' +
		 '

' +
		 '

');
    var heatgrid = this.el.find('#heatgrid');
    heatgrid.css({
      position: 'relative',
      overflow: 'scroll',
      width: '100%',
      height: '100%',
    });
    var popover = this.el.find('#heatgrid-popover');
    popover.css({
      position: 'absolute',
      background: '#aaa',
      border: '1px dotted black',
      'white-space': 'pre'
    });
    var highlight = this.el.find('#heatgrid-highlight');
    highlight.css({
      position: 'absolute',
	  //background: 'rgba(255,192,192,16)',
      width: '3px',
      height: '3px',
      margin: '0',
      padding: '0',
      border: '1px solid red',
    });
    var canvas = this.el.find('canvas');
    var xmult = parseInt(1000 / grid.headers.length);
    if (xmult < 1) xmult = 1;
    var xsize = grid.headers.length * xmult;
    var ysize = grid.data.length;
    canvas.attr({width: xsize, height: ysize});
    canvas.css({
      background: '#fff',
      width: '100%',
      height: ysize
    });
    console.debug('heatgrid canvas size is: x y =', xsize, ysize);
    var ctx = canvas[0].getContext('2d');

    if (!grid.data.length || !grid.data[0].length) {
      return;
    }

    var lastPos = { x: 0, y: 0 };
    var movefunc = function(x, y) {
      if (x >= grid.headers.length) x = grid.headers.length - 1;
      if (y >= grid.data.length) y = grid.data.length - 1;
      if (x < 0) x = 0;
      if (y < 0) y = 0;
      lastPos.x = x;
      lastPos.y = y;
      var info = [];
      for (var i = 0; i < grid.headers.length; i++) {
        if (grid.types[i] != 'number') {
          info.push(grid.data[y][i]);
        } else {
          break;
        }
      }
      info.push(grid.headers[x]);
      info.push('value=' + grid.data[y][x]);

      var cx = x / grid.headers.length * canvas.width();
      var cy = y / grid.data.length * canvas.height();
      highlight.css({left: cx - 2, top: cy - 2});
      if (cx < canvas.width() / 2) {
	popover.css({
	  left: cx + 30,
	  right: 'auto'
	});
      } else {
	popover.css({
	  left: 'auto',
	  right: heatgrid[0].clientWidth - cx + 10
	});
      }
      if (cy < canvas.height() / 2) {
	popover.css({
	  top: cy + 10,
	  bottom: 'auto'
	});
      } else {
	popover.css({
	  top: 'auto',
	  bottom: heatgrid[0].clientHeight - cy + 10
	});
      }
      popover.text(info.join('\n'));
    };
    heatgrid.mousemove(function(ev) {
      var pos = canvas.position();
      var offX = ev.pageX - pos.left - 1;
      var offY = ev.pageY - pos.top - 1;
      var x = parseInt(offX / canvas.width() * grid.headers.length);
      var y = parseInt(offY / canvas.height() * grid.data.length);
      movefunc(x, y);
    });
    heatgrid.keydown(function(ev) {
      if (ev.which == 38) { // up
	movefunc(lastPos.x, lastPos.y - 1);
      } else if (ev.which == 40) { // down
	movefunc(lastPos.x, lastPos.y + 1);
      } else if (ev.which == 37) { // left
	movefunc(lastPos.x - 1, lastPos.y);
      } else if (ev.which == 39) { // right
	movefunc(lastPos.x + 1, lastPos.y);
      } else {
	return true; // propagate event forward
      }
      ev.stopPropagation();
      return false;
    });
    heatgrid.mouseleave(function() {
      popover.hide();
    });
    heatgrid.mouseenter(function() {
      heatgrid.focus(); // so that keyboard bindings work
      popover.show();
    });

    var total = 0, count = 0;
    for (var y = 0; y < grid.data.length; y++) {
      for (var x = 0; x < grid.data[y].length; x++) {
        if (grid.types[x] != 'number') continue;
        var cell = parseFloat(grid.data[y][x]);
        if (!isNaN(cell)) {
          total += cell;
          count++;
        }
      }
    }
    var avg = total / count;

    var tdiff = 0;
    for (var y = 0; y < grid.data.length; y++) {
      for (var x = 0; x < grid.data[y].length; x++) {
        if (grid.types[x] != 'number') continue;
        var cell = parseFloat(grid.data[y][x]);
        if (!isNaN(cell)) {
          tdiff += (cell - avg) * (cell - avg);
        }
      }
    }
    var stddev = Math.sqrt(tdiff / count);
    console.debug('total,count,mean,stddev = ', total, count, avg, stddev);

    var img = ctx.createImageData(xsize, ysize);
    for (var y = 0; y < grid.data.length; y++) {
      for (var x = 0; x < grid.data[y].length; x++) {
        if (grid.types[x] != 'number') continue;
        var cell = parseFloat(grid.data[y][x]);
        if (isNaN(cell)) continue;
        var ofs = stddev ? (cell - avg) / stddev : 3;
        var color = gradient([192,192,192], [192,192,255], [0,0,255], ofs);
        if (!color) continue;
        var pix = (y * xsize + x*xmult) * 4;
        for (var i = 0; i < xmult; i++) {
          img.data[pix + 0] = color[0];
          img.data[pix + 1] = color[1];
          img.data[pix + 2] = color[2];
          img.data[pix + 3] = 255;
          pix += 4;
        }
      }
    }
    ctx.putImageData(img, 0, 0);
  }
};
<commit_msg>jslint fixes to heatgrid.js.<commit_after>/*
 * Copyright 2013 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
'use strict';

var HeatGrid = function(el) {
  this.el = $(el);

  var frac = function(minval, maxval, fraction) {
    return minval + fraction * (maxval - minval);
  };

  var gradient = function(mincolor, zerocolor, maxcolor,
                          ofs) {
    if (ofs == 0) {
      return zerocolor;
    } else if (ofs < 0) {
      return [frac(zerocolor[0], mincolor[0], -ofs / 2),
              frac(zerocolor[1], mincolor[1], -ofs / 2),
              frac(zerocolor[2], mincolor[2], -ofs / 2)];
    } else if (ofs > 0) {
      return [frac(zerocolor[0], maxcolor[0], ofs / 2),
              frac(zerocolor[1], maxcolor[1], ofs / 2),
              frac(zerocolor[2], maxcolor[2], ofs / 2)];
    }
  };

  this.draw = function(grid) {
    console.debug('heatgrid.draw', grid);
    this.el.html('
<canvas></canvas>' +
                 '

' +
                 '

');
    var heatgrid = this.el.find('#heatgrid');
    heatgrid.css({
      position: 'relative',
      overflow: 'scroll',
      width: '100%',
      height: '100%'
    });
    var popover = this.el.find('#heatgrid-popover');
    popover.css({
      position: 'absolute',
      background: '#aaa',
      border: '1px dotted black',
      'white-space': 'pre'
    });
    var highlight = this.el.find('#heatgrid-highlight');
    highlight.css({
      position: 'absolute',
          //background: 'rgba(255,192,192,16)',
      width: '3px',
      height: '3px',
      margin: '0',
      padding: '0',
      border: '1px solid red'
    });
    var canvas = this.el.find('canvas');
    var xmult = parseInt(1000 / grid.headers.length);
    if (xmult < 1) xmult = 1;
    var xsize = grid.headers.length * xmult;
    var ysize = grid.data.length;
    canvas.attr({width: xsize, height: ysize});
    canvas.css({
      background: '#fff',
      width: '100%',
      height: ysize
    });
    console.debug('heatgrid canvas size is: x y =', xsize, ysize);
    var ctx = canvas[0].getContext('2d');

    if (!grid.data.length || !grid.data[0].length) {
      return;
    }

    var lastPos = { x: 0, y: 0 };
    var movefunc = function(x, y) {
      if (x >= grid.headers.length) x = grid.headers.length - 1;
      if (y >= grid.data.length) y = grid.data.length - 1;
      if (x < 0) x = 0;
      if (y < 0) y = 0;
      lastPos.x = x;
      lastPos.y = y;
      var info = [];
      for (var i = 0; i < grid.headers.length; i++) {
        if (grid.types[i] != 'number') {
          info.push(grid.data[y][i]);
        } else {
          break;
        }
      }
      info.push(grid.headers[x]);
      info.push('value=' + grid.data[y][x]);

      var cx = x / grid.headers.length * canvas.width();
      var cy = y / grid.data.length * canvas.height();
      highlight.css({left: cx - 2, top: cy - 2});
      if (cx < canvas.width() / 2) {
        popover.css({
          left: cx + 30,
          right: 'auto'
        });
      } else {
        popover.css({
          left: 'auto',
          right: heatgrid[0].clientWidth - cx + 10
        });
      }
      if (cy < canvas.height() / 2) {
        popover.css({
          top: cy + 10,
          bottom: 'auto'
        });
      } else {
        popover.css({
          top: 'auto',
          bottom: heatgrid[0].clientHeight - cy + 10
        });
      }
      popover.text(info.join('\n'));
    };
    heatgrid.mousemove(function(ev) {
      var pos = canvas.position();
      var offX = ev.pageX - pos.left - 1;
      var offY = ev.pageY - pos.top - 1;
      var x = parseInt(offX / canvas.width() * grid.headers.length);
      var y = parseInt(offY / canvas.height() * grid.data.length);
      movefunc(x, y);
    });
    heatgrid.keydown(function(ev) {
      if (ev.which == 38) { // up
        movefunc(lastPos.x, lastPos.y - 1);
      } else if (ev.which == 40) { // down
        movefunc(lastPos.x, lastPos.y + 1);
      } else if (ev.which == 37) { // left
        movefunc(lastPos.x - 1, lastPos.y);
      } else if (ev.which == 39) { // right
        movefunc(lastPos.x + 1, lastPos.y);
      } else {
        return true; // propagate event forward
      }
      ev.stopPropagation();
      return false;
    });
    heatgrid.mouseleave(function() {
      popover.hide();
    });
    heatgrid.mouseenter(function() {
      heatgrid.focus(); // so that keyboard bindings work
      popover.show();
    });

    var total = 0, count = 0;
    for (var y = 0; y < grid.data.length; y++) {
      for (var x = 0; x < grid.data[y].length; x++) {
        if (grid.types[x] != 'number') continue;
        var cell = parseFloat(grid.data[y][x]);
        if (!isNaN(cell)) {
          total += cell;
          count++;
        }
      }
    }
    var avg = total / count;

    var tdiff = 0;
    for (var y = 0; y < grid.data.length; y++) {
      for (var x = 0; x < grid.data[y].length; x++) {
        if (grid.types[x] != 'number') continue;
        var cell = parseFloat(grid.data[y][x]);
        if (!isNaN(cell)) {
          tdiff += (cell - avg) * (cell - avg);
        }
      }
    }
    var stddev = Math.sqrt(tdiff / count);
    console.debug('total,count,mean,stddev = ', total, count, avg, stddev);

    var img = ctx.createImageData(xsize, ysize);
    for (var y = 0; y < grid.data.length; y++) {
      for (var x = 0; x < grid.data[y].length; x++) {
        if (grid.types[x] != 'number') continue;
        var cell = parseFloat(grid.data[y][x]);
        if (isNaN(cell)) continue;
        var ofs = stddev ? (cell - avg) / stddev : 3;
        var color = gradient([192, 192, 192],
                             [192, 192, 255],
                             [0, 0, 255], ofs);
        if (!color) continue;
        var pix = (y * xsize + x * xmult) * 4;
        for (var i = 0; i < xmult; i++) {
          img.data[pix + 0] = color[0];
          img.data[pix + 1] = color[1];
          img.data[pix + 2] = color[2];
          img.data[pix + 3] = 255;
          pix += 4;
        }
      }
    }
    ctx.putImageData(img, 0, 0);
  };
};
<|endoftext|>


<commit_before>(function ( window , undefined ) {
    'use strict';

    var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.oIndexedDB || window.msIndexedDB,
        IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange,
        transactionModes = {
            readonly: 'readonly',
            readwrite: 'readwrite'
        };

    var hasOwn = Object.prototype.hasOwnProperty;

    if ( !indexedDB ) {
        throw 'IndexedDB required';
    }

    var defaultMapper = function (value) {
        return value;
    };

    var CallbackList = function () {
        var state,
            list = [];

        var exec = function ( context , args ) {
            if ( list ) {
                args = args || [];
                state = state || [ context , args ];

                for ( var i = 0 , il = list.length ; i < il ; i++ ) {
                    list[ i ].apply( state[ 0 ] , state[ 1 ] );
                }

                list = [];
            }
        };

        this.add = function () {
            for ( var i = 0 , il = arguments.length ; i < il ; i ++ ) {
                list.push( arguments[ i ] );
            }

            if ( state ) {
                exec();
            }

            return this;
        };

        this.execute = function () {
            exec( this , arguments );
            return this;
        };
    };

    var Server = function ( db , name ) {
        var that = this,
            closed = false;

        this.add = function( table ) {
            if ( closed ) {
                throw 'Database has been closed';
            }

            var records = [];
            var counter = 0;

            for (var i = 0; i < arguments.length - 1; i++) {
                if (Array.isArray(arguments[i + 1])) {
                    for (var j = 0; j < (arguments[i + 1]).length; j++) {
                        records[counter] = (arguments[i + 1])[j];
                        counter++;
                    }
                } else {
                    records[counter] = arguments[i + 1];
                    counter++;
                }
            }

            var transaction = db.transaction( table , transactionModes.readwrite ),
                store = transaction.objectStore( table );

            return new Promise(function(resolve, reject){
              records.forEach( function ( record ) {
                  var req;
                  if ( record.item && record.key ) {
                      var key = record.key;
                      record = record.item;
                      req = store.add( record , key );
                  } else {
                      req = store.add( record );
                  }

                  req.onsuccess = function ( e ) {
                      var target = e.target;
                      var keyPath = target.source.keyPath;
                      if ( keyPath === null ) {
                          keyPath = '__id__';
                      }
                      Object.defineProperty( record , keyPath , {
                          value: target.result,
                          enumerable: true
                      });
                  };
              } );

              transaction.oncomplete = function () {
                  resolve( records , that );
              };
              transaction.onerror = function ( e ) {
                  reject( records , e );
              };
              transaction.onabort = function ( e ) {
                  reject( records , e );
              };

            });
        };

        this.update = function( table ) {
            if ( closed ) {
                throw 'Database has been closed';
            }

            var records = [];
            for ( var i = 0 ; i < arguments.length - 1 ; i++ ) {
                records[ i ] = arguments[ i + 1 ];
            }

            var transaction = db.transaction( table , transactionModes.readwrite ),
                store = transaction.objectStore( table ),
                keyPath = store.keyPath;

            return new Promise(function(resolve, reject){
              records.forEach( function ( record ) {
                  var req;
                  var count;
                  if ( record.item && record.key ) {
                      var key = record.key;
                      record = record.item;
                      req = store.put( record , key );
                  } else {
                      req = store.put( record );
                  }

                  req.onsuccess = function ( e ) {
                      // deferred.notify(); es6 promise can't notify
                  };
              } );

              transaction.oncomplete = function () {
                  resolve( records , that );
              };
              transaction.onerror = function ( e ) {
                  reject( records , e );
              };
              transaction.onabort = function ( e ) {
                  reject( records , e );
              };
            });

        };

        this.remove = function ( table , key ) {
            if ( closed ) {
                throw 'Database has been closed';
            }
            var transaction = db.transaction( table , transactionModes.readwrite ),
                store = transaction.objectStore( table );

            return new Promise(function(resolve, reject){
              var req = store.delete( key );
              transaction.oncomplete = function ( ) {
                  resolve( key );
              };
              transaction.onerror = function ( e ) {
                  reject( e );
              };
            });
        };

        this.clear = function ( table ) {
            if ( closed ) {
                throw 'Database has been closed';
            }
            var transaction = db.transaction( table , transactionModes.readwrite ),
                store = transaction.objectStore( table );

            var req = store.clear();
            return new Promise(function(resolve, reject){
              transaction.oncomplete = function ( ) {
                  resolve( );
              };
              transaction.onerror = function ( e ) {
                  reject( e );
              };
            });
        };

        this.close = function ( ) {
            if ( closed ) {
                throw 'Database has been closed';
            }
            db.close();
            closed = true;
            delete dbCache[ name ];
        };

        this.get = function ( table , id ) {
            if ( closed ) {
                throw 'Database has been closed';
            }
            var transaction = db.transaction( table ),
                store = transaction.objectStore( table );

            var req = store.get( id );
            return new Promise(function(resolve, reject){
              req.onsuccess = function ( e ) {
                  resolve( e.target.result );
              };
              transaction.onerror = function ( e ) {
                  reject( e );
              };
            });
        };

        this.query = function ( table , index ) {
            if ( closed ) {
                throw 'Database has been closed';
            }
            return new IndexQuery( table , db , index );
        };

        for ( var i = 0 , il = db.objectStoreNames.length ; i < il ; i++ ) {
            (function ( storeName ) {
                that[ storeName ] = { };
                for ( var i in that ) {
                    if ( !hasOwn.call( that , i ) || i === 'close' ) {
                        continue;
                    }
                    that[ storeName ][ i ] = (function ( i ) {
                        return function () {
                            var args = [ storeName ].concat( [].slice.call( arguments , 0 ) );
                            return that[ i ].apply( that , args );
                        };
                    })( i );
                }
            })( db.objectStoreNames[ i ] );
        }
    };

    var IndexQuery = function ( table , db , indexName ) {
        var that = this;
        var modifyObj = false;

        var runQuery = function ( type, args , cursorType , direction, limitRange, filters , mapper ) {
            var transaction = db.transaction( table, modifyObj ? transactionModes.readwrite : transactionModes.readonly ),
                store = transaction.objectStore( table ),
                index = indexName ? store.index( indexName ) : store,
                keyRange = type ? IDBKeyRange[ type ].apply( null, args ) : null,
                results = [],
                indexArgs = [ keyRange ],
                limitRange = limitRange ? limitRange : null,
                filters = filters ? filters : [],
                counter = 0;

            if ( cursorType !== 'count' ) {
                indexArgs.push( direction || 'next' );
            };

            // create a function that will set in the modifyObj properties into
            // the passed record.
            var modifyKeys = modifyObj ? Object.keys(modifyObj) : false;
            var modifyRecord = function(record) {
                for(var i = 0; i < modifyKeys.length; i++) {
                    var key = modifyKeys[i];
                    var val = modifyObj[key];
                    if(val instanceof Function) val = val(record);
                    record[key] = val;
                }
                return record;
            };

            index[cursorType].apply( index , indexArgs ).onsuccess = function ( e ) {
                var cursor = e.target.result;
                if ( typeof cursor === typeof 0 ) {
                    results = cursor;
                } else if ( cursor ) {
                	if ( limitRange !== null && limitRange[0] > counter) {
                    	counter = limitRange[0];
                    	cursor.advance(limitRange[0]);
                    } else if ( limitRange !== null && counter >= (limitRange[0] + limitRange[1]) ) {
                        //out of limit range... skip
                    } else {
                        var matchFilter = true;
                        var result = 'value' in cursor ? cursor.value : cursor.key;

                        filters.forEach( function ( filter ) {
                            if ( !filter || !filter.length ) {
                                //Invalid filter do nothing
                            } else if ( filter.length === 2 ) {
                                matchFilter = matchFilter && (result[filter[0]] === filter[1])
                            } else {
                                matchFilter = matchFilter && filter[0].apply(undefined,[result]);
                            }
                        });

                        if (matchFilter) {
                            counter++;
                            results.push( mapper(result) );
                            // if we're doing a modify, run it now
                            if(modifyObj) {
                                result = modifyRecord(result);
                                cursor.update(result);
                            }
                        }
                        cursor.continue();
                    }
                }
            };

            return new Promise(function(resolve, reject){
              transaction.oncomplete = function () {
                  resolve( results );
              };
              transaction.onerror = function ( e ) {
                  reject( e );
              };
              transaction.onabort = function ( e ) {
                  reject( e );
              };
            });
        };

        var Query = function ( type , args ) {
            var direction = 'next',
                cursorType = 'openCursor',
                filters = [],
                limitRange = null,
                mapper = defaultMapper,
                unique = false;

            var execute = function () {
                return runQuery( type , args , cursorType , unique ? direction + 'unique' : direction, limitRange, filters , mapper );
            };

            var limit = function () {
                limitRange = Array.prototype.slice.call( arguments , 0 , 2 )
                if (limitRange.length == 1) {
                    limitRange.unshift(0)
                }

                return {
                    execute: execute
                };
            };
            var count = function () {
                direction = null;
                cursorType = 'count';

                return {
                    execute: execute
                };
            };
            var keys = function () {
                cursorType = 'openKeyCursor';

                return {
                    desc: desc,
                    execute: execute,
                    filter: filter,
                    distinct: distinct,
                    map: map
                };
            };
            var filter = function ( ) {
                filters.push( Array.prototype.slice.call( arguments , 0 , 2 ) );

                return {
                    keys: keys,
                    execute: execute,
                    filter: filter,
                    desc: desc,
                    distinct: distinct,
                    modify: modify,
                    limit: limit,
                    map: map
                };
            };
            var desc = function () {
                direction = 'prev';

                return {
                    keys: keys,
                    execute: execute,
                    filter: filter,
                    distinct: distinct,
                    modify: modify,
                    map: map
                };
            };
            var distinct = function () {
                unique = true;
                return {
                    keys: keys,
                    count: count,
                    execute: execute,
                    filter: filter,
                    desc: desc,
                    modify: modify,
                    map: map
                };
            };
            var modify = function(update) {
                modifyObj = update;
                return {
                    execute: execute
                };
            };
            var map = function (fn) {
                mapper = fn;

                return {
                    execute: execute,
                    count: count,
                    keys: keys,
                    filter: filter,
                    desc: desc,
                    distinct: distinct,
                    modify: modify,
                    limit: limit,
                    map: map
                };
            };

            return {
                execute: execute,
                count: count,
                keys: keys,
                filter: filter,
                desc: desc,
                distinct: distinct,
                modify: modify,
                limit: limit,
                map: map
            };
        };

        'only bound upperBound lowerBound'.split(' ').forEach(function (name) {
            that[name] = function () {
                return new Query( name , arguments );
            };
        });

        this.filter = function () {
            var query = new Query( null , null );
            return query.filter.apply( query , arguments );
        };

        this.all = function () {
            return this.filter();
        };
    };

    var createSchema = function ( e , schema , db ) {
        if ( typeof schema === 'function' ) {
            schema = schema();
        }

        for ( var tableName in schema ) {
            var table = schema[ tableName ];
            var store;
            if (!hasOwn.call(schema, tableName) || db.objectStoreNames.contains(tableName)) {
                store = e.currentTarget.transaction.objectStore(tableName);
            } else {
                store = db.createObjectStore(tableName, table.key);
            }

            for ( var indexKey in table.indexes ) {
                if (store.indexNames.contains(indexKey)) {
                    continue;
                }

                var index = table.indexes[ indexKey ];
                store.createIndex( indexKey , index.key || indexKey , Object.keys(index).length ? index : { unique: false } );
            }
        }
    };

    var open = function ( e , server , version , schema ) {
        var db = e.target.result;
        var s = new Server( db , server );
        var upgrade;

        dbCache[ server ] = db;

        return Promise.resolve(s)
    };

    var dbCache = {};

    var db = {
        version: '0.9.0',
        open: function ( options ) {
            var request;

            var deferred = Promise.defer();

            if ( dbCache[ options.server ] ) {
                open( {
                    target: {
                        result: dbCache[ options.server ]
                    }
                } , options.server , options.version , options.schema )
                .then(deferred.resolve, deferred.reject)
            } else {
                request = indexedDB.open( options.server , options.version );

                request.onsuccess = function ( e ) {
                    open( e , options.server , options.version , options.schema )
                        .then(deferred.resolve, deferred.reject)
                };

                request.onupgradeneeded = function ( e ) {
                    createSchema( e , options.schema , e.target.result );
                };
                request.onerror = function ( e ) {
                    deferred.reject( e );
                };
            }

            return deferred.promise;
        }
    };

    if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
        module.exports = db;
    } else if ( typeof define === 'function' && define.amd ) {
        define( function() { return db; } );
    } else {
        window.db = db;
    }
})( window );
<commit_msg>Updated open function to use es6 promise<commit_after>(function ( window , undefined ) {
    'use strict';

    var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.oIndexedDB || window.msIndexedDB,
        IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange,
        transactionModes = {
            readonly: 'readonly',
            readwrite: 'readwrite'
        };

    var hasOwn = Object.prototype.hasOwnProperty;

    if ( !indexedDB ) {
        throw 'IndexedDB required';
    }

    var defaultMapper = function (value) {
        return value;
    };

    var CallbackList = function () {
        var state,
            list = [];

        var exec = function ( context , args ) {
            if ( list ) {
                args = args || [];
                state = state || [ context , args ];

                for ( var i = 0 , il = list.length ; i < il ; i++ ) {
                    list[ i ].apply( state[ 0 ] , state[ 1 ] );
                }

                list = [];
            }
        };

        this.add = function () {
            for ( var i = 0 , il = arguments.length ; i < il ; i ++ ) {
                list.push( arguments[ i ] );
            }

            if ( state ) {
                exec();
            }

            return this;
        };

        this.execute = function () {
            exec( this , arguments );
            return this;
        };
    };

    var Server = function ( db , name ) {
        var that = this,
            closed = false;

        this.add = function( table ) {
            if ( closed ) {
                throw 'Database has been closed';
            }

            var records = [];
            var counter = 0;

            for (var i = 0; i < arguments.length - 1; i++) {
                if (Array.isArray(arguments[i + 1])) {
                    for (var j = 0; j < (arguments[i + 1]).length; j++) {
                        records[counter] = (arguments[i + 1])[j];
                        counter++;
                    }
                } else {
                    records[counter] = arguments[i + 1];
                    counter++;
                }
            }

            var transaction = db.transaction( table , transactionModes.readwrite ),
                store = transaction.objectStore( table );

            return new Promise(function(resolve, reject){
              records.forEach( function ( record ) {
                  var req;
                  if ( record.item && record.key ) {
                      var key = record.key;
                      record = record.item;
                      req = store.add( record , key );
                  } else {
                      req = store.add( record );
                  }

                  req.onsuccess = function ( e ) {
                      var target = e.target;
                      var keyPath = target.source.keyPath;
                      if ( keyPath === null ) {
                          keyPath = '__id__';
                      }
                      Object.defineProperty( record , keyPath , {
                          value: target.result,
                          enumerable: true
                      });
                  };
              } );

              transaction.oncomplete = function () {
                  resolve( records , that );
              };
              transaction.onerror = function ( e ) {
                  reject( records , e );
              };
              transaction.onabort = function ( e ) {
                  reject( records , e );
              };

            });
        };

        this.update = function( table ) {
            if ( closed ) {
                throw 'Database has been closed';
            }

            var records = [];
            for ( var i = 0 ; i < arguments.length - 1 ; i++ ) {
                records[ i ] = arguments[ i + 1 ];
            }

            var transaction = db.transaction( table , transactionModes.readwrite ),
                store = transaction.objectStore( table ),
                keyPath = store.keyPath;

            return new Promise(function(resolve, reject){
              records.forEach( function ( record ) {
                  var req;
                  var count;
                  if ( record.item && record.key ) {
                      var key = record.key;
                      record = record.item;
                      req = store.put( record , key );
                  } else {
                      req = store.put( record );
                  }

                  req.onsuccess = function ( e ) {
                      // deferred.notify(); es6 promise can't notify
                  };
              } );

              transaction.oncomplete = function () {
                  resolve( records , that );
              };
              transaction.onerror = function ( e ) {
                  reject( records , e );
              };
              transaction.onabort = function ( e ) {
                  reject( records , e );
              };
            });

        };

        this.remove = function ( table , key ) {
            if ( closed ) {
                throw 'Database has been closed';
            }
            var transaction = db.transaction( table , transactionModes.readwrite ),
                store = transaction.objectStore( table );

            return new Promise(function(resolve, reject){
              var req = store.delete( key );
              transaction.oncomplete = function ( ) {
                  resolve( key );
              };
              transaction.onerror = function ( e ) {
                  reject( e );
              };
            });
        };

        this.clear = function ( table ) {
            if ( closed ) {
                throw 'Database has been closed';
            }
            var transaction = db.transaction( table , transactionModes.readwrite ),
                store = transaction.objectStore( table );

            var req = store.clear();
            return new Promise(function(resolve, reject){
              transaction.oncomplete = function ( ) {
                  resolve( );
              };
              transaction.onerror = function ( e ) {
                  reject( e );
              };
            });
        };

        this.close = function ( ) {
            if ( closed ) {
                throw 'Database has been closed';
            }
            db.close();
            closed = true;
            delete dbCache[ name ];
        };

        this.get = function ( table , id ) {
            if ( closed ) {
                throw 'Database has been closed';
            }
            var transaction = db.transaction( table ),
                store = transaction.objectStore( table );

            var req = store.get( id );
            return new Promise(function(resolve, reject){
              req.onsuccess = function ( e ) {
                  resolve( e.target.result );
              };
              transaction.onerror = function ( e ) {
                  reject( e );
              };
            });
        };

        this.query = function ( table , index ) {
            if ( closed ) {
                throw 'Database has been closed';
            }
            return new IndexQuery( table , db , index );
        };

        for ( var i = 0 , il = db.objectStoreNames.length ; i < il ; i++ ) {
            (function ( storeName ) {
                that[ storeName ] = { };
                for ( var i in that ) {
                    if ( !hasOwn.call( that , i ) || i === 'close' ) {
                        continue;
                    }
                    that[ storeName ][ i ] = (function ( i ) {
                        return function () {
                            var args = [ storeName ].concat( [].slice.call( arguments , 0 ) );
                            return that[ i ].apply( that , args );
                        };
                    })( i );
                }
            })( db.objectStoreNames[ i ] );
        }
    };

    var IndexQuery = function ( table , db , indexName ) {
        var that = this;
        var modifyObj = false;

        var runQuery = function ( type, args , cursorType , direction, limitRange, filters , mapper ) {
            var transaction = db.transaction( table, modifyObj ? transactionModes.readwrite : transactionModes.readonly ),
                store = transaction.objectStore( table ),
                index = indexName ? store.index( indexName ) : store,
                keyRange = type ? IDBKeyRange[ type ].apply( null, args ) : null,
                results = [],
                indexArgs = [ keyRange ],
                limitRange = limitRange ? limitRange : null,
                filters = filters ? filters : [],
                counter = 0;

            if ( cursorType !== 'count' ) {
                indexArgs.push( direction || 'next' );
            };

            // create a function that will set in the modifyObj properties into
            // the passed record.
            var modifyKeys = modifyObj ? Object.keys(modifyObj) : false;
            var modifyRecord = function(record) {
                for(var i = 0; i < modifyKeys.length; i++) {
                    var key = modifyKeys[i];
                    var val = modifyObj[key];
                    if(val instanceof Function) val = val(record);
                    record[key] = val;
                }
                return record;
            };

            index[cursorType].apply( index , indexArgs ).onsuccess = function ( e ) {
                var cursor = e.target.result;
                if ( typeof cursor === typeof 0 ) {
                    results = cursor;
                } else if ( cursor ) {
                	if ( limitRange !== null && limitRange[0] > counter) {
                    	counter = limitRange[0];
                    	cursor.advance(limitRange[0]);
                    } else if ( limitRange !== null && counter >= (limitRange[0] + limitRange[1]) ) {
                        //out of limit range... skip
                    } else {
                        var matchFilter = true;
                        var result = 'value' in cursor ? cursor.value : cursor.key;

                        filters.forEach( function ( filter ) {
                            if ( !filter || !filter.length ) {
                                //Invalid filter do nothing
                            } else if ( filter.length === 2 ) {
                                matchFilter = matchFilter && (result[filter[0]] === filter[1])
                            } else {
                                matchFilter = matchFilter && filter[0].apply(undefined,[result]);
                            }
                        });

                        if (matchFilter) {
                            counter++;
                            results.push( mapper(result) );
                            // if we're doing a modify, run it now
                            if(modifyObj) {
                                result = modifyRecord(result);
                                cursor.update(result);
                            }
                        }
                        cursor.continue();
                    }
                }
            };

            return new Promise(function(resolve, reject){
              transaction.oncomplete = function () {
                  resolve( results );
              };
              transaction.onerror = function ( e ) {
                  reject( e );
              };
              transaction.onabort = function ( e ) {
                  reject( e );
              };
            });
        };

        var Query = function ( type , args ) {
            var direction = 'next',
                cursorType = 'openCursor',
                filters = [],
                limitRange = null,
                mapper = defaultMapper,
                unique = false;

            var execute = function () {
                return runQuery( type , args , cursorType , unique ? direction + 'unique' : direction, limitRange, filters , mapper );
            };

            var limit = function () {
                limitRange = Array.prototype.slice.call( arguments , 0 , 2 )
                if (limitRange.length == 1) {
                    limitRange.unshift(0)
                }

                return {
                    execute: execute
                };
            };
            var count = function () {
                direction = null;
                cursorType = 'count';

                return {
                    execute: execute
                };
            };
            var keys = function () {
                cursorType = 'openKeyCursor';

                return {
                    desc: desc,
                    execute: execute,
                    filter: filter,
                    distinct: distinct,
                    map: map
                };
            };
            var filter = function ( ) {
                filters.push( Array.prototype.slice.call( arguments , 0 , 2 ) );

                return {
                    keys: keys,
                    execute: execute,
                    filter: filter,
                    desc: desc,
                    distinct: distinct,
                    modify: modify,
                    limit: limit,
                    map: map
                };
            };
            var desc = function () {
                direction = 'prev';

                return {
                    keys: keys,
                    execute: execute,
                    filter: filter,
                    distinct: distinct,
                    modify: modify,
                    map: map
                };
            };
            var distinct = function () {
                unique = true;
                return {
                    keys: keys,
                    count: count,
                    execute: execute,
                    filter: filter,
                    desc: desc,
                    modify: modify,
                    map: map
                };
            };
            var modify = function(update) {
                modifyObj = update;
                return {
                    execute: execute
                };
            };
            var map = function (fn) {
                mapper = fn;

                return {
                    execute: execute,
                    count: count,
                    keys: keys,
                    filter: filter,
                    desc: desc,
                    distinct: distinct,
                    modify: modify,
                    limit: limit,
                    map: map
                };
            };

            return {
                execute: execute,
                count: count,
                keys: keys,
                filter: filter,
                desc: desc,
                distinct: distinct,
                modify: modify,
                limit: limit,
                map: map
            };
        };

        'only bound upperBound lowerBound'.split(' ').forEach(function (name) {
            that[name] = function () {
                return new Query( name , arguments );
            };
        });

        this.filter = function () {
            var query = new Query( null , null );
            return query.filter.apply( query , arguments );
        };

        this.all = function () {
            return this.filter();
        };
    };

    var createSchema = function ( e , schema , db ) {
        if ( typeof schema === 'function' ) {
            schema = schema();
        }

        for ( var tableName in schema ) {
            var table = schema[ tableName ];
            var store;
            if (!hasOwn.call(schema, tableName) || db.objectStoreNames.contains(tableName)) {
                store = e.currentTarget.transaction.objectStore(tableName);
            } else {
                store = db.createObjectStore(tableName, table.key);
            }

            for ( var indexKey in table.indexes ) {
                if (store.indexNames.contains(indexKey)) {
                    continue;
                }

                var index = table.indexes[ indexKey ];
                store.createIndex( indexKey , index.key || indexKey , Object.keys(index).length ? index : { unique: false } );
            }
        }
    };

    var open = function ( e , server , version , schema ) {
        var db = e.target.result;
        var s = new Server( db , server );
        var upgrade;

        dbCache[ server ] = db;

        return Promise.resolve(s)
    };

    var dbCache = {};

    var db = {
        version: '0.9.0',
        open: function ( options ) {
            var request;

            return new Promise(function(resolve, reject){
              if ( dbCache[ options.server ] ) {
                  open( {
                      target: {
                          result: dbCache[ options.server ]
                      }
                  } , options.server , options.version , options.schema )
                  .then(resolve, reject)
              } else {
                  request = indexedDB.open( options.server , options.version );

                  request.onsuccess = function ( e ) {
                      open( e , options.server , options.version , options.schema )
                          .then(resolve, reject)
                  };

                  request.onupgradeneeded = function ( e ) {
                      createSchema( e , options.schema , e.target.result );
                  };
                  request.onerror = function ( e ) {
                      reject( e );
                  };
              }
            });
        }
    };

    if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
        module.exports = db;
    } else if ( typeof define === 'function' && define.amd ) {
        define( function() { return db; } );
    } else {
        window.db = db;
    }
})( window );
<|endoftext|>


<commit_before>
var fs = require('fs');
var path = require('path');
var http = require('http');

// Compatibility with node 0.7
exports.exists = fs.exists || path.exists;
exports.existsSync = fs.existsSync || path.existsSync;

// go though each property in an object
exports.each = function (object, self, method) {
  // if self is not given use nothing (global in non-strict mode)
  if (arguments.length === 2) {
    method = self;
    self = null;
  }

  Object.keys(object).forEach(function (name) {
    method.call(self, object[name], name);
  });
};

// create a HTTP connect error
exports.httpError = function (code, error){
  var err = new Error(http.STATUS_CODES[code]);
      err.status = code;
      err.origin = error;

  return err;
};

// Extremely simple progress tracker
function ProgressTracker(callback) {
  this.list = [];
  this.callback = callback;
}
exports.ProgressTracker = ProgressTracker;

ProgressTracker.prototype.add = function (list) {
  if (!Array.isArray(list)) list = [list];
  this.list = this.list.concat(list);
};
ProgressTracker.prototype.set = function(name) {
  this.list.splice(this.list.indexOf(name), 1);
  this.check();
};
ProgressTracker.prototype.check = function() {
  if (this.list.length === 0) this.callback();
};

// Allow simultaneously async loading
function mutiplyLoader() {
  if (arguments.length === 2) {
    this.args = arguments[0];
    this.handler = arguments[1];
  } else {
    this.handler = arguments[0];
  }

  this.list = [];
}
exports.mutiplyLoader = mutiplyLoader;

mutiplyLoader.prototype.done = function (error, result) {

  // Execute middle handler
  this.handler.call(this, error, result);

  // execute all callbacks in the list
  var i = this.list.length;
  while(i--) this.list[i](error, result);
};
mutiplyLoader.prototype.push = function (callback) {
  this.list.push(callback);
};
<commit_msg>[fix] do not set origin in httpError if not specified<commit_after>
var fs = require('fs');
var path = require('path');
var http = require('http');

// Compatibility with node 0.7
exports.exists = fs.exists || path.exists;
exports.existsSync = fs.existsSync || path.existsSync;

// go though each property in an object
exports.each = function (object, self, method) {
  // if self is not given use nothing (global in non-strict mode)
  if (arguments.length === 2) {
    method = self;
    self = null;
  }

  Object.keys(object).forEach(function (name) {
    method.call(self, object[name], name);
  });
};

// create a HTTP connect error
exports.httpError = function (code, error){
  var err = new Error(http.STATUS_CODES[code]);
      err.status = code;

  if (error) err.origin = error;

  return err;
};

// Extremely simple progress tracker
function ProgressTracker(callback) {
  this.list = [];
  this.callback = callback;
}
exports.ProgressTracker = ProgressTracker;

ProgressTracker.prototype.add = function (list) {
  if (!Array.isArray(list)) list = [list];
  this.list = this.list.concat(list);
};
ProgressTracker.prototype.set = function(name) {
  this.list.splice(this.list.indexOf(name), 1);
  this.check();
};
ProgressTracker.prototype.check = function() {
  if (this.list.length === 0) this.callback();
};

// Allow simultaneously async loading
function mutiplyLoader() {
  if (arguments.length === 2) {
    this.args = arguments[0];
    this.handler = arguments[1];
  } else {
    this.handler = arguments[0];
  }

  this.list = [];
}
exports.mutiplyLoader = mutiplyLoader;

mutiplyLoader.prototype.done = function (error, result) {

  // Execute middle handler
  this.handler.call(this, error, result);

  // execute all callbacks in the list
  var i = this.list.length;
  while(i--) this.list[i](error, result);
};
mutiplyLoader.prototype.push = function (callback) {
  this.list.push(callback);
};
<|endoftext|>


<commit_before>var util = require('util');
var _ = require('lodash');
var moment = require('moment');

function functor(obj) {
    /**function:functor(obj)
    Coerce ``obj`` to a function.

    If ``obj`` is a function, return the function. Otherwise return
    a constant function that returns ``obj`` when called.

    :param Object obj:
        The object to coerce.
    */
    return typeof obj != 'function'
        ? function() { return obj; }
        : obj;
}

function maybe_call(obj, that, args) {
    /**function:maybe_call(obj, that, args)
    Coerce a function to its result.

    If ``obj`` is a function, call it with the given arguments and return
    the result. Otherwise return ``obj``.

    :param Object obj:
        The function to call or result to return.
    :param Object that:
        The value of ``this`` to bind to the function.
    :param Array args:
        Arguments to call the function with.
    */
    return typeof obj == 'function'
        ? obj.apply(that, args)
        : obj;
}

function inherit(Parent, Child) {
    /**function:inherit(Parent, Child)
    Inherit the parent's prototype and mark the child as extending the parent.

    :param Class Parent:
        The parent class to inherit and extend from.
    :param Class Child:
        The child class that inherits and extends.
    */
    util.inherits(Child, Parent);
    _.extend(Child, Parent);
    return Child;
}

function basic_auth(username, password) {
    /**function:basic_auth(username, password)
    Return an HTTP Basic authentication header value for the given username
    and password.

    :param string username:
        The username to authenticate as.
    :param string password:
        The password to authenticate with.
    */
    var hash = new Buffer(username + ":" + password).toString('base64');
    return 'Basic ' + hash;
}

function vumi_utc(date) {
    /**function:vumi_utc(date)
    Format a date in Vumi's date format.

    :param obj date:
        A value ``moment`` can interpret as a UTC date.
    */
    return moment(date)
        .utc()
        .format('YYYY-MM-DD HH:mm:ss.SSSS');
}

function uuid() {
    /**function:uuid()
    Return a UUID (version 4).
    */
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
        /[xy]/g,
        function(c) {
            var r = Math.floor(Math.random() * 16);
            var v = c == 'x' ? r : (r & (0x3 | 0x8));
            return v.toString(16);
        });
}

function starts_with(haystack, needle) {
    /**function:starts_with(haystack, needle)
    Return ``true`` if haystack starts with needle and ``false`` otherwise.

    :param string haystack:
        The string to search within.
    :param string needle:
        The string to look for.

    If either parameter is false-like, it is treated as the empty string.
    */
    haystack = haystack || '';
    return haystack.lastIndexOf(needle || '', 0) === 0;
}

function exists(v) {
    /**function:exists(v)
    Return ``true`` if v is defined and not null, and ``false`` otherwise.

    :param Object v:
        The value to check.
    */
    return typeof v != 'undefined' && v !== null;
}

function is_integer(v) {
    /**function:is_integer(v)
    Return ``true`` if v is of type number and has no fractional part.

    :param Object v:
        The value to check.
    */
    return typeof v == 'number' && v % 1 === 0;
}

function infer_addr_type(delivery_class) {
    /**function:infer_addr_type(delivery_class)
    Return the address type for the given delivery class.

    A ``delivery class`` is type of system that messages can
    be sent or received over. Common values are ``sms``, ``ussd``,
    ``gtalk`` and ``twitter``.

    An ``address type`` is a type of address used to identify
    a user. Common values are ``msisdn``, ``gtalk_id`` and
    ``twitter_handler``.

    If the ``delivery_class`` isn't know, the ``delivery_class``
    itself is returned as the ``address_type``.

    :param string delivery_class:
        The delivery class to look up.
    */
    return {
        sms: 'msisdn',
        ussd: 'msisdn',
        gtalk: 'gtalk_id',
        twitter: 'twitter_handle'
    }[delivery_class];
}

function format_addr(addr, type) {
    /**function:format_addr(addr, type)
    Format an address as a standardized string.

    This function delegates to the formatter ``format_addr[type]`` or
    returns the address unchanged if there is no custom formatter.

    :param string addr:
        The address to format.
    :param string type:
        The address type for the address.
    */
    var formatter = format_addr[type] || _.identity;
    return formatter(addr);
}

format_addr.msisdn = function(addr) {
    /**function:format_addr.msisdn(addr)
    Canonicalize an MSISDN by adding a ``+`` prefix if one is not present.

    :param string addr:
        The MSISDN to format.
    */
    return '+' + addr.replace('+', '');
};

format_addr.gtalk_id = function(addr) {
    /**function:format_addr.gtalk_id(addr)
    Canonicalize a Gtalk address by stripping the device-specifier, if any.

    :param string addr:
        The Gtalk address to format.
    */
    return addr.split('/')[0];
};

function Extendable() {
    /**class:Extendable()

    A base class for extendable classes.
    */
}

Extendable.extend = function(Child) {
    /**class:Extendable.extend(Child)
    Create a sub-class.

    :param Class Child:
        The constructor for the child class.

    Example usage::

        var MyClass = Extendable.extend(function(self, name) {
            self.my_name = name;
        });

        var OtherClass = MyClass.extend(function(self, other) {
            MyClass.call("custom_name");
            self.other_var = other;
        });
    */
    var Parent = this;

    var Surrogate = function() {
        Array.prototype.unshift.call(arguments, this);
        return Child.apply(this, arguments);
    };

    return inherit(Parent, Surrogate);
};

var BaseError = inherit(Error, function(message) {
    /**class:BaseError()

    An extendable error class that inherits from :class:`Error`.

    Example usage::

        var MyError = BaseError.extend(function(self, message) {
            self.name = "MyError";
            self.message = message;
        });

    .. note::

       :class:`BaseError` copies `.extend` from :class:`Extendable`
       rather than inheriting it because it inherits from :class:`Error`
       already.
    */
    var self = this;
    Error.apply(self, arguments);
});
BaseError.extend = Extendable.extend;

var DeprecationError = BaseError.extend(function(self, message) {
    /**class:DeprecationError

    Thrown when deprecated functionality is used.
    */
    self.name = "DeprecationError";
    self.message = message;
});

this.functor = functor;
this.maybe_call = maybe_call;
this.inherit =inherit;
this.basic_auth = basic_auth;
this.vumi_utc = vumi_utc;
this.uuid = uuid;
this.starts_with = starts_with;
this.exists = exists;
this.is_integer = is_integer;
this.infer_addr_type = infer_addr_type;
this.format_addr = format_addr;
this.Extendable = Extendable;
this.BaseError = BaseError;
this.DeprectationError = DeprecationError;
<commit_msg>Mention that address types are Contact object fields and warn about use of infer_addr_type.<commit_after>var util = require('util');
var _ = require('lodash');
var moment = require('moment');

function functor(obj) {
    /**function:functor(obj)
    Coerce ``obj`` to a function.

    If ``obj`` is a function, return the function. Otherwise return
    a constant function that returns ``obj`` when called.

    :param Object obj:
        The object to coerce.
    */
    return typeof obj != 'function'
        ? function() { return obj; }
        : obj;
}

function maybe_call(obj, that, args) {
    /**function:maybe_call(obj, that, args)
    Coerce a function to its result.

    If ``obj`` is a function, call it with the given arguments and return
    the result. Otherwise return ``obj``.

    :param Object obj:
        The function to call or result to return.
    :param Object that:
        The value of ``this`` to bind to the function.
    :param Array args:
        Arguments to call the function with.
    */
    return typeof obj == 'function'
        ? obj.apply(that, args)
        : obj;
}

function inherit(Parent, Child) {
    /**function:inherit(Parent, Child)
    Inherit the parent's prototype and mark the child as extending the parent.

    :param Class Parent:
        The parent class to inherit and extend from.
    :param Class Child:
        The child class that inherits and extends.
    */
    util.inherits(Child, Parent);
    _.extend(Child, Parent);
    return Child;
}

function basic_auth(username, password) {
    /**function:basic_auth(username, password)
    Return an HTTP Basic authentication header value for the given username
    and password.

    :param string username:
        The username to authenticate as.
    :param string password:
        The password to authenticate with.
    */
    var hash = new Buffer(username + ":" + password).toString('base64');
    return 'Basic ' + hash;
}

function vumi_utc(date) {
    /**function:vumi_utc(date)
    Format a date in Vumi's date format.

    :param obj date:
        A value ``moment`` can interpret as a UTC date.
    */
    return moment(date)
        .utc()
        .format('YYYY-MM-DD HH:mm:ss.SSSS');
}

function uuid() {
    /**function:uuid()
    Return a UUID (version 4).
    */
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
        /[xy]/g,
        function(c) {
            var r = Math.floor(Math.random() * 16);
            var v = c == 'x' ? r : (r & (0x3 | 0x8));
            return v.toString(16);
        });
}

function starts_with(haystack, needle) {
    /**function:starts_with(haystack, needle)
    Return ``true`` if haystack starts with needle and ``false`` otherwise.

    :param string haystack:
        The string to search within.
    :param string needle:
        The string to look for.

    If either parameter is false-like, it is treated as the empty string.
    */
    haystack = haystack || '';
    return haystack.lastIndexOf(needle || '', 0) === 0;
}

function exists(v) {
    /**function:exists(v)
    Return ``true`` if v is defined and not null, and ``false`` otherwise.

    :param Object v:
        The value to check.
    */
    return typeof v != 'undefined' && v !== null;
}

function is_integer(v) {
    /**function:is_integer(v)
    Return ``true`` if v is of type number and has no fractional part.

    :param Object v:
        The value to check.
    */
    return typeof v == 'number' && v % 1 === 0;
}

function infer_addr_type(delivery_class) {
    /**function:infer_addr_type(delivery_class)
    Return the address type for the given delivery class.

    A ``delivery class`` is type of system that messages can
    be sent or received over. Common values are ``sms``, ``ussd``,
    ``gtalk`` and ``twitter``.

    An ``address type`` is a type of address used to identify a user
    and corresponds to a field on a :class:`Contact` object. Common
    values are ``msisdn``, ``gtalk_id`` and ``twitter_handler``.

    If the ``delivery_class`` isn't know, the ``delivery_class``
    itself is returned as the ``address_type``.

    :param string delivery_class:
        The delivery class to look up.

    .. warning::

       The mapping of delivery classes to address types is a low-level
       implementation detail that is subject to change. Use higher-level
       alternatives where possible.
    */
    return {
        sms: 'msisdn',
        ussd: 'msisdn',
        gtalk: 'gtalk_id',
        twitter: 'twitter_handle'
    }[delivery_class];
}

function format_addr(addr, type) {
    /**function:format_addr(addr, type)
    Format an address as a standardized string.

    This function delegates to the formatter ``format_addr[type]`` or
    returns the address unchanged if there is no custom formatter.

    :param string addr:
        The address to format.
    :param string type:
        The address type for the address.
    */
    var formatter = format_addr[type] || _.identity;
    return formatter(addr);
}

format_addr.msisdn = function(addr) {
    /**function:format_addr.msisdn(addr)
    Canonicalize an MSISDN by adding a ``+`` prefix if one is not present.

    :param string addr:
        The MSISDN to format.
    */
    return '+' + addr.replace('+', '');
};

format_addr.gtalk_id = function(addr) {
    /**function:format_addr.gtalk_id(addr)
    Canonicalize a Gtalk address by stripping the device-specifier, if any.

    :param string addr:
        The Gtalk address to format.
    */
    return addr.split('/')[0];
};

function Extendable() {
    /**class:Extendable()

    A base class for extendable classes.
    */
}

Extendable.extend = function(Child) {
    /**class:Extendable.extend(Child)
    Create a sub-class.

    :param Class Child:
        The constructor for the child class.

    Example usage::

        var MyClass = Extendable.extend(function(self, name) {
            self.my_name = name;
        });

        var OtherClass = MyClass.extend(function(self, other) {
            MyClass.call("custom_name");
            self.other_var = other;
        });
    */
    var Parent = this;

    var Surrogate = function() {
        Array.prototype.unshift.call(arguments, this);
        return Child.apply(this, arguments);
    };

    return inherit(Parent, Surrogate);
};

var BaseError = inherit(Error, function(message) {
    /**class:BaseError()

    An extendable error class that inherits from :class:`Error`.

    Example usage::

        var MyError = BaseError.extend(function(self, message) {
            self.name = "MyError";
            self.message = message;
        });

    .. note::

       :class:`BaseError` copies `.extend` from :class:`Extendable`
       rather than inheriting it because it inherits from :class:`Error`
       already.
    */
    var self = this;
    Error.apply(self, arguments);
});
BaseError.extend = Extendable.extend;

var DeprecationError = BaseError.extend(function(self, message) {
    /**class:DeprecationError

    Thrown when deprecated functionality is used.
    */
    self.name = "DeprecationError";
    self.message = message;
});

this.functor = functor;
this.maybe_call = maybe_call;
this.inherit =inherit;
this.basic_auth = basic_auth;
this.vumi_utc = vumi_utc;
this.uuid = uuid;
this.starts_with = starts_with;
this.exists = exists;
this.is_integer = is_integer;
this.infer_addr_type = infer_addr_type;
this.format_addr = format_addr;
this.Extendable = Extendable;
this.BaseError = BaseError;
this.DeprectationError = DeprecationError;
<|endoftext|>


<commit_before>'use strict';

var path = require('path');
var utils = require('lazy-cache')(require);
var fn = require;
require = utils; // eslint-disable-line

/**
 * Utils
 */

require('ask-when');
require('data-store', 'Store');
require('define-property', 'define');
require('extend-shallow', 'extend');
require('fs-exists-sync', 'exists');
require('get-value', 'get');
require('global-modules', 'gm');
require('gray-matter', 'matter');
require('is-answer');
require('isobject', 'isObject');
require('log-utils', 'log');
require('macro-store', 'MacroStore');
require('mixin-deep', 'merge');
require('parser-front-matter', 'parser');
require('resolve-dir');
require('resolve-file', 'resolve');
require = fn; // eslint-disable-line

utils.arrayify = function(val) {
  return val ? (Array.isArray(val) ? val : [val]) : [];
};

utils.renameKey = function(app) {
  var fn = app.options.renameKey;
  if (typeof fn !== 'function') {
    fn = function(key, file) {
      return file ? file.basename : path.basename(key);
    };
  }
  return fn;
};

utils.renameFile = function(app) {
  return function(file, next) {
    var dest = app.options.dest || app.cwd;
    file.base = dest;
    file.cwd = dest;

    file.path = path.join(file.base, file.basename);
    var data = utils.extend({}, file.data);

    if (utils.isObject(data.rename)) {
      for (var key in data.rename) {
        rename(dest, file, key, data.rename[key]);
      }
    }

    if (file.data.yfm) {
      file.content = utils.matter.stringify(file.content, file.data.yfm);
    }

    utils.stripPrefixes(file);
    next();
  };
};

function rename(cwd, file, key, val) {
  switch (key) {
    case 'path':
      file.path = path.resolve(file.base, val);
      break;
    case 'dirname':
      file.dirname = path.resolve(file.base, val);
      break;
    case 'relative':
      file.path = path.resolve(file.base, path.resolve(val));
      break;
    case 'basename':
      file.basename = val;
      break;
    case 'stem':
      file.stem = val;
      break;
    case 'extname':
      file.extname = val;
      break;
  }
}

/**
 * strip prefixes from dotfile and config templates
 */

utils.stripPrefixes = function(file) {
  file.basename = file.basename.replace(/^_/, '.');
  file.basename = file.basename.replace(/^\$/, '');
};

utils.getTasks = function(configFile, arrays) {
  arrays = utils.arrayify(arrays);
  var tasks = [];

  if (configFile) {
    tasks = utils.arrayify(arrays[0]);
    return tasks.length >= 1 ? tasks : ['default'];
  }

  for (var i = 0; i < arrays.length; i++) {
    var arr = utils.arrayify(arrays[i]);
    // if `default` task is defined, continue
    if (arr.length === 1 && arr[0] === 'default') {
      continue;
    }
    // if nothing is defined, continue
    if (arr.length === 0) {
      continue;
    }
    tasks = arr;
    break;
  }
  return tasks;
};

utils.firstIndex = function(arr, items) {
  items = utils.arrayify(items);
  var idx = -1;
  for (var i = 0; i < arr.length; i++) {
    if (items.indexOf(arr[i]) !== -1) {
      idx = i;
      break;
    }
  }
  return idx;
};

utils.logger = function(prop, color) {
  color = color || 'dim';
  return function(msg) {
    var rest = [].slice.call(arguments, 1);
    return console.log
      .bind(console, utils.log.timestamp, utils.log[prop])
      .apply(console, [utils.log[color](msg), ...rest]);
  };
};

/**
 * Return true if the generate CLI is enabled
 */

utils.runnerEnabled = function(app) {
  if (app.options.cli === true || process.env.GENERATE_CLI === 'true') {
    return true;
  }
  // if run from the generate cwd (and not using the `gen` command)
  if (process.cwd() === path.resolve(__dirname, '..')) {
    return false;
  }
  return true;
};

/**
 * Async helper that prompts the user and populates a template
 * with the answer.
 *
 * ```html
 * <%%= ask('author.name') %>
 * ```
 * @param {Object} `app`
 * @return {Function} Returns the helper function
 * @api public
 */

utils.ask = function(app) {
  return function ask(name, message, options, cb) {
    var args = [].slice.call(arguments, 1);
    cb = args.pop();

    if (typeof cb !== 'function') {
      throw new TypeError('expected a callback function');
    }

    var ask = utils.askWhen;
    var last = args[args.length - 1];
    var opts = {};

    if (utils.isObject(last)) {
      options = args.pop();
    }

    last = args[args.length - 1];
    if (typeof last === 'string') {
      opts.message = args.pop();
    }

    options = utils.merge({}, this.options, this.context, opts, options);
    options.save = false;

    ask.when(this.app, name, options, function(err, answers) {
      if (err) {
        cb(err);
        return;
      }
      app.data(answers);
      cb(null, utils.get(answers, name));
    });
  };
};

/**
 * Expose utils
 */

module.exports = utils;
<commit_msg>externalize `ask` helper<commit_after>'use strict';

var path = require('path');
var utils = require('lazy-cache')(require);
var fn = require;
require = utils; // eslint-disable-line

/**
 * Utils
 */

require('ask-when');
require('data-store', 'Store');
require('define-property', 'define');
require('extend-shallow', 'extend');
require('fs-exists-sync', 'exists');
require('get-value', 'get');
require('global-modules', 'gm');
require('gray-matter', 'matter');
require('helper-ask', 'ask');
require('is-answer');
require('isobject', 'isObject');
require('log-utils', 'log');
require('macro-store', 'MacroStore');
require('mixin-deep', 'merge');
require('parser-front-matter', 'parser');
require('resolve-dir');
require('resolve-file', 'resolve');
require = fn; // eslint-disable-line

utils.arrayify = function(val) {
  return val ? (Array.isArray(val) ? val : [val]) : [];
};

utils.renameKey = function(app) {
  var fn = app.options.renameKey;
  if (typeof fn !== 'function') {
    fn = function(key, file) {
      return file ? file.basename : path.basename(key);
    };
  }
  return fn;
};

utils.renameFile = function(app) {
  return function(file, next) {
    var dest = app.options.dest || app.cwd;
    file.base = dest;
    file.cwd = dest;

    file.path = path.join(file.base, file.basename);
    var data = utils.extend({}, file.data);

    if (utils.isObject(data.rename)) {
      for (var key in data.rename) {
        rename(dest, file, key, data.rename[key]);
      }
    }

    if (file.data.yfm) {
      file.content = utils.matter.stringify(file.content, file.data.yfm);
    }

    utils.stripPrefixes(file);
    next();
  };
};

function rename(cwd, file, key, val) {
  switch (key) {
    case 'path':
      file.path = path.resolve(file.base, val);
      break;
    case 'dirname':
      file.dirname = path.resolve(file.base, val);
      break;
    case 'relative':
      file.path = path.resolve(file.base, path.resolve(val));
      break;
    case 'basename':
      file.basename = val;
      break;
    case 'stem':
      file.stem = val;
      break;
    case 'extname':
      file.extname = val;
      break;
  }
}

/**
 * strip prefixes from dotfile and config templates
 */

utils.stripPrefixes = function(file) {
  file.basename = file.basename.replace(/^_/, '.');
  file.basename = file.basename.replace(/^\$/, '');
};

utils.getTasks = function(configFile, arrays) {
  arrays = utils.arrayify(arrays);
  var tasks = [];

  if (configFile) {
    tasks = utils.arrayify(arrays[0]);
    return tasks.length >= 1 ? tasks : ['default'];
  }

  for (var i = 0; i < arrays.length; i++) {
    var arr = utils.arrayify(arrays[i]);
    // if `default` task is defined, continue
    if (arr.length === 1 && arr[0] === 'default') {
      continue;
    }
    // if nothing is defined, continue
    if (arr.length === 0) {
      continue;
    }
    tasks = arr;
    break;
  }
  return tasks;
};

utils.firstIndex = function(arr, items) {
  items = utils.arrayify(items);
  var idx = -1;
  for (var i = 0; i < arr.length; i++) {
    if (items.indexOf(arr[i]) !== -1) {
      idx = i;
      break;
    }
  }
  return idx;
};

utils.logger = function(prop, color) {
  color = color || 'dim';
  return function(msg) {
    var rest = [].slice.call(arguments, 1);
    return console.log
      .bind(console, utils.log.timestamp, utils.log[prop])
      .apply(console, [utils.log[color](msg), ...rest]);
  };
};

/**
 * Return true if the generate CLI is enabled
 */

utils.runnerEnabled = function(app) {
  if (app.options.cli === true || process.env.GENERATE_CLI === 'true') {
    return true;
  }
  // if run from the generate cwd (and not using the `gen` command)
  if (process.cwd() === path.resolve(__dirname, '..')) {
    return false;
  }
  return true;
};

/**
 * Expose utils
 */

module.exports = utils;
<|endoftext|>


<commit_before>// -*- Mode: JavaScript; tab-width: 4 -*- vim:tabstop=4 syntax=javascript:
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

module.version = 0.1;
module.db = new Record();
module.TABLE_NAME = "Factoids";

module.loadDB =
function loadDB() {
	this.db.readINI(system.cwd + "/infobot.ini", this.TABLE_NAME);
}
module.saveDB =
function saveDB() {
	this.db.writeINI(system.cwd + "/infobot.ini", this.TABLE_NAME);
}
module.loadDB();

module.cmd_def =
function cmd_def(dest, args, nick, ident, host, serv, relay) {
	var term = args.split(" ")[0], def = args.split(" ").slice(1).join(" ");
	if (this.db.get(term))
		aucgbot.reply(serv, dest, nick, term, "is already defined:", this.db.get(term));
	else {
		this.db.set(term, def);
		this.saveDB();
	}
	return true;
}
module.cmd_fact =
function cmd_fact(dest, args, nick, ident, host, serv, relay) {
	var def = this.db.get(args);
	if (def)
		aucgbot.reply(serv, dest, nick, args + ":", def);
	return true;
}
module.cmd_sendfact =
function cmd_sendfact(dest, args, nick, ident, host, serv, relay) {
	var args = args.split(" ");
	if (args.length != 2)
		aucgbot.reply(serv, dest, nick, "Usage: sendfact <nick> <term>");
	else if (args[0] == serv.nick) {
		this.reply(serv, dest, nick, "Get me to talk to myself, yeah, great idea...");
	} else {
		var def = this.db.get(args[1]);
		if (def)
			aucgbot.send(serv, args[0], nick, "wanted you to know about", args[1] + ":", def);
	}
}
module.cmd_showfact =
function cmd_showfact(dest, args, nick, ident, host, serv, relay) {
	var args = args.split(" ");
	if (args.length != 2)
		aucgbot.reply(serv, dest, nick, "Usage: showfact <nick> <term>");
	else if (args[0] == serv.nick) {
		this.reply(serv, dest, nick, "Get me to talk to myself, yeah, great idea...");
	} else {
		var def = this.db.get(args[1]);
		if (def)
			aucgbot.send(serv, args[0], args[1] + ":", def);
	}
}<commit_msg>[infobot] optimisations, bugfixes, new no and reloadfacts commands<commit_after>// -*- Mode: JavaScript; tab-width: 4 -*- vim:tabstop=4 syntax=javascript:
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

module.version = 0.2;
module.db = new Record();
module.db.caseSensitive = false;
module.TABLE_NAME = "Factoids";

module.loadDB = function loadDB() this.db.readINI(system.cwd + "/infobot.ini", this.TABLE_NAME);
module.saveDB = function saveDB() this.db.writeINI(system.cwd + "/infobot.ini", this.TABLE_NAME);
module.loadDB();

module.cmd_def =
function cmd_def(dest, args, nick, ident, host, serv, relay) {
	var args = args.split(" "), term = args[0], def = args.slice(1).join(" ");
	if (this.db.get(term))
		aucgbot.reply(serv, dest, nick, term, "is already defined:", this.db.get(term));
	else {
		this.db.set(term, def);
		this.saveDB();
	}
	return true;
}
module.cmd_no =
function cmd_no(dest, args, nick, ident, host, serv, relay) {
	var args = args.split(" "), term = args[0], def = args.slice(1).join(" ");
	this.db.set(term, def);
	this.saveDB();
	return true;
}
module.cmd_reloadfacts =
function cmd_reloadfacts(dest, args, nick, ident, host, serv, relay) {
	aucgbot.reply(serv, dest, nick, "Loaded", this.loadDB(), "factoids.");
	return true;
}
module.cmd_fact =
function cmd_fact(dest, args, nick, ident, host, serv, relay) {
	var def = this.db.get(args);
	if (def)
		aucgbot.reply(serv, dest, nick, def);
	return true;
}
module.cmd_sendfact =
function cmd_sendfact(dest, args, nick, ident, host, serv, relay) {
	var args = args.split(" ");
	if (args.length != 2)
		aucgbot.reply(serv, dest, nick, "Usage: sendfact <nick> <term>");
	else if (args[0] == serv.nick)
		this.reply(serv, dest, nick, "Get me to talk to myself, yeah, great idea...");
	else {
		let def = this.db.get(args[1]);
		if (def)
			aucgbot.send(serv, args[0], nick, "wanted you to know about", args[1] + ":", def);
	}
	return true;
}
module.cmd_showfact =
function cmd_showfact(dest, args, nick, ident, host, serv, relay) {
	var args = args.split(" ");
	if (args.length != 2)
		aucgbot.reply(serv, dest, nick, "Usage: showfact <nick> <term>");
	else if (args[0] == serv.nick)
		this.reply(serv, dest, nick, "Get me to talk to myself, yeah, great idea...");
	else {
		let def = this.db.get(args[1]);
		if (def)
			aucgbot.send(serv, args[0], args[1] + ":", def);
	}
	return true;
}<|endoftext|>


<commit_before>'use strict';

const fs = require('fs');
const path = require('path');

let controllerDir;
let appName;

/**
 * returns application name
 *
 * The name of the application can be different and this function finds it out.
 *
 * @returns {string}
 */
 function getAppName() {
    const parts = __dirname.replace(/\\/g, '/').split('/');
    return parts[parts.length - 2].split('.')[0];
}

/**
 * looks for js-controller home folder
 *
 * @param {boolean} isInstall
 * @returns {string}
 */
function getControllerDir(isInstall) {
    // Find the js-controller location
    const possibilities = [
        'iobroker.js-controller',
        'ioBroker.js-controller',
    ];
    /** @type {string} */
    let controllerPath;
    for (const pkg of possibilities) {
        try {
            const possiblePath = require.resolve(pkg);
            if (fs.existsSync(possiblePath)) {
                controllerPath = possiblePath;
                break;
            }
        } catch (e) { /* not found */ }
    }
    if (controllerPath == null) {
        if (!isInstall) {
            console.log('Cannot find js-controller');
            process.exit(10);
        } else {
            process.exit();
        }
    }
    // we found the controller
    return path.dirname(controllerPath);
}

/**
 * reads controller base settings
 *
 * @alias getConfig
 * @returns {object}
 */
 function getConfig() {
    let configPath;
    if (fs.existsSync(
        configPath = path.join(controllerDir, 'conf', appName + '.json')
    )) {
        return JSON.parse(fs.readFileSync(configPath, 'utf8'));
    } else if (fs.existsSync(
        configPath = path.join(controllerDir, 'conf', + appName.toLowerCase() + '.json')
    )) {
        return JSON.parse(fs.readFileSync(configPath, 'utf8'));
    } else {
        throw new Error('Cannot find ' + controllerDir + '/conf/' + appName + '.json');
    }
}
appName       = getAppName();
controllerDir = getControllerDir(typeof process !== 'undefined' && process.argv && process.argv.indexOf('--install') !== -1);
const adapter = require(path.join(controllerDir, 'lib/adapter.js'));

exports.controllerDir = controllerDir;
exports.getConfig =     getConfig;
exports.Adapter =       adapter;
exports.appName =       appName;
<commit_msg>remove utils.js<commit_after><|endoftext|>