<commit_before>'use strict';

var aws = require('aws-sdk');
var exec = require('child_process').exec;
var fs = require('fs');
var os = require('os');
var packageJson = require('./../package.json');
var path = require('path');
var async = require('async');
var zip = new require('node-zip')();
var wrench = require('wrench');
var dotenv = require('dotenv');

var Lambda = function () {
  this.version = packageJson.version;

  return this;
};

Lambda.prototype._createSampleFile = function (file, boilerplateName) {
  var exampleFile = process.cwd() + '/' + file;
  var boilerplateFile = __dirname + '/' + (boilerplateName || file) + '.example';

  if (!fs.existsSync(exampleFile)) {
    fs.writeFileSync(exampleFile, fs.readFileSync(boilerplateFile));
    console.log(exampleFile + ' file successfully created');
  }
};

Lambda.prototype.setup = function (program) {
  console.log('Running setup.');
  this._createSampleFile('.env', '.env');
  this._createSampleFile(program.eventFile, 'event.json');
  this._createSampleFile('deploy.env', 'deploy.env');
  this._createSampleFile(program.contextFile, 'context.json');
  console.log('Setup done. Edit the .env, deploy.env, ' + program.contextFile + ' and ' + program.eventFile + ' files as needed.');
};

Lambda.prototype.run = function (program) {
  this._createSampleFile(program.eventFile, 'event.json');
  var splitHandler = program.handler.split('.');
  var filename = splitHandler[0] + '.js';
  var handlername = splitHandler[1];

  var handler = require(process.cwd() + '/' + filename)[handlername];
  var event = require(process.cwd() + '/' + program.eventFile);
  var context = require(process.cwd() + '/' + program.contextFile);

  // Set custom environment variables if program.configFile is defined
  if (program.configFile) {
    this._setRunTimeEnvironmentVars(program);
  }

  this._runHandler(handler, event, program.runtime, context);
};

Lambda.prototype._runHandler = function (handler, event, runtime, context) {

  var callback = function (err, result) {
    if (err) {
      console.log('Error: ' + err);
      process.exit(-1);
    }
    else {
      console.log('Success:');
      if (result) {
        console.log(JSON.stringify(result));
      }
      process.exit(0);
    }
  };

  var isNode43 = (runtime === "nodejs4.3");
  context.succeed = function (result) {
    if (isNode43) {
      console.log('context.succeed() is deprecated with Node.js 4.3 runtime');
    }
    callback(null, result);
  };
  context.fail = function (error) {
    if (isNode43) {
      console.log('context.fail() is deprecated with Node.js 4.3 runtime');
    }
    callback(error);
  };
  context.done = function () {
    if (isNode43) {
      console.log('context.done() is deprecated with Node.js 4.3 runtime');
    }
    callback();
  };

  switch(runtime) {
    case "nodejs":
      handler(event, context);
      break;
    case "nodejs4.3":
      handler(event, context, callback);
      break;
    default:
      console.error("Runtime [" + runtime + "] is not supported.");
  }

};

Lambda.prototype._params = function (program, buffer) {
  var params = {
    FunctionName: program.functionName + (program.environment ? '-' + program.environment : ''),
    Code: {
      ZipFile: buffer
    },
    Handler: program.handler,
    Role: program.role,
    Runtime: program.runtime,
    Description: program.description,
    MemorySize: program.memorySize,
    Timeout: program.timeout,
    Publish: program.publish,
    VpcConfig: {}
  };
  if (program.version) {
    params.FunctionName += ('-' + program.version);
  }
  if (program.vpcSubnets && program.vpcSecurityGroups) {
    params.VpcConfig = {
      'SubnetIds': program.vpcSubnets.split(','),
      'SecurityGroupIds': program.vpcSecurityGroups.split(',')
    };
  }

  return params;
};

/**
 * @deprecated
 */
Lambda.prototype._zipfileTmpPath = function (program) {
  var ms_since_epoch = +new Date();
  var filename = program.functionName + '-' + ms_since_epoch + '.zip';
  var zipfile = path.join(os.tmpDir(), filename);

  return zipfile;
};

Lambda.prototype._rsync = function (program, src, dest, excludeNodeModules, callback) {
  var excludes = ['.git*', '*.swp', '.editorconfig', 'deploy.env', '*.log', 'build/'],
      excludeGlobs = [];
  if (program.excludeGlobs) {
    excludeGlobs = program.excludeGlobs.split(' ');
  }
  var excludeArgs = excludeGlobs
    .concat(excludes)
    .concat(excludeNodeModules ? ['node_modules'] : [])
    .map(function(exclude) {
      return '--exclude=' + exclude;
    }).join(' ');

  exec('mkdir -p ' + dest, function(err) {
    if (err) {
      return callback(err);
    }

    // we need the extra / after src to make sure we are copying the content
    // of the directory, not the directory itself.
    exec('rsync -rL ' + excludeArgs + ' ' + src.trim() + '/ ' + dest, function (err) {
      if (err) {
        return callback(err);
      }

      return callback(null, true);
    });
  });
};

Lambda.prototype._npmInstall = function (program, codeDirectory, callback) {
  exec('npm -s install --production --prefix ' + codeDirectory, function (err) {
    if (err) {
      return callback(err);
    }

    return callback(null, true);
  });
};

Lambda.prototype._postInstallScript = function (codeDirectory, callback) {
  var script_filename = 'post_install.sh';
  var cmd = './'+script_filename;

  var filePath = [codeDirectory, script_filename].join('/');

  fs.exists(filePath, function(exists) {
    if (exists) {
      console.log('=> Running post install script '+script_filename);
      exec(cmd, { cwd: codeDirectory,maxBuffer: 50 * 1024 * 1024 }, function(error, stdout, stderr){

        if (error) callback(error +" stdout: " + stdout + "stderr"+stderr);
        else {
          console.log("\t\t"+stdout);
          callback(null);
        }
      });

    } else {
      callback(null);
    }
  });

};

Lambda.prototype._zip = function (program, codeDirectory, callback) {

  var options = {
    type: 'nodebuffer',
    compression: 'DEFLATE'
  };

  console.log('=> Zipping repo. This might take up to 30 seconds');
  var files = wrench.readdirSyncRecursive(codeDirectory);
  files.forEach(function (file) {
    var filePath = [codeDirectory, file].join('/');
    var isFile = fs.lstatSync(filePath).isFile();
    if (isFile) {
      var content = fs.readFileSync(filePath);
      zip.file(file, content);
    }
  });

  var data = zip.generate(options);

  return callback(null, data);
};

Lambda.prototype._nativeZip = function (program, codeDirectory, callback) {
  var zipfile = this._zipfileTmpPath(program),
    cmd = 'zip -r ' + zipfile + ' .';

  exec(cmd, {
    cwd: codeDirectory,
    maxBuffer: 50 * 1024 * 1024
  }, function (err) {
    if (err !== null) {
      return callback(err, null);
    }

    var data = fs.readFileSync(zipfile);
    callback(null, data);
  });
};

Lambda.prototype._codeDirectory = function (program) {
  var epoch_time = +new Date();

  return os.tmpDir() + '/' + program.functionName + '-' + epoch_time;
};

Lambda.prototype._cleanDirectory = function (codeDirectory, callback) {
  exec('rm -rf ' + codeDirectory, function (err) {
    if (err) {
      throw err;
    }

    fs.mkdir(codeDirectory, function(err) {
      if (err) {
        throw err;
      }

      return callback(null, true);
    });
  });
};

