diff --git a/README.md b/README.md
index 6dcc8a7..60a453f 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,11 @@
# 8 Step - React/Redux tutorial series
-This example application created by [getstream.io](https://getstream.io/?ref=github_stream_react_example) teaches you how to to build an Instagram style application with activity streams and newsfeeds.
+This example application created by [getstream.io](https://getstream.io/?ref=github_stream_react_example) teaches you how to to build an Instagram style application with activity streams and newsfeeds.
Visit [cabin.getstream.io](http://cabin.getstream.io/) for an overview of all 8 tutorials and a [live demo](http://cabin.getstream.io/demo). If you enjoy this tutorial please star this repo.
+> Note: Cabin requires Node v8.x or above.
+
@@ -27,3 +29,51 @@ Visit [cabin.getstream.io](http://cabin.getstream.io/) for an overview of all 8
* [Mapbox](https://www.mapbox.com/)
* [Digital Ocean](https://www.digitalocean.com/)
* [Stream](https://getstream.io)
+
+## Quick start
+
+This quick start is a minimal set of instructions for experienced developers
+and folks who have already setup their development environment in the past.
+
+For beginners and those new to the project, we strongly recommend starting with
+the introductory [Cabin – React & Redux Example App – Introduction](https://getstream.io/blog/cabin-react-redux-example-app-introduction/) blog post.
+
+Note: Paths below are relative to the root project directory.
+
+### 0. Setup
+1. Install the API package dependencies:
+ ``` bash
+ cd ./api && npm install
+ ```
+
+2. Install the App package dependencies:
+ ``` bash
+ cd ./app && npm install
+ ```
+
+3. Install a database server (if necessary) and create a database.
+4. Set local environment configuration in the `.env` environment.
+
+### 1. Run the API
+1. Start your database server
+2. Run the following shell command:
+ ``` bash
+ cd ./api
+ source ../env.sh; node index.js
+ ```
+
+### 2. Run the App
+1. Run the following shell command:
+ ``` bash
+ cd ./app
+ source ../env.sh; webpack --watch --progress
+ ```
+
+### 3. Run the Website
+1. Run the following shell command:
+ ``` bash
+ npm start
+ ```
+
+### 4. Win.
+1. Browse to `http://localhost:3000`.
diff --git a/api/config.js b/api/config.js
index e6a3934..bda35ec 100644
--- a/api/config.js
+++ b/api/config.js
@@ -4,41 +4,41 @@
* Config
*/
module.exports = {
- name: 'GetStream.io - React Example App',
- version: '1.0.0',
- env: process.env.NODE_ENV || 'development',
- port: process.env.PORT || 8000,
- jwt: {
- secret: process.env.JWT_SECRET,
- },
- db: {
- name: 'cabin',
- username: process.env.DB_USERNAME,
- password: process.env.DB_PASSWORD,
- host: process.env.DB_HOST,
- port: process.env.DB_PORT,
- },
- mapbox: {
- accessToken: process.env.MAPBOX_ACCESS_TOKEN,
- },
- s3: {
- key: process.env.S3_KEY,
- secret: process.env.S3_SECRET,
- bucket: process.env.S3_BUCKET,
- },
- stream: {
- appId: process.env.STREAM_APP_ID,
- key: process.env.STREAM_KEY,
- secret: process.env.STREAM_SECRET,
- },
- algolia: {
- appId: process.env.ALGOLIA_APP_ID,
- searchOnlyKey: process.env.ALGOLIA_SEARCH_ONLY_KEY,
- apiKey: process.env.ALGOLIA_API_KEY,
- },
- keen: {
- projectId: process.env.KEEN_PROJECT_ID,
- writeKey: process.env.KEEN_WRITE_KEY,
- readKey: process.env.KEEN_READ_KEY,
- },
+ name: 'GetStream.io - React Example App',
+ version: '1.0.0',
+ env: process.env.NODE_ENV || 'development',
+ port: process.env.PORT || 8000,
+ jwt: {
+ secret: process.env.JWT_SECRET,
+ },
+ db: {
+ name: 'cabin',
+ username: process.env.DB_USERNAME,
+ password: process.env.DB_PASSWORD,
+ host: process.env.DB_HOST,
+ port: process.env.DB_PORT,
+ },
+ mapbox: {
+ accessToken: process.env.MAPBOX_ACCESS_TOKEN,
+ },
+ s3: {
+ key: process.env.S3_KEY,
+ secret: process.env.S3_SECRET,
+ bucket: process.env.S3_BUCKET,
+ },
+ stream: {
+ appId: process.env.STREAM_APP_ID,
+ key: process.env.STREAM_KEY,
+ secret: process.env.STREAM_SECRET,
+ },
+ algolia: {
+ appId: process.env.ALGOLIA_APP_ID,
+ searchOnlyKey: process.env.ALGOLIA_SEARCH_ONLY_KEY,
+ apiKey: process.env.ALGOLIA_API_KEY,
+ },
+ keen: {
+ projectId: process.env.KEEN_PROJECT_ID,
+ writeKey: process.env.KEEN_WRITE_KEY,
+ readKey: process.env.KEEN_READ_KEY,
+ },
};
diff --git a/api/index.js b/api/index.js
index e329a7d..6d0022c 100644
--- a/api/index.js
+++ b/api/index.js
@@ -3,101 +3,104 @@
/**
* Module Dependencies
*/
-var config = require('./config'),
- bunyan = require('bunyan'),
- winston = require('winston'),
- bunyanWinston = require('bunyan-winston-adapter'),
- mysql = require('mysql'),
- jwt = require('restify-jwt'),
- Mail = require('winston-mail').Mail,
- Sentry = require('winston-sentry');
+var config = require('./config'),
+ bunyan = require('bunyan'),
+ winston = require('winston'),
+ bunyanWinston = require('bunyan-winston-adapter'),
+ mysql = require('mysql'),
+ jwt = require('restify-jwt'),
+ Mail = require('winston-mail').Mail,
+ Sentry = require('winston-sentry'),
+ restifyPlugins = require('restify-plugins');
/**
* Global Dependencies
*/
-global.__base = __dirname + '/';
-global.config = require('./config.js');
+global.__base = __dirname + '/';
+global.config = require('./config.js');
global.restify = require('restify');
/**
* Transports (Logging)
*/
var transports = [
- new winston.transports.Console({
- level: 'info',
- timestamp: function() {
- return new Date().toString();
- },
- json: true
- })
+ new winston.transports.Console({
+ level: 'info',
+ timestamp: function() {
+ return new Date().toString();
+ },
+ json: true,
+ }),
];
/**
* Sentry Transport (Logging)
*/
if (process.env.SENTRY) {
- new winston.transports.Console({ level: 'silly' }),
- new Sentry({
- patchGlobal: true,
- dsn: process.env.SENTRY,
- })
+ new winston.transports.Console({ level: 'silly' }), new Sentry({
+ patchGlobal: true,
+ dsn: process.env.SENTRY,
+ });
}
/**
* Logging
*/
global.log = new winston.Logger({
- transports: transports
+ transports: transports,
});
/**
* Initialize Server
*/
global.server = restify.createServer({
- name : config.name,
- version : config.version,
- log : bunyanWinston.createAdapter(log),
+ name: config.name,
+ version: config.version,
+ log: bunyanWinston.createAdapter(log),
});
/**
* Middleware
*/
-server.use(restify.bodyParser());
-server.use(restify.acceptParser(server.acceptable));
-server.use(restify.authorizationParser());
-server.use(restify.queryParser({ mapParams: true }));
+server.use(restifyPlugins.jsonBodyParser({ mapParams: true }));
+server.use(restifyPlugins.acceptParser(server.acceptable));
+server.use(restifyPlugins.queryParser({ mapParams: true }));
+server.use(restifyPlugins.multipartBodyParser());
server.pre(require('./lib/cors')());
-server.use(restify.fullResponse());
-server.use(jwt({ secret: config.jwt.secret }).unless({
- path: ['/users']
-}));
+server.use(restifyPlugins.fullResponse());
+server.use(
+ jwt({ secret: config.jwt.secret }).unless({
+ path: ['/users'],
+ }),
+);
/**
* Initialize MySQL Connection
*/
global.db = mysql.createConnection({
- host : config.db.host,
- user : config.db.username,
- password : config.db.password,
- database : config.db.name,
- timezone: 'UTC'
+ port: config.db.port,
+ host: config.db.host,
+ user: config.db.username,
+ password: config.db.password,
+ database: config.db.name,
+ timezone: 'UTC',
});
db.connect();
db.query(`
SET sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
-`)
+`);
/**
* Boot
*/
-server.listen(config.port, function () {
- require('./routes');
- log.info(
- '%s v%s ready to accept connections on port listening on port %s in %s environment',
- server.name,
- config.version,
- config.port,
- config.env
- );
+server.listen(config.port, function() {
+ require('./routes');
+ log.info(
+ '%s v%s ready to accept connections on port listening on port %s in %s environment',
+ server.name,
+ config.version,
+ config.port,
+ config.env,
+ );
});
diff --git a/api/lib/cors/index.js b/api/lib/cors/index.js
index 42d330f..8024a11 100644
--- a/api/lib/cors/index.js
+++ b/api/lib/cors/index.js
@@ -1,42 +1,61 @@
-'use strict';
-
function cors(options) {
-
- const defaultAllowHeaders = ['Authorization', 'Content-Type'];
- const defaultAllowMethods = ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD"];
-
- const opts = Object.assign({}, {
- allowHeaders: defaultAllowHeaders,
- allowMethods: defaultAllowMethods,
- allowOrigins: null,
- allowCreds: true,
- }, options || {});
-
- const setHeader = (req, res, methods) => {
- const origin = req.headers.origin;
- const requestMethod = req.headers['access-control-request-method'];
- const requestHeaders = req.headers['access-control-request-headers'];
-
- res.once('header', () => {
- if (opts.allowCreds) res.header('Access-Control-Allow-Credentials', 'true');
-
- if (opts.allowOrigins) {
- res.header('Access-Control-Allow-Origin',
- (Array.isArray(opts.allowOrigins)) ? opts.allowOrigins.join(', ') : opts.allowOrigins);
- } else {
- res.header('Access-Control-Allow-Origin', origin);
- }
-
- res.header('Access-Control-Allow-Methods', opts.allowMethods.join(', '));
- res.header('Access-Control-Allow-Headers', opts.allowHeaders.map(h => h.toUpperCase()).join(', '));
- });
- };
-
- return (req, res, next) => {
- setHeader(req, res);
- if (req.method == 'OPTIONS') return res.send(200);
- return next();
- };
-};
+ const defaultAllowHeaders = ['Authorization', 'Content-Type'];
+ const defaultAllowMethods = [
+ 'GET',
+ 'POST',
+ 'PUT',
+ 'DELETE',
+ 'PATCH',
+ 'HEAD',
+ ];
+
+ const opts = Object.assign(
+ {},
+ {
+ allowHeaders: defaultAllowHeaders,
+ allowMethods: defaultAllowMethods,
+ allowOrigins: null,
+ allowCreds: true,
+ },
+ options || {},
+ );
+
+ const setHeader = (req, res, methods) => {
+ const origin = req.headers.origin;
+ const requestMethod = req.headers['access-control-request-method'];
+ const requestHeaders = req.headers['access-control-request-headers'];
+
+ res.once('header', () => {
+ if (opts.allowCreds)
+ res.header('Access-Control-Allow-Credentials', 'true');
+
+ if (opts.allowOrigins) {
+ res.header(
+ 'Access-Control-Allow-Origin',
+ Array.isArray(opts.allowOrigins)
+ ? opts.allowOrigins.join(', ')
+ : opts.allowOrigins,
+ );
+ } else {
+ res.header('Access-Control-Allow-Origin', origin);
+ }
+
+ res.header(
+ 'Access-Control-Allow-Methods',
+ opts.allowMethods.join(', '),
+ );
+ res.header(
+ 'Access-Control-Allow-Headers',
+ opts.allowHeaders.map(h => h.toUpperCase()).join(', '),
+ );
+ });
+ };
+
+ return (req, res, next) => {
+ setHeader(req, res);
+ if (req.method == 'OPTIONS') return res.send(200);
+ return next();
+ };
+}
module.exports = cors;
diff --git a/api/lib/stream_utils/index.js b/api/lib/stream_utils/index.js
index 8f8543d..84ea5ae 100644
--- a/api/lib/stream_utils/index.js
+++ b/api/lib/stream_utils/index.js
@@ -1,40 +1,39 @@
-'use strict';
var async = require('async');
function referencesFromActivities(activitiesOrNotifications) {
- /*
+ /*
Returns the references from a list of activities
*/
- var references = {}
- activitiesOrNotifications.forEach(function(item) {
- var activities = (item.activities) ? item.activities : [
- item
- ];
- activities.forEach(function(activity) {
- Object.keys(activity).forEach(function(key) {
- if (activity[key] && activity[key].indexOf && activity[key].indexOf(':') != -1) {
- var parts = activity[key].split(':');
- var reference = parts[0];
- var referenceId = parts[1];
- if (!(reference in references)) {
- references[reference] = {};
- }
- references[reference][
- referenceId
- ] = 1;
- }
- });
- });
- });
- return references;
-};
+ var references = {};
+ activitiesOrNotifications.forEach(function(item) {
+ var activities = item.activities ? item.activities : [item];
+ activities.forEach(function(activity) {
+ Object.keys(activity).forEach(function(key) {
+ if (
+ activity[key] &&
+ activity[key].indexOf &&
+ activity[key].indexOf(':') != -1
+ ) {
+ var parts = activity[key].split(':');
+ var reference = parts[0];
+ var referenceId = parts[1];
+ if (!(reference in references)) {
+ references[reference] = {};
+ }
+ references[reference][referenceId] = 1;
+ }
+ });
+ });
+ });
+ return references;
+}
function loadReferencedObjects(references, userId, callback) {
- // TODO: subqueries are inneficient. Handle do i like and do i follow
- // in 2 separate queries
- var queries = [];
- if (references.upload) {
- let sql = `
+ // TODO: subqueries are inneficient. Handle do i like and do i follow
+ // in 2 separate queries
+ var queries = [];
+ if (references.upload) {
+ let sql = `
SELECT
uploads.id AS id,
users.id AS user_id,
@@ -51,14 +50,14 @@ function loadReferencedObjects(references, userId, callback) {
LEFT JOIN users ON (uploads.user_id = users.id)
WHERE uploads.id IN (?)
`;
- queries.push({
- 'name': 'upload',
- 'sql': sql
- });
- }
- if (references.user) {
- // do the same thing for users
- let sql = `
+ queries.push({
+ name: 'upload',
+ sql: sql,
+ });
+ }
+ if (references.user) {
+ // do the same thing for users
+ let sql = `
SELECT
users.id AS id,
users.id AS user_id,
@@ -79,52 +78,67 @@ function loadReferencedObjects(references, userId, callback) {
FROM users
WHERE users.id IN (?)
`;
- queries.push({
- 'name': 'user',
- 'sql': sql
- });
- }
- var referencedObject = {};
- // run all the queries
- async.eachSeries(queries, function iteratee(query, cb) {
- db.query(query.sql, [userId, Object.keys(references[query.name])], function(err, results) {
- if (err) {
- cb(err);
- }
- referencedObject[query.name] = {};
- results.forEach(function(result) {
- referencedObject[query.name][result.id] = result;
- });
- cb();
- });
- }, function done() {
- callback(referencedObject);
- });
+ queries.push({
+ name: 'user',
+ sql: sql,
+ });
+ }
+ var referencedObject = {};
+ // run all the queries
+ async.eachSeries(
+ queries,
+ function iteratee(query, cb) {
+ db.query(
+ query.sql,
+ [userId, Object.keys(references[query.name])],
+ function(err, results) {
+ if (err) {
+ cb(err);
+ }
+ referencedObject[query.name] = {};
+ results.forEach(function(result) {
+ referencedObject[query.name][result.id] = result;
+ });
+ cb();
+ },
+ );
+ },
+ function done() {
+ callback(referencedObject);
+ },
+ );
}
function enrichActivities(activitiesOrNotifications, refencedObjects) {
- /*
+ /*
* Enriches the activities by replacing references with the actual objects
*/
- activitiesOrNotifications.forEach(function(item) {
- var activities = (item.activities) ? item.activities : [item];
- activities.forEach(function(activity) {
- Object.keys(activity).forEach(function(key) {
- if (activity[key] && activity[key].indexOf && activity[key].indexOf(':') != -1) {
- var parts = activity[key].split(':');
- var reference = parts[0];
- var referenceId = parts[1];
- if (reference in refencedObjects && refencedObjects[reference][referenceId]) {
- activity[key] = refencedObjects[reference][referenceId];
- }
- }
- });
- });
- });
-};
+ activitiesOrNotifications.forEach(function(item) {
+ var activities = item.activities ? item.activities : [item];
+ activities.forEach(function(activity) {
+ Object.keys(activity).forEach(function(key) {
+ if (
+ activity[key] &&
+ activity[key].indexOf &&
+ activity[key].indexOf(':') != -1
+ ) {
+ var parts = activity[key].split(':');
+ var reference = parts[0];
+ var referenceId = parts[1];
+ if (
+ reference in refencedObjects &&
+ refencedObjects[reference][referenceId]
+ ) {
+ activity[key] = refencedObjects[reference][referenceId];
+ }
+ }
+ });
+ });
+ });
+}
module.exports = {
- 'referencesFromActivities': referencesFromActivities,
- 'loadReferencedObjects': loadReferencedObjects,
- 'enrichActivities': enrichActivities
+ referencesFromActivities: referencesFromActivities,
+ loadReferencedObjects: loadReferencedObjects,
+ enrichActivities: enrichActivities,
};
diff --git a/api/package-lock.json b/api/package-lock.json
new file mode 100644
index 0000000..49b739c
--- /dev/null
+++ b/api/package-lock.json
@@ -0,0 +1,1765 @@
+{
+ "name": "api",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "addressparser": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-0.3.2.tgz",
+ "integrity": "sha1-WYc/Nej89sc2HBAjkmHXbhU0i7I="
+ },
+ "agentkeepalive": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-2.2.0.tgz",
+ "integrity": "sha1-xdG9SxKQCPEWPyNvhuX66iAm4u8="
+ },
+ "ajv": {
+ "version": "4.11.8",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
+ "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=",
+ "requires": {
+ "co": "4.6.0",
+ "json-stable-stringify": "1.0.1"
+ }
+ },
+ "algoliasearch": {
+ "version": "3.24.3",
+ "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-3.24.3.tgz",
+ "integrity": "sha512-k9MM+dSUqrT180gtC5rWowvt9t+DTM7SvQIOfPczZKT971bGn9PUYmOlBVOW0gSW81QxOgC/PbLMvsIXdh2Q4w==",
+ "requires": {
+ "agentkeepalive": "2.2.0",
+ "debug": "2.6.8",
+ "envify": "4.1.0",
+ "es6-promise": "4.1.1",
+ "events": "1.1.1",
+ "foreach": "2.0.5",
+ "global": "4.3.2",
+ "inherits": "2.0.3",
+ "isarray": "2.0.2",
+ "load-script": "1.0.0",
+ "object-keys": "1.0.11",
+ "querystring-es3": "0.2.1",
+ "reduce": "1.0.1",
+ "semver": "5.4.1",
+ "tunnel-agent": "0.6.0"
+ }
+ },
+ "any-promise": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+ "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
+ },
+ "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": "0.2.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
+ "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ="
+ },
+ "async": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz",
+ "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==",
+ "requires": {
+ "lodash": "4.17.4"
+ }
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
+ },
+ "aws-sign2": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
+ "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8="
+ },
+ "aws4": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz",
+ "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4="
+ },
+ "babel-runtime": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+ "requires": {
+ "core-js": "2.5.0",
+ "regenerator-runtime": "0.11.0"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+ "optional": true
+ },
+ "Base64": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/Base64/-/Base64-1.0.1.tgz",
+ "integrity": "sha1-3vRcxQyWG8yb8jIdD1K8v+wfG7E="
+ },
+ "base64url": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz",
+ "integrity": "sha1-6sFuA+oUOO/5Qj1puqNiYu0fcLs="
+ },
+ "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"
+ }
+ },
+ "bignumber.js": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.0.2.tgz",
+ "integrity": "sha1-LR3DfuWWiGfs6pC22k0W5oYI0h0="
+ },
+ "boom": {
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
+ "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
+ "requires": {
+ "hoek": "2.16.3"
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
+ "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
+ "optional": true,
+ "requires": {
+ "balanced-match": "1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
+ },
+ "bufferjs": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/bufferjs/-/bufferjs-1.1.0.tgz",
+ "integrity": "sha1-CV/6OcXmtAoheKEWnJ7/xYSnMgE=",
+ "optional": true
+ },
+ "bunyan": {
+ "version": "1.8.12",
+ "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.12.tgz",
+ "integrity": "sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c=",
+ "requires": {
+ "dtrace-provider": "0.8.5",
+ "moment": "2.18.1",
+ "mv": "2.1.1",
+ "safe-json-stringify": "1.0.4"
+ }
+ },
+ "bunyan-winston-adapter": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/bunyan-winston-adapter/-/bunyan-winston-adapter-0.2.0.tgz",
+ "integrity": "sha1-lQMQYzQFq15l/bf+528Y/mqZj80="
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
+ },
+ "clone-regexp": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-1.0.0.tgz",
+ "integrity": "sha1-6uCiQT9VwJQvgYwin+/OhF1/Oxw=",
+ "requires": {
+ "is-regexp": "1.0.0",
+ "is-supported-regexp-flag": "1.0.0"
+ }
+ },
+ "co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
+ },
+ "colors": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
+ "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs="
+ },
+ "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"
+ }
+ },
+ "component-emitter": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz",
+ "integrity": "sha1-KWWU8nU9qmOZbSrwjRWpURbJrsM="
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "optional": true
+ },
+ "cookie": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
+ },
+ "cookiejar": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.0.1.tgz",
+ "integrity": "sha1-PRJ1L2rfaKiS8zJDNJK9WBK7Zo8="
+ },
+ "core-decorators": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/core-decorators/-/core-decorators-0.17.0.tgz",
+ "integrity": "sha1-P0MYCobSqwzFEGn0ah7D5J5869Y="
+ },
+ "core-js": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.0.tgz",
+ "integrity": "sha1-VpwFCRi+ZIazg3VSAorgRmtxcIY="
+ },
+ "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": "2.0.5",
+ "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
+ "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=",
+ "requires": {
+ "boom": "2.10.1"
+ }
+ },
+ "csprng": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/csprng/-/csprng-0.1.2.tgz",
+ "integrity": "sha1-S8aPEvo2jSUqWYQcusqXSxirReI=",
+ "requires": {
+ "sequin": "0.1.1"
+ }
+ },
+ "csv": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/csv/-/csv-1.1.1.tgz",
+ "integrity": "sha1-2ZUtWbH5ZKevvN2ATWgYpzGZpHc=",
+ "requires": {
+ "csv-generate": "1.0.0",
+ "csv-parse": "1.2.1",
+ "csv-stringify": "1.0.4",
+ "stream-transform": "0.1.2"
+ }
+ },
+ "csv-generate": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/csv-generate/-/csv-generate-1.0.0.tgz",
+ "integrity": "sha1-vVKIaFnQySXz5R9g86vtJi+hXK8="
+ },
+ "csv-parse": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-1.2.1.tgz",
+ "integrity": "sha1-kZnCPySQ2YxNmrKgFnsGknSYyd8="
+ },
+ "csv-stringify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-1.0.4.tgz",
+ "integrity": "sha1-vBi6ua1M7zGV/SV5gLWLR5xC0+U=",
+ "requires": {
+ "lodash.get": "4.4.2"
+ }
+ },
+ "ctype": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz",
+ "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8="
+ },
+ "cycle": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz",
+ "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI="
+ },
+ "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"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ }
+ }
+ },
+ "debug": {
+ "version": "2.6.8",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
+ "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
+ },
+ "detect-node": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.3.tgz",
+ "integrity": "sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc="
+ },
+ "dom-walk": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz",
+ "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg="
+ },
+ "dtrace-provider": {
+ "version": "0.8.5",
+ "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.5.tgz",
+ "integrity": "sha1-mOu6Ihr6xG4cOf02hY2Pk2dSS5I=",
+ "optional": true,
+ "requires": {
+ "nan": "2.6.2"
+ }
+ },
+ "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"
+ }
+ },
+ "ecdsa-sig-formatter": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz",
+ "integrity": "sha1-S8kmJ07Dtau1AW5+HWCSGsJisqE=",
+ "requires": {
+ "base64url": "2.0.0",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "emailjs": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/emailjs/-/emailjs-1.0.12.tgz",
+ "integrity": "sha1-vWVZxRxJYxJSGGJtoJi+ci96HHI=",
+ "requires": {
+ "addressparser": "0.3.2",
+ "bufferjs": "1.1.0",
+ "mimelib": "0.2.14",
+ "moment": "2.15.2",
+ "starttls": "1.0.1"
+ },
+ "dependencies": {
+ "moment": {
+ "version": "2.15.2",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.15.2.tgz",
+ "integrity": "sha1-G/3t9qbjRfMi/pVtXfW9CKjOhNw="
+ }
+ }
+ },
+ "encoding": {
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
+ "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
+ "requires": {
+ "iconv-lite": "0.4.18"
+ }
+ },
+ "envify": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/envify/-/envify-4.1.0.tgz",
+ "integrity": "sha512-IKRVVoAYr4pIx4yIWNsz9mOsboxlNXiu7TNBnem/K/uTHdkyzXWDzHCK7UTolqBbgaBz0tQHsD3YNls0uIIjiw==",
+ "requires": {
+ "esprima": "4.0.0",
+ "through": "2.3.8"
+ }
+ },
+ "es6-promise": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.1.1.tgz",
+ "integrity": "sha512-OaU1hHjgJf+b0NzsxCg7NdIYERD6Hy/PEmFLTjw+b65scuisG3Kt4QoTvJ66BBkPZ581gr0kpoVzKnxniM8nng=="
+ },
+ "escape-regexp-component": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/escape-regexp-component/-/escape-regexp-component-1.0.2.tgz",
+ "integrity": "sha1-nGO20LJf8qiMOtvRjFthrMO5+qI="
+ },
+ "esprima": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
+ "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw=="
+ },
+ "events": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
+ "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
+ },
+ "express-unless": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/express-unless/-/express-unless-0.3.1.tgz",
+ "integrity": "sha1-JVfBRudb65A+LSR/m1ugFFJpbiA="
+ },
+ "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="
+ },
+ "eyes": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz",
+ "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A="
+ },
+ "faye": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/faye/-/faye-1.2.4.tgz",
+ "integrity": "sha1-l47YpY8dSB5cH5i6y4lZ3l7FxkM=",
+ "requires": {
+ "asap": "2.0.6",
+ "csprng": "0.1.2",
+ "faye-websocket": "0.11.1",
+ "tough-cookie": "2.3.2",
+ "tunnel-agent": "0.6.0"
+ }
+ },
+ "faye-websocket": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz",
+ "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=",
+ "requires": {
+ "websocket-driver": "0.6.5"
+ }
+ },
+ "fb": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fb/-/fb-2.0.0.tgz",
+ "integrity": "sha1-kf1AMl2jTsQcaLJVMPw6Pg2s+mo=",
+ "requires": {
+ "any-promise": "1.3.0",
+ "babel-runtime": "6.26.0",
+ "core-decorators": "0.17.0",
+ "debug": "2.6.8",
+ "request": "2.81.0"
+ }
+ },
+ "foreach": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
+ "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k="
+ },
+ "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.1.4",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
+ "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=",
+ "requires": {
+ "asynckit": "0.4.0",
+ "combined-stream": "1.0.5",
+ "mime-types": "2.1.16"
+ }
+ },
+ "formidable": {
+ "version": "1.0.14",
+ "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.0.14.tgz",
+ "integrity": "sha1-Kz9MQRy7X91pXESEPiojUUpDIxo="
+ },
+ "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"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ }
+ }
+ },
+ "getstream": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/getstream/-/getstream-3.5.0.tgz",
+ "integrity": "sha1-frkgbCAtQl5LX4d8i8qxtk4j6v8=",
+ "requires": {
+ "Base64": "1.0.1",
+ "faye": "1.2.4",
+ "http-signature": "1.1.1",
+ "jsonwebtoken": "5.0.1",
+ "qs": "6.4.0",
+ "request": "2.81.0",
+ "xmlhttp-request": "0.4.1"
+ },
+ "dependencies": {
+ "jsonwebtoken": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-5.0.1.tgz",
+ "integrity": "sha1-XYXOWAQhkVviLkqnsT1LuZsoCio=",
+ "requires": {
+ "jws": "3.1.4"
+ }
+ }
+ }
+ },
+ "glob": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz",
+ "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=",
+ "optional": true,
+ "requires": {
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "global": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz",
+ "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=",
+ "requires": {
+ "min-document": "2.19.0",
+ "process": "0.5.2"
+ }
+ },
+ "handle-thing": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz",
+ "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ="
+ },
+ "har-schema": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz",
+ "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4="
+ },
+ "har-validator": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz",
+ "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=",
+ "requires": {
+ "ajv": "4.11.8",
+ "har-schema": "1.0.5"
+ }
+ },
+ "hawk": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
+ "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=",
+ "requires": {
+ "boom": "2.10.1",
+ "cryptiles": "2.0.5",
+ "hoek": "2.16.3",
+ "sntp": "1.0.9"
+ }
+ },
+ "hoek": {
+ "version": "2.16.3",
+ "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
+ "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0="
+ },
+ "hpack.js": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
+ "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
+ "requires": {
+ "inherits": "2.0.3",
+ "obuf": "1.1.1",
+ "readable-stream": "2.3.3",
+ "wbuf": "1.7.2"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ },
+ "readable-stream": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
+ "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "safe-buffer": "5.1.1",
+ "string_decoder": "1.0.3",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "string_decoder": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ }
+ }
+ },
+ "http-deceiver": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
+ "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc="
+ },
+ "http-signature": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
+ "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
+ "requires": {
+ "assert-plus": "0.2.0",
+ "jsprim": "1.4.1",
+ "sshpk": "1.13.1"
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.18",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz",
+ "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA=="
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "optional": true,
+ "requires": {
+ "once": "1.4.0",
+ "wrappy": "1.0.2"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "is-regexp": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz",
+ "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk="
+ },
+ "is-supported-regexp-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.0.tgz",
+ "integrity": "sha1-i1IMhfrnolM4LUsCZS4EVXbhO7g="
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
+ },
+ "isarray": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.2.tgz",
+ "integrity": "sha512-DKCXsIpN+352zm3Sd75dY9HyaIcxU6grh118GhTPXc85jJ5nEGKOsPQOwSuE7aRd+XVRcC/Em6W44onQEQ9RBg=="
+ },
+ "isemail": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz",
+ "integrity": "sha1-vgPfjMPineTSxd9lASY/H6RZXpo="
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
+ },
+ "joi": {
+ "version": "6.10.1",
+ "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz",
+ "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=",
+ "requires": {
+ "hoek": "2.16.3",
+ "isemail": "1.2.0",
+ "moment": "2.18.1",
+ "topo": "1.1.0"
+ }
+ },
+ "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-stable-stringify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
+ "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
+ "requires": {
+ "jsonify": "0.0.0"
+ }
+ },
+ "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="
+ },
+ "jsonify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
+ "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM="
+ },
+ "jsonwebtoken": {
+ "version": "7.4.3",
+ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.3.tgz",
+ "integrity": "sha1-d/UCHeBYtgWheD+hKD6ZgS5kVjg=",
+ "requires": {
+ "joi": "6.10.1",
+ "jws": "3.1.4",
+ "lodash.once": "4.1.1",
+ "ms": "2.0.0",
+ "xtend": "4.0.1"
+ }
+ },
+ "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"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ }
+ }
+ },
+ "jwa": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz",
+ "integrity": "sha1-oFUs4CIHQs1S4VN3SjKQXDDnVuU=",
+ "requires": {
+ "base64url": "2.0.0",
+ "buffer-equal-constant-time": "1.0.1",
+ "ecdsa-sig-formatter": "1.0.9",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "jws": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.4.tgz",
+ "integrity": "sha1-+ei5M46KhHJ31kRLFGT2GIDgUKI=",
+ "requires": {
+ "base64url": "2.0.0",
+ "jwa": "1.1.5",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "keen.io": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/keen.io/-/keen.io-0.1.3.tgz",
+ "integrity": "sha1-UFb1yYmrFMz2L8IO11mBFa59CeM=",
+ "requires": {
+ "superagent": "0.21.0",
+ "underscore": "1.5.2"
+ }
+ },
+ "knox": {
+ "version": "0.9.2",
+ "resolved": "https://registry.npmjs.org/knox/-/knox-0.9.2.tgz",
+ "integrity": "sha1-NzZZNmniTwJP2vcjtqHcSv2DmnE=",
+ "requires": {
+ "debug": "1.0.5",
+ "mime": "1.2.11",
+ "once": "1.4.0",
+ "stream-counter": "1.0.0",
+ "xml2js": "0.4.19"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.5.tgz",
+ "integrity": "sha1-9yQSF0MPmd7EwrRz6rkiKOh0wqw=",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "load-script": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz",
+ "integrity": "sha1-BJGTngvuVkPuSUp+PaPSuscMbKQ="
+ },
+ "lodash": {
+ "version": "4.17.4",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
+ "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4="
+ },
+ "lodash.get": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
+ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
+ },
+ "lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
+ },
+ "lru-cache": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz",
+ "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==",
+ "requires": {
+ "pseudomap": "1.0.2",
+ "yallist": "2.1.2"
+ }
+ },
+ "lsmod": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/lsmod/-/lsmod-1.0.0.tgz",
+ "integrity": "sha1-mgD3bco26yP6BTUK/htYXUKZ5ks="
+ },
+ "mapbox-geocoding": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/mapbox-geocoding/-/mapbox-geocoding-0.1.4.tgz",
+ "integrity": "sha1-XuNIfPTSGIdRmFU+7J4qz4GSak4=",
+ "requires": {
+ "request": "2.81.0"
+ }
+ },
+ "methods": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.0.1.tgz",
+ "integrity": "sha1-dbyRlD3/19oDfPPusO1zoAN80Us="
+ },
+ "mime": {
+ "version": "1.2.11",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz",
+ "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA="
+ },
+ "mime-db": {
+ "version": "1.29.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz",
+ "integrity": "sha1-SNJtI1WJZRcErFkWygYAGRQmaHg="
+ },
+ "mime-types": {
+ "version": "2.1.16",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz",
+ "integrity": "sha1-K4WKUuXs1RbbiXrCvodIeDBpjiM=",
+ "requires": {
+ "mime-db": "1.29.0"
+ }
+ },
+ "mimelib": {
+ "version": "0.2.14",
+ "resolved": "https://registry.npmjs.org/mimelib/-/mimelib-0.2.14.tgz",
+ "integrity": "sha1-KhqnJL0ZC4W9Um5jF6thBu39aDE=",
+ "requires": {
+ "addressparser": "0.2.1",
+ "encoding": "0.1.12"
+ },
+ "dependencies": {
+ "addressparser": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-0.2.1.tgz",
+ "integrity": "sha1-0RpbLu2gTP7+vfMZbBCuE9ts1gc="
+ }
+ }
+ },
+ "min-document": {
+ "version": "2.19.0",
+ "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz",
+ "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=",
+ "requires": {
+ "dom-walk": "0.1.1"
+ }
+ },
+ "minimalistic-assert": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz",
+ "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M="
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "optional": true,
+ "requires": {
+ "brace-expansion": "1.1.8"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+ "optional": true
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "optional": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "moment": {
+ "version": "2.18.1",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz",
+ "integrity": "sha1-w2GT3Tzhwu7SrbfIAtu8d6gbHA8="
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "mustache": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.0.tgz",
+ "integrity": "sha1-QCj3d4sXcIpImTCm5SrDvKDaQdA="
+ },
+ "mv": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz",
+ "integrity": "sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=",
+ "optional": true,
+ "requires": {
+ "mkdirp": "0.5.1",
+ "ncp": "2.0.0",
+ "rimraf": "2.4.5"
+ }
+ },
+ "mysql": {
+ "version": "2.14.1",
+ "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.14.1.tgz",
+ "integrity": "sha512-ZPXqQeYH7L1QPDyC77Rcp32cNCQnNjz8Y4BbF17tOjm5yhSfjFa3xS4PvuxWJtEEmwVc4ccI7sSntj4eyYRq0A==",
+ "requires": {
+ "bignumber.js": "4.0.2",
+ "readable-stream": "2.3.3",
+ "safe-buffer": "5.1.1",
+ "sqlstring": "2.2.0"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ },
+ "readable-stream": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
+ "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "safe-buffer": "5.1.1",
+ "string_decoder": "1.0.3",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "string_decoder": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ }
+ }
+ },
+ "nan": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz",
+ "integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U=",
+ "optional": true
+ },
+ "ncp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
+ "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=",
+ "optional": true
+ },
+ "negotiator": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
+ "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
+ },
+ "node-uuid": {
+ "version": "1.4.8",
+ "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz",
+ "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc="
+ },
+ "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="
+ },
+ "obuf": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.1.tgz",
+ "integrity": "sha1-EEEktsYCxnlogaBCVB0220OlJk4="
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "requires": {
+ "wrappy": "1.0.2"
+ }
+ },
+ "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=",
+ "optional": true
+ },
+ "performance-now": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz",
+ "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU="
+ },
+ "process": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz",
+ "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8="
+ },
+ "process-nextick-args": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+ "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
+ },
+ "pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
+ },
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
+ },
+ "qs": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz",
+ "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM="
+ },
+ "querystring-es3": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
+ "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM="
+ },
+ "raven": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/raven/-/raven-2.1.2.tgz",
+ "integrity": "sha512-pBopqPVAuzEP5jyyqEPxJvXg788dAJ9p8NXoHVLF598Ih7MApu2AWT/QHNk2Fa4Rx/xV9yTYDEtAujLXX1FvRg==",
+ "requires": {
+ "cookie": "0.3.1",
+ "json-stringify-safe": "5.0.1",
+ "lsmod": "1.0.0",
+ "stack-trace": "0.0.9",
+ "timed-out": "4.0.1",
+ "uuid": "3.0.0"
+ },
+ "dependencies": {
+ "stack-trace": {
+ "version": "0.0.9",
+ "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz",
+ "integrity": "sha1-qPbq7KkGdMMz58Q5U/J1tFFRBpU="
+ },
+ "uuid": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.0.tgz",
+ "integrity": "sha1-Zyj8BFnEUNeWqZwxg3VpvfZy1yg="
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "1.0.27-1",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.27-1.tgz",
+ "integrity": "sha1-a2eYPCA1fO/QfwFlABoW1xDZEHg=",
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "0.0.1",
+ "string_decoder": "0.10.31"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
+ }
+ }
+ },
+ "reduce": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/reduce/-/reduce-1.0.1.tgz",
+ "integrity": "sha1-FPouX/H8VgcDoCDLtfuqtpFWWAQ=",
+ "requires": {
+ "object-keys": "1.0.11"
+ }
+ },
+ "reduce-component": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/reduce-component/-/reduce-component-1.0.1.tgz",
+ "integrity": "sha1-4Mk1QsV0UhvqE98PlIjtgqt3xdo="
+ },
+ "regenerator-runtime": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz",
+ "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A=="
+ },
+ "request": {
+ "version": "2.81.0",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz",
+ "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=",
+ "requires": {
+ "aws-sign2": "0.6.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.1.4",
+ "har-validator": "4.2.1",
+ "hawk": "3.1.3",
+ "http-signature": "1.1.1",
+ "is-typedarray": "1.0.0",
+ "isstream": "0.1.2",
+ "json-stringify-safe": "5.0.1",
+ "mime-types": "2.1.16",
+ "oauth-sign": "0.8.2",
+ "performance-now": "0.2.0",
+ "qs": "6.4.0",
+ "safe-buffer": "5.1.1",
+ "stringstream": "0.0.5",
+ "tough-cookie": "2.3.2",
+ "tunnel-agent": "0.6.0",
+ "uuid": "3.1.0"
+ },
+ "dependencies": {
+ "uuid": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz",
+ "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g=="
+ }
+ }
+ },
+ "restify": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/restify/-/restify-5.2.0.tgz",
+ "integrity": "sha1-9xMxAu85WKVtpC92BBURKnigGCI=",
+ "requires": {
+ "assert-plus": "1.0.0",
+ "bunyan": "1.8.12",
+ "clone-regexp": "1.0.0",
+ "csv": "1.1.1",
+ "dtrace-provider": "0.8.5",
+ "escape-regexp-component": "1.0.2",
+ "formidable": "1.1.1",
+ "http-signature": "1.1.1",
+ "lodash": "4.17.4",
+ "lru-cache": "4.1.1",
+ "mime": "1.2.11",
+ "negotiator": "0.6.1",
+ "once": "1.4.0",
+ "qs": "6.4.0",
+ "restify-errors": "4.3.0",
+ "semver": "5.4.1",
+ "spdy": "3.4.7",
+ "uuid": "3.1.0",
+ "vasync": "1.6.4",
+ "verror": "1.10.0"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ },
+ "formidable": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.1.1.tgz",
+ "integrity": "sha1-lriIb3w8NQi5Mta9cMTTqI818ak="
+ },
+ "uuid": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz",
+ "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g=="
+ }
+ }
+ },
+ "restify-errors": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/restify-errors/-/restify-errors-4.3.0.tgz",
+ "integrity": "sha1-7JDzCTTX8xGRNRgd/DA+ML5gGr4=",
+ "requires": {
+ "assert-plus": "1.0.0",
+ "lodash": "4.17.4",
+ "safe-json-stringify": "1.0.4",
+ "verror": "1.10.0"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ }
+ }
+ },
+ "restify-jwt": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/restify-jwt/-/restify-jwt-0.4.0.tgz",
+ "integrity": "sha1-IidMjObvbm5rtQdLOB8rV7/3vR8=",
+ "requires": {
+ "async": "0.9.2",
+ "express-unless": "0.3.1",
+ "jsonwebtoken": "5.7.0"
+ },
+ "dependencies": {
+ "async": {
+ "version": "0.9.2",
+ "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
+ "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
+ },
+ "jsonwebtoken": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-5.7.0.tgz",
+ "integrity": "sha1-HJD5qGzlt0j1+XnBK3BAK0r83bQ=",
+ "requires": {
+ "jws": "3.1.4",
+ "ms": "0.7.3",
+ "xtend": "4.0.1"
+ }
+ },
+ "ms": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.3.tgz",
+ "integrity": "sha1-cIFVpeROM/X9D8U+gdDUCpG+H/8="
+ }
+ }
+ },
+ "restify-plugins": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/restify-plugins/-/restify-plugins-1.6.0.tgz",
+ "integrity": "sha1-eeEYiHt/DrAuZFeA+cVoDLermqk=",
+ "requires": {
+ "assert-plus": "1.0.0",
+ "bunyan": "1.8.12",
+ "csv": "1.1.1",
+ "escape-regexp-component": "1.0.2",
+ "formidable": "1.1.1",
+ "http-signature": "0.11.0",
+ "lru-cache": "4.1.1",
+ "mime": "1.4.0",
+ "once": "1.4.0",
+ "qs": "6.4.0",
+ "restify-errors": "4.3.0",
+ "vasync": "1.6.4"
+ },
+ "dependencies": {
+ "asn1": {
+ "version": "0.1.11",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz",
+ "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc="
+ },
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ },
+ "formidable": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.1.1.tgz",
+ "integrity": "sha1-lriIb3w8NQi5Mta9cMTTqI818ak="
+ },
+ "http-signature": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.11.0.tgz",
+ "integrity": "sha1-F5bPZ6ABrVzWhJ3KCZFIXwkIn+Y=",
+ "requires": {
+ "asn1": "0.1.11",
+ "assert-plus": "0.1.5",
+ "ctype": "0.5.3"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz",
+ "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA="
+ }
+ }
+ },
+ "mime": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.0.tgz",
+ "integrity": "sha512-n9ChLv77+QQEapYz8lV+rIZAW3HhAPW2CXnzb1GN5uMkuczshwvkW7XPsbzU0ZQN3sP47Er2KVkp2p3KyqZKSQ=="
+ }
+ }
+ },
+ "rimraf": {
+ "version": "2.4.5",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz",
+ "integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=",
+ "optional": true,
+ "requires": {
+ "glob": "6.0.4"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
+ "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
+ },
+ "safe-json-stringify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.0.4.tgz",
+ "integrity": "sha1-gaCY9Efku8P/MxKiQ1IbwGDvWRE=",
+ "optional": true
+ },
+ "sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
+ },
+ "select-hose": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
+ "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo="
+ },
+ "semver": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
+ "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg=="
+ },
+ "sequin": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/sequin/-/sequin-0.1.1.tgz",
+ "integrity": "sha1-XC04nWajg3NOqvvEXt6ywcsb5wE="
+ },
+ "sntp": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
+ "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=",
+ "requires": {
+ "hoek": "2.16.3"
+ }
+ },
+ "spdy": {
+ "version": "3.4.7",
+ "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz",
+ "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=",
+ "requires": {
+ "debug": "2.6.8",
+ "handle-thing": "1.2.5",
+ "http-deceiver": "1.2.7",
+ "safe-buffer": "5.1.1",
+ "select-hose": "2.0.0",
+ "spdy-transport": "2.0.20"
+ }
+ },
+ "spdy-transport": {
+ "version": "2.0.20",
+ "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.0.20.tgz",
+ "integrity": "sha1-c15yBUxIayNU/onnAiVgBKOazk0=",
+ "requires": {
+ "debug": "2.6.8",
+ "detect-node": "2.0.3",
+ "hpack.js": "2.1.6",
+ "obuf": "1.1.1",
+ "readable-stream": "2.3.3",
+ "safe-buffer": "5.1.1",
+ "wbuf": "1.7.2"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ },
+ "readable-stream": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
+ "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "safe-buffer": "5.1.1",
+ "string_decoder": "1.0.3",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "string_decoder": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ }
+ }
+ },
+ "sqlstring": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.2.0.tgz",
+ "integrity": "sha1-wxNcTqirzX5+50GklmqJHYak8ZE="
+ },
+ "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"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ }
+ }
+ },
+ "stack-trace": {
+ "version": "0.0.10",
+ "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
+ "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA="
+ },
+ "starttls": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/starttls/-/starttls-1.0.1.tgz",
+ "integrity": "sha1-5ggcJd5rF49adfjyccFIdEkYO0I="
+ },
+ "stream-counter": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/stream-counter/-/stream-counter-1.0.0.tgz",
+ "integrity": "sha1-kc8lac5NxQYf6816yyY5SloRR1E="
+ },
+ "stream-transform": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/stream-transform/-/stream-transform-0.1.2.tgz",
+ "integrity": "sha1-fY5rTgOsR4F3j4x5UXUBv7B2Kp8="
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
+ },
+ "stringstream": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
+ "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg="
+ },
+ "superagent": {
+ "version": "0.21.0",
+ "resolved": "https://registry.npmjs.org/superagent/-/superagent-0.21.0.tgz",
+ "integrity": "sha1-+xUCeYR1HucVIgDmzSHNbhml3oc=",
+ "requires": {
+ "component-emitter": "1.1.2",
+ "cookiejar": "2.0.1",
+ "debug": "2.6.8",
+ "extend": "1.2.1",
+ "form-data": "0.1.3",
+ "formidable": "1.0.14",
+ "methods": "1.0.1",
+ "mime": "1.2.11",
+ "qs": "1.2.0",
+ "readable-stream": "1.0.27-1",
+ "reduce-component": "1.0.1"
+ },
+ "dependencies": {
+ "async": {
+ "version": "0.9.2",
+ "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
+ "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
+ },
+ "combined-stream": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz",
+ "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=",
+ "requires": {
+ "delayed-stream": "0.0.5"
+ }
+ },
+ "delayed-stream": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz",
+ "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8="
+ },
+ "extend": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-1.2.1.tgz",
+ "integrity": "sha1-oPX9bPyDpf5J72mNYOyKYk3UV2w="
+ },
+ "form-data": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.3.tgz",
+ "integrity": "sha1-TuQ0bm61Ni6DRKAgdb2NvYxzc+o=",
+ "requires": {
+ "async": "0.9.2",
+ "combined-stream": "0.0.7",
+ "mime": "1.2.11"
+ }
+ },
+ "qs": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-1.2.0.tgz",
+ "integrity": "sha1-7Qeb4oaCFH5v2aNMwrDB4OxkU+4="
+ }
+ }
+ },
+ "through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
+ },
+ "timed-out": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
+ "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8="
+ },
+ "topo": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz",
+ "integrity": "sha1-6ddRYV0buH3IZdsYL6HKCl71NtU=",
+ "requires": {
+ "hoek": "2.16.3"
+ }
+ },
+ "tough-cookie": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz",
+ "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=",
+ "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": "5.1.1"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+ "optional": true
+ },
+ "underscore": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.5.2.tgz",
+ "integrity": "sha1-EzXF5PXm0zu7SwBrqMhqAPVW3gg="
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+ },
+ "vasync": {
+ "version": "1.6.4",
+ "resolved": "https://registry.npmjs.org/vasync/-/vasync-1.6.4.tgz",
+ "integrity": "sha1-3+k2Fq0OeugBszKp2Iv8XNyOHR8=",
+ "requires": {
+ "verror": "1.6.0"
+ },
+ "dependencies": {
+ "extsprintf": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.2.0.tgz",
+ "integrity": "sha1-WtlGwi9bMrp/jNdCZxHG6KP8JSk="
+ },
+ "verror": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.6.0.tgz",
+ "integrity": "sha1-fROyex+swuLakEBetepuW90lLqU=",
+ "requires": {
+ "extsprintf": "1.2.0"
+ }
+ }
+ }
+ },
+ "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"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ }
+ }
+ },
+ "wbuf": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.2.tgz",
+ "integrity": "sha1-1pe5nx9ZUS3ydRvkJ2nBWAtYAf4=",
+ "requires": {
+ "minimalistic-assert": "1.0.0"
+ }
+ },
+ "websocket-driver": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz",
+ "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=",
+ "requires": {
+ "websocket-extensions": "0.1.1"
+ }
+ },
+ "websocket-extensions": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz",
+ "integrity": "sha1-domUmcGEtu91Q3fC27DNbLVdKec="
+ },
+ "winston": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/winston/-/winston-2.3.1.tgz",
+ "integrity": "sha1-C0hCDZeMAYBM8CMLZIhhWYIloRk=",
+ "requires": {
+ "async": "1.0.0",
+ "colors": "1.0.3",
+ "cycle": "1.0.3",
+ "eyes": "0.1.8",
+ "isstream": "0.1.2",
+ "stack-trace": "0.0.10"
+ },
+ "dependencies": {
+ "async": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz",
+ "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k="
+ }
+ }
+ },
+ "winston-mail": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/winston-mail/-/winston-mail-1.3.0.tgz",
+ "integrity": "sha1-ELBXArc86fLpszKaUi6Ytu1NzcA=",
+ "requires": {
+ "emailjs": "1.0.12",
+ "mustache": "2.3.0"
+ }
+ },
+ "winston-sentry": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/winston-sentry/-/winston-sentry-0.2.1.tgz",
+ "integrity": "sha1-39zIKPNac1qOAeeBkYr2UuuXx1w=",
+ "requires": {
+ "lodash": "4.17.4",
+ "raven": "1.2.1"
+ },
+ "dependencies": {
+ "raven": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/raven/-/raven-1.2.1.tgz",
+ "integrity": "sha1-lJwTTbAooZC3u/j3kKrlQbfAIL0=",
+ "requires": {
+ "cookie": "0.3.1",
+ "json-stringify-safe": "5.0.1",
+ "lsmod": "1.0.0",
+ "stack-trace": "0.0.9",
+ "uuid": "3.0.0"
+ }
+ },
+ "stack-trace": {
+ "version": "0.0.9",
+ "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz",
+ "integrity": "sha1-qPbq7KkGdMMz58Q5U/J1tFFRBpU="
+ },
+ "uuid": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.0.tgz",
+ "integrity": "sha1-Zyj8BFnEUNeWqZwxg3VpvfZy1yg="
+ }
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ },
+ "xml2js": {
+ "version": "0.4.19",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
+ "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
+ "requires": {
+ "sax": "1.2.4",
+ "xmlbuilder": "9.0.4"
+ }
+ },
+ "xmlbuilder": {
+ "version": "9.0.4",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.4.tgz",
+ "integrity": "sha1-UZy0ymhtAFqEINNJbz8MruzKWA8="
+ },
+ "xmlhttp-request": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/xmlhttp-request/-/xmlhttp-request-0.4.1.tgz",
+ "integrity": "sha1-Y22ZNVqR4YZbOOoDkJndxZr2p6c="
+ },
+ "xtend": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
+ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
+ }
+ }
+}
diff --git a/api/package.json b/api/package.json
index 935da31..ea8dd63 100644
--- a/api/package.json
+++ b/api/package.json
@@ -1,44 +1,46 @@
{
- "name": "api",
- "version": "1.0.0",
- "description": "",
- "main": "index.js",
- "dependencies": {
- "algoliasearch": "^3.15.0",
- "async": "^2.0.0-rc.6",
- "bunyan": "^1.8.10",
- "bunyan-winston-adapter": "^0.2.0",
- "fb": "^1.1.1",
- "getstream": "^3.2.0",
- "jsonwebtoken": "^7.0.0",
- "keen.io": "^0.1.3",
- "knox": "^0.9.2",
- "mapbox-geocoding": "^0.1.4",
- "mysql": "^2.11.1",
- "node-uuid": "^1.4.7",
- "raven": "^1.2.0",
- "restify": "^4.1.0",
- "restify-jwt": "^0.4.0",
- "stack-trace": "^0.0.9",
- "winston": "^2.2.0",
- "winston-mail": "^1.2.0",
- "winston-sentry": "^0.1.4"
- },
- "devDependencies": {},
- "scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
- },
- "repository": {
- "type": "git",
- "url": "git+https://github.com/GetStream/stream-react-example.git"
- },
- "keywords": [
- "GetStream"
- ],
- "author": "Nick Parsons ",
- "license": "ISC",
- "bugs": {
- "url": "https://github.com/GetStream/stream-react-example/issues"
- },
- "homepage": "https://github.com/GetStream/stream-react-example#readme"
+ "name": "api",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "engines": {
+ "node": "9.x"
+ },
+ "dependencies": {
+ "algoliasearch": "^3.24.9",
+ "async": "^2.6.0",
+ "bunyan": "^1.8.12",
+ "bunyan-winston-adapter": "^0.2.0",
+ "fb": "^2.0.0",
+ "getstream": "^3.10.0",
+ "jsonwebtoken": "^8.1.0",
+ "keen.io": "^0.1.3",
+ "knox": "^0.9.2",
+ "mapbox-geocoding": "^0.1.5",
+ "mysql": "^2.15.0",
+ "node-uuid": "^1.4.8",
+ "raven": "^2.3.0",
+ "restify": "^6.3.4",
+ "restify-jwt": "^0.4.0",
+ "restify-plugins": "^1.6.0",
+ "stack-trace": "^0.0.10",
+ "winston": "^2.4.0",
+ "winston-mail": "^1.3.0",
+ "winston-sentry": "^0.2.1"
+ },
+ "devDependencies": {},
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/GetStream/stream-react-example.git"
+ },
+ "keywords": ["GetStream"],
+ "author": "Nick Parsons ",
+ "license": "ISC",
+ "bugs": {
+ "url": "https://github.com/GetStream/stream-react-example/issues"
+ },
+ "homepage": "https://github.com/GetStream/stream-react-example#readme"
}
diff --git a/api/routes/active.js b/api/routes/active.js
index 57c1171..10e28a1 100644
--- a/api/routes/active.js
+++ b/api/routes/active.js
@@ -1,11 +1,10 @@
'use strict';
server.get('/active', function(req, res, next) {
+ // extract query params
+ var params = req.params || {};
- // extract query params
- var params = req.params || {};
-
- var sql = `
+ var sql = `
SELECT
users.id AS id,
users.first_name AS first_name,
@@ -30,24 +29,18 @@ server.get('/active', function(req, res, next) {
LIMIT 3
`;
- db.query(sql, [params.user_id, params.user_id], function(err, result) {
-
- // catch all errors
- if (err) {
-
- // use global logger to log to console
- log.error(err);
-
- // return error message to client
- return next(new restify.InternalError(err.message));
-
- }
-
- // send response to client
- res.send(200, result);
- return next();
-
- });
+ db.query(sql, [params.user_id, params.user_id], function(err, result) {
+ // catch all errors
+ if (err) {
+ // use global logger to log to console
+ log.error(err);
+ // return error message to client
+ return next(new restify.InternalError(err.message));
+ }
+ // send response to client
+ res.send(200, result);
+ return next();
+ });
});
diff --git a/api/routes/comments.js b/api/routes/comments.js
index f45a4f8..b23aa8a 100644
--- a/api/routes/comments.js
+++ b/api/routes/comments.js
@@ -3,10 +3,10 @@
/**
* Module Dependencies
*/
-var async = require('async'),
- stream = require('getstream'),
- jwt = require('restify-jwt'),
- config = require('../config');
+var async = require('async'),
+ stream = require('getstream'),
+ jwt = require('restify-jwt'),
+ config = require('../config');
/**
* Get all comments (optionally for a specific upload id)
@@ -17,12 +17,11 @@ var async = require('async'),
* @returns {array} Returns a 200 status code with an array of comment objects
*/
server.get('/comments', function(req, res, next) {
+ // extract query params
+ var params = req.params || {};
- // extract query params
- var params = req.params || {};
-
- // build base sql statement
- var sql = `
+ // build base sql statement
+ var sql = `
SELECT
comments.*,
users.id AS user_id,
@@ -33,37 +32,32 @@ server.get('/comments', function(req, res, next) {
LEFT JOIN users ON comments.user_id = users.id
`;
- // if upload id exists, inject into sql query
- if (params.upload_id) {
- sql += ' WHERE upload_id=?';
- }
-
- // order by created timestamp
- sql += ' ORDER BY comments.created_at DESC ';
-
- // execute query
- db.query(sql, [params.upload_id], function(err, result) {
-
- // catch all errors
- if (err) {
-
- // use global logger to log to console
- log.error(err);
-
- // return error message to client
- return next(new restify.InternalError(err.message));
-
- }
-
- // send result to client
- res.send(200, result);
- return next();
-
- });
-
+ // if upload id exists, inject into sql query
+ if (params.upload_id) {
+ sql += ' WHERE upload_id=?';
+ }
+
+ // order by created timestamp
+ sql += ' ORDER BY comments.created_at DESC ';
+
+ // execute query
+ db.query(sql, [params.upload_id], function(err, result) {
+ // catch all errors
+ if (err) {
+ // use global logger to log to console
+ log.error(err);
+
+ // return error message to client
+ return next(new restify.InternalError(err.message));
+ }
+
+ // send result to client
+ res.send(200, result);
+ return next();
+ });
});
- /**
+/**
* Create a comment for a specific upload
* URL: /comments
* Method: POST
@@ -73,101 +67,102 @@ server.get('/comments', function(req, res, next) {
* @returns {object} Returns 201 status code with an object of the returned database result
*/
server.post('/comments', function(req, res, next) {
-
- // extract params from body
- var data = req.body || {};
-
- // async waterfall (see: https://github.com/caolan/async)
- async.waterfall([
-
- // insert comment into database
- function(cb) {
-
- data['created_at'] = new Date();
-
- // execute query with data as sanitized values
- db.query('INSERT INTO comments SET ?', data, function(err, comment) {
-
- if (err) {
- cb(err);
- }
- // use object assign to merge the object id
- comment = Object.assign({ id: comment.insertId }, data);
-
- cb(null, comment);
-
- });
-
- },
-
- // get upload associated with comment
- function(comment, cb) {
-
- // execute query using upload id from previous sql query
- db.query('SELECT user_id FROM uploads WHERE id = ?', [comment.upload_id], function(err, upload) {
-
- if (err) {
- cb(err);
- }
-
- // use object assign to merge objects from previous queries
- var result = Object.assign({ author_id: upload[0].user_id }, comment, upload);
-
- cb(null, result);
-
- });
-
- },
-
- // submit to stream
- function(result, cb) {
-
- // instantiate a new client (server side)
- var streamClient = stream.connect(config.stream.key, config.stream.secret);
-
- // instantiate a feed using feed class 'user' and the user id from the database
- var userFeed = streamClient.feed('user', data.user_id);
-
- // build activity object for stream feed
- var activity = {
- actor: `user:${data.user_id}`,
- verb: 'comment',
- object: `upload:${data.upload_id}`,
- foreign_id: `comment:${result.id}`,
- time: result.created_at,
- comment: data.comment,
- to: [`notification:${result.author_id}`],
- };
-
- // add activity to the feed
- userFeed.addActivity(activity)
- .then(function(response) {
- cb(null, result);
- })
- .catch(function(err) {
- cb(err);
- });
-
- }
-
- // final cb callback
- ], function(err, result) {
-
- // catch all errors
- if (err) {
-
- // use global logger to log to console
- log.error(err);
-
- // return error message to client
- return next(new restify.InternalError(err));
-
- }
-
- // send response to client
- res.send(201, result);
- return next();
-
- });
-
+ // extract params from body
+ var data = req.body || {};
+
+ // async waterfall (see: https://github.com/caolan/async)
+ async.waterfall(
+ [
+ // insert comment into database
+ function(cb) {
+ data['created_at'] = new Date();
+
+ // execute query with data as sanitized values
+ db.query('INSERT INTO comments SET ?', data, function(
+ err,
+ comment,
+ ) {
+ if (err) {
+ cb(err);
+ }
+ // use object assign to merge the object id
+ comment = Object.assign({ id: comment.insertId }, data);
+
+ cb(null, comment);
+ });
+ },
+
+ // get upload associated with comment
+ function(comment, cb) {
+ // execute query using upload id from previous sql query
+ db.query(
+ 'SELECT user_id FROM uploads WHERE id = ?',
+ [comment.upload_id],
+ function(err, upload) {
+ if (err) {
+ cb(err);
+ }
+
+ // use object assign to merge objects from previous queries
+ var result = Object.assign(
+ { author_id: upload[0].user_id },
+ comment,
+ upload,
+ );
+
+ cb(null, result);
+ },
+ );
+ },
+
+ // submit to stream
+ function(result, cb) {
+ // instantiate a new client (server side)
+ var streamClient = stream.connect(
+ config.stream.key,
+ config.stream.secret,
+ );
+
+ // instantiate a feed using feed class 'user' and the user id from the database
+ var userFeed = streamClient.feed('user', data.user_id);
+
+ // build activity object for stream feed
+ var activity = {
+ actor: `user:${data.user_id}`,
+ verb: 'comment',
+ object: `upload:${data.upload_id}`,
+ foreign_id: `comment:${result.id}`,
+ time: result.created_at,
+ comment: data.comment,
+ to: [`notification:${result.author_id}`],
+ };
+
+ // add activity to the feed
+ userFeed
+ .addActivity(activity)
+ .then(function(response) {
+ cb(null, result);
+ })
+ .catch(function(err) {
+ cb(err);
+ });
+ },
+
+ // final cb callback
+ ],
+ function(err, result) {
+ // catch all errors
+ if (err) {
+ // use global logger to log to console
+ log.error(err);
+
+ // return error message to client
+ return next(new restify.InternalError(err));
+ }
+
+ // send response to client
+ res.send(201, result);
+ return next();
+ },
+ );
});
diff --git a/api/routes/contributions.js b/api/routes/contributions.js
index 7f62e28..cb4879e 100644
--- a/api/routes/contributions.js
+++ b/api/routes/contributions.js
@@ -9,28 +9,26 @@
* @returns {array} Returns a 200 status code with an array of upload (aka contribution) objects
*/
server.get('/contributions', function(req, res, next) {
-
- // extract query params
- var params = req.params || {};
-
- // execute query
- db.query('SELECT * FROM uploads WHERE user_id = ? ORDER BY created_at DESC', [params.user_id], function(err, result) {
-
- // catch all errors
- if (err) {
-
- // use global logger to log to console
- log.error(err);
-
- // return error message to client
- return next(new restify.InternalError(err.message));
-
- }
-
- // send response to client
- res.send(200, result)
- return next();
-
- });
-
+ // extract query params
+ var params = req.params || {};
+
+ // execute query
+ db.query(
+ 'SELECT * FROM uploads WHERE user_id = ? ORDER BY created_at DESC',
+ [params.user_id],
+ function(err, result) {
+ // catch all errors
+ if (err) {
+ // use global logger to log to console
+ log.error(err);
+
+ // return error message to client
+ return next(new restify.InternalError(err.message));
+ }
+
+ // send response to client
+ res.send(200, result);
+ return next();
+ },
+ );
});
diff --git a/api/routes/explore.js b/api/routes/explore.js
index 7bf7985..34ff014 100644
--- a/api/routes/explore.js
+++ b/api/routes/explore.js
@@ -1,6 +1,6 @@
'use strict';
- /**
+/**
* Get images for explore page for a specific user
* URL: /explore
* Method: GET
@@ -9,12 +9,11 @@
* @returns {array} Returns a 200 status code with an array of upload (aka explore) objects
*/
server.get('/explore', function(req, res, next) {
+ // extract query params
+ var params = req.params || {};
- // extract query params
- var params = req.params || {};
-
- // build sql query
- var sql = `
+ // build sql query
+ var sql = `
SELECT
uploads.*,
COUNT(likes.id) AS likeTotal
@@ -27,24 +26,19 @@ server.get('/explore', function(req, res, next) {
LIMIT 15
`;
- // execute query
- db.query(sql, [params.user_id], function(err, result) {
-
- // catch all errors
- if (err) {
-
- // use global logger to log to console
- log.error(err);
-
- // return error message to client
- return next(new restify.InternalError(err.message));
-
- }
-
- // send response to client
- res.send(200, result)
- return next();
-
- });
-
-})
+ // execute query
+ db.query(sql, [params.user_id], function(err, result) {
+ // catch all errors
+ if (err) {
+ // use global logger to log to console
+ log.error(err);
+
+ // return error message to client
+ return next(new restify.InternalError(err.message));
+ }
+
+ // send response to client
+ res.send(200, result);
+ return next();
+ });
+});
diff --git a/api/routes/followers.js b/api/routes/followers.js
index 264005b..debb53e 100644
--- a/api/routes/followers.js
+++ b/api/routes/followers.js
@@ -15,65 +15,66 @@ var stream = require('getstream');
* @returns {object} Returns a 201 status code with the object created
*/
server.post('/followers', function(req, res, next) {
-
- // extract params from body
- var data = req.body || {};
- data['created_at'] = new Date();
-
- // execute query using data from body
- db.query('INSERT INTO followers SET ?', data, function(err, result) {
-
- // catch all errors
- if (err) {
-
- // use global logger to log to console
- log.error(err);
-
- // return error message to client
- return next(new restify.InternalError(err.message));
-
- }
-
- // instantiate a new client (server side)
- var streamClient = stream.connect(config.stream.key, config.stream.secret);
-
- // instantiate a feed using feed class 'user' and the user id from the database
- var userFeed = streamClient.feed('user', data.user_id);
-
- // build activity object for stream feed
- var activity = {
- actor: `user:${data.user_id}`,
- verb: 'follow',
- object: `user:${data.follower_id}`,
- foreign_id: `follow:${result.insertId}`,
- time: data['created_at'],
- to: [`notification:${data.follower_id}`]
- };
-
- // instantiate a feed using feed class 'timeline_flat' and the user id from the database
- var timeline = streamClient.feed('timeline_flat', data.user_id);
- timeline.follow('user_posts', data.follower_id);
-
- // instantiate a feed using feed class 'timeline_aggregated' and the user id from the database
- var timelineAggregated = streamClient.feed('timeline_aggregated', data.user_id);
- timelineAggregated.follow('user', data.follower_id);
-
- // add activity to the feed
- userFeed.addActivity(activity)
- .then(function(response) {
- //log.info(response);
- })
- .catch(function(reason) {
- log.error(reason);
- return next(new restify.InternalError(reason.error));
- });
-
- // send response to client
- res.send(201, Object.assign({ id: result.insertId }, data));
- return next();
-
- });
-
+ // extract params from body
+ var data = req.body || {};
+ data['created_at'] = new Date();
+
+ // execute query using data from body
+ db.query('INSERT INTO followers SET ?', data, function(err, result) {
+ // catch all errors
+ if (err) {
+ // use global logger to log to console
+ log.error(err);
+
+ // return error message to client
+ return next(new restify.InternalError(err.message));
+ }
+
+ // instantiate a new client (server side)
+ var streamClient = stream.connect(
+ config.stream.key,
+ config.stream.secret,
+ );
+
+ // instantiate a feed using feed class 'user' and the user id from the database
+ var userFeed = streamClient.feed('user', data.user_id);
+
+ // build activity object for stream feed
+ var activity = {
+ actor: `user:${data.user_id}`,
+ verb: 'follow',
+ object: `user:${data.follower_id}`,
+ foreign_id: `follow:${result.insertId}`,
+ time: data['created_at'],
+ to: [`notification:${data.follower_id}`],
+ };
+
+ // instantiate a feed using feed class 'timeline_flat' and the user id from the database
+ var timeline = streamClient.feed('timeline_flat', data.user_id);
+ timeline.follow('user_posts', data.follower_id);
+
+ // instantiate a feed using feed class 'timeline_aggregated' and the user id from the database
+ var timelineAggregated = streamClient.feed(
+ 'timeline_aggregated',
+ data.user_id,
+ );
+ timelineAggregated.follow('user', data.follower_id);
+
+ // add activity to the feed
+ userFeed
+ .addActivity(activity)
+ .then(function(response) {
+ //log.info(response);
+ })
+ .catch(function(reason) {
+ log.error(reason);
+ return next(new restify.InternalError(reason.error));
+ });
+
+ // send response to client
+ res.send(201, Object.assign({ id: result.insertId }, data));
+ return next();
+ });
});
/**
@@ -86,42 +87,42 @@ server.post('/followers', function(req, res, next) {
* @returns {string} Returns a 204 status code
*/
server.del('/followers', function(req, res, next) {
-
- // extract query params
- var params = req.params || {};
-
- // build sql query
- var sql = 'DELETE FROM followers WHERE user_id = ? AND follower_id = ?';
-
- // execute sql
- db.query(sql, [params.user_id, params.follower_id], function(err, result) {
-
- // instantiate a new client (server side)
- var streamClient = stream.connect(config.stream.key, config.stream.secret);
-
- // instantiate a feed using feed class 'user' and the user id from the database
- var flatFeed = streamClient.feed('timeline_flat', params.user_id);
- var aggregatedFeed = streamClient.feed('timeline_aggregated', params.user_id);
-
- // stop following user
- flatFeed.unfollow('user_posts', params.follower_id);
- aggregatedFeed.unfollow('user', params.follower_id);
-
- // catch all errors
- if (err) {
-
- // use global logger to log to console
- log.error(err);
-
- // return error message to client
- return next(new restify.InternalError(err.message));
-
- }
-
- // send response to client
- res.send(204);
- return next();
-
- });
-
+ // extract query params
+ var params = req.params || {};
+
+ // build sql query
+ var sql = 'DELETE FROM followers WHERE user_id = ? AND follower_id = ?';
+
+ // execute sql
+ db.query(sql, [params.user_id, params.follower_id], function(err, result) {
+ // instantiate a new client (server side)
+ var streamClient = stream.connect(
+ config.stream.key,
+ config.stream.secret,
+ );
+
+ // instantiate a feed using feed class 'user' and the user id from the database
+ var flatFeed = streamClient.feed('timeline_flat', params.user_id);
+ var aggregatedFeed = streamClient.feed(
+ 'timeline_aggregated',
+ params.user_id,
+ );
+
+ // stop following user
+ flatFeed.unfollow('user_posts', params.follower_id);
+ aggregatedFeed.unfollow('user', params.follower_id);
+
+ // catch all errors
+ if (err) {
+ // use global logger to log to console
+ log.error(err);
+
+ // return error message to client
+ return next(new restify.InternalError(err.message));
+ }
+
+ // send response to client
+ res.send(204);
+ return next();
+ });
});
diff --git a/api/routes/following-activity.js b/api/routes/following-activity.js
index b195cd6..c403aed 100644
--- a/api/routes/following-activity.js
+++ b/api/routes/following-activity.js
@@ -3,9 +3,9 @@
/**
* Module Dependencies
*/
- var async = require('async'),
- stream = require('getstream'),
- streamUtils = require('./../lib/stream_utils');
+var async = require('async'),
+ stream = require('getstream'),
+ streamUtils = require('./../lib/stream_utils');
/**
* Get following activity for a specific user
@@ -16,81 +16,90 @@
* @returns {object} Returns a 200 status code with an array of search objects
*/
server.get('/following-activity', function(req, res, next) {
-
- // extract query params
- var params = req.params || {};
-
- // async waterfall (see: https://github.com/caolan/async)
- async.waterfall([
-
- // connect to stream
- function(cb) {
-
- // instantiate a new client (server side)
- var streamClient = stream.connect(config.stream.key, config.stream.secret);
-
- // instantiate a feed using feed class 'user' and user id from params
- var user = streamClient.feed('timeline_aggregated', params.user_id);
-
- cb(null, user);
-
- },
-
- // get and loop through activities
- function(user, cb) {
-
- // empty array to hold activities
- var arr = [];
-
- // get activities from stream
- user.get({ limit: 100 })
- .then(function(stream) {
-
- // length of activity results
- var ln = stream.results.length;
-
- // if length is empty, return
- if (!ln) {
- res.send(204);
- return next();
- }
-
- /*
+ // extract query params
+ var params = req.params || {};
+
+ // async waterfall (see: https://github.com/caolan/async)
+ async.waterfall(
+ [
+ // connect to stream
+ function(cb) {
+ // instantiate a new client (server side)
+ var streamClient = stream.connect(
+ config.stream.key,
+ config.stream.secret,
+ );
+
+ // instantiate a feed using feed class 'user' and user id from params
+ var user = streamClient.feed(
+ 'timeline_aggregated',
+ params.user_id,
+ );
+
+ cb(null, user);
+ },
+
+ // get and loop through activities
+ function(user, cb) {
+ // empty array to hold activities
+ var arr = [];
+
+ // get activities from stream
+ user
+ .get({ limit: 100 })
+ .then(function(stream) {
+ // length of activity results
+ var ln = stream.results.length;
+
+ // if length is empty, return
+ if (!ln) {
+ res.send(204);
+ return next();
+ }
+
+ /*
* Activities stored in Stream reference user ids and upload ids
* We need the full object, not just the reference for the template
* The steps below query the DB to translate user:2 into
* Something like {'username': 'Nick', 'img':...}
*/
- var references = streamUtils.referencesFromActivities(stream.results);
- streamUtils.loadReferencedObjects(references, params.user_id, function(referencedObjects){
- streamUtils.enrichActivities(stream.results, referencedObjects);
- // return the enriched activities
- cb(null, stream.results);
- });
- }).catch(function(error) {
- cb(error);
- });
-
- },
-
- // final cb function
- ], function(err, result) {
-
- // catch all errors
- if (err) {
-
- // use global logger to log to console
- log.error(err);
-
- // return error message to client
- return next(new restify.InternalError(err.message));
-
- }
-
- // send response to client
- res.send(200, result);
- return next();
- });
-
+ var references = streamUtils.referencesFromActivities(
+ stream.results,
+ );
+ streamUtils.loadReferencedObjects(
+ references,
+ params.user_id,
+ function(referencedObjects) {
+ streamUtils.enrichActivities(
+ stream.results,
+ referencedObjects,
+ );
+ // return the enriched activities
+ cb(null, stream.results);
+ },
+ );
+ })
+ .catch(function(error) {
+ cb(error);
+ });
+ },
+
+ // final cb function
+ ],
+ function(err, result) {
+ // catch all errors
+ if (err) {
+ // use global logger to log to console
+ log.error(err);
+
+ // return error message to client
+ return next(new restify.InternalError(err.message));
+ }
+
+ // send response to client
+ res.send(200, result);
+ return next();
+ },
+ );
});
diff --git a/api/routes/incoming-activity.js b/api/routes/incoming-activity.js
index ddab859..6596c75 100644
--- a/api/routes/incoming-activity.js
+++ b/api/routes/incoming-activity.js
@@ -3,12 +3,9 @@
/**
* Module Dependencies
*/
-var async = require('async'),
- stream = require('getstream'),
- streamUtils = require('./../lib/stream_utils');
-
-
-
+var async = require('async'),
+ stream = require('getstream'),
+ streamUtils = require('./../lib/stream_utils');
/**
* Get incoming activity for a specific user
@@ -19,85 +16,90 @@ var async = require('async'),
* @returns {object} Returns a 200 status code with an array of search objects
*/
server.get('/incoming-activity', function(req, res, next) {
-
- // extract query params
- var params = req.params || {};
-
- // async waterfall (see: https://github.com/caolan/async)
- async.waterfall([
-
- // connect to stream
- function(cb) {
-
- // instantiate a new client (server side)
- var streamClient = stream.connect(config.stream.key, config.stream.secret);
-
- // instantiate a feed using feed class 'notification' and user id from params
- var notificationFeed = streamClient.feed('notification', params.user_id);
-
- cb(null, notificationFeed);
-
- },
-
- // get and loop through activities
- function(notificationFeed, cb) {
-
- // empty array to hold activities
- var arr = [];
-
- // get activities from stream
- notificationFeed.get({ limit: 100 })
- .then(function(stream) {
-
- // length of activity results
- var ln = stream.results.length;
-
- // if length is empty, return
- if (!ln) {
- res.send(204);
- return next();
- }
-
- /*
+ // extract query params
+ var params = req.params || {};
+
+ // async waterfall (see: https://github.com/caolan/async)
+ async.waterfall(
+ [
+ // connect to stream
+ function(cb) {
+ // instantiate a new client (server side)
+ var streamClient = stream.connect(
+ config.stream.key,
+ config.stream.secret,
+ );
+
+ // instantiate a feed using feed class 'notification' and user id from params
+ var notificationFeed = streamClient.feed(
+ 'notification',
+ params.user_id,
+ );
+
+ cb(null, notificationFeed);
+ },
+
+ // get and loop through activities
+ function(notificationFeed, cb) {
+ // empty array to hold activities
+ var arr = [];
+
+ // get activities from stream
+ notificationFeed
+ .get({ limit: 100 })
+ .then(function(stream) {
+ // length of activity results
+ var ln = stream.results.length;
+
+ // if length is empty, return
+ if (!ln) {
+ res.send(204);
+ return next();
+ }
+
+ /*
* Activities stored in Stream reference user ids and upload ids
* We need the full object, not just the reference for the template
* The steps below query the DB to translate user:2 into
* Something like {'username': 'Nick', 'img':...}
*/
- var references = streamUtils.referencesFromActivities(stream.results);
- streamUtils.loadReferencedObjects(references, params.user_id, function(referencedObjects){
- streamUtils.enrichActivities(stream.results, referencedObjects);
- // return the enriched activities
- cb(null, stream.results);
- })
-
-
-
- })
- .catch(function(error) {
- cb(error);
- });
-
- },
-
- // final cb function
- ], function(err, result) {
-
- // catch all errors
- if (err) {
-
- // use global logger to log to console
- log.error(err);
-
- // return error message to client
- return next(new restify.InternalError(err.message));
-
- }
-
- // send response to client
- res.send(200, result);
- return next();
- });
-
+ var references = streamUtils.referencesFromActivities(
+ stream.results,
+ );
+ streamUtils.loadReferencedObjects(
+ references,
+ params.user_id,
+ function(referencedObjects) {
+ streamUtils.enrichActivities(
+ stream.results,
+ referencedObjects,
+ );
+ // return the enriched activities
+ cb(null, stream.results);
+ },
+ );
+ })
+ .catch(function(error) {
+ cb(error);
+ });
+ },
+
+ // final cb function
+ ],
+ function(err, result) {
+ // catch all errors
+ if (err) {
+ // use global logger to log to console
+ log.error(err);
+
+ // return error message to client
+ return next(new restify.InternalError(err.message));
+ }
+
+ // send response to client
+ res.send(200, result);
+ return next();
+ },
+ );
});
diff --git a/api/routes/index.js b/api/routes/index.js
index 47ee32e..bae7ae5 100644
--- a/api/routes/index.js
+++ b/api/routes/index.js
@@ -3,9 +3,9 @@
/**
* Catch All
*/
-server.opts(/\.*/, function (req, res, next) {
- res.send(200);
- next();
+server.opts(/\.*/, function(req, res, next) {
+ res.send(200);
+ next();
});
/**
diff --git a/api/routes/likes.js b/api/routes/likes.js
index 20d45cf..ea0c66c 100644
--- a/api/routes/likes.js
+++ b/api/routes/likes.js
@@ -3,8 +3,8 @@
/**
* Module Dependencies
*/
-var async = require('async'),
- stream = require('getstream');
+var async = require('async'),
+ stream = require('getstream');
/**
* Get all likes (optionally for a specific user and/or upload)
@@ -16,49 +16,47 @@ var async = require('async'),
* @returns {object} Returns a 200 status code with an array of like objects
*/
server.get('/likes', function(req, res, next) {
+ // extract query params
+ var params = req.params || {};
- // extract query params
- var params = req.params || {};
+ // empty array to hold onto our params for sql query
+ var bindings = [];
- // empty array to hold onto our params for sql query
- var bindings = [];
+ // base sql query
+ var userSql = '';
- // base sql query
- var userSql = '';
+ // if a user id was passed in, get all of the likes for that user
+ if (params.user_id) {
+ userSql += `,IF((SELECT 1 AS liked FROM likes WHERE user_id = ? AND upload_id = ?), true, false) AS liked`;
+ bindings.push(params.user_id);
+ bindings.push(params.upload_id);
+ }
- // if a user id was passed in, get all of the likes for that user
- if (params.user_id) {
- userSql += `,IF((SELECT 1 AS liked FROM likes WHERE user_id = ? AND upload_id = ?), true, false) AS liked`;
- bindings.push(params.user_id)
- bindings.push(params.upload_id)
- }
-
- // create like count sql
- var sql = `
+ // create like count sql
+ var sql = `
SELECT
COUNT(*) AS likes
${userSql}
FROM likes
`;
- // if upload id was passed, append query and push upload id into bindings array
- if (params.upload_id) {
- sql += ' WHERE upload_id = ? ';
- bindings.push(params.upload_id)
- }
-
- db.query(sql, bindings, function(err, result) {
- if (err) {
- log.error(err);
- return next(new restify.InternalError(err.message));
- }
- res.send(200, result[0]);
- return next();
- });
-
+ // if upload id was passed, append query and push upload id into bindings array
+ if (params.upload_id) {
+ sql += ' WHERE upload_id = ? ';
+ bindings.push(params.upload_id);
+ }
+
+ db.query(sql, bindings, function(err, result) {
+ if (err) {
+ log.error(err);
+ return next(new restify.InternalError(err.message));
+ }
+ res.send(200, result[0]);
+ return next();
+ });
});
- /**
+/**
* Create a likes for a specific upload
* URL: /likes
* Method: POST
@@ -68,114 +66,124 @@ server.get('/likes', function(req, res, next) {
* @returns {object} Returns a 201 status code with the created object
*/
server.post('/likes', function(req, res, next) {
-
- // extract params from body
- var data = req.body || {};
- data['created_at'] = new Date();
-
- // async waterfall (see: https://github.com/caolan/async)
- async.waterfall([
-
- // insert like into database
- function(cb) {
-
- // execute query and use data passed in via body
- db.query('INSERT INTO likes SET ?', data, function(err, like) {
-
- if (err) {
- log.error(err);
- return next(new restify.InternalError(err.message));
- }
-
- // use object assign to merge row id
- like = Object.assign({ id: like.insertId }, data);
-
- cb(null, like);
-
- });
-
- },
-
- // get user id from upload
- function(like, cb) {
- db.query('SELECT * FROM uploads WHERE id = ?', [like.upload_id], function(err, upload) {
- if (err) {
- cb(err);
- }
- cb(null, like, upload);
- });
- },
- // send back in response
- function(like, upload, cb) {
- db.query('SELECT COUNT(*) AS total FROM likes WHERE upload_id = ?', [ like.upload_id ], function(err, count) {
- if (err) {
- cb(err);
- }
- var result = Object.assign({ id: like.id }, { user_id: upload.user_id }, { likes: count[0].total }, data);
- cb(null, result);
- });
-
- },
-
- function(result, cb) {
- db.query('SELECT user_id FROM uploads WHERE id = ?', [ result.upload_id ], function(err, row) {
- if (err) {
- return cb(err);
- }
- cb(null, Object.assign(result, { to: row[0].user_id }))
- });
- },
-
- // last cb function
- function(result, cb) {
-
- // instantiate a new client (server side)
- var streamClient = stream.connect(config.stream.key, config.stream.secret);
-
- // instantiate a feed using feed class 'user' and the user id from the database
- var userFeed = streamClient.feed('user', data.user_id);
-
- // build activity object for stream feed
- var activity = {
- actor: `user:${data.user_id}`,
- verb: 'like',
- object: `upload:${data.upload_id}`,
- foreign_id: `like:${result.id}`,
- time: data['created_at'],
- to: [`notification:${result.to}`],
- };
-
- // add activity to the feed
- userFeed.addActivity(activity)
- .then(function(response) {
- cb(null, result);
- })
- .catch(function(err) {
- cb(err);
- });
-
- }
-
- // final cb callback
- ], function(err, result) {
-
- // catch all errors
- if (err) {
-
- // use global logger to log to console
- log.error(err);
-
- // return error message to client
- return next(new restify.InternalError(err));
-
- }
-
- // send response to client
- res.send(201, result);
- return next();
-
- });
-
+ // extract params from body
+ var data = req.body || {};
+ data['created_at'] = new Date();
+
+ // async waterfall (see: https://github.com/caolan/async)
+ async.waterfall(
+ [
+ // insert like into database
+ function(cb) {
+ // execute query and use data passed in via body
+ db.query('INSERT INTO likes SET ?', data, function(err, like) {
+ if (err) {
+ log.error(err);
+ return next(new restify.InternalError(err.message));
+ }
+
+ // use object assign to merge row id
+ like = Object.assign({ id: like.insertId }, data);
+
+ cb(null, like);
+ });
+ },
+
+ // get user id from upload
+ function(like, cb) {
+ db.query(
+ 'SELECT * FROM uploads WHERE id = ?',
+ [like.upload_id],
+ function(err, upload) {
+ if (err) {
+ cb(err);
+ }
+ cb(null, like, upload);
+ },
+ );
+ },
+ // send back in response
+ function(like, upload, cb) {
+ db.query(
+ 'SELECT COUNT(*) AS total FROM likes WHERE upload_id = ?',
+ [like.upload_id],
+ function(err, count) {
+ if (err) {
+ cb(err);
+ }
+ var result = Object.assign(
+ { id: like.id },
+ { user_id: upload.user_id },
+ { likes: count[0].total },
+ data,
+ );
+ cb(null, result);
+ },
+ );
+ },
+
+ function(result, cb) {
+ db.query(
+ 'SELECT user_id FROM uploads WHERE id = ?',
+ [result.upload_id],
+ function(err, row) {
+ if (err) {
+ return cb(err);
+ }
+ cb(null, Object.assign(result, { to: row[0].user_id }));
+ },
+ );
+ },
+
+ // last cb function
+ function(result, cb) {
+ // instantiate a new client (server side)
+ var streamClient = stream.connect(
+ config.stream.key,
+ config.stream.secret,
+ );
+
+ // instantiate a feed using feed class 'user' and the user id from the database
+ var userFeed = streamClient.feed('user', data.user_id);
+
+ // build activity object for stream feed
+ var activity = {
+ actor: `user:${data.user_id}`,
+ verb: 'like',
+ object: `upload:${data.upload_id}`,
+ foreign_id: `like:${result.id}`,
+ time: data['created_at'],
+ to: [`notification:${result.to}`],
+ };
+
+ // add activity to the feed
+ userFeed
+ .addActivity(activity)
+ .then(function(response) {
+ cb(null, result);
+ })
+ .catch(function(err) {
+ cb(err);
+ });
+ },
+
+ // final cb callback
+ ],
+ function(err, result) {
+ // catch all errors
+ if (err) {
+ // use global logger to log to console
+ log.error(err);
+
+ // return error message to client
+ return next(new restify.InternalError(err));
+ }
+
+ // send response to client
+ res.send(201, result);
+ return next();
+ },
+ );
});
/**
@@ -188,64 +196,61 @@ server.post('/likes', function(req, res, next) {
* @returns {object} Returns a 201 status code
*/
server.del('/likes', function(req, res, next) {
-
- // extract query params
- var params = req.params || {};
-
- // async waterfall (see: https://github.com/caolan/async)
- async.waterfall([
-
- // delete like form database
- function(cb) {
-
- // execute query
- db.query('DELETE FROM likes WHERE user_id = ? AND upload_id = ?', [ params.user_id, params.upload_id ], function(err, like) {
-
- if (err) {
- cb(err);
- }
-
- cb(null, like);
-
- });
- },
-
- // get like count for response
- function(like, cb) {
-
- // execute query
- db.query('SELECT COUNT(*) AS likes FROM likes WHERE upload_id = ?', [ params.upload_id ], function(err, count) {
-
- if (err) {
- cb(err);
- }
-
- var result = Object.assign(like, count);
-
- cb(null, result);
-
- });
-
- }
-
-// last cb callback
-], function(err, result) {
-
- // catch all errors
- if (err) {
-
- // use global logger to log to console
- log.error(err);
-
- // return error message to client
- return next(new restify.InternalError(err));
-
- }
-
- // send response to client
- res.send(200, result[0]);
- return next();
-
- });
-
+ // extract query params
+ var params = req.params || {};
+
+ // async waterfall (see: https://github.com/caolan/async)
+ async.waterfall(
+ [
+ // delete like form database
+ function(cb) {
+ // execute query
+ db.query(
+ 'DELETE FROM likes WHERE user_id = ? AND upload_id = ?',
+ [params.user_id, params.upload_id],
+ function(err, like) {
+ if (err) {
+ cb(err);
+ }
+
+ cb(null, like);
+ },
+ );
+ },
+
+ // get like count for response
+ function(like, cb) {
+ // execute query
+ db.query(
+ 'SELECT COUNT(*) AS likes FROM likes WHERE upload_id = ?',
+ [params.upload_id],
+ function(err, count) {
+ if (err) {
+ cb(err);
+ }
+
+ var result = Object.assign(like, count);
+
+ cb(null, result);
+ },
+ );
+ },
+
+ // last cb callback
+ ],
+ function(err, result) {
+ // catch all errors
+ if (err) {
+ // use global logger to log to console
+ log.error(err);
+
+ // return error message to client
+ return next(new restify.InternalError(err));
+ }
+
+ // send response to client
+ res.send(200, result[0]);
+ return next();
+ },
+ );
});
diff --git a/api/routes/locations.js b/api/routes/locations.js
index 51e072d..b3b23a5 100644
--- a/api/routes/locations.js
+++ b/api/routes/locations.js
@@ -9,42 +9,36 @@
* @returns {object} Returns a 200 status code with an array of search objects
*/
server.get('/locations', function(req, res, next) {
+ // extract query params
+ var params = req.params || {};
- // extract query params
- var params = req.params || {};
+ // if params don't exist, respond with empty object
+ if (!params.q) {
+ res.send(200, []);
+ return next();
+ }
- // if params don't exist, respond with empty object
- if (!params.q) {
- res.send(200, []);
- return next();
- }
-
- // build sql query
- var sql = `
+ // build sql query
+ var sql = `
SELECT *
FROM uploads
WHERE location LIKE ?
ORDER BY created_at DESC
`;
- // build query
- db.query(sql, [params.q], function(err, result) {
-
- // catch all errors
- if (err) {
-
- // use global logger to log to console
- log.error(err);
-
- // return error message to client
- return next(new restify.InternalError(err.message));
-
- }
-
- // send response to client
- res.send(200, result)
- return next();
-
- });
-
-})
+ // build query
+ db.query(sql, [params.q], function(err, result) {
+ // catch all errors
+ if (err) {
+ // use global logger to log to console
+ log.error(err);
+
+ // return error message to client
+ return next(new restify.InternalError(err.message));
+ }
+
+ // send response to client
+ res.send(200, result);
+ return next();
+ });
+});
diff --git a/api/routes/searches.js b/api/routes/searches.js
index 41e8c98..04bf92e 100644
--- a/api/routes/searches.js
+++ b/api/routes/searches.js
@@ -9,12 +9,11 @@
* @returns {object} Returns a 200 status code with an array of search objects
*/
server.get('/searches', function(req, res, next) {
+ // extract query params
+ var params = req.params || {};
- // extract query params
- var params = req.params || {};
-
- // build sql query
- var sql = `
+ // build sql query
+ var sql = `
SELECT
search,
created_at
@@ -25,26 +24,21 @@ server.get('/searches', function(req, res, next) {
LIMIT 10
`;
- // execute query
- db.query(sql, [ params.user_id ], function(err, results) {
-
- // catch all errors
- if (err) {
-
- // use global logger to log to console
- log.error(err);
-
- // return error message to client
- return next(new restify.InternalError(err.message));
-
- }
-
- // send response to client
- res.send(200, results);
- return next();
-
- });
-
+ // execute query
+ db.query(sql, [params.user_id], function(err, results) {
+ // catch all errors
+ if (err) {
+ // use global logger to log to console
+ log.error(err);
+
+ // return error message to client
+ return next(new restify.InternalError(err.message));
+ }
+
+ // send response to client
+ res.send(200, results);
+ return next();
+ });
});
/**
@@ -57,25 +51,21 @@ server.get('/searches', function(req, res, next) {
* @returns {object} Returns a 200 status code with an array of search objects
*/
server.post('/searches', function(req, res, next) {
-
- // extract params from body
- var data = req.body || {};
-
- // execute query using data from body
- db.query('INSERT INTO searches SET ?', data, function(err, result) {
-
- if (err) {
- log.error(err);
- return next(new restify.InternalError(err.message));
- }
-
- // user object.assign to inject new record id
- result = Object.assign({ id: result.insertId }, data);
-
- // send response to client
- res.send(201, result);
- return next();
-
- });
-
+ // extract params from body
+ var data = req.body || {};
+
+ // execute query using data from body
+ db.query('INSERT INTO searches SET ?', data, function(err, result) {
+ if (err) {
+ log.error(err);
+ return next(new restify.InternalError(err.message));
+ }
+
+ // user object.assign to inject new record id
+ result = Object.assign({ id: result.insertId }, data);
+
+ // send response to client
+ res.send(201, result);
+ return next();
+ });
});
diff --git a/api/routes/stats.js b/api/routes/stats.js
index 5357d5b..084a925 100644
--- a/api/routes/stats.js
+++ b/api/routes/stats.js
@@ -2,7 +2,7 @@
* Module Dependencies
*/
var async = require('async'),
- Keen = require('keen.io');
+ Keen = require('keen.io');
/**
* Upload an image
* URL: /uploads
@@ -12,116 +12,111 @@ var async = require('async'),
* @returns {object} Returns a 201 status code with the upload object
*/
server.get('/stats/:user_id', function(req, res, next) {
-
- // extract query params
- var params = req.params || {};
- var userId = params.user_id;
-
- // async waterfall (see: https://github.com/caolan/async)
- async.waterfall([
-
- // keen query
- function(cb) {
-
- // configure instance of keenClient
- var keenClient = Keen.configure({
- projectId: config.keen.projectId,
- writeKey: config.keen.writeKey,
- readKey: config.keen.readKey,
- masterKey: config.keen.masterKey,
- });
-
- // build query
- var keenQuery = new Keen.Query("count", {
- event_collection: 'views',
- timeframe: 'this_30_days',
- group_by: "postId",
- filters: [{
- property_name: 'postAuthorId',
- operator: 'eq',
- property_value: userId,
- }]
- });
-
- // run query
- keenClient.run(keenQuery, function(err, res) {
-
- if (err) {
- cb(err);
- }
-
- function compareItems(a, b) {
- return (a['result'] - b['result']) * -1;
- }
-
- var sortedItems = res.result;
- sortedItems.sort(compareItems);
-
- var topItems = sortedItems.slice(0, 5);
- var postIds = [];
- var postViewCounts = {};
-
- // loop through top items
- topItems.forEach(function(value) {
- postIds.push(value['postId'])
- postViewCounts[value['postId']] = value['result']
- });
-
- cb(null, postIds, postViewCounts);
-
- });
-
- },
-
- // database query
- function(postIds, postViewCounts, cb) {
-
- // run query if we have results
- if (postIds.length == 0) {
- var uploads = [];
- cb(null, uploads);
- } else {
- db.query('SELECT * FROM uploads WHERE id IN (?)', [postIds], function(err, uploads) {
-
- if (err) {
- log.error(err);
- return next(new restify.InternalError(err.message));
- }
-
- uploads.forEach(function(upload) {
- upload.viewCount = postViewCounts[upload.id]
- });
-
- function compareUploads(a, b) {
- return (a['viewCount'] - b['viewCount']) * -1;
- }
-
- uploads.sort(compareUploads);
-
- cb(null, uploads);
-
- });
- };
-
- }
-
- ], function(err, result) {
-
- // catch all errors
- if (err) {
-
- // use global logger to log to console
- log.error(err);
-
- // return error message to client
- return next(new restify.InternalError(err));
-
- }
-
- // send response to client
- res.send(200, { 'mostViewed': result });
- return next();
-
- });
-
+ // extract query params
+ var params = req.params || {};
+ var userId = params.user_id;
+
+ // async waterfall (see: https://github.com/caolan/async)
+ async.waterfall(
+ [
+ // keen query
+ function(cb) {
+ // configure instance of keenClient
+ var keenClient = Keen.configure({
+ projectId: config.keen.projectId,
+ writeKey: config.keen.writeKey,
+ readKey: config.keen.readKey,
+ masterKey: config.keen.masterKey,
+ });
+
+ // build query
+ var keenQuery = new Keen.Query('count', {
+ event_collection: 'views',
+ timeframe: 'this_30_days',
+ group_by: 'postId',
+ filters: [
+ {
+ property_name: 'postAuthorId',
+ operator: 'eq',
+ property_value: userId,
+ },
+ ],
+ });
+
+ // run query
+ keenClient.run(keenQuery, function(err, res) {
+ if (err) {
+ cb(err);
+ }
+
+ function compareItems(a, b) {
+ return (a['result'] - b['result']) * -1;
+ }
+
+ var sortedItems = res.result;
+ sortedItems.sort(compareItems);
+
+ var topItems = sortedItems.slice(0, 5);
+ var postIds = [];
+ var postViewCounts = {};
+
+ // loop through top items
+ topItems.forEach(function(value) {
+ postIds.push(value['postId']);
+ postViewCounts[value['postId']] = value['result'];
+ });
+
+ cb(null, postIds, postViewCounts);
+ });
+ },
+
+ // database query
+ function(postIds, postViewCounts, cb) {
+ // run query if we have results
+ if (postIds.length == 0) {
+ var uploads = [];
+ cb(null, uploads);
+ } else {
+ db.query(
+ 'SELECT * FROM uploads WHERE id IN (?)',
+ [postIds],
+ function(err, uploads) {
+ if (err) {
+ log.error(err);
+ return next(
+ new restify.InternalError(err.message),
+ );
+ }
+
+ uploads.forEach(function(upload) {
+ upload.viewCount = postViewCounts[upload.id];
+ });
+
+ function compareUploads(a, b) {
+ return (a['viewCount'] - b['viewCount']) * -1;
+ }
+
+ uploads.sort(compareUploads);
+
+ cb(null, uploads);
+ },
+ );
+ }
+ },
+ ],
+ function(err, result) {
+ // catch all errors
+ if (err) {
+ // use global logger to log to console
+ log.error(err);
+
+ // return error message to client
+ return next(new restify.InternalError(err));
+ }
+
+ // send response to client
+ res.send(200, { mostViewed: result });
+ return next();
+ },
+ );
});
diff --git a/api/routes/trending.js b/api/routes/trending.js
index 2a91c17..f793c32 100644
--- a/api/routes/trending.js
+++ b/api/routes/trending.js
@@ -9,12 +9,11 @@
* @returns {object} Returns a 200 status code with an array of upload objects
*/
server.get('/trending', function(req, res, next) {
+ // extract params
+ var params = req.params || {};
- // extract params
- var params = req.params || {};
-
- // build sql query
- var sql = `
+ // build sql query
+ var sql = `
SELECT
uploads.*,
COUNT(likes.id) AS likeTotal
@@ -26,24 +25,19 @@ server.get('/trending', function(req, res, next) {
ORDER BY COUNT(likes.id) DESC
`;
- // execute query
- db.query(sql, [params.user_id], function(err, result) {
-
- // catch all errors
- if (err) {
-
- // use global logger to log to console
- log.error(err);
-
- // return error message to client
- return next(new restify.InternalError(err.message));
-
- }
-
- // send response to client
- res.send(200, result)
- return next();
-
- });
-
+ // execute query
+ db.query(sql, [params.user_id], function(err, result) {
+ // catch all errors
+ if (err) {
+ // use global logger to log to console
+ log.error(err);
+
+ // return error message to client
+ return next(new restify.InternalError(err.message));
+ }
+
+ // send response to client
+ res.send(200, result);
+ return next();
+ });
});
diff --git a/api/routes/uploads.js b/api/routes/uploads.js
index b909d24..14f8435 100644
--- a/api/routes/uploads.js
+++ b/api/routes/uploads.js
@@ -3,13 +3,13 @@
/**
* Module Dependencies
*/
-var knox = require('knox'),
- uuid = require('node-uuid'),
- geo = require('mapbox-geocoding'),
- async = require('async'),
- stream = require('getstream'),
- streamUtils = require('../lib/stream_utils'),
- algoliaSearch = require('algoliasearch');
+var knox = require('knox'),
+ uuid = require('node-uuid'),
+ geo = require('mapbox-geocoding'),
+ async = require('async'),
+ stream = require('getstream'),
+ streamUtils = require('../lib/stream_utils'),
+ algoliaSearch = require('algoliasearch');
/**
* Get uploads based on query
@@ -22,140 +22,141 @@ var knox = require('knox'),
* @returns {object} Returns a 200 status code with an array of upload objects
*/
server.get('/uploads', function(req, res, next) {
-
- // extract query params
- var params = req.params || {};
-
- // default sql
- var sql = '';
-
- // if the params type and query are defined, build query for 'type'
- if (params.type && params.query) {
-
- // check type and build query
- switch (params.type) {
- case 'hashtags':
- sql = `
+ // extract query params
+ var params = req.params || {};
+
+ // default sql
+ var sql = '';
+
+ // if the params type and query are defined, build query for 'type'
+ if (params.type && params.query) {
+ // check type and build query
+ switch (params.type) {
+ case 'hashtags':
+ sql = `
SELECT *
FROM uploads
WHERE hashtags LIKE '%${params.query.substring(1)}%'
`;
- break;
- case 'location':
- sql = `
+ break;
+ case 'location':
+ sql = `
SELECT *
FROM uploads
WHERE location LIKE '%${params.query}%'
`;
- break;
- case 'user':
- const userName = params.query.split(' ')
- sql = `
+ break;
+ case 'user':
+ const userName = params.query.split(' ');
+ sql = `
SELECT *
FROM uploads
LEFT JOIN users
ON uploads.user_id = users.id
WHERE users.first_name = ${db.escape(userName[0])}
- AND CONCAT(SUBSTR(users.last_name, 1, 1), '.') = ${db.escape(userName[1])}
+ AND CONCAT(SUBSTR(users.last_name, 1, 1), '.') = ${db.escape(
+ userName[1],
+ )}
`;
- break;
- }
-
- // execute sql query
- db.query(sql, function(err, result) {
-
- // catch all errors
- if (err) {
-
- // use global logger to log to console
- log.error(err);
-
- // return error message to client
- return next(new restify.InternalError(err.message));
-
- }
-
- // send response to client
- res.send(200, result);
- return next();
-
- });
-
- // otherwise default to normal query
- } else {
-
- // async waterfall (see: https://github.com/caolan/async)
- async.waterfall([
-
- // connect to stream
- function(cb) {
-
- // instantiate a new client (server side)
- var streamClient = stream.connect(config.stream.key, config.stream.secret);
-
- // instantiate a feed using feed class 'timeline_flat' and user id from params
- var timelineFlatFeed = streamClient.feed('timeline_flat', params.user_id);
-
- cb(null, timelineFlatFeed);
-
- },
-
- // get and loop through activities
- function(timelineFlatFeed, cb) {
-
- // build query params for stream (id_lt is preferred)
- var uploadGetParams = { limit: 5, }
- if (params.last_id) uploadGetParams.id_lt = params.last_id
-
- // get activities from stream
- timelineFlatFeed.get(uploadGetParams)
- .then(function(stream) {
-
- // length of activity results
- var ln = stream.results.length;
-
- // exit if length is zero
- if (!ln) {
- res.send(204);
- return next();
- }
-
- // enrich the activities
- var references = streamUtils.referencesFromActivities(stream.results);
- streamUtils.loadReferencedObjects(references, params.user_id, function(referencedObjects) {
- streamUtils.enrichActivities(stream.results, referencedObjects);
- cb(null, stream.results);
- });
-
- })
- .catch(function(error) {
- cb(error);
- });
-
- }
-
- // final cb callback
- ], function(err, result) {
-
- // catch all errors
- if (err) {
-
- // use global logger to log to console
- log.error(err);
-
- // return error message to client
- return next(new restify.InternalError(err));
-
- }
-
- // send response to client
- res.send(200, result);
- return next();
-
- });
-
- }
-
+ break;
+ }
+
+ // execute sql query
+ db.query(sql, function(err, result) {
+ // catch all errors
+ if (err) {
+ // use global logger to log to console
+ log.error(err);
+
+ // return error message to client
+ return next(new restify.InternalError(err.message));
+ }
+
+ // send response to client
+ res.send(200, result);
+ return next();
+ });
+
+ // otherwise default to normal query
+ } else {
+ // async waterfall (see: https://github.com/caolan/async)
+ async.waterfall(
+ [
+ // connect to stream
+ function(cb) {
+ // instantiate a new client (server side)
+ var streamClient = stream.connect(
+ config.stream.key,
+ config.stream.secret,
+ );
+
+ // instantiate a feed using feed class 'timeline_flat' and user id from params
+ var timelineFlatFeed = streamClient.feed(
+ 'timeline_flat',
+ params.user_id,
+ );
+
+ cb(null, timelineFlatFeed);
+ },
+
+ // get and loop through activities
+ function(timelineFlatFeed, cb) {
+ // build query params for stream (id_lt is preferred)
+ var uploadGetParams = { limit: 5 };
+ if (params.last_id) uploadGetParams.id_lt = params.last_id;
+
+ // get activities from stream
+ timelineFlatFeed
+ .get(uploadGetParams)
+ .then(function(stream) {
+ // length of activity results
+ var ln = stream.results.length;
+
+ // exit if length is zero
+ if (!ln) {
+ res.send(204);
+ return next();
+ }
+
+ // enrich the activities
+ var references = streamUtils.referencesFromActivities(
+ stream.results,
+ );
+ streamUtils.loadReferencedObjects(
+ references,
+ params.user_id,
+ function(referencedObjects) {
+ streamUtils.enrichActivities(
+ stream.results,
+ referencedObjects,
+ );
+ cb(null, stream.results);
+ },
+ );
+ })
+ .catch(function(error) {
+ cb(error);
+ });
+ },
+
+ // final cb callback
+ ],
+ function(err, result) {
+ // catch all errors
+ if (err) {
+ // use global logger to log to console
+ log.error(err);
+
+ // return error message to client
+ return next(new restify.InternalError(err));
+ }
+
+ // send response to client
+ res.send(200, result);
+ return next();
+ },
+ );
+ }
});
/**
@@ -168,12 +169,11 @@ server.get('/uploads', function(req, res, next) {
* @returns {object} Returns a 200 status code with the upload object
*/
server.get('/upload', function(req, res, next) {
+ // extract query params
+ var params = req.params || {};
- // extract query params
- var params = req.params || {};
-
- // build sql statement
- var sql = `
+ // build sql statement
+ var sql = `
SELECT
uploads.*,
users.id AS user_id,
@@ -189,26 +189,21 @@ server.get('/upload', function(req, res, next) {
ORDER BY uploads.created_at DESC
`;
- // execute sql query
- db.query(sql, [params.user_id, params.id], function(err, result) {
-
- // catch all errors
- if (err) {
-
- // use global logger to log to console
- log.error(err);
-
- // return error message to client
- return next(new restify.InternalError(err.message));
-
- }
-
- // send response to client
- res.send(200, result[0]);
- return next();
-
- });
-
+ // execute sql query
+ db.query(sql, [params.user_id, params.id], function(err, result) {
+ // catch all errors
+ if (err) {
+ // use global logger to log to console
+ log.error(err);
+
+ // return error message to client
+ return next(new restify.InternalError(err.message));
+ }
+
+ // send response to client
+ res.send(200, result[0]);
+ return next();
+ });
});
/**
@@ -224,160 +219,159 @@ server.get('/upload', function(req, res, next) {
* @returns {object} Returns a 201 status code with the upload object
*/
server.post('/uploads', function(req, res, next) {
-
- // extract params from body and file from uploaded files
- var data = req.body || {},
- file = req.files || {};
-
- // generate unique filename using uuid and assign to object
- data.filename = uuid.v4();
- data['created_at'] = new Date();
-
- // async waterfall (see: https://github.com/caolan/async)
- async.waterfall([
-
- // upload file to amazon s3
- function(cb) {
-
- // initialize knox client
- var knoxClient = knox.createClient({
- key: config.s3.key,
- secret: config.s3.secret,
- bucket: config.s3.bucket
- });
-
- // send put via knox
- knoxClient.putFile(file.image.path, 'uploads/' + data.filename, {
- 'Content-Type': file.image.type,
- 'x-amz-acl': 'public-read'
- }, function(err, result) {
-
- if (err || result.statusCode != 200) {
- cb(err);
- } else {
-
- cb(null);
- }
- });
-
- },
-
- // use mapbox to get latitude and longitude
- function(cb) {
-
- // initialize mapbox client
- geo.setAccessToken(config.mapbox.accessToken);
-
- // get location data
- geo.geocode('mapbox.places', data.location, function (err, location) {
-
- if (err) {
- cb(err);
- } else {
-
- // if the location was found
- if (location.features.length) {
-
- // extract coorindates
- var coords = location.features[0].geometry.coordinates;
- if (coords.length) {
-
- // assign to latitude and longitude in data object
- data.longitude = coords[0];
- data.latitude = coords[1];
-
- }
-
- }
-
- cb(null)
- }
- });
-
- },
-
- // insert record into database
- function(cb) {
-
- // run query using node mysql, passing the data object as params
- db.query('INSERT INTO uploads SET ?', data, function(err, result) {
-
- if (err) {
- cb(err);
- } else {
-
- // use object assign to merge the object id
- result = Object.assign({}, { id: result.insertId }, data);
-
- cb(null, result);
- }
- });
-
- },
-
- // submit to algolia for indexing
- function(result, cb) {
-
- // initialize algolia
- var algolia = algoliaSearch(config.algolia.appId, config.algolia.apiKey);
-
- // initialize algoia index
- var index = algolia.initIndex('cabin');
-
- // add returned database object for indexing
- index.addObject(result);
-
- cb(null, result);
-
- },
-
- // submit to stream
- function(result, cb) {
-
- // instantiate a new client (server side)
- var streamClient = stream.connect(config.stream.key, config.stream.secret);
-
- // build activity object for stream feed
- var activity = {
- actor: `user:${data.user_id}`,
- verb: 'add',
- object: `upload:${result.id}`,
- foreign_id: `upload:${result.id}`,
- time: data['created_at']
- };
-
- // instantiate a feed using feed class 'user_posts' and the user id from the database
- var userFeed = streamClient.feed('user_posts', data.user_id);
-
- // add activity to the feed
- userFeed.addActivity(activity)
- .then(function(response) {
- cb(null, result);
- })
- .catch(function(err) {
- cb(err);
- });
-
- }
-
- // final cb function
- ], function(err, result) {
-
- // catch all errors
- if (err) {
-
- // use global logger to log to console
- log.error(err);
-
- // return error message to client
- return next(new restify.InternalError(err));
-
- }
-
- // respond to client with result from database
- res.send(201, result);
- return next();
-
- });
-
+ // extract params from body and file from uploaded files
+ var data = req.body || {},
+ file = req.files || {};
+
+ // generate unique filename using uuid and assign to object
+ data.filename = uuid.v4();
+ data['created_at'] = new Date();
+
+ // async waterfall (see: https://github.com/caolan/async)
+ async.waterfall(
+ [
+ // upload file to amazon s3
+ function(cb) {
+ // initialize knox client
+ var knoxClient = knox.createClient({
+ key: config.s3.key,
+ secret: config.s3.secret,
+ bucket: config.s3.bucket,
+ });
+
+ // send put via knox
+ knoxClient.putFile(
+ file.image.path,
+ 'uploads/' + data.filename,
+ {
+ 'Content-Type': file.image.type,
+ 'x-amz-acl': 'public-read',
+ },
+ function(err, result) {
+ if (err || result.statusCode != 200) {
+ cb(err);
+ } else {
+ cb(null);
+ }
+ },
+ );
+ },
+
+ // use mapbox to get latitude and longitude
+ function(cb) {
+ // initialize mapbox client
+ geo.setAccessToken(config.mapbox.accessToken);
+
+ // get location data
+ geo.geocode('mapbox.places', data.location, function(
+ err,
+ location,
+ ) {
+ if (err) {
+ cb(err);
+ } else {
+ // if the location was found
+ if (location.features.length) {
+ // extract coorindates
+ var coords =
+ location.features[0].geometry.coordinates;
+ if (coords.length) {
+ // assign to latitude and longitude in data object
+ data.longitude = coords[0];
+ data.latitude = coords[1];
+ }
+ }
+
+ cb(null);
+ }
+ });
+ },
+
+ // insert record into database
+ function(cb) {
+ // run query using node mysql, passing the data object as params
+ db.query('INSERT INTO uploads SET ?', data, function(
+ err,
+ result,
+ ) {
+ if (err) {
+ cb(err);
+ } else {
+ // use object assign to merge the object id
+ result = Object.assign(
+ {},
+ { id: result.insertId },
+ data,
+ );
+
+ cb(null, result);
+ }
+ });
+ },
+
+ // submit to algolia for indexing
+ function(result, cb) {
+ // initialize algolia
+ var algolia = algoliaSearch(
+ config.algolia.appId,
+ config.algolia.apiKey,
+ );
+
+ // initialize algoia index
+ var index = algolia.initIndex('cabin');
+
+ // add returned database object for indexing
+ index.addObject(result);
+
+ cb(null, result);
+ },
+
+ // submit to stream
+ function(result, cb) {
+ // instantiate a new client (server side)
+ var streamClient = stream.connect(
+ config.stream.key,
+ config.stream.secret,
+ );
+
+ // build activity object for stream feed
+ var activity = {
+ actor: `user:${data.user_id}`,
+ verb: 'add',
+ object: `upload:${result.id}`,
+ foreign_id: `upload:${result.id}`,
+ time: data['created_at'],
+ };
+
+ // instantiate a feed using feed class 'user_posts' and the user id from the database
+ var userFeed = streamClient.feed('user_posts', data.user_id);
+
+ // add activity to the feed
+ userFeed
+ .addActivity(activity)
+ .then(function(response) {
+ cb(null, result);
+ })
+ .catch(function(err) {
+ cb(err);
+ });
+ },
+
+ // final cb function
+ ],
+ function(err, result) {
+ // catch all errors
+ if (err) {
+ // use global logger to log to console
+ log.error(err);
+
+ // return error message to client
+ return next(new restify.InternalError(err));
+ }
+
+ // respond to client with result from database
+ res.send(201, result);
+ return next();
+ },
+ );
});
diff --git a/api/routes/users.js b/api/routes/users.js
index fa6b252..59fe4db 100644
--- a/api/routes/users.js
+++ b/api/routes/users.js
@@ -3,11 +3,11 @@
/**
* Module Dependencies
*/
-var stream = require('getstream'),
- jwt = require('jsonwebtoken'),
- async = require('async'),
- FB = require('fb'),
- algoliaSearch = require('algoliasearch');
+var stream = require('getstream'),
+ jwt = require('jsonwebtoken'),
+ async = require('async'),
+ FB = require('fb'),
+ algoliaSearch = require('algoliasearch');
/**
* Get user by id
@@ -18,21 +18,19 @@ var stream = require('getstream'),
* @returns {object} Returns a 200 status code with the user object
*/
server.get('/users/:id', function(req, res, next) {
+ // extract params
+ var params = req.params || {};
- // extract params
- var params = req.params || {};
+ // empty array to hold bindings
+ var bindings = [];
- // empty array to hold bindings
- var bindings = [];
+ // base sql query
+ var sql = '';
- // base sql query
- var sql = '';
-
- // if a user id exists
- if (params.user_id) {
-
- // build sql query
- sql = `
+ // if a user id exists
+ if (params.user_id) {
+ // build sql query
+ sql = `
SELECT
users.id AS id,
users.fb_uid AS fb_uid,
@@ -68,14 +66,20 @@ server.get('/users/:id', function(req, res, next) {
OR email = ?
`;
- // push query params into bindings array
- bindings = [params.user_id, params.user_id, params.id, params.id, params.id, params.id];
-
- // select user based off of provided fb_uid or email
- } else {
-
- // build sql
- sql = `
+ // push query params into bindings array
+ bindings = [
+ params.user_id,
+ params.user_id,
+ params.id,
+ params.id,
+ params.id,
+ params.id,
+ ];
+
+ // select user based off of provided fb_uid or email
+ } else {
+ // build sql
+ sql = `
SELECT
users.id AS id,
users.fb_uid AS fb_uid,
@@ -90,34 +94,28 @@ server.get('/users/:id', function(req, res, next) {
OR email = ?
`;
- // push query params into bindings array
- bindings = [params.id, params.id, params.id];
-
- }
-
- // execute query
- db.query(sql, bindings, function(err, result) {
-
- // catch all errors
- if (err) {
-
- // use global logger to log to console
- log.error(err);
+ // push query params into bindings array
+ bindings = [params.id, params.id, params.id];
+ }
- // return error message to client
- return next(new restify.InternalError(err.message));
+ // execute query
+ db.query(sql, bindings, function(err, result) {
+ // catch all errors
+ if (err) {
+ // use global logger to log to console
+ log.error(err);
- }
+ // return error message to client
+ return next(new restify.InternalError(err.message));
+ }
- // use object.assign to merge stream tokens
- result = Object.assign({}, result[0]);
-
- // send response to client
- res.send(200, result);
- return next();
-
- });
+ // use object.assign to merge stream tokens
+ result = Object.assign({}, result[0]);
+ // send response to client
+ res.send(200, result);
+ return next();
+ });
});
/**
@@ -132,152 +130,200 @@ server.get('/users/:id', function(req, res, next) {
* @returns {object} Returns a 201 or 200 status code with the user object
*/
server.post('/users', function(req, res, next) {
-
- // extract data from body
- var data = req.body || {};
- var fbUserId = data.fb_user_id;
- var accessToken = data.token;
- var options = {
- appId : '1714548178824131',
- xfbml : true,
- version : 'v2.6',
- status : true,
- cookie : true,
- };
- var fb = new FB.Facebook(options);
- fb.setAccessToken(accessToken);
-
- async.waterfall([
-
- function (cb) {
- // query the userdata from FB
- fb.api('/me', 'get', { fields: 'id,name,email, first_name, last_name' }, function(facebookUserData) {
- cb(null, facebookUserData);
- });
- },
-
- function(facebookUserData, cb) {
-
- // build the data we're going to insert
- var data = {};
- data.email = facebookUserData.email;
- data.fb_uid = facebookUserData.id;
- data.first_name = facebookUserData.first_name;
- data.last_name = facebookUserData.last_name;
-
- // try select first
- db.query('SELECT * FROM users WHERE email=' + db.escape(data.email), function(err, result) {
-
- if (err) {
- log.error(err);
- return next(new restify.InternalError(err.message));
- }
-
- // instantiate a new client (server side)
- var streamClient = stream.connect(config.stream.key, config.stream.secret);
-
- // generate jwt
- var jwtToken = jwt.sign({
- request: {
- email: data.email
- }
- }, config.jwt.secret);
-
- // if user exists, return result
- if (result.length) {
-
- var userId = result[0].id;
-
- // get tokens from stream client
- var tokens = {
- timeline: {
- flat: streamClient.getReadOnlyToken('timeline_flat', userId),
- aggregated: streamClient.getReadOnlyToken('timeline_aggregrated', userId),
- },
- notification : streamClient.getReadOnlyToken('notification', userId),
- };
-
- // user object.assign to insert tokens from stream and jwt
- result = Object.assign({}, result[0], { tokens: tokens }, { jwt: jwtToken });
-
- // send response to client
- res.send(200, result);
- return next();
-
- }
-
- // execute query
- db.query('INSERT INTO users SET ?', data, function(err, result) {
-
- if (err) {
- log.error(err);
- return next(new restify.InternalError(err.message));
- }
-
- // user object.assign to insert new row id and tokens from stream
- result = Object.assign({}, { id: result.insertId }, data, tokens);
-
- // initialize algolia
- var algolia = algoliaSearch(config.algolia.appId, config.algolia.apiKey);
-
- // initialize algoia index
- var index = algolia.initIndex('cabin');
-
- // add returned database object for indexing
- index.addObject(result);
-
- // use object.assign insert jwt
- result = Object.assign({}, result, { jwt: jwtToken });
-
- var userId = result.id;
-
- // auto follow user id 1 (a.k.a stream cabin)
- db.query('INSERT INTO followers SET user_id=?, follower_id=?', [userId, 1], function(err, result) {
-
- // instantiate a new client (server side)
- var streamClient = stream.connect(config.stream.key, config.stream.secret);
-
- // instantiate a feed using feed class 'user' and the user id from the database
- var userFeed = streamClient.feed('user', userId);
-
- // build activity object for stream feed
- var activity = {
- actor: `user:${userId}`,
- verb: 'follow',
- object: `user:${1}`,
- foreign_id: `follow:${userId}`,
- time: data['created_at'],
- to: [`notification:${1}`]
- };
-
- // instantiate a feed using feed class 'timeline_flat' and the user id from the database
- var timeline = streamClient.feed('timeline_flat', userId);
- timeline.follow('user_posts', 1);
-
- // instantiate a feed using feed class 'timeline_aggregated' and the user id from the database
- var timelineAggregated = streamClient.feed('timeline_aggregated', userId);
- timelineAggregated.follow('user', 1);
-
- // add activity to the feed
- userFeed.addActivity(activity)
- .then(function(response) {
-
- // send response to client
- res.send(201, result);
- return next();
-
- })
- .catch(function(reason) {
- log.error(reason);
- return next(new restify.InternalError(reason.error));
- });
-
- });
-
- });
-
- });
- }]);
+ // extract data from body
+ var data = req.body || {};
+ var fbUserId = data.fb_user_id;
+ var accessToken = data.token;
+ var options = {
+ appId: '1714548178824131',
+ xfbml: true,
+ version: 'v2.6',
+ status: true,
+ cookie: true,
+ };
+ var fb = new FB.Facebook(options);
+ fb.setAccessToken(accessToken);
+
+ async.waterfall([
+ function(cb) {
+ // query the userdata from FB
+ fb.api(
+ '/me',
+ 'get',
+ { fields: 'id,name,email, first_name, last_name' },
+ function(facebookUserData) {
+ cb(null, facebookUserData);
+ },
+ );
+ },
+
+ function(facebookUserData, cb) {
+ // build the data we're going to insert
+ var data = {};
+ data.email = facebookUserData.email;
+ data.fb_uid = facebookUserData.id;
+ data.first_name = facebookUserData.first_name;
+ data.last_name = facebookUserData.last_name;
+
+ // try select first
+ db.query(
+ 'SELECT * FROM users WHERE email=' + db.escape(data.email),
+ function(err, result) {
+ if (err) {
+ log.error(err);
+ return next(new restify.InternalError(err.message));
+ }
+
+ // instantiate a new client (server side)
+ var streamClient = stream.connect(
+ config.stream.key,
+ config.stream.secret,
+ );
+
+ // generate jwt
+ var jwtToken = jwt.sign(
+ {
+ request: {
+ email: data.email,
+ },
+ },
+ config.jwt.secret,
+ );
+
+ // if user exists, return result
+ if (result.length) {
+ var userId = result[0].id;
+
+ // get tokens from stream client
+ var tokens = {
+ timeline: {
+ flat: streamClient.getReadOnlyToken(
+ 'timeline_flat',
+ userId,
+ ),
+ aggregated: streamClient.getReadOnlyToken(
+ 'timeline_aggregrated',
+ userId,
+ ),
+ },
+ notification: streamClient.getReadOnlyToken(
+ 'notification',
+ userId,
+ ),
+ };
+
+ // user object.assign to insert tokens from stream and jwt
+ result = Object.assign(
+ {},
+ result[0],
+ { tokens: tokens },
+ { jwt: jwtToken },
+ );
+
+ // send response to client
+ res.send(200, result);
+ return next();
+ }
+
+ // execute query
+ db.query('INSERT INTO users SET ?', data, function(
+ err,
+ result,
+ ) {
+ if (err) {
+ log.error(err);
+ return next(new restify.InternalError(err.message));
+ }
+
+ // user object.assign to insert new row id and tokens from stream
+ result = Object.assign(
+ {},
+ { id: result.insertId },
+ data,
+ tokens,
+ );
+
+ // initialize algolia
+ var algolia = algoliaSearch(
+ config.algolia.appId,
+ config.algolia.apiKey,
+ );
+
+ // initialize algoia index
+ var index = algolia.initIndex('cabin');
+
+ // add returned database object for indexing
+ index.addObject(result);
+
+ // use object.assign insert jwt
+ result = Object.assign({}, result, { jwt: jwtToken });
+
+ var userId = result.id;
+
+ // auto follow user id 1 (a.k.a stream cabin)
+ db.query(
+ 'INSERT INTO followers SET user_id=?, follower_id=?',
+ [userId, 1],
+ function(err, result) {
+ // instantiate a new client (server side)
+ var streamClient = stream.connect(
+ config.stream.key,
+ config.stream.secret,
+ );
+
+ // instantiate a feed using feed class 'user' and the user id from the database
+ var userFeed = streamClient.feed(
+ 'user',
+ userId,
+ );
+
+ // build activity object for stream feed
+ var activity = {
+ actor: `user:${userId}`,
+ verb: 'follow',
+ object: `user:${1}`,
+ foreign_id: `follow:${userId}`,
+ time: data['created_at'],
+ to: [`notification:${1}`],
+ };
+
+ // instantiate a feed using feed class 'timeline_flat' and the user id from the database
+ var timeline = streamClient.feed(
+ 'timeline_flat',
+ userId,
+ );
+ timeline.follow('user_posts', 1);
+
+ // instantiate a feed using feed class 'timeline_aggregated' and the user id from the database
+ var timelineAggregated = streamClient.feed(
+ 'timeline_aggregated',
+ userId,
+ );
+ timelineAggregated.follow('user', 1);
+
+ // add activity to the feed
+ userFeed
+ .addActivity(activity)
+ .then(function(response) {
+ // send response to client
+ res.send(201, result);
+ return next();
+ })
+ .catch(function(reason) {
+ log.error(reason);
+ return next(
+ new restify.InternalError(
+ reason.error,
+ ),
+ );
+ });
+ },
+ );
+ });
+ },
+ );
+ },
+ ]);
});
/**
@@ -289,25 +335,22 @@ server.post('/users', function(req, res, next) {
* @returns {object} Returns a 204 status code
*/
server.del('/users/:user_id', function(req, res, next) {
-
- var params = req.params || {};
-
- db.query('DELETE FROM users WHERE id = ?', [params.user_id], function(err, result) {
-
- // catch all errors
- if (err) {
-
- // use global logger to log to console
- log.error(err);
-
- // return error message to client
- return next(new restify.InternalError(err.message));
-
- }
-
- res.send(204);
- return next();
-
- });
-
+ var params = req.params || {};
+
+ db.query('DELETE FROM users WHERE id = ?', [params.user_id], function(
+ err,
+ result,
+ ) {
+ // catch all errors
+ if (err) {
+ // use global logger to log to console
+ log.error(err);
+
+ // return error message to client
+ return next(new restify.InternalError(err.message));
+ }
+
+ res.send(204);
+ return next();
+ });
});
diff --git a/api/yarn.lock b/api/yarn.lock
index 815db12..53398e8 100644
--- a/api/yarn.lock
+++ b/api/yarn.lock
@@ -2,9 +2,9 @@
# yarn lockfile v1
-Base64@>=0.3.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/Base64/-/Base64-1.0.0.tgz#b6b73ee342ce64bf66d6003a4536683bf8a349b5"
+Base64@~1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/Base64/-/Base64-1.0.1.tgz#def45cc50c961bcc9bf2321d0f52bcbfec1f1bb1"
addressparser@^0.3.2:
version "0.3.2"
@@ -14,7 +14,7 @@ addressparser@~0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/addressparser/-/addressparser-0.2.1.tgz#d11a5b2eeda04cfefebdf3196c10ae13db6cd607"
-agentkeepalive@^2.1.1:
+agentkeepalive@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-2.2.0.tgz#c5d1bd4b129008f1163f236f86e5faea2026e2ef"
@@ -25,17 +25,26 @@ ajv@^4.9.1:
co "^4.6.0"
json-stable-stringify "^1.0.1"
-algoliasearch@^3.15.0:
- version "3.22.1"
- resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-3.22.1.tgz#132abb11134c52a3fd3ded3fcf6acb64f5eb738d"
+ajv@^5.1.0:
+ version "5.5.2"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965"
+ dependencies:
+ co "^4.6.0"
+ fast-deep-equal "^1.0.0"
+ fast-json-stable-stringify "^2.0.0"
+ json-schema-traverse "^0.3.0"
+
+algoliasearch@^3.24.9:
+ version "3.24.9"
+ resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-3.24.9.tgz#19063470efe5b6779ec081394b1f7aa400438273"
dependencies:
- agentkeepalive "^2.1.1"
- debug "2.3.3"
+ agentkeepalive "^2.2.0"
+ debug "^2.6.8"
envify "^4.0.0"
- es6-promise "^4.0.5"
+ es6-promise "^4.1.0"
events "^1.1.0"
foreach "^2.0.5"
- global "^4.3.0"
+ global "^4.3.2"
inherits "^2.0.1"
isarray "^2.0.1"
load-script "^1.0.0"
@@ -43,7 +52,19 @@ algoliasearch@^3.15.0:
querystring-es3 "^0.2.1"
reduce "^1.0.1"
semver "^5.1.0"
- tunnel-agent "^0.4.3"
+ tunnel-agent "^0.6.0"
+
+ansi-regex@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
+
+ansi-styles@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
+
+any-promise@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
asap@*:
version "2.0.5"
@@ -73,9 +94,9 @@ async@^0.9.0, async@~0.9.0:
version "0.9.2"
resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d"
-async@^2.0.0-rc.6:
- version "2.1.5"
- resolved "https://registry.yarnpkg.com/async/-/async-2.1.5.tgz#e587c68580994ac67fc56ff86d3ac56bdbe810bc"
+async@^2.6.0:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4"
dependencies:
lodash "^4.14.0"
@@ -91,22 +112,20 @@ aws-sign2@~0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f"
-aws4@^1.2.1:
+aws-sign2@~0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
+
+aws4@^1.2.1, aws4@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
-babel-runtime@^6.3.19:
- version "6.23.0"
- resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b"
+babel-runtime@^6.23.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
dependencies:
core-js "^2.4.0"
- regenerator-runtime "^0.10.0"
-
-backoff@^2.4.0:
- version "2.5.0"
- resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f"
- dependencies:
- precond "0.2"
+ regenerator-runtime "^0.11.0"
balanced-match@^0.4.1:
version "0.4.2"
@@ -122,9 +141,15 @@ bcrypt-pbkdf@^1.0.0:
dependencies:
tweetnacl "^0.14.3"
-bignumber.js@3.1.2:
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-3.1.2.tgz#f3bdb99ad5268a15fc1f0bed2fb018e2693fe236"
+bignumber.js@4.0.4:
+ version "4.0.4"
+ resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-4.0.4.tgz#7c40f5abcd2d6623ab7b99682ee7db81b11889a4"
+
+bl@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/bl/-/bl-1.1.2.tgz#fdca871a99713aa00d19e3bbba41c44787a65398"
+ dependencies:
+ readable-stream "~2.0.5"
boom@2.x.x:
version "2.10.1"
@@ -132,6 +157,18 @@ boom@2.x.x:
dependencies:
hoek "2.x.x"
+boom@4.x.x:
+ version "4.3.1"
+ resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31"
+ dependencies:
+ hoek "4.x.x"
+
+boom@5.x.x:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02"
+ dependencies:
+ hoek "4.x.x"
+
brace-expansion@^1.0.0:
version "1.1.6"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9"
@@ -155,28 +192,40 @@ bunyan-winston-adapter@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/bunyan-winston-adapter/-/bunyan-winston-adapter-0.2.0.tgz#950310633405ab5e65fdb7fee76f18fe6a998fcd"
-bunyan@^1.4.0:
- version "1.8.8"
- resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.8.tgz#6549ed6db088e4d82b7be3bcc6d0697159f6e209"
+bunyan@^1.8.0, bunyan@^1.8.12:
+ version "1.8.12"
+ resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.12.tgz#f150f0f6748abdd72aeae84f04403be2ef113797"
optionalDependencies:
dtrace-provider "~0.8"
moment "^2.10.6"
mv "~2"
safe-json-stringify "~1"
-bunyan@^1.8.10:
- version "1.8.10"
- resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.10.tgz#201fedd26c7080b632f416072f53a90b9a52981c"
- optionalDependencies:
- dtrace-provider "~0.8"
- moment "^2.10.6"
- mv "~2"
- safe-json-stringify "~1"
+caseless@~0.11.0:
+ version "0.11.0"
+ resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7"
caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
+chalk@^1.1.1:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
+ dependencies:
+ ansi-styles "^2.2.1"
+ escape-string-regexp "^1.0.2"
+ has-ansi "^2.0.0"
+ strip-ansi "^3.0.0"
+ supports-color "^2.0.0"
+
+clone-regexp@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-1.0.0.tgz#eae0a2413f55c0942f818c229fefce845d7f3b1c"
+ dependencies:
+ is-regexp "^1.0.0"
+ is-supported-regexp-flag "^1.0.0"
+
co@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
@@ -197,6 +246,10 @@ combined-stream@~0.0.4:
dependencies:
delayed-stream "0.0.5"
+commander@^2.9.0:
+ version "2.13.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c"
+
component-emitter@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.1.2.tgz#296594f2753daa63996d2af08d15a95116c9aec3"
@@ -205,10 +258,6 @@ concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
-cookie@0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.1.0.tgz#90eb469ddce905c866de687efc43131d8801f9d0"
-
cookie@0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
@@ -217,9 +266,9 @@ cookiejar@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.0.1.tgz#3d12752f6adf68a892f332433492bd5812bb668f"
-core-decorators@^0.12.3:
- version "0.12.3"
- resolved "https://registry.yarnpkg.com/core-decorators/-/core-decorators-0.12.3.tgz#6b3f83378e680d48b0c08da4489899b7532dcb43"
+core-decorators@^0.17.0:
+ version "0.17.0"
+ resolved "https://registry.yarnpkg.com/core-decorators/-/core-decorators-0.17.0.tgz#3f43180a86d2ab0cc51069f46a1ec3e49e7cebd6"
core-js@^2.4.0:
version "2.4.1"
@@ -235,32 +284,40 @@ cryptiles@2.x.x:
dependencies:
boom "2.x.x"
+cryptiles@3.x.x:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe"
+ dependencies:
+ boom "5.x.x"
+
csprng@*:
version "0.1.2"
resolved "https://registry.yarnpkg.com/csprng/-/csprng-0.1.2.tgz#4bc68f12fa368d252a59841cbaca974b18ab45e2"
dependencies:
sequin "*"
-csv-generate@^0.0.6:
- version "0.0.6"
- resolved "https://registry.yarnpkg.com/csv-generate/-/csv-generate-0.0.6.tgz#97e4e63ae46b21912cd9475bc31469d26f5ade66"
+csv-generate@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/csv-generate/-/csv-generate-1.1.2.tgz#ec6b00edaed6e59ad9c20582f4c364e28b146240"
-csv-parse@^1.0.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/csv-parse/-/csv-parse-1.2.0.tgz#047b73868ab9a85746e885f637f9ed0fb645a425"
+csv-parse@^1.3.3:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/csv-parse/-/csv-parse-1.3.3.tgz#d1cfd8743c2f849a0abb2fd544db56695d19a490"
-csv-stringify@^0.0.8:
- version "0.0.8"
- resolved "https://registry.yarnpkg.com/csv-stringify/-/csv-stringify-0.0.8.tgz#52cc3b3dfc197758c55ad325a95be85071f9e51b"
+csv-stringify@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/csv-stringify/-/csv-stringify-1.1.2.tgz#77a41526581bce3380f12b00d7c5bbac70c82b58"
+ dependencies:
+ lodash.get "~4.4.2"
-csv@^0.4.0:
- version "0.4.6"
- resolved "https://registry.yarnpkg.com/csv/-/csv-0.4.6.tgz#8dbae7ddfdbaae62c1ea987c3e0f8a9ac737b73d"
+csv@^1.1.0, csv@^1.1.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/csv/-/csv-1.2.1.tgz#5231edfc1c7152512ec45781076a7a97ff525c0c"
dependencies:
- csv-generate "^0.0.6"
- csv-parse "^1.0.0"
- csv-stringify "^0.0.8"
- stream-transform "^0.1.0"
+ csv-generate "^1.1.2"
+ csv-parse "^1.3.3"
+ csv-stringify "^1.1.2"
+ stream-transform "^0.2.2"
ctype@0.5.3:
version "0.5.3"
@@ -276,7 +333,7 @@ dashdash@^1.12.0:
dependencies:
assert-plus "^1.0.0"
-debug@2, debug@2.3.3, debug@^2.2.0:
+debug@2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.3.3.tgz#40c453e67e6e13c901ddec317af8986cda9eff8c"
dependencies:
@@ -288,6 +345,12 @@ debug@^1.0.2:
dependencies:
ms "0.6.2"
+debug@^2.6.3, debug@^2.6.8:
+ version "2.6.9"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+ dependencies:
+ ms "2.0.0"
+
delayed-stream@0.0.5:
version "0.0.5"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-0.0.5.tgz#d4b1f43a93e8296dfe02694f4680bc37a313c73f"
@@ -296,15 +359,19 @@ delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+detect-node@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.3.tgz#a2033c09cc8e158d37748fbde7507832bd6ce127"
+
dom-walk@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018"
-dtrace-provider@^0.6.0:
- version "0.6.0"
- resolved "https://registry.yarnpkg.com/dtrace-provider/-/dtrace-provider-0.6.0.tgz#0b078d5517937d873101452d9146737557b75e51"
+dtrace-provider@^0.8.1:
+ version "0.8.6"
+ resolved "https://registry.yarnpkg.com/dtrace-provider/-/dtrace-provider-0.8.6.tgz#428a223afe03425d2cd6d6347fdf40c66903563d"
dependencies:
- nan "^2.0.8"
+ nan "^2.3.3"
dtrace-provider@~0.8:
version "0.8.1"
@@ -349,14 +416,18 @@ envify@^4.0.0:
esprima "~3.1.0"
through "~2.3.4"
-es6-promise@^4.0.5:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.1.0.tgz#dda03ca8f9f89bc597e689842929de7ba8cebdf0"
+es6-promise@^4.1.0:
+ version "4.2.2"
+ resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.2.tgz#f722d7769af88bd33bc13ec6605e1f92966b82d9"
escape-regexp-component@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/escape-regexp-component/-/escape-regexp-component-1.0.2.tgz#9c63b6d0b25ff2a88c3adbd18c5b61acc3b9faa2"
+escape-string-regexp@^1.0.2:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+
esprima@~3.1.0:
version "3.1.3"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
@@ -365,6 +436,12 @@ events@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924"
+ewma@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/ewma/-/ewma-2.0.1.tgz#9876c1c491ac5733c8666001a3961a04c97cf1e8"
+ dependencies:
+ assert-plus "^1.0.0"
+
express-unless@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/express-unless/-/express-unless-0.3.0.tgz#5c795e7392571512dd28f520b3857a52b21261a2"
@@ -377,6 +454,10 @@ extend@~3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4"
+extend@~3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
+
extsprintf@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550"
@@ -393,13 +474,21 @@ eyes@0.1.x:
version "0.1.8"
resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0"
+fast-deep-equal@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff"
+
+fast-json-stable-stringify@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
+
faye-websocket@>=0.9.1:
version "0.11.1"
resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.1.tgz#f0efe18c4f56e4f40afc7e06c719fd5ee6188f38"
dependencies:
websocket-driver ">=0.5.1"
-faye@>=1.2.0:
+faye@~1.2.0:
version "1.2.4"
resolved "https://registry.yarnpkg.com/faye/-/faye-1.2.4.tgz#978ed8a58f1d481e5c1f98bacb8959de5ec5c643"
dependencies:
@@ -409,14 +498,15 @@ faye@>=1.2.0:
tough-cookie "*"
tunnel-agent "*"
-fb@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/fb/-/fb-1.1.1.tgz#b3f036689e55098d6f88a6dee6551d0316fd6b57"
+fb@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/fb/-/fb-2.0.0.tgz#91fd40325da34ec41c68b25530fc3a3e0dacfa6a"
dependencies:
- babel-runtime "^6.3.19"
- core-decorators "^0.12.3"
- debug "^2.2.0"
- request "^2.67.0"
+ any-promise "^1.3.0"
+ babel-runtime "^6.23.0"
+ core-decorators "^0.17.0"
+ debug "^2.6.3"
+ request "^2.81.0"
foreach@^2.0.5:
version "2.0.5"
@@ -434,6 +524,14 @@ form-data@0.1.3:
combined-stream "~0.0.4"
mime "~1.2.11"
+form-data@~2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.0.0.tgz#6f0aebadcc5da16c13e1ecc11137d85f9b883b25"
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.5"
+ mime-types "^2.1.11"
+
form-data@~2.1.1:
version "2.1.2"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.2.tgz#89c3534008b97eada4cbb157d58f6f5df025eae4"
@@ -442,31 +540,49 @@ form-data@~2.1.1:
combined-stream "^1.0.5"
mime-types "^2.1.12"
+form-data@~2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf"
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.5"
+ mime-types "^2.1.12"
+
formidable@1.0.14:
version "1.0.14"
resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.0.14.tgz#2b3f4c411cbb5fdd695c44843e2a23514a43231a"
-formidable@^1.0.14:
+formidable@^1.0.17, formidable@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.1.1.tgz#96b8886f7c3c3508b932d6bd70c4d3a88f35f1a9"
+generate-function@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74"
+
+generate-object-property@^1.1.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0"
+ dependencies:
+ is-property "^1.0.0"
+
getpass@^0.1.1:
version "0.1.6"
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.6.tgz#283ffd9fc1256840875311c1b60e8c40187110e6"
dependencies:
assert-plus "^1.0.0"
-getstream@^3.2.0:
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/getstream/-/getstream-3.5.0.tgz#7eb9206c202d425e4b5f877c8bcab1b64e23eaff"
+getstream@^3.10.0:
+ version "3.10.0"
+ resolved "https://registry.yarnpkg.com/getstream/-/getstream-3.10.0.tgz#e7a099075157ac669e970e2bffbca38c86f3f487"
dependencies:
- Base64 ">=0.3.0"
- faye ">=1.2.0"
- http-signature ">=1.0.2"
- jsonwebtoken "5.0.1"
- qs ">=6.2.0"
- request ">=2.67.0"
- xmlhttp-request ">=0.4.0"
+ Base64 "~1.0.0"
+ faye "~1.2.0"
+ http-signature "~1.1.1"
+ jsonwebtoken "7.1.9"
+ qs "~6.2.0"
+ request "2.75.0"
+ xmlhttp-request "~0.4.1"
glob@^6.0.1:
version "6.0.4"
@@ -478,14 +594,14 @@ glob@^6.0.1:
once "^1.3.0"
path-is-absolute "^1.0.0"
-global@^4.3.0:
- version "4.3.1"
- resolved "https://registry.yarnpkg.com/global/-/global-4.3.1.tgz#5f757908c7cbabce54f386ae440e11e26b7916df"
+global@^4.3.2:
+ version "4.3.2"
+ resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f"
dependencies:
min-document "^2.19.0"
process "~0.5.1"
-handle-thing@^1.2.4:
+handle-thing@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-1.2.5.tgz#fd7aad726bf1a5fd16dfc29b2f7a6601d27139c4"
@@ -493,6 +609,19 @@ har-schema@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e"
+har-schema@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
+
+har-validator@~2.0.6:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d"
+ dependencies:
+ chalk "^1.1.1"
+ commander "^2.9.0"
+ is-my-json-valid "^2.12.4"
+ pinkie-promise "^2.0.0"
+
har-validator@~4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a"
@@ -500,6 +629,19 @@ har-validator@~4.2.1:
ajv "^4.9.1"
har-schema "^1.0.5"
+har-validator@~5.0.3:
+ version "5.0.3"
+ resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd"
+ dependencies:
+ ajv "^5.1.0"
+ har-schema "^2.0.0"
+
+has-ansi@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
+ dependencies:
+ ansi-regex "^2.0.0"
+
hawk@~3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4"
@@ -509,10 +651,23 @@ hawk@~3.1.3:
hoek "2.x.x"
sntp "1.x.x"
+hawk@~6.0.2:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038"
+ dependencies:
+ boom "4.x.x"
+ cryptiles "3.x.x"
+ hoek "4.x.x"
+ sntp "2.x.x"
+
hoek@2.x.x:
version "2.16.3"
resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"
+hoek@4.x.x:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d"
+
hpack.js@^2.1.6:
version "2.1.6"
resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2"
@@ -522,18 +677,10 @@ hpack.js@^2.1.6:
readable-stream "^2.0.1"
wbuf "^1.1.0"
-http-deceiver@^1.2.4:
+http-deceiver@^1.2.7:
version "1.2.7"
resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
-http-signature@>=1.0.2, http-signature@~1.1.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
- dependencies:
- assert-plus "^0.2.0"
- jsprim "^1.2.2"
- sshpk "^1.7.0"
-
http-signature@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-0.11.0.tgz#1796cf67a001ad5cd6849dca0991485f09089fe6"
@@ -542,6 +689,22 @@ http-signature@^0.11.0:
assert-plus "^0.1.5"
ctype "0.5.3"
+http-signature@^1.2.0, http-signature@~1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
+ dependencies:
+ assert-plus "^1.0.0"
+ jsprim "^1.2.2"
+ sshpk "^1.7.0"
+
+http-signature@~1.1.0, http-signature@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
+ dependencies:
+ assert-plus "^0.2.0"
+ jsprim "^1.2.2"
+ sshpk "^1.7.0"
+
iconv-lite@~0.4.13:
version "0.4.15"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb"
@@ -553,10 +716,31 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
-inherits@2, inherits@^2.0.1, inherits@~2.0.1:
+inherits@2, inherits@^2.0.1, inherits@~2.0.1, inherits@~2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+is-my-json-valid@^2.12.4:
+ version "2.17.1"
+ resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz#3da98914a70a22f0a8563ef1511a246c6fc55471"
+ dependencies:
+ generate-function "^2.0.0"
+ generate-object-property "^1.1.0"
+ jsonpointer "^4.0.0"
+ xtend "^4.0.0"
+
+is-property@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84"
+
+is-regexp@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
+
+is-supported-regexp-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.0.tgz#8b520c85fae7a253382d4b02652e045576e13bb8"
+
is-typedarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
@@ -600,6 +784,10 @@ jsbn@~0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
+json-schema-traverse@^0.3.0:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340"
+
json-schema@0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
@@ -618,20 +806,39 @@ jsonify@~0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
-jsonwebtoken@5.0.1, jsonwebtoken@^5.0.0:
+jsonpointer@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9"
+
+jsonwebtoken@7.1.9:
+ version "7.1.9"
+ resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-7.1.9.tgz#847804e5258bec5a9499a8dc4a5e7a3bae08d58a"
+ dependencies:
+ joi "^6.10.1"
+ jws "^3.1.3"
+ lodash.once "^4.0.0"
+ ms "^0.7.1"
+ xtend "^4.0.1"
+
+jsonwebtoken@^5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-5.0.1.tgz#5d85ce580421915be22e4aa7b13d4bb99b280a2a"
dependencies:
jws "^3.0.0"
-jsonwebtoken@^7.0.0:
- version "7.3.0"
- resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-7.3.0.tgz#85118d6a70e3fccdf14389f4e7a1c3f9c8a9fbba"
+jsonwebtoken@^8.1.0:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.1.0.tgz#c6397cd2e5fd583d65c007a83dc7bb78e6982b83"
dependencies:
- joi "^6.10.1"
jws "^3.1.4"
+ lodash.includes "^4.3.0"
+ lodash.isboolean "^3.0.3"
+ lodash.isinteger "^4.0.4"
+ lodash.isnumber "^3.0.3"
+ lodash.isplainobject "^4.0.6"
+ lodash.isstring "^4.0.1"
lodash.once "^4.0.0"
- ms "^0.7.1"
+ ms "^2.0.0"
xtend "^4.0.1"
jsprim@^1.2.2:
@@ -652,7 +859,7 @@ jwa@^1.1.4:
ecdsa-sig-formatter "1.0.9"
safe-buffer "^5.0.1"
-jws@^3.0.0, jws@^3.1.4:
+jws@^3.0.0, jws@^3.1.3, jws@^3.1.4:
version "3.1.4"
resolved "https://registry.yarnpkg.com/jws/-/jws-3.1.4.tgz#f9e8b9338e8a847277d6444b1464f61880e050a2"
dependencies:
@@ -667,10 +874,6 @@ keen.io@^0.1.3:
superagent "~0.21.0"
underscore "~1.5.2"
-keep-alive-agent@^0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/keep-alive-agent/-/keep-alive-agent-0.0.1.tgz#44847ca394ce8d6b521ae85816bd64509942b385"
-
knox@^0.9.2:
version "0.9.2"
resolved "https://registry.yarnpkg.com/knox/-/knox-0.9.2.tgz#3736593669e24f024fdaf723b6a1dc4afd839a71"
@@ -685,11 +888,39 @@ load-script@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/load-script/-/load-script-1.0.0.tgz#0491939e0bee5643ee494a7e3da3d2bac70c6ca4"
+lodash.get@~4.4.2:
+ version "4.4.2"
+ resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
+
+lodash.includes@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
+
+lodash.isboolean@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
+
+lodash.isinteger@^4.0.4:
+ version "4.0.4"
+ resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
+
+lodash.isnumber@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc"
+
+lodash.isplainobject@^4.0.6:
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
+
+lodash.isstring@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
+
lodash.once@^4.0.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
-lodash@^4.0.0, lodash@^4.12.0, lodash@^4.14.0:
+lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.4, lodash@^4.2.1:
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
@@ -700,13 +931,20 @@ lru-cache@^4.0.1:
pseudomap "^1.0.1"
yallist "^2.0.0"
+lru-cache@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55"
+ dependencies:
+ pseudomap "^1.0.2"
+ yallist "^2.1.2"
+
lsmod@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/lsmod/-/lsmod-1.0.0.tgz#9a00f76dca36eb23fa05350afe1b585d4299e64b"
-mapbox-geocoding@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/mapbox-geocoding/-/mapbox-geocoding-0.1.4.tgz#5ee3487cf4d218875198553eec9e2acf81926a4e"
+mapbox-geocoding@^0.1.5:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/mapbox-geocoding/-/mapbox-geocoding-0.1.5.tgz#97c4048669eb4431088cef2ea9a9078c6eb9f8ed"
dependencies:
request "^2.67.0"
@@ -718,13 +956,23 @@ mime-db@~1.26.0:
version "1.26.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.26.0.tgz#eaffcd0e4fc6935cf8134da246e2e6c35305adff"
+mime-db@~1.30.0:
+ version "1.30.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01"
+
+mime-types@^2.1.11, mime-types@~2.1.17:
+ version "2.1.17"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a"
+ dependencies:
+ mime-db "~1.30.0"
+
mime-types@^2.1.12, mime-types@~2.1.7:
version "2.1.14"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.14.tgz#f7ef7d97583fcaf3b7d282b6f8b5679dab1e94ee"
dependencies:
mime-db "~1.26.0"
-mime@*, mime@^1.2.11:
+mime@*:
version "1.3.4"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53"
@@ -732,6 +980,10 @@ mime@1.2.11, mime@~1.2.11:
version "1.2.11"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.2.11.tgz#58203eed86e3a5ef17aed2b7d9ebd47f0a60dd10"
+mime@^1.3.4, mime@^1.4.1:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
+
mimelib@0.2.14:
version "0.2.14"
resolved "https://registry.yarnpkg.com/mimelib/-/mimelib-0.2.14.tgz#2a1aa724bd190b85bd526e6317ab6106edfd6831"
@@ -781,10 +1033,18 @@ ms@0.7.2:
version "0.7.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765"
+ms@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+
ms@^0.7.1:
version "0.7.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff"
+ms@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
+
mustache@^2.2.1:
version "2.3.0"
resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.0.tgz#4028f7778b17708a489930a6e52ac3bca0da41d0"
@@ -797,15 +1057,16 @@ mv@~2:
ncp "~2.0.0"
rimraf "~2.4.0"
-mysql@^2.11.1:
- version "2.13.0"
- resolved "https://registry.yarnpkg.com/mysql/-/mysql-2.13.0.tgz#998f1f8ca46e2e3dd7149ce982413653986aae47"
+mysql@^2.15.0:
+ version "2.15.0"
+ resolved "https://registry.yarnpkg.com/mysql/-/mysql-2.15.0.tgz#ea16841156343e8f2e47fc8985ec41cdd9573b5c"
dependencies:
- bignumber.js "3.1.2"
- readable-stream "1.1.14"
- sqlstring "2.2.0"
+ bignumber.js "4.0.4"
+ readable-stream "2.3.3"
+ safe-buffer "5.1.1"
+ sqlstring "2.3.0"
-nan@^2.0.8, nan@^2.3.3:
+nan@^2.3.3:
version "2.5.1"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.5.1.tgz#d5b01691253326a97a2bbee9e61c55d8d60351e2"
@@ -817,11 +1078,11 @@ negotiator@^0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
-node-uuid@^1.4.1, node-uuid@^1.4.7, node-uuid@~1.4.1:
- version "1.4.7"
- resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.7.tgz#6da5a17668c4b3dd59623bda11cf7fa4c1f60a6f"
+node-uuid@^1.4.8, node-uuid@~1.4.7:
+ version "1.4.8"
+ resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.8.tgz#b040eb0923968afabf8d32fb1f17f1167fdab907"
-oauth-sign@~0.8.1:
+oauth-sign@~0.8.1, oauth-sign@~0.8.2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
@@ -829,11 +1090,11 @@ object-keys@^1.0.11, object-keys@~1.0.0:
version "1.0.11"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d"
-obuf@^1.0.0, obuf@^1.1.0:
+obuf@^1.0.0, obuf@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.1.tgz#104124b6c602c6796881a042541d36db43a5264e"
-once@^1.3.0:
+once@^1.3.0, once@^1.3.2, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
dependencies:
@@ -847,9 +1108,23 @@ performance-now@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
-precond@0.2:
- version "0.2.3"
- resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac"
+performance-now@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
+
+pidusage@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/pidusage/-/pidusage-1.2.0.tgz#65ee96ace4e08a4cd3f9240996c85b367171ee92"
+
+pinkie-promise@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
+ dependencies:
+ pinkie "^2.0.0"
+
+pinkie@^2.0.0:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
process-nextick-args@~1.0.6:
version "1.0.7"
@@ -859,7 +1134,7 @@ process@~0.5.1:
version "0.5.2"
resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf"
-pseudomap@^1.0.1:
+pseudomap@^1.0.1, pseudomap@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
@@ -871,31 +1146,40 @@ qs@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-1.2.0.tgz#ed079be28682147e6fd9a34cc2b0c1e0ec6453ee"
-qs@>=6.2.0, qs@^6.2.1, qs@~6.4.0:
+qs@^6.2.1, qs@~6.4.0:
version "6.4.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
+qs@^6.5.1, qs@~6.5.1:
+ version "6.5.1"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
+
+qs@~6.2.0:
+ version "6.2.3"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.3.tgz#1cfcb25c10a9b2b483053ff39f5dfc9233908cfe"
+
querystring-es3@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
-raven@^0.11.0:
- version "0.11.0"
- resolved "https://registry.yarnpkg.com/raven/-/raven-0.11.0.tgz#32981138a93e4c8ad08cfc17e46b85b453dc107b"
+raven@^1.1.4:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/raven/-/raven-1.2.1.tgz#949c134db028a190b7bbf8f790aae541b7c020bd"
dependencies:
- cookie "0.1.0"
+ cookie "0.3.1"
+ json-stringify-safe "5.0.1"
lsmod "1.0.0"
- node-uuid "~1.4.1"
- stack-trace "0.0.7"
+ stack-trace "0.0.9"
+ uuid "3.0.0"
-raven@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/raven/-/raven-1.2.0.tgz#0f0d4463362e03f04793b3aab47619cbaf39da75"
+raven@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/raven/-/raven-2.3.0.tgz#96f15346bdaa433b3b6d47130804506155833d69"
dependencies:
cookie "0.3.1"
- json-stringify-safe "5.0.1"
lsmod "1.0.0"
stack-trace "0.0.9"
+ timed-out "4.0.1"
uuid "3.0.0"
readable-stream@1.0.27-1:
@@ -907,14 +1191,17 @@ readable-stream@1.0.27-1:
isarray "0.0.1"
string_decoder "~0.10.x"
-readable-stream@1.1.14:
- version "1.1.14"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
+readable-stream@2.3.3, readable-stream@^2.2.9:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c"
dependencies:
core-util-is "~1.0.0"
- inherits "~2.0.1"
- isarray "0.0.1"
- string_decoder "~0.10.x"
+ inherits "~2.0.3"
+ isarray "~1.0.0"
+ process-nextick-args "~1.0.6"
+ safe-buffer "~5.1.1"
+ string_decoder "~1.0.3"
+ util-deprecate "~1.0.1"
readable-stream@^2.0.1:
version "2.2.6"
@@ -928,6 +1215,17 @@ readable-stream@^2.0.1:
string_decoder "~0.10.x"
util-deprecate "~1.0.1"
+readable-stream@~2.0.5:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e"
+ dependencies:
+ core-util-is "~1.0.0"
+ inherits "~2.0.1"
+ isarray "~1.0.0"
+ process-nextick-args "~1.0.6"
+ string_decoder "~0.10.x"
+ util-deprecate "~1.0.1"
+
reduce-component@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/reduce-component/-/reduce-component-1.0.1.tgz#e0c93542c574521bea13df0f9488ed82ab77c5da"
@@ -938,11 +1236,37 @@ reduce@^1.0.1:
dependencies:
object-keys "~1.0.0"
-regenerator-runtime@^0.10.0:
- version "0.10.3"
- resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz#8c4367a904b51ea62a908ac310bf99ff90a82a3e"
+regenerator-runtime@^0.11.0:
+ version "0.11.1"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
+
+request@2.75.0:
+ version "2.75.0"
+ resolved "https://registry.yarnpkg.com/request/-/request-2.75.0.tgz#d2b8268a286da13eaa5d01adf5d18cc90f657d93"
+ dependencies:
+ aws-sign2 "~0.6.0"
+ aws4 "^1.2.1"
+ bl "~1.1.2"
+ caseless "~0.11.0"
+ combined-stream "~1.0.5"
+ extend "~3.0.0"
+ forever-agent "~0.6.1"
+ form-data "~2.0.0"
+ har-validator "~2.0.6"
+ hawk "~3.1.3"
+ http-signature "~1.1.0"
+ is-typedarray "~1.0.0"
+ isstream "~0.1.2"
+ json-stringify-safe "~5.0.1"
+ mime-types "~2.1.7"
+ node-uuid "~1.4.7"
+ oauth-sign "~0.8.1"
+ qs "~6.2.0"
+ stringstream "~0.0.4"
+ tough-cookie "~2.3.0"
+ tunnel-agent "~0.4.1"
-request@>=2.67.0, request@^2.67.0:
+request@^2.67.0:
version "2.81.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0"
dependencies:
@@ -969,6 +1293,53 @@ request@>=2.67.0, request@^2.67.0:
tunnel-agent "^0.6.0"
uuid "^3.0.0"
+request@^2.81.0:
+ version "2.83.0"
+ resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356"
+ dependencies:
+ 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 "~2.1.17"
+ oauth-sign "~0.8.2"
+ performance-now "^2.1.0"
+ qs "~6.5.1"
+ safe-buffer "^5.1.1"
+ stringstream "~0.0.5"
+ tough-cookie "~2.3.3"
+ tunnel-agent "^0.6.0"
+ uuid "^3.1.0"
+
+restify-errors@^4.2.3:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/restify-errors/-/restify-errors-4.3.0.tgz#ec90f30934d7f3119135181dfc303e30be601abe"
+ dependencies:
+ assert-plus "^1.0.0"
+ lodash "^4.2.1"
+ verror "^1.8.1"
+ optionalDependencies:
+ safe-json-stringify "^1.0.3"
+
+restify-errors@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/restify-errors/-/restify-errors-5.0.0.tgz#668717e100683eec6ce0d515f89ff1dbec254a8d"
+ dependencies:
+ assert-plus "^1.0.0"
+ lodash "^4.2.1"
+ verror "^1.8.1"
+ optionalDependencies:
+ safe-json-stringify "^1.0.3"
+
restify-jwt@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/restify-jwt/-/restify-jwt-0.4.0.tgz#22274c8ce6ef6e6e6bb5074b381f2b57bff7bd1f"
@@ -977,31 +1348,50 @@ restify-jwt@^0.4.0:
express-unless "^0.3.0"
jsonwebtoken "^5.0.0"
-restify@^4.1.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/restify/-/restify-4.3.0.tgz#03b67960d1d42a6dafcde3bd82fb882173a27678"
+restify-plugins@^1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/restify-plugins/-/restify-plugins-1.6.0.tgz#79e118887b7f0eb02e645780f9c5680cb7ab9aa9"
dependencies:
- assert-plus "^0.1.5"
- backoff "^2.4.0"
- bunyan "^1.4.0"
- csv "^0.4.0"
+ assert-plus "^1.0.0"
+ bunyan "^1.8.0"
+ csv "^1.1.0"
escape-regexp-component "^1.0.2"
- formidable "^1.0.14"
+ formidable "^1.0.17"
http-signature "^0.11.0"
- keep-alive-agent "^0.0.1"
lru-cache "^4.0.1"
- mime "^1.2.11"
- negotiator "^0.6.1"
- node-uuid "^1.4.1"
- once "^1.3.0"
+ mime "^1.3.4"
+ once "^1.3.2"
qs "^6.2.1"
- semver "^4.3.3"
- spdy "^3.3.3"
- tunnel-agent "^0.4.0"
- vasync "1.6.3"
- verror "^1.4.0"
+ restify-errors "^4.2.3"
+ vasync "^1.6.3"
+
+restify@^6.3.4:
+ version "6.3.4"
+ resolved "https://registry.yarnpkg.com/restify/-/restify-6.3.4.tgz#097990b22ba40f02a074a7d4cb1c27690759e288"
+ dependencies:
+ assert-plus "^1.0.0"
+ bunyan "^1.8.12"
+ clone-regexp "^1.0.0"
+ csv "^1.1.1"
+ escape-regexp-component "^1.0.2"
+ ewma "^2.0.1"
+ formidable "^1.1.1"
+ http-signature "^1.2.0"
+ lodash "^4.17.4"
+ lru-cache "^4.1.1"
+ mime "^1.4.1"
+ negotiator "^0.6.1"
+ once "^1.4.0"
+ pidusage "^1.2.0"
+ qs "^6.5.1"
+ restify-errors "^5.0.0"
+ semver "^5.4.1"
+ spdy "^3.4.7"
+ uuid "^3.1.0"
+ vasync "^1.6.4"
+ verror "^1.10.0"
optionalDependencies:
- dtrace-provider "^0.6.0"
+ dtrace-provider "^0.8.1"
rimraf@~2.4.0:
version "2.4.5"
@@ -1009,11 +1399,15 @@ rimraf@~2.4.0:
dependencies:
glob "^6.0.1"
+safe-buffer@5.1.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
+
safe-buffer@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7"
-safe-json-stringify@~1:
+safe-json-stringify@^1.0.3, safe-json-stringify@~1:
version "1.0.4"
resolved "https://registry.yarnpkg.com/safe-json-stringify/-/safe-json-stringify-1.0.4.tgz#81a098f447e4bbc3ff3312a243521bc060ef5911"
@@ -1025,14 +1419,14 @@ select-hose@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
-semver@^4.3.3:
- version "4.3.6"
- resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da"
-
semver@^5.1.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
+semver@^5.4.1:
+ version "5.4.1"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e"
+
sequin@*:
version "0.1.0"
resolved "https://registry.yarnpkg.com/sequin/-/sequin-0.1.0.tgz#17c5566d9d555413aa12fc8bc96ed309c80e0aad"
@@ -1043,29 +1437,38 @@ sntp@1.x.x:
dependencies:
hoek "2.x.x"
-spdy-transport@^2.0.15:
- version "2.0.18"
- resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-2.0.18.tgz#43fc9c56be2cccc12bb3e2754aa971154e836ea6"
+sntp@2.x.x:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8"
+ dependencies:
+ hoek "4.x.x"
+
+spdy-transport@^2.0.18:
+ version "2.0.20"
+ resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-2.0.20.tgz#735e72054c486b2354fe89e702256004a39ace4d"
dependencies:
- debug "^2.2.0"
+ debug "^2.6.8"
+ detect-node "^2.0.3"
hpack.js "^2.1.6"
- obuf "^1.1.0"
- readable-stream "^2.0.1"
- wbuf "^1.4.0"
+ obuf "^1.1.1"
+ readable-stream "^2.2.9"
+ safe-buffer "^5.0.1"
+ wbuf "^1.7.2"
-spdy@^3.3.3:
- version "3.4.4"
- resolved "https://registry.yarnpkg.com/spdy/-/spdy-3.4.4.tgz#e0406407ca90ff01b553eb013505442649f5a819"
+spdy@^3.4.7:
+ version "3.4.7"
+ resolved "https://registry.yarnpkg.com/spdy/-/spdy-3.4.7.tgz#42ff41ece5cc0f99a3a6c28aabb73f5c3b03acbc"
dependencies:
- debug "^2.2.0"
- handle-thing "^1.2.4"
- http-deceiver "^1.2.4"
+ debug "^2.6.8"
+ handle-thing "^1.2.5"
+ http-deceiver "^1.2.7"
+ safe-buffer "^5.0.1"
select-hose "^2.0.0"
- spdy-transport "^2.0.15"
+ spdy-transport "^2.0.18"
-sqlstring@2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.2.0.tgz#c3135c4ea8abcd7e7ee741a4966a891d86a4f191"
+sqlstring@2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.0.tgz#525b8a4fd26d6f71aa61e822a6caf976d31ad2a8"
sshpk@^1.7.0:
version "1.11.0"
@@ -1082,14 +1485,14 @@ sshpk@^1.7.0:
jsbn "~0.1.0"
tweetnacl "~0.14.0"
-stack-trace@0.0.7:
- version "0.0.7"
- resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.7.tgz#c72e089744fc3659f508cdce3621af5634ec0fff"
-
-stack-trace@0.0.9, stack-trace@0.0.x, stack-trace@^0.0.9:
+stack-trace@0.0.9, stack-trace@0.0.x:
version "0.0.9"
resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.9.tgz#a8f6eaeca90674c333e7c43953f275b451510695"
+stack-trace@^0.0.10:
+ version "0.0.10"
+ resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
+
starttls@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/starttls/-/starttls-1.0.1.tgz#e6081c25de6b178f5a75f8f271c1487449183b42"
@@ -1098,18 +1501,30 @@ stream-counter@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/stream-counter/-/stream-counter-1.0.0.tgz#91cf2569ce4dc5061febcd7acb26394a5a114751"
-stream-transform@^0.1.0:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/stream-transform/-/stream-transform-0.1.2.tgz#7d8e6b4e03ac4781778f8c79517501bfb0762a9f"
+stream-transform@^0.2.2:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/stream-transform/-/stream-transform-0.2.2.tgz#75867487f49528f8bf1d82499658753d02df7838"
string_decoder@~0.10.x:
version "0.10.31"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
-stringstream@~0.0.4:
+string_decoder@~1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab"
+ dependencies:
+ safe-buffer "~5.1.0"
+
+stringstream@~0.0.4, stringstream@~0.0.5:
version "0.0.5"
resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
+strip-ansi@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
+ dependencies:
+ ansi-regex "^2.0.0"
+
superagent@~0.21.0:
version "0.21.0"
resolved "https://registry.yarnpkg.com/superagent/-/superagent-0.21.0.tgz#fb15027984751ee7152200e6cd21cd6e19a5de87"
@@ -1126,10 +1541,18 @@ superagent@~0.21.0:
readable-stream "1.0.27-1"
reduce-component "1.0.1"
+supports-color@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
+
through@~2.3.4:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
+timed-out@4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f"
+
topo@1.x.x:
version "1.1.0"
resolved "https://registry.yarnpkg.com/topo/-/topo-1.1.0.tgz#e9d751615d1bb87dc865db182fa1ca0a5ef536d5"
@@ -1142,13 +1565,19 @@ tough-cookie@*, tough-cookie@~2.3.0:
dependencies:
punycode "^1.4.1"
+tough-cookie@~2.3.3:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561"
+ dependencies:
+ punycode "^1.4.1"
+
tunnel-agent@*, tunnel-agent@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
dependencies:
safe-buffer "^5.0.1"
-tunnel-agent@^0.4.0, tunnel-agent@^0.4.3:
+tunnel-agent@~0.4.1:
version "0.4.3"
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb"
@@ -1168,9 +1597,13 @@ uuid@3.0.0, uuid@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.0.tgz#6728fc0459c450d796a99c31837569bdf672d728"
-vasync@1.6.3:
- version "1.6.3"
- resolved "https://registry.yarnpkg.com/vasync/-/vasync-1.6.3.tgz#4a69d7052a47f4ce85503d7641df1cbf40432a94"
+uuid@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04"
+
+vasync@^1.6.3, vasync@^1.6.4:
+ version "1.6.4"
+ resolved "https://registry.yarnpkg.com/vasync/-/vasync-1.6.4.tgz#dfe93616ad0e7ae801b332a9d88bfc5cdc8e1d1f"
dependencies:
verror "1.6.0"
@@ -1186,15 +1619,15 @@ verror@1.6.0:
dependencies:
extsprintf "1.2.0"
-verror@^1.4.0:
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/verror/-/verror-1.9.0.tgz#107a8a2d14c33586fc4bb830057cd2d19ae2a6ee"
+verror@^1.10.0, verror@^1.8.1:
+ version "1.10.0"
+ resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
dependencies:
assert-plus "^1.0.0"
core-util-is "1.0.2"
extsprintf "^1.2.0"
-wbuf@^1.1.0, wbuf@^1.4.0:
+wbuf@^1.1.0, wbuf@^1.7.2:
version "1.7.2"
resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.2.tgz#d697b99f1f59512df2751be42769c1580b5801fe"
dependencies:
@@ -1210,23 +1643,23 @@ websocket-extensions@>=0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.1.tgz#76899499c184b6ef754377c2dbb0cd6cb55d29e7"
-winston-mail@^1.2.0:
+winston-mail@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/winston-mail/-/winston-mail-1.3.0.tgz#10b05702b73ce9f2e9b3329a522e98b6ed4dcdc0"
dependencies:
emailjs "^1.0.8"
mustache "^2.2.1"
-winston-sentry@^0.1.4:
- version "0.1.5"
- resolved "https://registry.yarnpkg.com/winston-sentry/-/winston-sentry-0.1.5.tgz#b86efc01d757c84bc5da78314c7788b42776be50"
+winston-sentry@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/winston-sentry/-/winston-sentry-0.2.1.tgz#dfdcc828f35a735a8e01e781918af652eb97c75c"
dependencies:
- lodash "^4.12.0"
- raven "^0.11.0"
+ lodash "^4.17.4"
+ raven "^1.1.4"
-winston@^2.2.0:
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/winston/-/winston-2.3.1.tgz#0b48420d978c01804cf0230b648861598225a119"
+winston@^2.4.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/winston/-/winston-2.4.0.tgz#808050b93d52661ed9fb6c26b3f0c826708b0aee"
dependencies:
async "~1.0.0"
colors "1.0.x"
@@ -1252,14 +1685,14 @@ xmlbuilder@^4.1.0:
dependencies:
lodash "^4.0.0"
-xmlhttp-request@>=0.4.0:
+xmlhttp-request@~0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/xmlhttp-request/-/xmlhttp-request-0.4.1.tgz#636d99355a91e1865b38ea039099ddc59af6a7a7"
-xtend@^4.0.1:
+xtend@^4.0.0, xtend@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
-yallist@^2.0.0:
+yallist@^2.0.0, yallist@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
diff --git a/app/config.js b/app/config.js
index 5b5c4a1..17c4863 100644
--- a/app/config.js
+++ b/app/config.js
@@ -4,29 +4,29 @@
* Config
*/
module.exports = {
- name: 'GetStream.io - React Example App',
- version: '1.0.0',
- env: process.env.NODE_ENV || 'DEVELOPMENT',
- mapbox: {
- accessToken: process.env.MAPBOX_ACCESS_TOKEN,
- },
- stream: {
- appId: process.env.STREAM_APP_ID,
- key: process.env.STREAM_KEY,
- },
- api: {
- baseUrl: process.env.API_URL,
- },
- imgix: {
- baseUrl: process.env.IMGIX_BASE_URL,
- },
- algolia: {
- appId: process.env.ALGOLIA_APP_ID,
- searchOnlyKey: process.env.ALGOLIA_SEARCH_ONLY_KEY,
- },
- keen: {
- projectId: process.env.KEEN_PROJECT_ID,
- writeKey: process.env.KEEN_WRITE_KEY,
- readKey: process.env.KEEN_READ_KEY,
- }
+ name: 'GetStream.io - React Example App',
+ version: '1.0.0',
+ env: process.env.NODE_ENV || 'DEVELOPMENT',
+ mapbox: {
+ accessToken: process.env.MAPBOX_ACCESS_TOKEN,
+ },
+ stream: {
+ appId: process.env.STREAM_APP_ID,
+ key: process.env.STREAM_KEY,
+ },
+ api: {
+ baseUrl: process.env.API_URL,
+ },
+ imgix: {
+ baseUrl: process.env.IMGIX_BASE_URL,
+ },
+ algolia: {
+ appId: process.env.ALGOLIA_APP_ID,
+ searchOnlyKey: process.env.ALGOLIA_SEARCH_ONLY_KEY,
+ },
+ keen: {
+ projectId: process.env.KEEN_PROJECT_ID,
+ writeKey: process.env.KEEN_WRITE_KEY,
+ readKey: process.env.KEEN_READ_KEY,
+ },
};
diff --git a/app/modules/App.js b/app/modules/App.js
index b308e43..27e739c 100644
--- a/app/modules/App.js
+++ b/app/modules/App.js
@@ -1,51 +1,47 @@
-import React, { Component, cloneElement } from 'react'
-import { connect } from 'react-redux'
-import { browserHistory } from 'react-router'
+import React, { Component, cloneElement } from 'react';
+import { connect } from 'react-redux';
+import { browserHistory } from 'react-router';
-import stream from 'getstream'
-import config from 'config'
+import stream from 'getstream';
+import config from 'config';
-const Home = require('./routes/Home/Home').default
+const Home = require('./routes/Home/Home').default;
import {
- App as AppActions,
- User as UserActions,
- Photos as PhotoActions,
- Header as HeaderActions,
- Stream as StreamActions,
-} from 'actions'
+ App as AppActions,
+ User as UserActions,
+ Photos as PhotoActions,
+ Header as HeaderActions,
+ Stream as StreamActions,
+} from 'actions';
-import {
- Header,
-} from 'components'
-
-@connect(state => ({
- header: state.Header,
- user: state.User,
-}))
+import { Header } from 'components';
/**
* AppHeader component
*/
+@connect(state => ({
+ header: state.Header,
+ user: state.User,
+}))
class AppHeader extends Component {
-
- /**
+ /**
* render
* @returns markup
*/
- render() {
-
- const { header, user, router, } = this.props
-
- return (
-
- )
- }
+ render() {
+ const { header, user, router } = this.props;
+
+ return (
+
+ );
+ }
}
/**
@@ -55,33 +51,31 @@ class AppHeader extends Component {
* @param location
*/
function handleRouteChange(dispatch, route, location) {
- if (route) {
-
- if (route.getHeaderLeft) {
- route.getHeaderLeft(location, (err, component) => {
- dispatch(HeaderActions.left(component))
- })
- } else {
- dispatch(HeaderActions.left(null))
- }
-
- if (route.getHeaderMiddle) {
- route.getHeaderMiddle(location, (err, component) => {
- dispatch(HeaderActions.middle(component))
- })
- } else {
- dispatch(HeaderActions.middle(null))
- }
-
- if (route.getHeaderRight) {
- route.getHeaderRight(location, (err, component) => {
- dispatch(HeaderActions.right(component))
- })
- } else {
- dispatch(HeaderActions.right(null))
- }
-
- }
+ if (route) {
+ if (route.getHeaderLeft) {
+ route.getHeaderLeft(location, (err, component) => {
+ dispatch(HeaderActions.left(component));
+ });
+ } else {
+ dispatch(HeaderActions.left(null));
+ }
+
+ if (route.getHeaderMiddle) {
+ route.getHeaderMiddle(location, (err, component) => {
+ dispatch(HeaderActions.middle(component));
+ });
+ } else {
+ dispatch(HeaderActions.middle(null));
+ }
+
+ if (route.getHeaderRight) {
+ route.getHeaderRight(location, (err, component) => {
+ dispatch(HeaderActions.right(component));
+ });
+ } else {
+ dispatch(HeaderActions.right(null));
+ }
+ }
}
/**
@@ -89,121 +83,136 @@ function handleRouteChange(dispatch, route, location) {
* Bootstraps application
*/
class App extends Component {
-
- static contextTypes = {
- router: React.PropTypes.object.isRequired,
- }
-
- componentWillMount() {
- // instantiate a new client (client side)
- this.client = stream.connect(config.stream.key, null, config.stream.appId)
- }
-
- /**
+ static contextTypes = {
+ router: React.PropTypes.object.isRequired,
+ };
+
+ componentWillMount() {
+ // instantiate a new client (client side)
+ this.client = stream.connect(
+ config.stream.key,
+ null,
+ config.stream.appId,
+ );
+ }
+
+ /**
* componentDidUpdate
* @param oldProps
* @returns {*}
*/
- componentDidUpdate(oldProps) {
-
- handleRouteChange(
- this.props.dispatch,
- this.props.routes[this.props.routes.length - 1],
- this.props.location
- )
-
- if (oldProps.user.id != this.props.user.id && !this.props.user.id) {
- return browserHistory.push('/landing')
- }
-
- if (oldProps.user.id != this.props.user.id && this.props.user.id) {
- this.connectToStream()
- this.props.dispatch(AppActions.init())
- }
-
- }
-
- /**
+ componentDidUpdate(oldProps) {
+ handleRouteChange(
+ this.props.dispatch,
+ this.props.routes[this.props.routes.length - 1],
+ this.props.location,
+ );
+
+ if (oldProps.user.id != this.props.user.id && !this.props.user.id) {
+ return browserHistory.push('/landing');
+ }
+
+ if (oldProps.user.id != this.props.user.id && this.props.user.id) {
+ this.connectToStream();
+ this.props.dispatch(AppActions.init());
+ }
+ }
+
+ /**
* componentDidMount
*/
- componentDidMount() {
-
- const { dispatch } = this.props
-
- FB.getLoginStatus(res => {
- if (res.status !== 'connected') {
- if (this.props.location.pathname != '/landing') {
- browserHistory.replace('/landing')
- }
- this.props.dispatch(AppActions.initDone())
- return
- }
-
- dispatch(UserActions.fbLogin(res))
-
- if (this.props.location.pathname == '/landing') {
- browserHistory.replace('/')
- }
-
- })
-
- }
-
- connectToStream = () => {
- // follow 'timeline_flat' feed
- this.timeline = this.client.feed('timeline_flat', this.props.user.id, this.props.tokens.timelineFlat)
- this.timeline
- .subscribe(data => {
- this.props.dispatch(StreamActions.timeline(data))
- })
- .then(() => {
- //console.log('Full (Timeline Flat): Connected to faye channel, waiting for realtime updates');
- }, (err) => {
- console.error('Full (Timeline Flat): Could not estabilsh faye connection', err);
- });
-
- // follow 'notifications' feed
- this.notification = this.client.feed('notification', this.props.user.id, this.props.tokens.notification)
- this.notification
- .subscribe(data => {
- this.props.dispatch(StreamActions.event(data))
- })
- .then(() => {
- //console.log('Full (Notifications): Connected to faye channel, waiting for realtime updates');
- }, (err) => {
- console.error('Full (Notifications): Could not estabilsh faye connection', err);
- });
- }
-
- /**
+ componentDidMount() {
+ const { dispatch } = this.props;
+
+ FB.getLoginStatus(res => {
+ if (res.status !== 'connected') {
+ if (this.props.location.pathname != '/landing') {
+ browserHistory.replace('/landing');
+ }
+ this.props.dispatch(AppActions.initDone());
+ return;
+ }
+
+ dispatch(UserActions.fbLogin(res));
+
+ if (this.props.location.pathname == '/landing') {
+ browserHistory.replace('/');
+ }
+ });
+ }
+
+ connectToStream = () => {
+ // follow 'timeline_flat' feed
+ this.timeline = this.client.feed(
+ 'timeline_flat',
+ this.props.user.id,
+ this.props.tokens.timelineFlat,
+ );
+ this.timeline
+ .subscribe(data => {
+ this.props.dispatch(StreamActions.timeline(data));
+ })
+ .then(
+ () => {
+ //console.log('Full (Timeline Flat): Connected to faye channel, waiting for realtime updates');
+ },
+ err => {
+ console.error(
+ 'Full (Timeline Flat): Could not estabilsh faye connection',
+ err,
+ );
+ },
+ );
+
+ // follow 'notifications' feed
+ this.notification = this.client.feed(
+ 'notification',
+ this.props.user.id,
+ this.props.tokens.notification,
+ );
+ this.notification
+ .subscribe(data => {
+ this.props.dispatch(StreamActions.event(data));
+ })
+ .then(
+ () => {
+ //console.log('Full (Notifications): Connected to faye channel, waiting for realtime updates');
+ },
+ err => {
+ console.error(
+ 'Full (Notifications): Could not estabilsh faye connection',
+ err,
+ );
+ },
+ );
+ };
+
+ /**
* render
* @returns markup
*/
- render() {
-
- if (this.props.loading) return