diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9eac20b --- /dev/null +++ b/.gitignore @@ -0,0 +1,66 @@ +# Node modules +./node_modules + +# Notes and stuff +notes.txt +example.json + +# .gitignore Template +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Typescript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env diff --git a/README.md b/README.md index cb007d2..2161ac0 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,6 @@ # project_what_have_you_done Build an application to help track the legislative activities of your local representatives. + + +https://github.com/unitedstates/congress-legislators +https://theunitedstates.io/congress-legislators/legislators-current.json diff --git a/app.js b/app.js new file mode 100644 index 0000000..bfe1cef --- /dev/null +++ b/app.js @@ -0,0 +1,70 @@ +var express = require("express"); +var path = require("path"); +var favicon = require("serve-favicon"); +var logger = require("morgan"); +var cookieParser = require("cookie-parser"); +var bodyParser = require("body-parser"); +var expressValidator = require('express-validator'); +var exphbs = require('express-handlebars'); +// var helpers = require('./helpers/helpers'); + +// Require each route +var index = require("./routes/index"); + +// Require keys +var keys = require("../../../Modules/Cles/items.js"); + +var app = express(); + +// view engine setup +app.engine('handlebars', exphbs({ + defaultLayout: 'main', + helpers: { + reps: function(items, options) { + var out = ""; + }, + foo: function(){ + return 'foo'; + } + } +})); +app.set("view engine", "handlebars"); + +// uncomment after placing your favicon in /public +//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); +app.use(logger("dev")); +app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ extended: true })); +app.use(cookieParser()); +app.use(express.static(path.join(__dirname, "public"))); +app.use(expressValidator()); + +// Set routes +app.use("/", index); +//app.use("/results", results); + +// catch 404 and forward to error handler +app.use(function(req, res, next) { + var err = new Error("Not Found"); + err.status = 404; + next(err); +}); + +// error handler +app.use(function(err, req, res, next) { + // set locals, only providing error in development + res.locals.message = err.message; + res.locals.error = req.app.get("env") === "development" ? err : {}; + + // render the error page + res.status(err.status || 500); + res.render("error"); +}); + +module.exports = app; diff --git a/bin/www b/bin/www new file mode 100644 index 0000000..22f988a --- /dev/null +++ b/bin/www @@ -0,0 +1,90 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var app = require('../app'); +var debug = require('debug')('project-what-have-you-done:server'); +var http = require('http'); + +/** + * Get port from environment and store in Express. + */ + +var port = normalizePort(process.env.PORT || '3000'); +app.set('port', port); + +/** + * Create HTTP server. + */ + +var server = http.createServer(app); + +/** + * Listen on provided port, on all network interfaces. + */ + +server.listen(port); +server.on('error', onError); +server.on('listening', onListening); + +/** + * Normalize a port into a number, string, or false. + */ + +function normalizePort(val) { + var port = parseInt(val, 10); + + if (isNaN(port)) { + // named pipe + return val; + } + + if (port >= 0) { + // port number + return port; + } + + return false; +} + +/** + * Event listener for HTTP server "error" event. + */ + +function onError(error) { + if (error.syscall !== 'listen') { + throw error; + } + + var bind = typeof port === 'string' + ? 'Pipe ' + port + : 'Port ' + port; + + // handle specific listen errors with friendly messages + switch (error.code) { + case 'EACCES': + console.error(bind + ' requires elevated privileges'); + process.exit(1); + break; + case 'EADDRINUSE': + console.error(bind + ' is already in use'); + process.exit(1); + break; + default: + throw error; + } +} + +/** + * Event listener for HTTP server "listening" event. + */ + +function onListening() { + var addr = server.address(); + var bind = typeof addr === 'string' + ? 'pipe ' + addr + : 'port ' + addr.port; + debug('Listening on ' + bind); +} diff --git a/helpers/helpers.js b/helpers/helpers.js new file mode 100644 index 0000000..64b8c7d --- /dev/null +++ b/helpers/helpers.js @@ -0,0 +1,13 @@ +var helpers = { + reps: function(items, options) { + var out = ""; + } +}; + +module.exports = helpers; \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/index.js @@ -0,0 +1 @@ + diff --git a/models/google.js b/models/google.js new file mode 100644 index 0000000..935d478 --- /dev/null +++ b/models/google.js @@ -0,0 +1,100 @@ +var request = require("request"); +var keys = require("C:/Users/Jared/Modules/Cles/items"); + +// Retrieves basic information about +// Necessary because part of original API shut down +var executeGoogleRequest = (line1, city, state, zip, callback) => { + + var address = `${line1} ${city} ${state} ${zip}`; + var officialArray = []; + var senateIndices = []; + var houseIndices = []; + var indexArray = []; + + // Options object, which gets passed to request call + var options = { + method: 'GET', + url: 'https://www.googleapis.com/civicinfo/v2/representatives', + qs: + { address: address, + includeOffices: 'true', + levels: 'country', + key: keys.google, + fields: 'offices(name,officialIndices),officials(name,party,urls,photoUrl,channels)' }, + headers: + { 'postman-token': keys.postmanToken, + 'cache-control': 'no-cache', + authorization: 'Basic ' + keys.googleBasic } }; + + request(options, function(error, response, body) { + if (error) throw new Error(error); + + + var APIerr = null; + if (response.statusCode !== 200 ) { + APIerr = `Invalid API Response: ${body}`; + callback(error, APIerr, null); + + } else { + // Parse response + var obj = JSON.parse(body); + + // For each INDEX in obj.offices - unknown quantity + var i = 0; + + while (i < (obj.offices.length)) { + // If the rep is in the Senate or House, add them to + // their respective arrays + if(obj['offices'][i]['name'] === "United States Senate") { + senateIndices = obj['offices'][i]['officialIndices']; + i++; + + } else if (obj['offices'][i]['name'].substring(0, 19) === "United States House") { + houseIndices = obj['offices'][i]['officialIndices']; + i++; + + } else { + i++; + } + } + indices = senateIndices.concat(houseIndices); + + // For each index in indices, go to officials[index] and grab info + indices.forEach(function(index) { + var officialInfo = { + name: obj.officials[index].name, + party: obj.officials[index].party, + siteURL: obj.officials[index].urls, + photoURL: obj.officials[index].photoUrl, + channels: obj.officials[index].channels + } + + + // Parse social media elsewhere? + // Get Twitter info if available, otherwise get FB info + var i; + for(i = 0; i < officialInfo.channels.length; i++) { + if(officialInfo.channels[i].type === "Twitter") { + officialInfo.twitter = obj.officials[index].channels[i].id.toLowerCase(); + } else if(officialInfo.channels[i].type === "Facebook") { + officialInfo.facebook = obj.officials[index].channels[i].id.toLowerCase(); + } else if(officialInfo.channels[i].type === "YouTube") { + officialInfo.youtube = obj.officials[index].channels[i].id.toLowerCase(); + } + } + // Delete channels property from officialInfo + // It's now unneccesary + delete officialInfo.channels; + // Push each official object into an array + officialArray.push(officialInfo); + }); + + callback(error, APIerr, officialArray); + } + + }); +}; + +module.exports = { + executeGoogleRequest +} diff --git a/models/init.js b/models/init.js new file mode 100644 index 0000000..98c5af1 --- /dev/null +++ b/models/init.js @@ -0,0 +1,27 @@ +var request = require("request"); +var keys = require("C:/Users/Jared/Modules/Cles/items"); +var line1 = "352 Woodford St."; +var city = "Portland"; +var state = "ME"; +var zip = "04103"; +var address = `${line1} ${city} ${state} ${zip}`; + +// Options object, which gets passed to request call +var options = { + method: 'GET', + url: 'https://www.googleapis.com/civicinfo/v2/representatives', + qs: + { address: address, + includeOffices: 'true', + levels: 'country', + key: keys.google }, + headers: + { 'postman-token': keys.postmanToken, + 'cache-control': 'no-cache', + authorization: 'Basic ' + keys.googleBasic } }; + +request(options, function (error, response, body) { + if (error) throw new Error(error); + + console.log(body); +}); diff --git a/models/officials.js b/models/officials.js new file mode 100644 index 0000000..b307e4b --- /dev/null +++ b/models/officials.js @@ -0,0 +1,18 @@ + +class Official { + constructor(name, party, urls, photo) { + this.name = name, + this.party = party, + this.url = urls, + this.photo = photo + } +} + +const officials = [ + // new Official... +]; + +module.exports = { + Official, + officials +}; diff --git a/models/propub.js b/models/propub.js new file mode 100644 index 0000000..5535f73 --- /dev/null +++ b/models/propub.js @@ -0,0 +1,85 @@ +var request = require("request"); +var async = require("async"); +var votes = require("./votes"); +var keys = require("C:/Users/Jared/Modules/Cles/items"); + +// officials is the object the other two apis have dealt with +var executeProPubRequest = (officials, callback) => { + // could also put executeProPubRequest inside loop for each official + async.forEachOf(officials, function(official, i, callbackTwo) { + + var options = { + method: 'GET', + url: "https://api.propublica.org/congress/v1/members/" + officials[i].bioID + "/votes.json", + headers: { 'x-api-key': keys.proPub }, + }; + + request(options, function(error, response, body) { + if (error) throw new Error(error); + + var APIerr = null; + if (response.statusCode !== 200 ) { + APIerr = `Invalid API Response: ${body}`; + callbackTwo(error, APIerr, null); + } else { + + var obj = JSON.parse(body); + // results[0] requires bracketed index + // because it's just a big wrapper + officials[i]['chamber'] = obj.results[0].votes[0].chamber; + officials[i]['votes']= []; + + // IIFE to push votes into votes array + let j; + for(j = 0; j <= 4; j++) { + let newVote = new votes.Vote(obj, j); + officials[i]['votes'].push(newVote); + } // closes for + } // closes else + callbackTwo(error, APIerr, null); + }); // closes request + // closes async +}, function(error, APIerr, officials) { + //console.log(officials); + console.log("done"); + callback(error, APIerr, officials); +}); + + // closes executeProPubRequest +}; + + + +var MEofficials = [ + { name: 'Susan M. Collins', + party: 'Republican', + siteURL: [ 'https://www.collins.senate.gov/' ], + photoURL: 'http://bioguide.congress.gov/bioguide/photo/C/C001035.jpg', + twitter: 'SenatorCollins', + bioID: "C001035" }, + { name: 'Angus S. King Jr.', + party: 'Independent', + siteURL: [ 'http://www.king.senate.gov/' ], + photoURL: 'http://king.senate.gov/imo/media/image/Senator-King-Official-thumb.png', + twitter: 'SenAngusKing', + bioID: "K000383" }, + { name: 'Chellie Pingree', + party: 'Democratic', + siteURL: [ 'http://pingree.house.gov/' ], + photoURL: 'http://bioguide.congress.gov/bioguide/photo/P/P000597.jpg', + twitter: 'chelliepingree', + bioID: 'P000597' } +]; + +executeProPubRequest(MEofficials, (error, APIerr, officialArray) => { + if (error) {throw err;} + if (APIerr) { + console.log(APIerr); + } else { + console.log(officialArray); + } +}); + +module.exports = { + executeProPubRequest +} diff --git a/models/usgithub.js b/models/usgithub.js new file mode 100644 index 0000000..71382ee --- /dev/null +++ b/models/usgithub.js @@ -0,0 +1,59 @@ +var request = require("request"); + +// officials parameter is array of information from last request +// This API call retrieves each representative's bioID based +// on social media account information. This info is checked +// through three possible social media routes - currently +// all representatives have one of the three +var executeUSGithubRequest = function(officials, callback) { + + var options = { + method: 'GET', + url: 'https://theunitedstates.io/congress-legislators/legislators-social-media.json', + }; + + request(options, function (error, response, body) { + if (error) throw new Error(error); + var APIerr = null; + if (response.statusCode !== 200 ) { + APIerr = `Invalid API Response: ${body}`; + callback(error, APIerr, null); + } else { + var obj = JSON.parse(body); + + // For each object in the officials array, find the matching + // 'official_full' property and assign it to a new bioID in + // the appropriate officials object + + var i; + var j; + for(i = 0; i <= (officials.length - 1); i++) { + for(j = 0; j <= obj.length; j++) { + if((officials[i].facebook) && (obj[j].social.facebook)){ + if(officials[i].facebook === obj[j].social.facebook.toLowerCase()) { + officials[i].bioID = obj[j].id.bioguide; + break; + } + } else if((officials[i].twitter) && (obj[j].social.twitter)) { + if(officials[i].twitter === obj[j].social.twitter.toLowerCase()) { + officials[i].bioID = obj[j].id.bioguide; + break; + } + } else if((officials[i].youtube) && (obj[j].social.youtube)) { + if(officials[i].youtube === obj[j].social.youtube.toLowerCase()) { + officials[i].bioID = obj[j].id.bioguide; + break; + } + } + } + } + + callback(error, APIerr, officials); + } + }); + +}; + +module.exports = { + executeUSGithubRequest +} diff --git a/models/usgithubtest.js b/models/usgithubtest.js new file mode 100644 index 0000000..160595a --- /dev/null +++ b/models/usgithubtest.js @@ -0,0 +1,88 @@ +var request = require("request"); + +var executeUSGithubRequest = function(officials, callback) { + + var options = { + method: 'GET', + url: 'https://theunitedstates.io/congress-legislators/legislators-social-media.json', + }; + + request(options, function (error, response, body) { + if (error) throw new Error(error); + var APIerr = null; + if (response.statusCode !== 200 ) { + APIerr = `Invalid API Response: ${body}`; + callback(error, APIerr, null); + } else { + var obj = JSON.parse(body); + + // For each object in the officials array, find the matching + // 'official_full' property and assign it to a new bioID in + // the appropriate officials object + + var i; + var j; + for(i = 0; i <= (officials.length - 1); i++) { + for(j = 0; j <= obj.length; j++) { + if((officials[i].facebook) && (obj[j].social.facebook)){ + if(officials[i].facebook === obj[j].social.facebook.toLowerCase()) { + officials[i].bioID = obj[j].id.bioguide; + break; + } + } else if((officials[i].twitter) && (obj[j].social.twitter)) { + if(officials[i].twitter === obj[j].social.twitter.toLowerCase()) { + officials[i].bioID = obj[j].id.bioguide; + break; + } + } else if((officials[i].youtube) && (obj[j].social.youtube)) { + if(officials[i].youtube === obj[j].social.youtube.toLowerCase()) { + officials[i].bioID = obj[j].id.bioguide; + break; + } + } + } + } + + callback(error, APIerr, officials); + } + }); + +}; + + +var MEofficials = [ { name: 'Susan M. Collins', + party: 'Republican', + siteURL: [ 'https://www.collins.senate.gov/' ], + photoURL: 'http://bioguide.congress.gov/bioguide/photo/C/C001035.jpg', + facebook: 'susancollins', + twitter: 'senatorcollins', + youtube: 'senatorsusancollins' }, + { name: 'Angus S. King Jr.', + party: 'Independent', + siteURL: [ 'http://www.king.senate.gov/' ], + photoURL: 'http://king.senate.gov/imo/media/image/Senator-King-Official-thumb.png', + facebook: 'senatorangusskingjr', + twitter: 'senangusking', + youtube: 'senatorangusking' }, + { name: 'Chellie Pingree', + party: 'Democratic', + siteURL: [ 'http://pingree.house.gov/' ], + photoURL: 'http://bioguide.congress.gov/bioguide/photo/P/P000597.jpg', + facebook: 'chelliepingree', + twitter: 'chelliepingree', + youtube: 'congresswomanpingree' } ] + + +executeUSGithubRequest(MEofficials, (error, APIerr, officialArray) => { + if (error) {throw err;} + if (APIerr) { + console.log(APIerr); + } else { + console.log(officialArray); + } +}); + + +module.exports = { + executeUSGithubRequest +} diff --git a/models/votes.js b/models/votes.js new file mode 100644 index 0000000..dac63f0 --- /dev/null +++ b/models/votes.js @@ -0,0 +1,18 @@ +class Vote { + constructor(obj, i) { + this.billNumber = obj.results[0].votes[i].bill.number; + this.description = obj.results[0].votes[i].description; + this.question = obj.results[0].votes[i].question; + this.result = obj.results[0].votes[i].result; + this.date = obj.results[0].votes[i].date; + this.time = obj.results[0].votes[i].time; + this.totalYes = obj.results[0].votes[i].total.yes; + this.totalNo = obj.results[0].votes[i].total.no; + this.notVoting = obj.results[0].votes[i].total.not_voting; + this.position = obj.results[0].votes[i].position; + } +} + +module.exports = { + Vote +} diff --git a/officials.js b/officials.js new file mode 100644 index 0000000..7bb54d7 --- /dev/null +++ b/officials.js @@ -0,0 +1,112 @@ + +// IIFE +// ================================================= + // for each official, execute the request and collect information + let i; + for(i = 0; i <= (officials.length - 1); i++) { + // IIFE + (function(i) { + var options = { + method: 'GET', + url: "https://api.propublica.org/congress/v1/members/" + officials[i].bioID + "/votes.json", + headers: { 'x-api-key': keys.proPub }, + }; + + request(options, function(error, response, body) { + if (error) throw new Error(error); + + var APIerr = null; + if (response.statusCode !== 200 ) { + APIerr = `Invalid API Response: ${response}`; + callback(error, APIerr, null); + } else { + + var obj = JSON.parse(body); + // assign chamber and init votes array + // results[0] requires bracketed index + // because it's just a big wrapper + officials[i]['chamber'] = obj.results[0].votes[0].chamber; + officials[i]['votes']= []; + + // specifically pushing 5 votes + let j; + for(j = 0; j <= 4; j++) { + (function(j) { + let newVote = new votes.Vote(obj, j); + officials[i]['votes'].push(newVote); + })(j); + } + + + + + callback(officials); + // closes request + }}); + // closes IIFE and invokes + })(i); + // closes for loop + } +// closes execute ProPub request +} + + + +// ASYNC.EACH +// ====================================================== + +var executeProPubRequest = (officials, callback) => { + var resultsArray = []; + // official is object with rep information + async.each(officials, function(official, callback) { + var options = { + method: 'GET', + url: "https://api.propublica.org/congress/v1/members/" + official.bioID + "/votes.json", + headers: { 'x-api-key': keys.proPub } + }; + + request(options, function(error, response, body) { + if (error) throw new Error(error); + + var APIerr = null; + if (response.statusCode !== 200 ) { + APIerr = `Invalid API Response: ${response}`; + callback(error, APIerr, null); + } else { + + var obj = JSON.parse(body); + // assign chamber and init votes array + // results[0] requires bracketed index + // because it's just a big wrapper + official['chamber'] = obj.results[0].votes[0].chamber; + official['votes']= []; + + // specifically pushing 5 votes + let j; + for(j = 0; j <= 4; j++) { + (function(j) { + let newVote = new votes.Vote(obj, j); + official['votes'].push(newVote); + })(j); + } + // closes else + } + resultsArray.push(official); + // runs at end of every loop iteration + callback(); + // closes request + }), + + // intermediate callback + function(err) { + // if err + if(err) { console.log(err); } + callback(resultsArray); + }; + // closes async.each + }); + + }; + + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..de01025 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1091 @@ +{ + "name": "project-what-have-you-done", + "version": "0.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/express": { + "version": "https://registry.npmjs.org/@types/express/-/express-4.0.37.tgz", + "integrity": "sha1-YlrDdlFpZ24BiXykcBHCY3V4SXE=", + "requires": { + "@types/express-serve-static-core": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.0.53.tgz", + "@types/serve-static": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.7.32.tgz" + } + }, + "@types/express-serve-static-core": { + "version": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.0.53.tgz", + "integrity": "sha1-FyOjXRRH8sVeE8hyHqs0SOQvTYI=", + "requires": { + "@types/node": "https://registry.npmjs.org/@types/node/-/node-8.0.46.tgz" + } + }, + "@types/mime": { + "version": "https://registry.npmjs.org/@types/mime/-/mime-2.0.0.tgz", + "integrity": "sha1-WnMG42fFObn2VDSZ3o3VGfrDeos=" + }, + "@types/node": { + "version": "https://registry.npmjs.org/@types/node/-/node-8.0.46.tgz", + "integrity": "sha1-bhdmstDtBmMdW1+Hu45yyNu2iI4=" + }, + "@types/serve-static": { + "version": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.7.32.tgz", + "integrity": "sha1-D2cy5NqwgTdx3Y/I/hSUDzRyi0w=", + "requires": { + "@types/express-serve-static-core": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.0.53.tgz", + "@types/mime": "https://registry.npmjs.org/@types/mime/-/mime-2.0.0.tgz" + } + }, + "accepts": { + "version": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", + "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", + "requires": { + "mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "negotiator": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz" + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "align-text": { + "version": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "longest": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" + } + }, + "amdefine": { + "version": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "array-flatten": { + "version": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "async": { + "version": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha1-YaKau2/MAm/qd+VtHG7FOnlZUfQ=", + "requires": { + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "basic-auth": { + "version": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", + "integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=" + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "body-parser": { + "version": "https://registry.npmjs.org/body-parser/-/body-parser-1.17.2.tgz", + "integrity": "sha1-+IkqvI+eYn1Crtr7yma/WrmRBO4=", + "requires": { + "bytes": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "content-type": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", + "depd": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", + "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "qs": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "raw-body": "https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz", + "type-is": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz" + }, + "dependencies": { + "debug": { + "version": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", + "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4=", + "requires": { + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + } + } + } + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "requires": { + "hoek": "4.2.0" + } + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "bytes": { + "version": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=" + }, + "camelcase": { + "version": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "optional": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "center-align": { + "version": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "optional": true, + "requires": { + "align-text": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "lazy-cache": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz" + } + }, + "cliui": { + "version": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "optional": true, + "requires": { + "center-align": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "right-align": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "wordwrap": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" + }, + "dependencies": { + "wordwrap": { + "version": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "optional": true + } + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "content-disposition": { + "version": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=" + }, + "cookie": { + "version": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-parser": { + "version": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.3.tgz", + "integrity": "sha1-D+MfoZ0AC5X0qt8fU/3CuKIDuqU=", + "requires": { + "cookie": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "cookie-signature": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + } + }, + "cookie-signature": { + "version": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "requires": { + "hoek": "4.2.0" + } + } + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "debug": { + "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + } + }, + "decamelize": { + "version": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "optional": true + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.11" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "depd": { + "version": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + }, + "destroy": { + "version": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "ee-first": { + "version": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "encodeurl": { + "version": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", + "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=" + }, + "escape-html": { + "version": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "etag": { + "version": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "express": { + "version": "https://registry.npmjs.org/express/-/express-4.15.5.tgz", + "integrity": "sha1-ZwI1ypWYiQpa6BcLg9tyK4Qu2Sc=", + "requires": { + "accepts": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", + "array-flatten": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "content-disposition": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "content-type": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "cookie": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "cookie-signature": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "depd": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "encodeurl": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", + "escape-html": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "etag": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "finalhandler": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.6.tgz", + "fresh": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "merge-descriptors": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "methods": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "path-to-regexp": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "proxy-addr": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.5.tgz", + "qs": "https://registry.npmjs.org/qs/-/qs-6.5.0.tgz", + "range-parser": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "send": "https://registry.npmjs.org/send/-/send-0.15.6.tgz", + "serve-static": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.6.tgz", + "setprototypeof": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "statuses": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "type-is": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", + "utils-merge": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "vary": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" + }, + "dependencies": { + "qs": { + "version": "https://registry.npmjs.org/qs/-/qs-6.5.0.tgz", + "integrity": "sha1-jQSVTTZN7z78VbWgeT4eLIsebkk=" + } + } + }, + "express-handlebars": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/express-handlebars/-/express-handlebars-3.0.0.tgz", + "integrity": "sha1-gKBwu4GbCeSvLKbQeA91zgXnXC8=", + "requires": { + "glob": "6.0.4", + "graceful-fs": "4.1.11", + "handlebars": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.5.tgz", + "object.assign": "4.1.0", + "promise": "7.3.1" + } + }, + "express-validator": { + "version": "https://registry.npmjs.org/express-validator/-/express-validator-4.2.1.tgz", + "integrity": "sha1-MpAUsuZ1O8wHy9LJ/T/IzsCKDis=", + "requires": { + "@types/express": "https://registry.npmjs.org/@types/express/-/express-4.0.37.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "validator": "https://registry.npmjs.org/validator/-/validator-8.2.0.tgz" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "finalhandler": { + "version": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.6.tgz", + "integrity": "sha1-AHrqM9Gk0+QgF/YkhIrVjSEvgU8=", + "requires": { + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "encodeurl": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", + "escape-html": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "statuses": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "unpipe": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + }, + "foreachasync": { + "version": "https://registry.npmjs.org/foreachasync/-/foreachasync-3.0.0.tgz", + "integrity": "sha1-VQKYfchxS+M5IJfzLgBxyd7gfPY=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", + "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz" + } + }, + "forwarded": { + "version": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "requires": { + "inflight": "1.0.6", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "handlebars": { + "version": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.5.tgz", + "integrity": "sha1-ksbta7FkEQxQ1NjQ+93HCAbG+Oc=", + "requires": { + "async": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "optimist": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "uglify-js": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz" + }, + "dependencies": { + "async": { + "version": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.0", + "sntp": "2.1.0" + } + }, + "hbs": { + "version": "https://registry.npmjs.org/hbs/-/hbs-4.0.1.tgz", + "integrity": "sha1-S/2YZQ3IydrESzyprfnAmOi8M7Y=", + "requires": { + "handlebars": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.5.tgz", + "walk": "https://registry.npmjs.org/walk/-/walk-2.3.9.tgz" + } + }, + "hoek": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" + }, + "http-errors": { + "version": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "requires": { + "depd": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "setprototypeof": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "statuses": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "iconv-lite": { + "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", + "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ipaddr.js": { + "version": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.4.0.tgz", + "integrity": "sha1-KWrKh4qCGBbluF0KKFqZvP9FgvA=" + }, + "is-buffer": { + "version": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kind-of": { + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz" + } + }, + "lazy-cache": { + "version": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "optional": true + }, + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + }, + "longest": { + "version": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, + "media-typer": { + "version": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=" + }, + "mime-db": { + "version": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" + }, + "mime-types": { + "version": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "requires": { + "mime-db": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" + }, + "morgan": { + "version": "https://registry.npmjs.org/morgan/-/morgan-1.8.2.tgz", + "integrity": "sha1-eErHc05KRTqcbm6GgKkyknXItoc=", + "requires": { + "basic-auth": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "depd": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "on-headers": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" + }, + "dependencies": { + "debug": { + "version": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "requires": { + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + } + } + } + }, + "ms": { + "version": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "negotiator": { + "version": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=" + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "requires": { + "define-properties": "1.1.2", + "function-bind": "1.1.1", + "has-symbols": "1.0.0", + "object-keys": "1.0.11" + } + }, + "on-finished": { + "version": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + } + }, + "on-headers": { + "version": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "optimist": { + "version": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "requires": { + "minimist": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "wordwrap": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz" + } + }, + "parseurl": { + "version": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-to-regexp": { + "version": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "2.0.6" + } + }, + "proxy-addr": { + "version": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.5.tgz", + "integrity": "sha1-ccDuOxAt4/IC87ZPYI0XP8uhqRg=", + "requires": { + "forwarded": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "ipaddr.js": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.4.0.tgz" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=" + }, + "range-parser": { + "version": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz", + "integrity": "sha1-mUl2z2pQlqQRYoQEkvC9xdbn+5Y=", + "requires": { + "bytes": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", + "unpipe": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + } + }, + "repeat-string": { + "version": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "request": { + "version": "2.83.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", + "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.1", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" + }, + "dependencies": { + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + } + } + }, + "right-align": { + "version": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "optional": true, + "requires": { + "align-text": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz" + } + }, + "safe-buffer": { + "version": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=" + }, + "send": { + "version": "https://registry.npmjs.org/send/-/send-0.15.6.tgz", + "integrity": "sha1-IPI6nJJbdiq4JwX+L52yUqzkfjQ=", + "requires": { + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "depd": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "destroy": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "encodeurl": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", + "escape-html": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "etag": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "fresh": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "mime": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "range-parser": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "statuses": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz" + } + }, + "serve-favicon": { + "version": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.4.5.tgz", + "integrity": "sha1-SdmkaGMVOpJAaRyJPSsOfYXW1DY=", + "requires": { + "etag": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "fresh": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + } + }, + "serve-static": { + "version": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.6.tgz", + "integrity": "sha1-uXN3P2NEmTTaVOW+ul4x2fQhFXc=", + "requires": { + "encodeurl": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", + "escape-html": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "send": "https://registry.npmjs.org/send/-/send-0.15.6.tgz" + } + }, + "setprototypeof": { + "version": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "requires": { + "hoek": "4.2.0" + } + }, + "source-map": { + "version": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "requires": { + "amdefine": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz" + } + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } + }, + "statuses": { + "version": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "type-is": { + "version": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", + "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", + "requires": { + "media-typer": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz" + } + }, + "uglify-js": { + "version": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "optional": true, + "requires": { + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "uglify-to-browserify": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "yargs": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz" + }, + "dependencies": { + "source-map": { + "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "optional": true + } + } + }, + "uglify-to-browserify": { + "version": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "optional": true + }, + "underscore": { + "version": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "unpipe": { + "version": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "utils-merge": { + "version": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=" + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" + }, + "validator": { + "version": "https://registry.npmjs.org/validator/-/validator-8.2.0.tgz", + "integrity": "sha1-PBI3KQ43CSNVNE/veMIxJJ2rd7k=" + }, + "vary": { + "version": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "walk": { + "version": "https://registry.npmjs.org/walk/-/walk-2.3.9.tgz", + "integrity": "sha1-MbTbZnjyrgHDnqn7hyWpAx5Vins=", + "requires": { + "foreachasync": "https://registry.npmjs.org/foreachasync/-/foreachasync-3.0.0.tgz" + } + }, + "window-size": { + "version": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "optional": true + }, + "wordwrap": { + "version": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "yargs": { + "version": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "optional": true, + "requires": { + "camelcase": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "cliui": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "decamelize": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "window-size": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..b3bd255 --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "project-what-have-you-done", + "version": "0.0.0", + "private": true, + "scripts": { + "start": "node ./bin/www" + }, + "dependencies": { + "async": "^2.6.0", + "body-parser": "~1.17.1", + "cookie-parser": "~1.4.3", + "debug": "~2.6.3", + "express": "~4.15.2", + "express-handlebars": "^3.0.0", + "express-validator": "^4.2.1", + "hbs": "~4.0.1", + "morgan": "~1.8.1", + "request": "^2.83.0", + "serve-favicon": "~2.4.2", + "underscore": "^1.8.3" + } +} diff --git a/protest.js b/protest.js new file mode 100644 index 0000000..adbbca7 --- /dev/null +++ b/protest.js @@ -0,0 +1,102 @@ +var request = require("request"); +var votes = require("./models/votes"); +var keys = require("C:/Users/Jared/Modules/Cles/items"); +var async = require('async'); + +// officials is the object the other two apis have dealt with +// Retreive votes from Propublica API +var executeProPubRequest = (officials, indexCallback) => { + async.map(officials, + + // For each official, retrieve chamber and votes + // Results returned to second callback + function(official, doneCallback) { + var options = { + method: 'GET', + url: "https://api.propublica.org/congress/v1/members/" + official.bioID + "/votes.json", + headers: { 'x-api-key': keys.proPub } + }; + + // Actual API request + request(options, function(error, response, body) { + if (error) throw new Error(error); + var APIerr = null; + // callback + if (response.statusCode !== 200 ) { + APIerr = `Invalid API Response: ${response}`; + // fix + //callback(error, APIerr, null); + } else { + var obj = JSON.parse(body); + + // assign chamber and init votes array + // results[0] requires bracketed index + // because it's just a big wrapper + official['chamber'] = obj.results[0].votes[0].chamber; + official['votes']= []; + + // specifically pushing 5 votes + let j; + for(j = 0; j <= 4; j++) { + (function(j) { + let newVote = new votes.Vote(obj, j); + official['votes'].push(newVote); + })(j); + } + // closes else + } + + // return completed official item + return doneCallback(null, official); + // closes request + }); + // closes iterator callback + }, + + // callback once each item has finished + function(err, results) { + if(err) { console.log(err); } + indexCallback(results); + } + + // closes async.map + ); + + +// closes executeProPubRequest +}; + + +// var MEofficials = [ +// { name: 'Susan M. Collins', +// party: 'Republican', +// siteURL: [ 'https://www.collins.senate.gov/' ], +// photoURL: 'http://bioguide.congress.gov/bioguide/photo/C/C001035.jpg', +// facebook: 'susancollins', +// twitter: 'senatorcollins', +// youtube: 'senatorsusancollins', +// bioID: 'C001035' }, +// { name: 'Angus S. King Jr.', +// party: 'Independent', +// siteURL: [ 'http://www.king.senate.gov/' ], +// photoURL: 'http://king.senate.gov/imo/media/image/Senator-King-Official-thumb.png', +// facebook: 'senatorangusskingjr', +// twitter: 'senangusking', +// youtube: 'senatorangusking', +// bioID: 'K000383' }, +// { name: 'Chellie Pingree', +// party: 'Democratic', +// siteURL: [ 'http://pingree.house.gov/' ], +// photoURL: 'http://bioguide.congress.gov/bioguide/photo/P/P000597.jpg', +// facebook: 'chelliepingree', +// twitter: 'chelliepingree', +// youtube: 'congresswomanpingree', +// bioID: 'P000597' } ]; + +// executeProPubRequest(MEofficials, (officialArray) => { +// console.log(officialArray); +// }); + +module.exports = { + executeProPubRequest +}; diff --git a/public/javascripts/scripts.js b/public/javascripts/scripts.js new file mode 100644 index 0000000..e69de29 diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css new file mode 100644 index 0000000..170741a --- /dev/null +++ b/public/stylesheets/style.css @@ -0,0 +1,36 @@ +body { + padding: 50px; + font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; + background-color: lightgray; +} + +a { + color: #00B7FF; +} + +h1 { + font-weight: bolder; +} + +.greeting-text { + background-color: #054e81; + color: ivory; + box-shadow: 0px 2px gray; +} + +.container { + box-shadow: 0px 0px 1px 1px gray; +} + +.form-box { + background-color: #066cb3; + color: ivory; +} + +form { + height: 350px; +} + +.form-control { + background-color: ivory; +} diff --git a/routes/index.js b/routes/index.js new file mode 100644 index 0000000..ef013cc --- /dev/null +++ b/routes/index.js @@ -0,0 +1,47 @@ +var express = require('express'); +var cookieParser = require('cookie-parser'); +var router = express.Router(); +var google = require('../models/google'); +var usIDs = require('../models/usgithub'); +var propub = require('../protest'); + +/* GET home page. */ +router.get('/', function(req, res, next) { + res.render('home', { title: 'Find Your Representative' }); +}); + + +/* On submit, send object results */ +router.get('/results', function(req, res, next) { + var address = req.query; + + // CALL API HERE + google.executeGoogleRequest(address.firstline, address.city, address.state, address.zip, function(error, APIerr, officialArray) { + if (error) { throw error; } + else if (APIerr) { + console.log(APIerr); + } else { + // CALL SECOND API HERE + usIDs.executeUSGithubRequest(officialArray, function(error, APIerr, offficialArray) { + if (error) { throw error; } + else if (APIerr) { + console.log(APIerr); + } else { + + // CALL THIRD API HERE + propub.executeProPubRequest(officialArray, function(officialArray) { + if (error) { throw error; } + else if (APIerr) { + console.log(APIerr); + } else { + // console.dir(officialArray[0].votes); + res.render('results', { officialArray: officialArray }); + } + }); + }; + }); + } + }); +}); + +module.exports = router; diff --git a/routes/users.js b/routes/users.js new file mode 100644 index 0000000..623e430 --- /dev/null +++ b/routes/users.js @@ -0,0 +1,9 @@ +var express = require('express'); +var router = express.Router(); + +/* GET users listing. */ +router.get('/', function(req, res, next) { + res.send('respond with a resource'); +}); + +module.exports = router; diff --git a/test.js b/test.js new file mode 100644 index 0000000..5026bdb --- /dev/null +++ b/test.js @@ -0,0 +1,110 @@ +var request = require("request"); +var keys = require("C:/Users/Jared/Modules/Cles/items"); + +// change to double quotes - jshint? + +var executeGoogleRequest = (line1, city, state, zip, callback) => { + + var address = `${line1} ${city} ${state} ${zip}`; + var officialArray = []; + var senateIndices = []; + var houseIndices = []; + var indexArray = []; + + // Options object, which gets passed to request call + var options = { + method: 'GET', + url: 'https://www.googleapis.com/civicinfo/v2/representatives', + qs: + { address: address, + includeOffices: 'true', + levels: 'country', + key: keys.google, + fields: 'offices(name,officialIndices),officials(name,party,urls,photoUrl,channels)' }, + headers: + { 'postman-token': keys.postmanToken, + 'cache-control': 'no-cache', + authorization: 'Basic ' + keys.googleBasic } }; + + request(options, function(error, response, body) { + if (error) throw new Error(error); + + + var APIerr = null; + if (response.statusCode !== 200 ) { + APIerr = `Invalid API Response: ${body}`; + callback(error, APIerr, null); + } else { + + var obj = JSON.parse(body); + // For each INDEX in obj.offices - unknown quantity + var i = 0; + while (i < (obj.offices.length)) { + // If the rep is in the Senate or House, add them to + // their respective arrays + if(obj['offices'][i]['name'] === "United States Senate") { + senateIndices = obj['offices'][i]['officialIndices']; + i++; + } else if (obj['offices'][i]['name'].substring(0, 19) === "United States House") { + houseIndices = obj['offices'][i]['officialIndices']; + i++; + } else { + i++; + } + } + indices = senateIndices.concat(houseIndices); + + // For each index in indices, go to officials[index] and grab info + indices.forEach(function(index) { + var officialInfo = { + name: obj.officials[index].name, + party: obj.officials[index].party, + siteURL: obj.officials[index].urls, + photoURL: obj.officials[index].photoUrl, + channels: obj.officials[index].channels + } + + + + // Get Twitter info if available, otherwise get FB info + var i; + for(i = 0; i < officialInfo.channels.length; i++) { + if(officialInfo.channels[i].type === "Twitter") { + officialInfo.twitter = obj.officials[index].channels[i].id.toLowerCase(); + } else if(officialInfo.channels[i].type === "Facebook") { + officialInfo.facebook = obj.officials[index].channels[i].id.toLowerCase(); + } else if(officialInfo.channels[i].type === "YouTube") { + officialInfo.youtube = obj.officials[index].channels[i].id.toLowerCase(); + } + } + // Delete channels property from officialInfo + // It's now unneccesary + delete officialInfo.channels; + // Push each official object into an array + officialArray.push(officialInfo); + + }); + + callback(error, APIerr, officialArray); + } + + }); +}; + +var exampleLine = "352 Woodford St."; +var exampleCity = "Portland"; +var exampleState = "ME"; +var exampleZip = "04103"; + +executeGoogleRequest(exampleLine, exampleCity, exampleState, exampleZip, function(error, APIerr, officialArray) { + if (error) {throw err;} + if (APIerr) { + console.log(APIerr); + } else { + console.log(officialArray); + } +}); + +module.exports = { + executeGoogleRequest +} \ No newline at end of file diff --git a/views/error.handlebars b/views/error.handlebars new file mode 100644 index 0000000..0659765 --- /dev/null +++ b/views/error.handlebars @@ -0,0 +1,3 @@ +