Lambda.prototype._setEnvironmentVars = function (program, codeDirectory) {
  console.log('=> Setting "environment variables" for Lambda from %s', program.configFile);
  // Which file is the handler?
  var handlerFileName = codeDirectory + '/' + program.handler.split('.').shift() + '.js';
  var contents = fs.readFileSync(handlerFileName);

  var configValues = fs.readFileSync(program.configFile);
  var prefix = '////////////////////////////////////\n// "Environment Variables"\n';
  var config = dotenv.parse(configValues);
  var contentStr = contents.toString();

  if(program.environment){
      prefix += 'process.env["environment"]=' + JSON.stringify(program.environment) + ';\n';
  }

  for (var k in config) {
    if (!config.hasOwnProperty(k)) {
      continue;
    }

    // Use JSON.stringify to ensure that it's valid code.
    prefix += 'process.env["' + k + '"]=' + JSON.stringify(config[k]) + ';\n';
  }
  prefix += '////////////////////////////////////\n\n';

  // If the first line of the file is 'use strict', append after
  if (contentStr.trim().indexOf('use strict') === 1) {
    contentStr = contentStr.replace(/([`'"]use strict[`'"][;]?)/, '$1\n' + prefix);
  } else {
    contentStr = prefix + contentStr;
  }

  fs.writeFileSync(handlerFileName, contentStr);
};

Lambda.prototype._setRunTimeEnvironmentVars = function (program) {
  var configValues = fs.readFileSync(program.configFile);
  var config = dotenv.parse(configValues);

  for (var k in config) {
    if (!config.hasOwnProperty(k)) {
      continue;
    }

    process.env[k]=config[k];
  }
};

Lambda.prototype._uploadExisting = function(lambda, params, cb) {
  return lambda.updateFunctionCode({
    'FunctionName': params.FunctionName,
    'ZipFile': params.Code.ZipFile,
    'Publish': params.publish
  }, function(err, data) {
    if(err) {
      return cb(err, data);
    }

    return lambda.updateFunctionConfiguration({
      'FunctionName': params.FunctionName,
      'Description': params.Description,
      'Handler': params.Handler,
      'MemorySize': params.MemorySize,
      'Role': params.Role,
      'Timeout': params.Timeout,
      'VpcConfig': params.VpcConfig
    }, function(err, data) {
      return cb(err, data);
    });
  });
};

Lambda.prototype._uploadNew = function(lambda, params, cb) {
  return lambda.createFunction(params, function(err, data) {
    return cb(err, data);
  });
};

Lambda.prototype._archive = function (program, archive_callback) {
  return program.prebuiltDirectory
    ? this._archivePrebuilt(program, archive_callback)
    : this._buildAndArchive(program, archive_callback);
}

Lambda.prototype._archivePrebuilt = function (program, archive_callback) {

  var codeDirectory = this._codeDirectory(program)
  var _this = this;
  this._rsync(program, program.prebuiltDirectory, codeDirectory, false, function (err) {
    if (err) {
      return archive_callback(err);
    }

    // Add custom environment variables if program.configFile is defined
    if (program.configFile) {
      _this._setEnvironmentVars(program, codeDirectory);
    }
    console.log('=> Zipping deployment package');
    var archive = process.platform !== 'win32' ? _this._nativeZip : _this._zip;
    archive = archive.bind(_this);

    archive(program, codeDirectory, archive_callback);
  });
}

Lambda.prototype._buildAndArchive = function (program, archive_callback) {
  this._createSampleFile('.env', '.env');

  // Warn if not building on 64-bit linux
  var arch = process.platform + '.' + process.arch;
  if (arch !== 'linux.x64') {
    console.warn('Warning!!! You are building on a platform that is not 64-bit Linux (%s). ' +
      'If any of your Node dependencies include C-extensions, they may not work as expected in the ' +
      'Lambda environment.\n\n', arch);
  }

  var _this = this;
  var codeDirectory = _this._codeDirectory(program);

  _this._cleanDirectory(codeDirectory, function(err) {
    if (err) {
      return archive_callback(err);
    }
    console.log('=> Moving files to temporary directory');
    // Move files to tmp folder
    _this._rsync(program, '.', codeDirectory, true, function (err) {
      if (err) {
        return archive_callback(err);
      }
      console.log('=> Running npm install --production');
      _this._npmInstall(program, codeDirectory, function (err) {
        if (err) {
          return archive_callback(err);
        }

        _this._postInstallScript(codeDirectory, function (err) {
          if (err) {
            return archive_callback(err);
          }

          // Add custom environment variables if program.configFile is defined
          if (program.configFile) {
            _this._setEnvironmentVars(program, codeDirectory);
          }
          console.log('=> Zipping deployment package');

          var archive = process.platform !== 'win32' ? _this._nativeZip : _this._zip;
          archive = archive.bind(_this);

          archive(program, codeDirectory, archive_callback);
        });
      });
    });
  });
};

Lambda.prototype.package = function (program) {
  var _this = this;
  if (!program.packageDirectory) {
    throw 'packageDirectory not specified!';
  } else {
    try {
      var isDir = fs.lstatSync(program.packageDirectory).isDirectory();

      if (!isDir) {
        throw program.packageDirectory + ' is not a directory!';
      }
    } catch(err) {
      if (err.code === 'ENOENT') {
        console.log('=> Creating package directory');
        fs.mkdirSync(program.packageDirectory);
      } else {
        throw err;
      }
    }
  }

  _this._archive(program, function (err, buffer) {
    if (err) {
      throw err;
    }

    var basename = program.functionName + (program.environment ? '-' + program.environment : '');
    var zipfile = path.join(program.packageDirectory, basename + '.zip');
    console.log('=> Writing packaged zip');
    fs.writeFile(zipfile, buffer, function(err) {
      if (err) {
        throw err;
      }
      console.log('Packaged zip created: ' + zipfile);
    });
  });
};

Lambda.prototype.deploy = function (program) {
  var _this = this;
  var regions = program.region.split(',');
  _this._archive(program, function (err, buffer) {
    if (err) {
      throw err;
    }

    console.log('=> Reading zip file to memory');
    var params = _this._params(program, buffer);

    async.map(regions, function (region, cb) {
      console.log('=> Uploading zip file to AWS Lambda ' + region + ' with parameters:');
      console.log(params);

      var aws_security = {
        accessKeyId: program.accessKey,
        secretAccessKey: program.secretKey,
        region: region
      };

      if (program.sessionToken){
        aws_security.sessionToken = program.sessionToken;
      }

      aws.config.update(aws_security);

      var lambda = new aws.Lambda({
        apiVersion: '2015-03-31'
      });

      return lambda.getFunction({
        'FunctionName': params.FunctionName
      }, function(err) {
        if(err) {
          return _this._uploadNew(lambda, params, cb);
        }

        return _this._uploadExisting(lambda, params, cb);
      });
    }, function (err, results) {
      if (err) {
        throw err;
      } else {
        console.log('=> Zip file(s) done uploading. Results follow: ');
        console.log(results);
      }
    });
  });
};

module.exports = new Lambda();
<commit_msg>Set environment variables before requiring module (#137)<commit_after>'use strict';

var aws = require('aws-sdk');
var exec = require('child_process').exec;
var fs = require('fs');
var os = require('os');
var packageJson = require('./../package.json');
var path = require('path');
var async = require('async');
var zip = new require('node-zip')();
var wrench = require('wrench');
var dotenv = require('dotenv');

var Lambda = function () {
  this.version = packageJson.version;

  return this;
};

Lambda.prototype._createSampleFile = function (file, boilerplateName) {
  var exampleFile = process.cwd() + '/' + file;
  var boilerplateFile = __dirname + '/' + (boilerplateName || file) + '.example';

  if (!fs.existsSync(exampleFile)) {
    fs.writeFileSync(exampleFile, fs.readFileSync(boilerplateFile));
    console.log(exampleFile + ' file successfully created');
  }
};

Lambda.prototype.setup = function (program) {
  console.log('Running setup.');
  this._createSampleFile('.env', '.env');
  this._createSampleFile(program.eventFile, 'event.json');
  this._createSampleFile('deploy.env', 'deploy.env');
  this._createSampleFile(program.contextFile, 'context.json');
  console.log('Setup done. Edit the .env, deploy.env, ' + program.contextFile + ' and ' + program.eventFile + ' files as needed.');
};

Lambda.prototype.run = function (program) {
  this._createSampleFile(program.eventFile, 'event.json');
  var splitHandler = program.handler.split('.');
  var filename = splitHandler[0] + '.js';
  var handlername = splitHandler[1];

  // Set custom environment variables if program.configFile is defined
  if (program.configFile) {
    this._setRunTimeEnvironmentVars(program);
  }

  var handler = require(process.cwd() + '/' + filename)[handlername];
  var event = require(process.cwd() + '/' + program.eventFile);
  var context = require(process.cwd() + '/' + program.contextFile);

  this._runHandler(handler, event, program.runtime, context);
};

Lambda.prototype._runHandler = function (handler, event, runtime, context) {

  var callback = function (err, result) {
    if (err) {
      console.log('Error: ' + err);
      process.exit(-1);
    }
    else {
      console.log('Success:');
      if (result) {
        console.log(JSON.stringify(result));
      }
      process.exit(0);
    }
  };

  var isNode43 = (runtime === "nodejs4.3");
  context.succeed = function (result) {
    if (isNode43) {
      console.log('context.succeed() is deprecated with Node.js 4.3 runtime');
    }
    callback(null, result);
  };
  context.fail = function (error) {
    if (isNode43) {
      console.log('context.fail() is deprecated with Node.js 4.3 runtime');
    }
    callback(error);
  };
  context.done = function () {
    if (isNode43) {
      console.log('context.done() is deprecated with Node.js 4.3 runtime');
    }
    callback();
  };

  switch(runtime) {
    case "nodejs":
      handler(event, context);
      break;
    case "nodejs4.3":
      handler(event, context, callback);
      break;
    default:
      console.error("Runtime [" + runtime + "] is not supported.");
  }

};

Lambda.prototype._params = function (program, buffer) {
  var params = {
    FunctionName: program.functionName + (program.environment ? '-' + program.environment : ''),
    Code: {
      ZipFile: buffer
    },
    Handler: program.handler,
    Role: program.role,
    Runtime: program.runtime,
    Description: program.description,
    MemorySize: program.memorySize,
    Timeout: program.timeout,
    Publish: program.publish,
    VpcConfig: {}
  };
  if (program.version) {
    params.FunctionName += ('-' + program.version);
  }
  if (program.vpcSubnets && program.vpcSecurityGroups) {
    params.VpcConfig = {
      'SubnetIds': program.vpcSubnets.split(','),
      'SecurityGroupIds': program.vpcSecurityGroups.split(',')
    };
  }

  return params;
};

/**
 * @deprecated
 */
Lambda.prototype._zipfileTmpPath = function (program) {
  var ms_since_epoch = +new Date();
  var filename = program.functionName + '-' + ms_since_epoch + '.zip';
  var zipfile = path.join(os.tmpDir(), filename);

  return zipfile;
};

Lambda.prototype._rsync = function (program, src, dest, excludeNodeModules, callback) {
  var excludes = ['.git*', '*.swp', '.editorconfig', 'deploy.env', '*.log', 'build/'],
      excludeGlobs = [];
  if (program.excludeGlobs) {
    excludeGlobs = program.excludeGlobs.split(' ');
  }
  var excludeArgs = excludeGlobs
    .concat(excludes)
    .concat(excludeNodeModules ? ['node_modules'] : [])
    .map(function(exclude) {
      return '--exclude=' + exclude;
    }).join(' ');

  exec('mkdir -p ' + dest, function(err) {
    if (err) {
      return callback(err);
    }

    // we need the extra / after src to make sure we are copying the content
    // of the directory, not the directory itself.
    exec('rsync -rL ' + excludeArgs + ' ' + src.trim() + '/ ' + dest, function (err) {
      if (err) {
        return callback(err);
      }

      return callback(null, true);
    });
  });
};

Lambda.prototype._npmInstall = function (program, codeDirectory, callback) {
  exec('npm -s install --production --prefix ' + codeDirectory, function (err) {
    if (err) {
      return callback(err);
    }

    return callback(null, true);
  });
};

Lambda.prototype._postInstallScript = function (codeDirectory, callback) {
  var script_filename = 'post_install.sh';
  var cmd = './'+script_filename;

  var filePath = [codeDirectory, script_filename].join('/');

  fs.exists(filePath, function(exists) {
    if (exists) {
      console.log('=> Running post install script '+script_filename);
      exec(cmd, { cwd: codeDirectory,maxBuffer: 50 * 1024 * 1024 }, function(error, stdout, stderr){

        if (error) callback(error +" stdout: " + stdout + "stderr"+stderr);
        else {
          console.log("\t\t"+stdout);
          callback(null);
        }
      });

    } else {
      callback(null);
    }
  });

};

Lambda.prototype._zip = function (program, codeDirectory, callback) {

  var options = {
    type: 'nodebuffer',
    compression: 'DEFLATE'
  };

  console.log('=> Zipping repo. This might take up to 30 seconds');
  var files = wrench.readdirSyncRecursive(codeDirectory);
  files.forEach(function (file) {
    var filePath = [codeDirectory, file].join('/');
    var isFile = fs.lstatSync(filePath).isFile();
    if (isFile) {
      var content = fs.readFileSync(filePath);
      zip.file(file, content);
    }
  });

  var data = zip.generate(options);

  return callback(null, data);
};

Lambda.prototype._nativeZip = function (program, codeDirectory, callback) {
  var zipfile = this._zipfileTmpPath(program),
    cmd = 'zip -r ' + zipfile + ' .';

  exec(cmd, {
    cwd: codeDirectory,
    maxBuffer: 50 * 1024 * 1024
  }, function (err) {
    if (err !== null) {
      return callback(err, null);
    }

    var data = fs.readFileSync(zipfile);
    callback(null, data);
  });
};

Lambda.prototype._codeDirectory = function (program) {
  var epoch_time = +new Date();

  return os.tmpDir() + '/' + program.functionName + '-' + epoch_time;
};

Lambda.prototype._cleanDirectory = function (codeDirectory, callback) {
  exec('rm -rf ' + codeDirectory, function (err) {
    if (err) {
      throw err;
    }

    fs.mkdir(codeDirectory, function(err) {
      if (err) {
        throw err;
      }

      return callback(null, true);
    });
  });
};

Lambda.prototype._setEnvironmentVars = function (program, codeDirectory) {
  console.log('=> Setting "environment variables" for Lambda from %s', program.configFile);
  // Which file is the handler?
  var handlerFileName = codeDirectory + '/' + program.handler.split('.').shift() + '.js';
  var contents = fs.readFileSync(handlerFileName);

  var configValues = fs.readFileSync(program.configFile);
  var prefix = '////////////////////////////////////\n// "Environment Variables"\n';
  var config = dotenv.parse(configValues);
  var contentStr = contents.toString();

  if(program.environment){
      prefix += 'process.env["environment"]=' + JSON.stringify(program.environment) + ';\n';
  }

  for (var k in config) {
    if (!config.hasOwnProperty(k)) {
      continue;
    }

    // Use JSON.stringify to ensure that it's valid code.
    prefix += 'process.env["' + k + '"]=' + JSON.stringify(config[k]) + ';\n';
  }
  prefix += '////////////////////////////////////\n\n';

  // If the first line of the file is 'use strict', append after
  if (contentStr.trim().indexOf('use strict') === 1) {
    contentStr = contentStr.replace(/([`'"]use strict[`'"][;]?)/, '$1\n' + prefix);
  } else {
    contentStr = prefix + contentStr;
  }

  fs.writeFileSync(handlerFileName, contentStr);
};

Lambda.prototype._setRunTimeEnvironmentVars = function (program) {
  var configValues = fs.readFileSync(program.configFile);
  var config = dotenv.parse(configValues);

  for (var k in config) {
    if (!config.hasOwnProperty(k)) {
      continue;
    }

    process.env[k]=config[k];
  }
};

Lambda.prototype._uploadExisting = function(lambda, params, cb) {
  return lambda.updateFunctionCode({
    'FunctionName': params.FunctionName,
    'ZipFile': params.Code.ZipFile,
    'Publish': params.publish
  }, function(err, data) {
    if(err) {
      return cb(err, data);
    }

    return lambda.updateFunctionConfiguration({
      'FunctionName': params.FunctionName,
      'Description': params.Description,
      'Handler': params.Handler,
      'MemorySize': params.MemorySize,
      'Role': params.Role,
      'Timeout': params.Timeout,
      'VpcConfig': params.VpcConfig
    }, function(err, data) {
      return cb(err, data);
    });
  });
};

Lambda.prototype._uploadNew = function(lambda, params, cb) {
  return lambda.createFunction(params, function(err, data) {
    return cb(err, data);
  });
};

Lambda.prototype._archive = function (program, archive_callback) {
  return program.prebuiltDirectory
    ? this._archivePrebuilt(program, archive_callback)
    : this._buildAndArchive(program, archive_callback);
}

Lambda.prototype._archivePrebuilt = function (program, archive_callback) {

  var codeDirectory = this._codeDirectory(program)
  var _this = this;
  this._rsync(program, program.prebuiltDirectory, codeDirectory, false, function (err) {
    if (err) {
      return archive_callback(err);
    }

    // Add custom environment variables if program.configFile is defined
    if (program.configFile) {
      _this._setEnvironmentVars(program, codeDirectory);
    }
    console.log('=> Zipping deployment package');
    var archive = process.platform !== 'win32' ? _this._nativeZip : _this._zip;
    archive = archive.bind(_this);

    archive(program, codeDirectory, archive_callback);
  });
}

Lambda.prototype._buildAndArchive = function (program, archive_callback) {
  this._createSampleFile('.env', '.env');

  // Warn if not building on 64-bit linux
  var arch = process.platform + '.' + process.arch;
  if (arch !== 'linux.x64') {
    console.warn('Warning!!! You are building on a platform that is not 64-bit Linux (%s). ' +
      'If any of your Node dependencies include C-extensions, they may not work as expected in the ' +
      'Lambda environment.\n\n', arch);
  }

  var _this = this;
  var codeDirectory = _this._codeDirectory(program);

  _this._cleanDirectory(codeDirectory, function(err) {
    if (err) {
      return archive_callback(err);
    }
    console.log('=> Moving files to temporary directory');
    // Move files to tmp folder
    _this._rsync(program, '.', codeDirectory, true, function (err) {
      if (err) {
        return archive_callback(err);
      }
      console.log('=> Running npm install --production');
      _this._npmInstall(program, codeDirectory, function (err) {
        if (err) {
          return archive_callback(err);
        }

        _this._postInstallScript(codeDirectory, function (err) {
          if (err) {
            return archive_callback(err);
          }

          // Add custom environment variables if program.configFile is defined
          if (program.configFile) {
            _this._setEnvironmentVars(program, codeDirectory);
          }
          console.log('=> Zipping deployment package');

          var archive = process.platform !== 'win32' ? _this._nativeZip : _this._zip;
          archive = archive.bind(_this);

          archive(program, codeDirectory, archive_callback);
        });
      });
    });
  });
};

Lambda.prototype.package = function (program) {
  var _this = this;
  if (!program.packageDirectory) {
    throw 'packageDirectory not specified!';
  } else {
    try {
      var isDir = fs.lstatSync(program.packageDirectory).isDirectory();

      if (!isDir) {
        throw program.packageDirectory + ' is not a directory!';
      }
    } catch(err) {
      if (err.code === 'ENOENT') {
        console.log('=> Creating package directory');
        fs.mkdirSync(program.packageDirectory);
      } else {
        throw err;
      }
    }
  }

  _this._archive(program, function (err, buffer) {
    if (err) {
      throw err;
    }

    var basename = program.functionName + (program.environment ? '-' + program.environment : '');
    var zipfile = path.join(program.packageDirectory, basename + '.zip');
    console.log('=> Writing packaged zip');
    fs.writeFile(zipfile, buffer, function(err) {
      if (err) {
        throw err;
      }
      console.log('Packaged zip created: ' + zipfile);
    });
  });
};

Lambda.prototype.deploy = function (program) {
  var _this = this;
  var regions = program.region.split(',');
  _this._archive(program, function (err, buffer) {
    if (err) {
      throw err;
    }

    console.log('=> Reading zip file to memory');
    var params = _this._params(program, buffer);

    async.map(regions, function (region, cb) {
      console.log('=> Uploading zip file to AWS Lambda ' + region + ' with parameters:');
      console.log(params);

      var aws_security = {
        accessKeyId: program.accessKey,
        secretAccessKey: program.secretKey,
        region: region
      };

      if (program.sessionToken){
        aws_security.sessionToken = program.sessionToken;
      }

      aws.config.update(aws_security);

      var lambda = new aws.Lambda({
        apiVersion: '2015-03-31'
      });

      return lambda.getFunction({
        'FunctionName': params.FunctionName
      }, function(err) {
        if(err) {
          return _this._uploadNew(lambda, params, cb);
        }

        return _this._uploadExisting(lambda, params, cb);
      });
    }, function (err, results) {
      if (err) {
        throw err;
      } else {
        console.log('=> Zip file(s) done uploading. Results follow: ');
        console.log(results);
      }
    });
  });
};

module.exports = new Lambda();
<|endoftext|>


<commit_before>"use strict"

var fs = require("fs");
var path = require("path");

var aws = require("aws-sdk");
var glob = require("glob");
var jsonFile = require("jsonfile");
var console = require("better-console");
var prettyjson = require('prettyjson');

function event(message, data, errorOrCallback, callbackOrCallbackData, callbackData) {
	var error;
	var callback;
	var callbackData;
	if (typeof(errorOrCallback === "function")) {
		error = null;
		callback = errorOrCallback;
		callbackData = callbackOrCallbackData;
	}
	else {
		error = errorOrCallback;
		callback = callbackOrCallbackData;
	}
	if (error) {
		if (!data) data = {};
		data.error = error;
	}
	if (message || data) message = prettyjson.render({ message: message, data: data });
	if (message) console[error ? "error" : "log"](message);
	if (callback) callback(error, callbackData);
}

function getEC2Client(region) {
	return new aws.EC2( { region: region } );
}

function preProcess(regionName, templatePathPatterns, callback) {
	getEC2Client(regionName).describeRegions(function(error, regionsDescription) {
		if (error) event("Unable to get regions", { region: regionName }, error, callback);
		else {
			var regionNames = regionsDescription.Regions.map(function(o) { return o.RegionName; });
			if (!Array.isArray(templatePathPatterns) || templatePathPatterns.length === 0) templatePathPatterns = [ "./*.cloudformation" ];
			templatePathPatterns.forEach(function(templatePathPattern) {
				glob(templatePathPattern, function (error, templatePaths) {
					if (error) event("Unable to find templates", templatePathPatterns, error, callback);
					else {
						var templatesToDo = templatePaths.length;
						var templateCallback = function(message, data, error) {
							event(message, data, error, callback);
							if (--templatesToDo === 0) event("Templates completed", { paths: templatePaths }, callback, templatePaths);
						};
						templatePaths.forEach(function(templatePath) {
							var templateName = path.basename(templatePath);
							var templateDirectory = path.dirname(templatePath);
							var templateInfo = { template : templateName };
							jsonFile.readFile(templatePath, function (error, template) {
								if (error) templateCallback("Unable to read template", templateInfo, error);
								else {
									var originalTemplateString = JSON.stringify(template);
									var tasksToDo = 2; // resources + mappings
									var taskCallback = function(message, data, error) {
										event(message, data, error, templateCallback);
										if (error) templateCallback("Template not saved", templateInfo);
										else if (--tasksToDo === 0 ) {
											var templateString = JSON.stringify(template);
											var templateChanged = (templateString !== originalTemplateString);
											if (templateChanged) jsonFile.writeFile(templatePath, template, function(error) {
												templateCallback(error ? "Unable to save template" : "Template completed", templateInfo, error);
											});
											else templateCallback("Template unchanged", templateInfo);
										}
									}
									event("Pre-processing template", { name : templateName, tasks: tasksToDo });
									var directoryPath = templatePath + ".d";
									var resourcesPath = path.join(directoryPath, "resources");
									var includePathsPattern = resourcesPath + "/*/*/**";
									glob(includePathsPattern, function(error, includePaths) {
										if (error) taskCallback("Unable to get include paths", { pattern : includePathsPattern }, error);
										else {
											var includesToProcess = includePaths.length;
											var includeCallback = function(message, data, error) {
												event(message, data, error, taskCallback);
												if (--includesToProcess === 0) taskCallback("Includes completed", templateInfo);
											};
											includePaths.forEach(function(includePath) {
												var includeInfo = { template: templateName, path: includePath };
												var pathParts = path.relative(resourcesPath, includePath).split(path.sep);
												if (pathParts.length <= 1) includeCallback();
												else if (pathParts.some(function(pathPart) { return pathPart === "."; })) includeCallback("Ignoring include as it is a hidden file", includeInfo);
												else {
													var resourceKey = pathParts[0];
													includeInfo.resource = resourceKey;
													var resource = template.Resources[resourceKey];
													var match = pathParts[1].match(/^configs|userdata(.ps1|.cmd|)$/);
													if (!match) includeCallback("Include must be config or userdata", includeInfo);
													else {
														var includeType; // config or userdata
														var configKey;
														var configType; // file or command
														var userdataWrapper; // powershell, cmd or empty
														var ignore;
														switch (match[0]) {
															case "configs":
																includeType = "config";
																if (pathParts.length <=3) {
																	includeCallback();
																	ignore = true;
																}
																else {
																	includeInfo.config = configKey = pathParts[2];
																	var match = pathParts[3].match(/^files|commands$/);
																	if (!match) {
																		includeCallback("Config include must be file or command", includeInfo);
																		ignore = true;
																	}
																	else {
																		switch (match[0]) {
																			case "files":
																				configType = "file";
																				break;
																			case "commands":
																				configType = "command";
																				break;
																		}
																		includeInfo.configType = configType;
																	}
																}
																break;
															default:
																includeType = "userdata";
																switch (match[1]) {
																	case ".ps1":
																		userdataWrapper = "powershell";
																		break;
																	case ".cmd":
																		userdataWrapper = "script"
																		break;
																}
																includeInfo.userdataType = userdataType = match[1];
														}
														includeInfo.type = includeType;
														if (!ignore) fs.stat(includePath, function(error, stat) {
															if (error) includeCallback("Unable to get Include file stats", includeInfo, error);
															else if (!stat.isFile()) includeCallback();
															//need to support ignoring of windows system/hidden files here
															else fs.readFile(includePath, "utf8", function (error, contentString) {
																if (error) includeCallback(err.errno === 34 ? "Include file not found" : "Unable to read include file", includeInfo, error);
																else {
																	var includeObject;
																	var includeProperty;
																	var objectPath = "Resources/" + resourceKey;
																	switch (includeType) {
																		case "config":
																			var keyParts = pathParts.slice(4);
																			switch (configType) {
																				case "file":
																					for (var i = 0; i < keyParts.length; i++) {
																						var original = keyParts[i];
																						var working = original;
																						//if first part is e.g. C$, change to C:
																						if (i === 0) {
																							var match = working.match(/^([A-z])\$$/);
																							if (match) working = match[1] + ":";
																						}
																						//if part starts with $$ or $., remove the first $
																						var match = working.match(/^\$(\.\$.*)$/)
																						if (match) working = match[1];
																						if (working !== original) keyParts[i] = working;
																					}
																					includeProperty = "content";
																					break;
																				case "command":
																					includeProperty = "command";
																					break;
																			}
																			var key = keyParts.join("/");
																			includeInfo.key = key;
																			var typeKey = configType + "s";
																			objectPath += "/Metadata/AWS::CloudFormation::Init/" + configKey + "/" + typeKey + "/\"" + key + "\"";
																			includeObject = resource.Metadata["AWS::CloudFormation::Init"][configKey][typeKey][key];
																			break;
																		case "userdata":
																			if (userdataWrapper && contentString) contentString = "<" + userdataWrapper + ">\n" + contentString + "\n</" + userdataWrapper + ">";
																			objectPath += "/Properties";
																			includeObject = resource.Properties;
																			includeProperty = "UserData";
																			break;
																	}
																	includeInfo.objectPath = (objectPath += "/" + includeProperty);
																	if (!includeObject) includeCallback("Template object not found", includeInfo);
																	else {
																		var originalContentString = JSON.stringify(includeObject[includeProperty]);
																		var contentArray = [];
																		for (var i = 0; ; true) {
																			var searchString = contentString.substring(i);
																			var match = searchString.match(/(?:\{\{((?:b64)?ref) ([\w.:]*)\}\})|(?:\{\{(att) (\w*) ([\w.]*)\}\})/);
																			var stringToPush = null;
																			if (!match) stringToPush = searchString;
																			else {
																				var j = match.index;
																				if (j > 0) stringToPush = searchString.substring(0, j);
																			}
																			if (stringToPush) {
																				var lastIndex = contentArray.length - 1;
																				if (lastIndex > -1) {
																					var last = contentArray[lastIndex];
																					if (typeof last === "string") {
																						contentArray[lastIndex] = last + str;
																						stringToPush = null;
																					}
																				}
																				if (stringToPush) contentArray.push(stringToPush);
																			}
																			if (!match) break;
																			var variableType = (match[1] || match[3]);
																			if (variableType) {
																				var variable = null;
																				switch (variableType) {
																					case "ref":
																					case "b64ref":
																						variable = { "Ref": match[2] };
																						if (variableType === "b64ref") variable = { "Fn::Base64" : variable };
																						break;
																					case "att":
																						variable = { "Fn::GetAtt": [ match[4], match[5] ] };
																						break;
																				}
																				contentArray.push(variable);
																				var variableInfo = {
																					template: templateName,
																					type: variableType,
																					string: match[0],
																					object: JSON.stringify(variable)
																				};
																				event("Variable found", variableInfo);
																			}
																			i += j + match[0].length;
																		}
																		includeInfo.variableCount = contentArray.filter(function(o) { return typeof o === "object" }).length;
																		var contentObject = (contentArray.length === 1) ? contentArray[0] : { "Fn::Join": [ "", contentArray ] };
																		if (contentObject && (includeType === "userdata")) contentObject = { "Fn::Base64": contentObject }
																		contentString = JSON.stringify(contentObject);
																		var contentChanged = (contentString !== originalContentString);
																		if (contentChanged) includeObject[includeProperty] = contentObject;
																		includeCallback(contentChanged ? "Include changed" : "Include unchanged", includeInfo);
																	}
																}
															});
														});
													}
												}
											});
										}
									});
									var configPath = templatePath + ".config";
									var configName = path.basename(configPath);
									var configInfo = { template: templateName, config: configName }
									jsonFile.readFile(configPath, function(error, config) {
										if (error) {
											if (error.no === 34) taskCallback("Config not found", configInfo);
											else taskCallback("Unable to read config", configInfo, error);
										}
										else {
											var mappings = config.mappings;
											var mappingsKeys = Object.keys(mappings);
											var mappingsToDo = mappingsKeys.length;
											var mappingCallback = function(message, data, error) {
												event(message, data, error, taskCallback);
												if (--mappingsToDo === 0) taskCallback("Mappings completed", templateInfo);
											};
											Object.keys(mappings).forEach(function(key) {
												var mapping = mappings[key];
												var type = mapping.type;
												var mappingInfo = { template: templateName, key: key, type: type };
												var templateMapping = template.Mappings[key];
												if (!templateMapping) mappingsTaskCallback("Mapping ignored", mappingInfo);
												else {
													switch (mapping.type) {
														case "ami":
															var owner = mapping["ami:owner"];
															var name = mapping["ami:name"];
															mappingInfo.owner = owner;
															mappingInfo.name = name;
															var amiMappingRegionsToDo = regionNames.length;
															var amiMappingRegionCallback = function(message, data, error) {
																event(message, data, error, mappingCallback);
																if (--amiMappingRegionsToDo === 0) mappingCallback("Regions' AMIs completed", mappingInfo);
															};
															regionNames.forEach(function(regionName) {
																mappingInfo.region = regionName;
																var amiMappingRegion = templateMapping[regionName];
																var originalAmiId = amiMappingRegion ? amiMappingRegion.ID : null;
																event("Searching for AMI", mappingInfo);
																getEC2Client(regionName).describeImages({
																	Owners: [ owner ],
																	Filters: [ { Name: "name", Values: [ name ] } ]
																}, function(error, amisDescription) {
																	if (error) amiMappingRegionCallback("AMI not found", mappingInfo, error);
																	else {
																		var amis = amisDescription.Images.sort(function(a, b) {
																			var a = a.Name;
																			var b = b.Name;
																			return (a > b) ? 1 : ((a < b) ? -1 : 0);
																		});
																		if (amis.length === 0) amiMappingRegionCallback("AMI not found", mappingInfo);
																		else {
																			var amiId = amis[0].ImageId;
																			mappingInfo.amiId = amiId;
																			var amiChanged = (amiId !== originalAmiId);
																			if (amiChanged) {
																				if (originalAmiId) mappingInfo.originalAmiId = originalAmiId;
																				templateMapping[regionName] = { ID: amiId };
																			}
																			amiMappingRegionCallback(amiChanged ? "AMI changed" : "AMI unchanged", mappingInfo);
																			delete mappingInfo.amiId;
																			delete mappingInfo.previousAmiId;
																		}
																	}
																});
																delete mappingInfo.region;
															});
															break;
														default:
															mappingCallback("Currently, only AMI mappings supported", mappingInfo);
															break;
													}
												}
											});
										}
									});
								}
							});
						});
					}
				});
			});
		}
	});
}

module.exports = preProcess;
<commit_msg>Dropped .config file, mappings now separate files<commit_after>"use strict"

var fs = require("fs");
var path = require("path");

var aws = require("aws-sdk");
var glob = require("glob");
var jsonFile = require("jsonfile");
var console = require("better-console");
var prettyjson = require('prettyjson');

function event(message, data, errorOrCallback, callbackOrCallbackData, callbackData) {
	var error;
	var callback;
	var callbackData;
	if (typeof(errorOrCallback === "function")) {
		error = null;
		callback = errorOrCallback;
		callbackData = callbackOrCallbackData;
	}
	else {
		error = errorOrCallback;
		callback = callbackOrCallbackData;
	}
	if (error) {
		if (!data) data = {};
		data.error = error;
	}
	if (message || data) message = prettyjson.render({ message: message, data: data });
	if (message) console[error ? "error" : "log"](message);
	if (callback) callback(error, callbackData);
}

function getEC2Client(region) {
	return new aws.EC2( { region: region } );
}

function preProcess(regionName, templatePathPatterns, callback) {
	getEC2Client(regionName).describeRegions(function(error, regionsDescription) {
		if (error) event("Unable to get regions", { region: regionName }, error, callback);
		else {
			var regionNames = regionsDescription.Regions.map(function(o) { return o.RegionName; });
			if (!Array.isArray(templatePathPatterns) || templatePathPatterns.length === 0) templatePathPatterns = [ "./*.cloudformation" ];
			templatePathPatterns.forEach(function(templatePathPattern) {
				glob(templatePathPattern, function (error, templatePaths) {
					if (error) event("Unable to find templates", templatePathPatterns, error, callback);
					else {
						var templatesToDo = templatePaths.length;
						var templateCallback = function(message, data, error) {
							event(message, data, error, callback);
							if (--templatesToDo === 0) event("Templates completed", { paths: templatePaths }, callback, templatePaths);
						};
						templatePaths.forEach(function(templatePath) {
							var templateName = path.basename(templatePath);
							var templateDirectory = path.dirname(templatePath);
							var templateInfo = { template : templateName };
							jsonFile.readFile(templatePath, function (error, template) {
								if (error) templateCallback("Unable to read template", templateInfo, error);
								else {
									var originalTemplateString = JSON.stringify(template);
									var tasksToDo = 2; // resources + mappings
									var taskCallback = function(message, data, error) {
										event(message, data, error, templateCallback);
										if (error) templateCallback("Template not saved", templateInfo);
										else if (--tasksToDo === 0 ) {
											var templateString = JSON.stringify(template);
											var templateChanged = (templateString !== originalTemplateString);
											if (templateChanged) jsonFile.writeFile(templatePath, template, function(error) {
												templateCallback(error ? "Unable to save template" : "Template completed", templateInfo, error);
											});
											else templateCallback("Template unchanged", templateInfo);
										}
									}
									event("Pre-processing template", { name : templateName, tasks: tasksToDo });
									var directoryPath = templatePath + ".d";
									var resourcesPath = path.join(directoryPath, "resources");
									var includePathsPattern = resourcesPath + "/*/*/**";
									glob(includePathsPattern, function(error, includePaths) {
										if (error) taskCallback("Unable to get include paths", { pattern : includePathsPattern }, error);
										else {
											var includesToProcess = includePaths.length;
											var includeCallback = function(message, data, error) {
												event(message, data, error, taskCallback);
												if (--includesToProcess === 0) taskCallback("Includes completed", templateInfo);
											};
											includePaths.forEach(function(includePath) {
												var includeInfo = { template: templateName, path: includePath };
												var pathParts = path.relative(resourcesPath, includePath).split(path.sep);
												if (pathParts.length <= 1) includeCallback();
												else if (pathParts.some(function(pathPart) { return pathPart === "."; })) includeCallback("Ignoring include as it is a hidden file", includeInfo);
												else {
													var resourceKey = pathParts[0];
													includeInfo.resource = resourceKey;
													var resource = template.Resources[resourceKey];
													var match = pathParts[1].match(/^configs|userdata(.ps1|.cmd|)$/);
													if (!match) includeCallback("Include must be config or userdata", includeInfo);
													else {
														var includeType; // config or userdata
														var configKey;
														var configType; // file or command
														var userdataWrapper; // powershell, cmd or empty
														var ignore;
														switch (match[0]) {
															case "configs":
																includeType = "config";
																if (pathParts.length <=3) {
																	includeCallback();
																	ignore = true;
																}
																else {
																	includeInfo.config = configKey = pathParts[2];
																	var match = pathParts[3].match(/^files|commands$/);
																	if (!match) {
																		includeCallback("Config include must be file or command", includeInfo);
																		ignore = true;
																	}
																	else {
																		switch (match[0]) {
																			case "files":
																				configType = "file";
																				break;
																			case "commands":
																				configType = "command";
																				break;
																		}
																		includeInfo.configType = configType;
																	}
																}
																break;
															default:
																includeType = "userdata";
																switch (match[1]) {
																	case ".ps1":
																		userdataWrapper = "powershell";
																		break;
																	case ".cmd":
																		userdataWrapper = "script"
																		break;
																}
																includeInfo.userdataType = userdataType = match[1];
														}
														includeInfo.type = includeType;
														if (!ignore) fs.stat(includePath, function(error, stat) {
															if (error) includeCallback("Unable to get Include file stats", includeInfo, error);
															else if (!stat.isFile()) includeCallback();
															//need to support ignoring of windows system/hidden files here
															else fs.readFile(includePath, "utf8", function (error, contentString) {
																if (error) includeCallback(err.errno === 34 ? "Include file not found" : "Unable to read include file", includeInfo, error);
																else {
																	var includeObject;
																	var includeProperty;
																	var objectPath = "Resources/" + resourceKey;
																	switch (includeType) {
																		case "config":
																			var keyParts = pathParts.slice(4);
																			switch (configType) {
																				case "file":
																					for (var i = 0; i < keyParts.length; i++) {
																						var original = keyParts[i];
																						var working = original;
																						//if first part is e.g. C$, change to C:
																						if (i === 0) {
																							var match = working.match(/^([A-z])\$$/);
																							if (match) working = match[1] + ":";
																						}
																						//if part starts with $$ or $., remove the first $
																						var match = working.match(/^\$(\.\$.*)$/)
																						if (match) working = match[1];
																						if (working !== original) keyParts[i] = working;
																					}
																					includeProperty = "content";
																					break;
																				case "command":
																					includeProperty = "command";
																					break;
																			}
																			var key = keyParts.join("/");
																			includeInfo.key = key;
																			var typeKey = configType + "s";
																			objectPath += "/Metadata/AWS::CloudFormation::Init/" + configKey + "/" + typeKey + "/\"" + key + "\"";
																			includeObject = resource.Metadata["AWS::CloudFormation::Init"][configKey][typeKey][key];
																			break;
																		case "userdata":
																			if (userdataWrapper && contentString) contentString = "<" + userdataWrapper + ">\n" + contentString + "\n</" + userdataWrapper + ">";
																			objectPath += "/Properties";
																			includeObject = resource.Properties;
																			includeProperty = "UserData";
																			break;
																	}
																	includeInfo.objectPath = (objectPath += "/" + includeProperty);
																	if (!includeObject) includeCallback("Template object not found", includeInfo);
																	else {
																		var originalContentString = JSON.stringify(includeObject[includeProperty]);
																		var contentArray = [];
																		for (var i = 0; ; true) {
																			var searchString = contentString.substring(i);
																			var match = searchString.match(/(?:\{\{((?:b64)?ref) ([\w.:]*)\}\})|(?:\{\{(att) (\w*) ([\w.]*)\}\})/);
																			var stringToPush = null;
																			if (!match) stringToPush = searchString;
																			else {
																				var j = match.index;
																				if (j > 0) stringToPush = searchString.substring(0, j);
																			}
																			if (stringToPush) {
																				var lastIndex = contentArray.length - 1;
																				if (lastIndex > -1) {
																					var last = contentArray[lastIndex];
																					if (typeof last === "string") {
																						contentArray[lastIndex] = last + str;
																						stringToPush = null;
																					}
																				}
																				if (stringToPush) contentArray.push(stringToPush);
																			}
																			if (!match) break;
																			var variableType = (match[1] || match[3]);
																			if (variableType) {
																				var variable = null;
																				switch (variableType) {
																					case "ref":
																					case "b64ref":
																						variable = { "Ref": match[2] };
																						if (variableType === "b64ref") variable = { "Fn::Base64" : variable };
																						break;
																					case "att":
																						variable = { "Fn::GetAtt": [ match[4], match[5] ] };
																						break;
																				}
																				contentArray.push(variable);
																				var variableInfo = {
																					template: templateName,
																					type: variableType,
																					string: match[0],
																					object: JSON.stringify(variable)
																				};
																				event("Variable found", variableInfo);
																			}
																			i += j + match[0].length;
																		}
																		includeInfo.variableCount = contentArray.filter(function(o) { return typeof o === "object" }).length;
																		var contentObject = (contentArray.length === 1) ? contentArray[0] : { "Fn::Join": [ "", contentArray ] };
																		if (contentObject && (includeType === "userdata")) contentObject = { "Fn::Base64": contentObject }
																		contentString = JSON.stringify(contentObject);
																		var contentChanged = (contentString !== originalContentString);
																		if (contentChanged) includeObject[includeProperty] = contentObject;
																		includeCallback(contentChanged ? "Include changed" : "Include unchanged", includeInfo);
																	}
																}
															});
														});
													}
												}
											});
										}
									});
									var mappingsPath = path.join(directoryPath, "mappings");
									var mappingPathsPattern = mappingsPath + "/*";
									glob(mappingPathsPattern, function(error, mappingPaths) {
										if (error) taskCallback("Unable to get mappings paths", { pattern : mappingPathsPattern }, error);
										else {
											var mappingsToProcess = mappingPaths.length;
											var mappingCallback = function(message, data, error) {
												event(message, data, error, taskCallback);
												if (--mappingsToProcess === 0) taskCallback("Mappings completed", templateInfo);
											};
											mappingPaths.forEach(function(mappingPath) {
												var mappingExtension = path.extname(mappingPath)
												var mappingName = path.basename(mappingPath, mappingExtension);
												var mappingInfo = {
													template: templateName,
													path: mappingPath,
													name: mappingName
												};
												jsonFile.readFile(mappingPath, function(error, mapping) {
													if (error) {
														if (error.no === 34) taskCallback("Config not found", mappingInfo);
														else taskCallback("Unable to read mapping", mappingInfo, error);
													}
													else {
														var type = mapping.type;
														mappingInfo.type = type;
														var templateMapping = template.Mappings[mappingName];
														if (!templateMapping) mappingCallback("Mapping ignored", mappingInfo);
														else {
															switch (mapping.type) {
																case "ami":
																	var ami = mapping.ami;
																	var owner = ami.owner;
																	var name = ami.name;
																	mappingInfo.ami = { owner: owner, name: name };
																	var amiMappingRegionsToDo = regionNames.length;
																	var amiMappingRegionCallback = function(message, data, error) {
																		event(message, data, error, mappingCallback);
																		if (--amiMappingRegionsToDo === 0) mappingCallback("Regions' AMIs completed", mappingInfo);
																	};
																	regionNames.forEach(function(regionName) {
																		mappingInfo.region = regionName;
																		var amiMappingRegion = templateMapping[regionName];
																		var originalAmiId = amiMappingRegion ? amiMappingRegion.ID : null;
																		event("Searching for AMI", mappingInfo);
																		getEC2Client(regionName).describeImages({
																			Owners: [ owner ],
																			Filters: [ { Name: "name", Values: [ name ] } ]
																		}, function(error, amisDescription) {
																			if (error) amiMappingRegionCallback("AMI not found", mappingInfo, error);
																			else {
																				var amis = amisDescription.Images.sort(function(a, b) {
																					var a = a.Name;
																					var b = b.Name;
																					return (a > b) ? 1 : ((a < b) ? -1 : 0);
																				});
																				if (amis.length === 0) amiMappingRegionCallback("AMI not found", mappingInfo);
																				else {
																					var amiId = amis[0].ImageId;
																					mappingInfo.amiId = amiId;
																					var amiChanged = (amiId !== originalAmiId);
																					if (amiChanged) {
																						if (originalAmiId) mappingInfo.originalAmiId = originalAmiId;
																						templateMapping[regionName] = { ID: amiId };
																					}
																					amiMappingRegionCallback(amiChanged ? "AMI changed" : "AMI unchanged", mappingInfo);
																					delete mappingInfo.amiId;
																					delete mappingInfo.previousAmiId;
																				}
																			}
																		});
																		delete mappingInfo.region;
																	});
																	break;
																default:
																	mappingCallback("Currently, only AMI mappings supported", mappingInfo);
																	break;
															}
														}
													}
												});
											});
										}
									});
								}
							});
						});
					}
				});
			});
		}
	});
}

module.exports = preProcess;
<|endoftext|>


<commit_before>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* 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';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace stdlib
*/
var stdlib = {};

/**
* @name array
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/array}
*/
setReadOnly( stdlib, 'array', require( '@stdlib/array' ) );

/**
* @name assert
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/assert}
*/
setReadOnly( stdlib, 'assert', require( '@stdlib/assert' ) );

/**
* @name bench
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/bench}
*/
setReadOnly( stdlib, 'bench', require( '@stdlib/bench' ) );

/**
* @name bigint
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/bigint}
*/
setReadOnly( stdlib, 'bigint', require( '@stdlib/bigint' ) );

/**
* @name blas
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/blas}
*/
setReadOnly( stdlib, 'blas', require( '@stdlib/blas' ) );

/**
* @name buffer
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/buffer}
*/
setReadOnly( stdlib, 'buffer', require( '@stdlib/buffer' ) );

/**
* @name cli
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/cli}
*/
setReadOnly( stdlib, 'cli', require( '@stdlib/cli' ) );

/**
* @name complex
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/complex}
*/
setReadOnly( stdlib, 'complex', require( '@stdlib/complex' ) );

/**
* @name constants
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/constants}
*/
setReadOnly( stdlib, 'constants', require( '@stdlib/constants' ) );

/**
* @name datasets
* @memberof stdlib
* @readonly
* @type {Function}
* @see {@link module:@stdlib/datasets}
*/
setReadOnly( stdlib, 'datasets', require( '@stdlib/datasets' ) );

/**
* @name error
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/error}
*/
setReadOnly( stdlib, 'error', require( '@stdlib/error' ) );

/**
* @name fs
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/fs}
*/
setReadOnly( stdlib, 'fs', require( '@stdlib/fs' ) );

/**
* @name iter
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/iter}
*/
setReadOnly( stdlib, 'iter', require( '@stdlib/iter' ) );

/**
* @name math
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/math}
*/
setReadOnly( stdlib, 'math', require( '@stdlib/math' ) );

/**
* @name ml
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/ml}
*/
setReadOnly( stdlib, 'ml', require( '@stdlib/ml' ) );

/**
* @name namespace
* @memberof stdlib
* @readonly
* @type {Function}
* @see {@link module:@stdlib/namespace}
*/
setReadOnly( stdlib, 'namespace', require( '@stdlib/namespace' ) );

/**
* @name ndarray
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/ndarray}
*/
setReadOnly( stdlib, 'ndarray', require( '@stdlib/ndarray' ) );

/**
* @name net
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/net}
*/
setReadOnly( stdlib, 'net', require( '@stdlib/net' ) );

/**
* @name nlp
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/nlp}
*/
setReadOnly( stdlib, 'nlp', require( '@stdlib/nlp' ) );

/**
* @name number
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/number}
*/
setReadOnly( stdlib, 'number', require( '@stdlib/number' ) );

/**
* @name os
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/os}
*/
setReadOnly( stdlib, 'os', require( '@stdlib/os' ) );

/**
* @name plot
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/plot}
*/
setReadOnly( stdlib, 'plot', require( '@stdlib/plot' ) );

/**
* @name process
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/process}
*/
setReadOnly( stdlib, 'process', require( '@stdlib/process' ) );

/**
* @name proxy
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/proxy}
*/
setReadOnly( stdlib, 'proxy', require( '@stdlib/proxy' ) );

/**
* @name random
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/random}
*/
setReadOnly( stdlib, 'random', require( '@stdlib/random' ) );

/**
* @name regexp
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/regexp}
*/
setReadOnly( stdlib, 'regexp', require( '@stdlib/regexp' ) );

/**
* @name repl
* @memberof stdlib
* @readonly
* @type {Function}
* @see {@link module:@stdlib/repl}
*/
setReadOnly( stdlib, 'repl', require( '@stdlib/repl' ) );

/**
* @name simulate
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/simulate}
*/
setReadOnly( stdlib, 'simulate', require( '@stdlib/simulate' ) );

/**
* @name stats
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/stats}
*/
setReadOnly( stdlib, 'stats', require( '@stdlib/stats' ) );

/**
* @name streams
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/streams}
*/
setReadOnly( stdlib, 'streams', require( '@stdlib/streams' ) );

/**
* @name strided
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/strided}
*/
setReadOnly( stdlib, 'strided', require( '@stdlib/strided' ) );

/**
* @name string
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/string}
*/
setReadOnly( stdlib, 'string', require( '@stdlib/string' ) );

/**
* @name symbol
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/symbol}
*/
setReadOnly( stdlib, 'symbol', require( '@stdlib/symbol' ) );

/**
* @name time
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/time}
*/
setReadOnly( stdlib, 'time', require( '@stdlib/time' ) );

/**
* @name types
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/types}
*/
setReadOnly( stdlib, 'types', require( '@stdlib/types' ) );

/**
* @name utils
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/utils}
*/
setReadOnly( stdlib, 'utils', require( '@stdlib/utils' ) );

// EXPORTS //

module.exports = stdlib;
<commit_msg>Update namespace<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* 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';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace stdlib
*/
var stdlib = {};

/**
* @name array
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/array}
*/
setReadOnly( stdlib, 'array', require( '@stdlib/array' ) );

/**
* @name assert
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/assert}
*/
setReadOnly( stdlib, 'assert', require( '@stdlib/assert' ) );

/**
* @name bench
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/bench}
*/
setReadOnly( stdlib, 'bench', require( '@stdlib/bench' ) );

/**
* @name bigint
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/bigint}
*/
setReadOnly( stdlib, 'bigint', require( '@stdlib/bigint' ) );

/**
* @name blas
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/blas}
*/
setReadOnly( stdlib, 'blas', require( '@stdlib/blas' ) );

/**
* @name buffer
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/buffer}
*/
setReadOnly( stdlib, 'buffer', require( '@stdlib/buffer' ) );

/**
* @name cli
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/cli}
*/
setReadOnly( stdlib, 'cli', require( '@stdlib/cli' ) );

/**
* @name complex
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/complex}
*/
setReadOnly( stdlib, 'complex', require( '@stdlib/complex' ) );

/**
* @name constants
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/constants}
*/
setReadOnly( stdlib, 'constants', require( '@stdlib/constants' ) );

/**
* @name datasets
* @memberof stdlib
* @readonly
* @type {Function}
* @see {@link module:@stdlib/datasets}
*/
setReadOnly( stdlib, 'datasets', require( '@stdlib/datasets' ) );

/**
* @name error
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/error}
*/
setReadOnly( stdlib, 'error', require( '@stdlib/error' ) );

/**
* @name fs
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/fs}
*/
setReadOnly( stdlib, 'fs', require( '@stdlib/fs' ) );

/**
* @name function
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/function}
*/
setReadOnly( stdlib, 'function', require( '@stdlib/function' ) );

/**
* @name iter
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/iter}
*/
setReadOnly( stdlib, 'iter', require( '@stdlib/iter' ) );

/**
* @name math
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/math}
*/
setReadOnly( stdlib, 'math', require( '@stdlib/math' ) );

/**
* @name ml
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/ml}
*/
setReadOnly( stdlib, 'ml', require( '@stdlib/ml' ) );

/**
* @name namespace
* @memberof stdlib
* @readonly
* @type {Function}
* @see {@link module:@stdlib/namespace}
*/
setReadOnly( stdlib, 'namespace', require( '@stdlib/namespace' ) );

/**
* @name ndarray
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/ndarray}
*/
setReadOnly( stdlib, 'ndarray', require( '@stdlib/ndarray' ) );

/**
* @name net
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/net}
*/
setReadOnly( stdlib, 'net', require( '@stdlib/net' ) );

/**
* @name nlp
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/nlp}
*/
setReadOnly( stdlib, 'nlp', require( '@stdlib/nlp' ) );

/**
* @name number
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/number}
*/
setReadOnly( stdlib, 'number', require( '@stdlib/number' ) );

/**
* @name os
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/os}
*/
setReadOnly( stdlib, 'os', require( '@stdlib/os' ) );

/**
* @name plot
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/plot}
*/
setReadOnly( stdlib, 'plot', require( '@stdlib/plot' ) );

/**
* @name process
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/process}
*/
setReadOnly( stdlib, 'process', require( '@stdlib/process' ) );

/**
* @name proxy
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/proxy}
*/
setReadOnly( stdlib, 'proxy', require( '@stdlib/proxy' ) );

/**
* @name random
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/random}
*/
setReadOnly( stdlib, 'random', require( '@stdlib/random' ) );

/**
* @name regexp
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/regexp}
*/
setReadOnly( stdlib, 'regexp', require( '@stdlib/regexp' ) );

/**
* @name repl
* @memberof stdlib
* @readonly
* @type {Function}
* @see {@link module:@stdlib/repl}
*/
setReadOnly( stdlib, 'repl', require( '@stdlib/repl' ) );

/**
* @name simulate
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/simulate}
*/
setReadOnly( stdlib, 'simulate', require( '@stdlib/simulate' ) );

/**
* @name stats
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/stats}
*/
setReadOnly( stdlib, 'stats', require( '@stdlib/stats' ) );

/**
* @name streams
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/streams}
*/
setReadOnly( stdlib, 'streams', require( '@stdlib/streams' ) );

/**
* @name strided
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/strided}
*/
setReadOnly( stdlib, 'strided', require( '@stdlib/strided' ) );

/**
* @name string
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/string}
*/
setReadOnly( stdlib, 'string', require( '@stdlib/string' ) );

/**
* @name symbol
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/symbol}
*/
setReadOnly( stdlib, 'symbol', require( '@stdlib/symbol' ) );

/**
* @name time
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/time}
*/
setReadOnly( stdlib, 'time', require( '@stdlib/time' ) );

/**
* @name types
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/types}
*/
setReadOnly( stdlib, 'types', require( '@stdlib/types' ) );

/**
* @name utils
* @memberof stdlib
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/utils}
*/
setReadOnly( stdlib, 'utils', require( '@stdlib/utils' ) );

// EXPORTS //

module.exports = stdlib;
<|endoftext|>


<commit_before>var VM = require('ethereumjs-vm');
var Account = require('ethereumjs-account');
var Trie = require('merkle-patricia-tree');
var Transaction = require('ethereumjs-tx');
var utils = require('ethereumjs-util');
var Server = require('./server.js');
var Provider = require('./provider.js');
var Manager = require('./manager.js');

FastRpc = {

  startServer: function() {
    Server.startServer();
  },

  Provider: Provider,

  Manager: Manager

}

module.exports = FastRpc;

<commit_msg>add method to generate provider<commit_after>var VM = require('ethereumjs-vm');
var Account = require('ethereumjs-account');
var Trie = require('merkle-patricia-tree');
var Transaction = require('ethereumjs-tx');
var utils = require('ethereumjs-util');
var Server = require('./server.js');
var Provider = require('./provider.js');
var Manager = require('./manager.js');

FastRpc = {

  startServer: function() {
    Server.startServer();
  },

  Provider: Provider,

  Manager: Manager,

  web3Provider: function() {
    var manager  = new this.Manager();
    var provider = new this.Provider(manager);

    return provider;
  }

}

module.exports = FastRpc;

<|endoftext|>


<commit_before>//Reddit Notifier main.js!
//This is where the magic happens

//Get dependencies
var data = require('self').data;
var prefs = require("sdk/simple-prefs");
var request = require("sdk/request");
var notifications = require("sdk/notifications");
var timers = require("sdk/timers");
var tabs = require("sdk/tabs");
var windowutils = require("window-utils");
var toolbarbutton = require("./toolbarbutton");
var userstyles = require("./userstyles");

var config = {
	name: "RedditNotifier",
	urls: {
		unreadMessage: "http://www.reddit.com/message/unread/",
		unreadMessageJSON: "http://www.reddit.com/message/unread.json",
		login: "https://ssl.reddit.com/login"
	},
	//multiplied by 1000 to get seconds
	refreshTime: prefs.prefs.timing*1000,
	forceShow: prefs.prefs.forceShow,
	delayLoad: 5000,
	icons: {
		big: data.url("reddit-notifier-icon.png"),
		small: data.url("reddit-notifier-icon-small.png"),
		smallUnread: data.url("reddit-notifier-icon-small-unread.png")
	},
	errors: {
		loggedOut: "It looks like you are logged out of Reddit. Try logging in."
	},
	toolbar: {
		id: "redditnotifierbutton",
		tooltip: "RedditNotifier\nClick to open inbox, middle click to refresh",
		backgroundColor: "#ff3f00",
		textColor: "#FFF",
	    move: {
	      toolbarID: "nav-bar",
	      insertBefore: "home-button",
	      forceMove: false
	    }
	}
}

var main = {
	addonButton: null,
	timer: null,
	numUnread: 0,
	error: false,
	//Called by the browser at runtime
	init: function(options, callbacks) {
		//create button for refreshing/opening inbox
		main.addonButton = toolbarbutton.ToolbarButton({
			id: config.toolbar.id,
		  	label: config.name,
		  	tooltiptext: config.toolbar.tooltip,
		  	textColor: config.toolbar.textColor,
		  	backgroundColor: config.toolbar.backgroundColor,
		  	onClick: function (e) {
		  		if (e.button == 1 || (e.button == 0 && e.ctrlKey)) {
		  			//reset the error
		  			main.error = false;
		  			main.update();
		  		}
		  	},
		  	onCommand: function () {
				main.openTab(config.urls.unreadMessage);
		  	}
		});
		//This should probably only run if the options.loadReason is an install
		if (options.loadReason === "install" || config.forceShow) {
			main.addonButton.moveTo(config.toolbar.move);
		}
		//Sets the image and such
		userstyles.load(data.url("bubble.css"));
		//run the for the first time, don't do it right when the browser loads though
		main.timer = timers.setTimeout(main.update, config.delayLoad);
	},
	update: function() {
		timers.clearTimeout(main.timer);
		//change the button icon to reflect the refresh
		main.addonButton.type = "refresh";
		//runs the request, calls the updateButton function
		request.Request({
			url: config.urls.unreadMessageJSON,
			onComplete: function (returned) {
				var response = returned.json;
				//check if logged in
				if (response.hasOwnProperty("data")) {
					//store the old number for comparison
					var oldNum = main.numUnread;
					//Store the array of messages
					//Let's make this smarter someday. I should store the timestamp of the newest message.
					var messages = response["data"]["children"];
					//Get the number
					main.numUnread = 0;
					//Count the number of messages
					for (var message in messages) {
						if (messages.hasOwnProperty(message)) {
							main.numUnread++;
						}
					}
					//There are no errors!
					main.error = false;
					//If the number is greater, alert the user
					if (main.numUnread > oldNum) {
						var numNew = main.numUnread - oldNum;
						//plurality
						if (numNew === 1) {
							var plural = "is";
						} else {
							var plural = "are";
						}
						main.notify("New Messages", "There " + plural +" " + numNew + " new message(s).", function() {
							main.openTab(config.urls.unreadMessage);
						});
					}
					main.updateButton();
				} else {
					//logged out
					main.numUnread = 0;
					if (!main.error) {
						main.notify("Error", config.errors.loggedOut, function() {
							main.openTab(config.urls.login);
						});
						main.error = true;
					}
					main.updateButton(main.numUnread);
				}
				//call again after set amount of time
				main.timer = timers.setTimeout(main.update, config.refreshTime);
			}
		}).get();
	},
	updateButton: function() {
		//change the badge
		if (main.numUnread >= 10) {
			main.addonButton.badge = "∞";
		} else {
			main.addonButton.badge = main.numUnread;
		}
		//change the icon
		if (main.numUnread > 0) {
			main.addonButton.type = "unread";
		} else {
			main.addonButton.type = "read";
		}
	},
	notify: function(title, text, callback, data) {
		//Only show notifications if the user wants them
		if (prefs.prefs.showNotifications) {
			notifications.notify({
				title: config.name + " - " + title,
			 	text: text,
			 	iconURL: config.icons.big,
			 	data: data,
			 	onClick: function(data) {
			 		if (typeof(callback) === 'function') {
			 			callback(data);
			 		}
			 	}
			});
		}
	},
	openTab: function(url) {
		//check if already open
		for each (var tab in tabs) {
			if (tab.url === url) {
				//reload and then switch to the tab
				tab.reload();
				tab.activate();
				return;
			}
		}
		tabs.open(url);
	},
	timingOption: function(name) {
		//Change the refresh time to the new value
		if (prefs.prefs[name] >= 30) {
			config.refreshTime = prefs.prefs[name]*1000;
		} else {
			config.refreshTime = 30000;
		}
	}
}

exports.main = main.init;
//This function verifies the user input
prefs.on("timing", main.timingOption);<commit_msg>Right click to refresh. Reset button on click.<commit_after>//Reddit Notifier main.js!
//This is where the magic happens

//Get dependencies
var data = require('self').data;
var prefs = require("sdk/simple-prefs");
var request = require("sdk/request");
var notifications = require("sdk/notifications");
var timers = require("sdk/timers");
var tabs = require("sdk/tabs");
var windowutils = require("window-utils");
var toolbarbutton = require("./toolbarbutton");
var userstyles = require("./userstyles");

var config = {
	name: "RedditNotifier",
	urls: {
		unreadMessage: "http://www.reddit.com/message/unread/",
		unreadMessageJSON: "http://www.reddit.com/message/unread.json",
		login: "https://ssl.reddit.com/login"
	},
	//multiplied by 1000 to get seconds
	refreshTime: prefs.prefs.timing*1000,
	forceShow: prefs.prefs.forceShow,
	delayLoad: 5000,
	icons: {
		big: data.url("reddit-notifier-icon.png"),
		small: data.url("reddit-notifier-icon-small.png"),
		smallUnread: data.url("reddit-notifier-icon-small-unread.png")
	},
	errors: {
		loggedOut: "It looks like you are logged out of Reddit. Try logging in."
	},
	toolbar: {
		id: "redditnotifierbutton",
		tooltip: "RedditNotifier\nClick to open inbox, opposite click to refresh",
		backgroundColor: "#ff3f00",
		textColor: "#FFF",
	    move: {
	      toolbarID: "nav-bar",
	      insertBefore: "home-button",
	      forceMove: false
	    }
	}
}

var main = {
	addonButton: null,
	timer: null,
	numUnread: 0,
	error: false,
	//Called by the browser at runtime
	init: function(options, callbacks) {
		//create button for refreshing/opening inbox
		main.addonButton = toolbarbutton.ToolbarButton({
			id: config.toolbar.id,
		  	label: config.name,
		  	tooltiptext: config.toolbar.tooltip,
		  	textColor: config.toolbar.textColor,
		  	backgroundColor: config.toolbar.backgroundColor,
		  	onContext: function (e) {
		  		e.preventDefault();
		  		//reset the error
		  		main.error = false;
		  		main.update();
		  	},
		  	onCommand: function () {
		  		//reset the count on click
		  		main.numUnread = 0;
		  		main.updateButton();
				main.openTab(config.urls.unreadMessage);
		  	}
		});
		//This should probably only run if the options.loadReason is an install
		if (options.loadReason === "install" || config.forceShow) {
			main.addonButton.moveTo(config.toolbar.move);
		}
		//Sets the image and such
		userstyles.load(data.url("bubble.css"));
		//run the for the first time, don't do it right when the browser loads though
		main.timer = timers.setTimeout(main.update, config.delayLoad);
	},
	update: function() {
		timers.clearTimeout(main.timer);
		//change the button icon to reflect the refresh
		main.addonButton.type = "refresh";
		//runs the request, calls the updateButton function
		request.Request({
			url: config.urls.unreadMessageJSON,
			onComplete: function (returned) {
				var response = returned.json;
				//check if logged in
				if (response.hasOwnProperty("data")) {
					//store the old number for comparison
					var oldNum = main.numUnread;
					//Store the array of messages
					//Let's make this smarter someday. I should store the timestamp of the newest message.
					var messages = response["data"]["children"];
					//Get the number
					main.numUnread = 0;
					//Count the number of messages
					for (var message in messages) {
						if (messages.hasOwnProperty(message)) {
							main.numUnread++;
						}
					}
					//There are no errors!
					main.error = false;
					//If the number is greater, alert the user
					if (main.numUnread > oldNum) {
						var numNew = main.numUnread - oldNum;
						//plurality
						if (numNew === 1) {
							var plural = "is";
						} else {
							var plural = "are";
						}
						main.notify("New Messages", "There " + plural +" " + numNew + " new message(s).", function() {
							main.openTab(config.urls.unreadMessage);
						});
					}
					main.updateButton();
				} else {
					//logged out
					main.numUnread = 0;
					if (!main.error) {
						main.notify("Error", config.errors.loggedOut, function() {
							main.openTab(config.urls.login);
						});
						main.error = true;
					}
					main.updateButton(main.numUnread);
				}
				//call again after set amount of time
				main.timer = timers.setTimeout(main.update, config.refreshTime);
			}
		}).get();
	},
	updateButton: function() {
		//change the badge
		if (main.numUnread >= 10) {
			main.addonButton.badge = "∞";
		} else {
			main.addonButton.badge = main.numUnread;
		}
		//change the icon
		if (main.numUnread > 0) {
			main.addonButton.type = "unread";
		} else {
			main.addonButton.type = "read";
		}
	},
	notify: function(title, text, callback, data) {
		//Only show notifications if the user wants them
		if (prefs.prefs.showNotifications) {
			notifications.notify({
				title: config.name + " - " + title,
			 	text: text,
			 	iconURL: config.icons.big,
			 	data: data,
			 	onClick: function(data) {
			 		if (typeof(callback) === 'function') {
			 			callback(data);
			 		}
			 	}
			});
		}
	},
	openTab: function(url) {
		//check if already open
		for each (var tab in tabs) {
			if (tab.url === url) {
				//reload and then switch to the tab
				tab.reload();
				tab.activate();
				return;
			}
		}
		tabs.open(url);
	},
	timingOption: function(name) {
		//Change the refresh time to the new value
		if (prefs.prefs[name] >= 30) {
			config.refreshTime = prefs.prefs[name]*1000;
		} else {
			config.refreshTime = 30000;
		}
	}
}

exports.main = main.init;
//This function verifies the user input
prefs.on("timing", main.timingOption);<|endoftext|>


<commit_before>'use babel';

export default {
  config: {
    puppetExecutablePath: {
      title: 'Puppet Executable Path',
      type: 'string',
      description: 'Path to Puppet executable (e.g. /opt/puppetlabs/bin/puppet) if not in shell env path.',
      default: 'puppet',
    },
    puppetParserArgs: {
      title: 'Puppet Parser Arguments',
      type: 'array',
      description: 'Arguments and/or flags to pass to parser.',
      default: [],
      items: {
        type: 'string'
      }
    }
  },

  provideLinter() {
    return {
      name: 'Puppet',
      grammarScopes: ['source.puppet'],
      scope: 'file',
      lintsOnChange: false,
      lint: (activeEditor) => {
        // set const vars
        const helpers = require('atom-linter');
        const regex = /(Error|Warning).*:\s(.*)\sat.*\.pp:(\d+):?(\d+)?/;
        const regex_new = /(Error|Warning).*:\s(.*)\s\(file.*line: (\d+), column: (\d+)/;
        const file = activeEditor.getPath();

        // add arg to puppet to use parser subcommand
        var args = ['parser']

        // add arbitrary puppet args
        if (atom.config.get('linter-puppet-parsing.puppetParserArgs')[0] !== '')
          args = args.concat(atom.config.get('linter-puppet-parsing.puppetParserArgs'));

        // add arg to parser for sub-subcommand to validate and file to validate
        args = args.concat(['validate', file]);

        return helpers.exec(atom.config.get('linter-puppet-parsing.puppetExecutablePath'), args, {stream: 'stderr', allowEmptyStderr: true}).then(output => {
          var toReturn = [];
          output.split(/\r?\n/).forEach(function (line) {
            // setup matchers for normal line and col info or eof location
            const matches_line_col = regex.exec(line);
            const matches_new = regex_new.exec(line)
            const matches_eof = /Syntax error at end of/.exec(line);

            // parse the errors and warnings with line and col info output from puppet parser validate
            if (matches_line_col != null) {
              toReturn.push({
                severity: matches_line_col[1].toLowerCase(),
                excerpt: matches_line_col[2],
                location: {
                  file: file,
                  position: [[Number.parseInt(matches_line_col[3]) - 1, Number.parseInt(matches_line_col[4]) - 1], [Number.parseInt(matches_line_col[3]) - 1, Number.parseInt(matches_line_col[4])]],
                },
              });
            }
            // same kind of parsing, but for puppet>=5.4 output
            else if (matches_new != null) {
              toReturn.push({
                severity: matches_new[1].toLowerCase(),
                excerpt: matches_new[2],
                location: {
                  file: file,
                  position: [[Number.parseInt(matches_new[3]) - 1, Number.parseInt(matches_new[4]) - 1], [Number.parseInt(matches_new[3]) - 1, Number.parseInt(matches_new[4])]],
                },
              });
            }
            // parse the errors and warnings with end of file from puppet parser validate
            else if (matches_eof != null) {
              toReturn.push({
                severity: 'error',
                excerpt: 'Syntax error at end of file.',
                location: {
                  file: file,
                  position: [[activeEditor.getLastScreenRow() - 1, 0], [activeEditor.getLastScreenRow() - 1, 1]],
                },
              });
            }
          });
          return toReturn;
        });
      }
    };
  }
};
<commit_msg>optimize array concat<commit_after>'use babel';

export default {
  config: {
    puppetExecutablePath: {
      title: 'Puppet Executable Path',
      type: 'string',
      description: 'Path to Puppet executable (e.g. /opt/puppetlabs/bin/puppet) if not in shell env path.',
      default: 'puppet',
    },
    puppetParserArgs: {
      title: 'Puppet Parser Arguments',
      type: 'array',
      description: 'Arguments and/or flags to pass to parser.',
      default: [],
      items: {
        type: 'string'
      }
    }
  },

  provideLinter() {
    return {
      name: 'Puppet',
      grammarScopes: ['source.puppet'],
      scope: 'file',
      lintsOnChange: false,
      lint: (activeEditor) => {
        // set const vars
        const helpers = require('atom-linter');
        const regex = /(Error|Warning).*:\s(.*)\sat.*\.pp:(\d+):?(\d+)?/;
        const regex_new = /(Error|Warning).*:\s(.*)\s\(file.*line: (\d+), column: (\d+)/;
        const file = activeEditor.getPath();

        // add arg to puppet to use parser subcommand
        var args = ['parser']

        // add arbitrary puppet args
        if (atom.config.get('linter-puppet-parsing.puppetParserArgs')[0] !== '')
          args.push(...atom.config.get('linter-puppet-parsing.puppetParserArgs'));

        // add arg to parser for sub-subcommand to validate and file to validate
        args.push(...['validate', file]);

        return helpers.exec(atom.config.get('linter-puppet-parsing.puppetExecutablePath'), args, {stream: 'stderr', allowEmptyStderr: true}).then(output => {
          var toReturn = [];
          output.split(/\r?\n/).forEach(function (line) {
            // setup matchers for normal line and col info or eof location
            const matches_line_col = regex.exec(line);
            const matches_new = regex_new.exec(line)
            const matches_eof = /Syntax error at end of/.exec(line);

            // parse the errors and warnings with line and col info output from puppet parser validate
            if (matches_line_col != null) {
              toReturn.push({
                severity: matches_line_col[1].toLowerCase(),
                excerpt: matches_line_col[2],
                location: {
                  file: file,
                  position: [[Number.parseInt(matches_line_col[3]) - 1, Number.parseInt(matches_line_col[4]) - 1], [Number.parseInt(matches_line_col[3]) - 1, Number.parseInt(matches_line_col[4])]],
                },
              });
            }
            // same kind of parsing, but for puppet>=5.4 output
            else if (matches_new != null) {
              toReturn.push({
                severity: matches_new[1].toLowerCase(),
                excerpt: matches_new[2],
                location: {
                  file: file,
                  position: [[Number.parseInt(matches_new[3]) - 1, Number.parseInt(matches_new[4]) - 1], [Number.parseInt(matches_new[3]) - 1, Number.parseInt(matches_new[4])]],
                },
              });
            }
            // parse the errors and warnings with end of file from puppet parser validate
            else if (matches_eof != null) {
              toReturn.push({
                severity: 'error',
                excerpt: 'Syntax error at end of file.',
                location: {
                  file: file,
                  position: [[activeEditor.getLastScreenRow() - 1, 0], [activeEditor.getLastScreenRow() - 1, 1]],
                },
              });
            }
          });
          return toReturn;
        });
      }
    };
  }
};
<|endoftext|>


<commit_before>var tabs = require("sdk/tabs");
var data = require("sdk/self").data;

var panel = require("sdk/panel").Panel({
  contentURL: data.url("panel.html"),
  contentScriptFile: [
	data.url("panel.js"),
	data.url("jquery.min.js")
	],
  onHide: handleHide
});

var button = require('sdk/ui/button/toggle').ToggleButton({
  id: "reddit-submission-finder-panel",
  label: "Reddit Submission Finder",
  icon: {
    "16": "./icon-16.png",
    "32": "./icon-32.png",
    "64": "./icon-64.png"
  },
  onChange: handleChange
});

panel.on("show", function() {
  panel.port.emit("show", tabs.activeTab.url);
});

panel.on("hide", function() {
  panel.port.emit("hide");
});

panel.port.on("open-link", function (url) {
  console.log(url);
  tabs.open(url);
});

function handleChange(state) {
  if (state.checked) {
    panel.show({
      position: button,
	  width: 400,
	  height: 400
    });
  }
}

function handleHide() {
  button.state('window', {checked: false});
}<commit_msg>close panel when submission is clicked<commit_after>var tabs = require("sdk/tabs");
var data = require("sdk/self").data;

var panel = require("sdk/panel").Panel({
  contentURL: data.url("panel.html"),
  contentScriptFile: [
	data.url("panel.js"),
	data.url("jquery.min.js")
	],
  onHide: handleHide
});

var button = require('sdk/ui/button/toggle').ToggleButton({
  id: "reddit-submission-finder-panel",
  label: "Reddit Submission Finder",
  icon: {
    "16": "./icon-16.png",
    "32": "./icon-32.png",
    "64": "./icon-64.png"
  },
  onChange: handleChange
});

panel.on("show", function() {
  panel.port.emit("show", tabs.activeTab.url);
});

panel.on("hide", function() {
  panel.port.emit("hide");
});

panel.port.on("open-link", function (url) {
  console.log(url);
  tabs.open(url);
  panel.hide();
});

function handleChange(state) {
  if (state.checked) {
    panel.show({
      position: button,
	  width: 400,
	  height: 400
    });
  }
}

function handleHide() {
  button.state('window', {checked: false});
}<|endoftext|>