{{message}}

+

{{error.status}}

+
{{error.stack}}
diff --git a/views/home.handlebars b/views/home.handlebars new file mode 100644 index 0000000..17e84b4 --- /dev/null +++ b/views/home.handlebars @@ -0,0 +1,36 @@ +
+
+

{{title}}

+

Enter your address to display a list of your Congressional representatives and recent bills they have voted on.

+
+
+
+
+ +
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+
+
+
diff --git a/views/layouts/main.handlebars b/views/layouts/main.handlebars new file mode 100644 index 0000000..a891930 --- /dev/null +++ b/views/layouts/main.handlebars @@ -0,0 +1,23 @@ + + + + {{title}} + + + + + +
+ + {{{body}}} + +
+ + diff --git a/views/results.handlebars b/views/results.handlebars new file mode 100644 index 0000000..8d22d71 --- /dev/null +++ b/views/results.handlebars @@ -0,0 +1,29 @@ +

Your Representatives

+ + +{{#each officialArray}} + {{this.name}} + {{this.party}} + {{this.siteURL}} + {{this.photoURL}} + {{this.bioID}} +{{/each}} +
+{{!-- {{#reps officialArray}} + {{name}} +{{/reps}} --}} + +{{foo}} + +{{#each votes as |vote|}} + {{vote.billNumber}} + {{vote.description}} + {{vote.question}} + {{vote.result}} + {{vote.date}} + {{vote.time}} + {{vote.totalYes}} + {{vote.totalNo}} + {{vote.notVoting}} + {{vote.position}} +{{/each}} \ No newline at end of file