feat(portal-api): integrate portal-watch (#510)

This commit is contained in:
Sérgio Ramos 2017-06-22 18:09:13 +01:00 committed by Wyatt Preul
parent 8530b24691
commit bc679d6ac6
16 changed files with 705 additions and 468 deletions

View File

@ -101,6 +101,12 @@ api:
- CONSUL=consul - CONSUL=consul
- PORT=3000 - PORT=3000
- RETHINK_HOST=rethinkdb - RETHINK_HOST=rethinkdb
- DOCKER_HOST=$DOCKER_HOST
- DOCKER_CERT_PATH=$DOCKER_CERT_PATH
- DOCKER_CLIENT_TIMEOUT=$DOCKER_CLIENT_TIMEOUT
- SDC_URL=$SDC_URL
- SDC_ACCOUNT=$SDC_ACCOUNT
- SDC_KEY_ID=$SDC_KEY_ID
expose: expose:
- 3000 - 3000

View File

@ -22,6 +22,7 @@
"apollo": "^0.2.2", "apollo": "^0.2.2",
"apr-intercept": "^1.0.4", "apr-intercept": "^1.0.4",
"constant-case": "^2.0.0", "constant-case": "^2.0.0",
"force-array": "^3.1.0",
"graphql-tag": "^2.4.0", "graphql-tag": "^2.4.0",
"jest-cli": "^20.0.4", "jest-cli": "^20.0.4",
"joyent-manifest-editor": "^1.0.0", "joyent-manifest-editor": "^1.0.0",

View File

@ -138,6 +138,7 @@ const UiConnect = connect(mapStateToProps, mapDispatchToProps);
const ServicesGql = graphql(ServicesQuery, { const ServicesGql = graphql(ServicesQuery, {
options(props) { options(props) {
return { return {
pollInterval: 1000,
variables: { variables: {
deploymentGroupSlug: props.match.params.deploymentGroup deploymentGroupSlug: props.match.params.deploymentGroup
} }

View File

@ -1,9 +1,17 @@
mutation provisionManifest($deploymentGroupId: ID!, $type: ManifestType!, $format: ManifestFormat!, $raw: String!) { mutation provisionManifest($deploymentGroupId: ID!, $type: ManifestType!, $format: ManifestFormat!, $raw: String!) {
provisionManifest(deploymentGroupId: $deploymentGroupId, type: $type, format: $format, raw: $raw) { provisionManifest(deploymentGroupId: $deploymentGroupId, type: $type, format: $format, raw: $raw) {
id manifestId
created scale {
type serviceName
format replicas
obj }
plan {
running
actions {
type
service
machines
}
}
} }
} }

View File

@ -1,4 +1,5 @@
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import forceArray from 'force-array';
const apollo = state => state.apollo; const apollo = state => state.apollo;
@ -76,7 +77,7 @@ const getService = (service, index, datacenter) => ({
const processServices = (services, datacenter) => { const processServices = (services, datacenter) => {
console.log('services = ', services); console.log('services = ', services);
return services.reduce((ss, s, i) => { return forceArray(services).reduce((ss, s, i) => {
// Check whether it exits in thing, if so, add as child // Check whether it exits in thing, if so, add as child
// if not, create and add as child // if not, create and add as child

View File

@ -53,7 +53,7 @@ type StateConvergencePlan {
type Version { type Version {
created: Date! # Either Int or define scalar created: Date! # Either Int or define scalar
manifest: Manifest! manifestId: ID!
scale(serviceName: String): [ServiceScale]! scale(serviceName: String): [ServiceScale]!
plan(running: Boolean): StateConvergencePlan plan(running: Boolean): StateConvergencePlan
} }
@ -90,6 +90,7 @@ type Service {
parent: ID # parent service id parent: ID # parent service id
package: Package! # we don't have this in current mock data, package: Package! # we don't have this in current mock data,
environment: [Environment] environment: [Environment]
active: Boolean! # let's say that we update the manifest, and remove a service. we still want to track this service even though it might not exist because it might have machines running still
} }
# for metrics max / min (I guess) # for metrics max / min (I guess)
@ -190,7 +191,7 @@ type Mutation {
createDeploymentGroup(name: String!) : DeploymentGroup createDeploymentGroup(name: String!) : DeploymentGroup
updateDeploymentGroup(id: ID!, name: String!) : DeploymentGroup updateDeploymentGroup(id: ID!, name: String!) : DeploymentGroup
provisionManifest(deploymentGroupId: ID!, type: ManifestType!, format: ManifestFormat!, raw: String!) : Manifest provisionManifest(deploymentGroupId: ID!, type: ManifestType!, format: ManifestFormat!, raw: String!) : Version
scale(serviceId: ID!, replicas: Int!) : Version scale(serviceId: ID!, replicas: Int!) : Version
stopServices(ids: [ID]!) : [Service] stopServices(ids: [ID]!) : [Service]

View File

@ -4,6 +4,7 @@ const Schema = require('joyent-cp-gql-schema');
const Graphi = require('graphi'); const Graphi = require('graphi');
const Piloted = require('piloted'); const Piloted = require('piloted');
const PortalData = require('portal-data'); const PortalData = require('portal-data');
const PortalWatch = require('portal-watch');
const Pack = require('../package.json'); const Pack = require('../package.json');
const Resolvers = require('./resolvers'); const Resolvers = require('./resolvers');
@ -18,14 +19,22 @@ module.exports = function (server, options, next) {
} }
const data = new PortalData(options.data); const data = new PortalData(options.data);
const watch = new PortalWatch(Object.assign(options.watch, {
data
}));
data.connect((err) => { data.connect((err) => {
if (err) { if (err) {
return next(err); return next(err);
} }
server.bind(data); server.bind(Object.assign(data, {
watch
}));
Piloted.on('refresh', internals.refresh(data)); Piloted.on('refresh', internals.refresh(data));
watch.poll();
server.register([ server.register([
{ {

View File

@ -37,6 +37,7 @@
"joyent-cp-gql-schema": "^1.0.4", "joyent-cp-gql-schema": "^1.0.4",
"piloted": "^3.1.1", "piloted": "^3.1.1",
"portal-data": "^1.1.0", "portal-data": "^1.1.0",
"portal-watch": "^1.0.0",
"toppsy": "^1.1.0" "toppsy": "^1.1.0"
} }
} }

View File

@ -9,6 +9,8 @@ const Toppsy = require('toppsy');
const Vision = require('vision'); const Vision = require('vision');
const Pack = require('./package'); const Pack = require('./package');
const Portal = require('./lib'); const Portal = require('./lib');
const Path = require('path');
const Fs = require('fs');
const server = new Hapi.Server(); const server = new Hapi.Server();
server.connection({ port: 3000 }); server.connection({ port: 3000 });
@ -20,11 +22,38 @@ const swaggerOptions = {
} }
}; };
const {
DOCKER_HOST,
DOCKER_CERT_PATH,
DOCKER_CLIENT_TIMEOUT,
SDC_URL,
SDC_ACCOUNT,
SDC_KEY_ID
} = process.env;
const portalOptions = { const portalOptions = {
data: { data: {
db: { db: {
host: process.env.RETHINK_HOST || 'localhost' host: process.env.RETHINK_HOST || 'localhost'
},
docker: {
host: DOCKER_HOST,
ca: DOCKER_CERT_PATH ?
Fs.readFileSync(Path.join(DOCKER_CERT_PATH, 'ca.pem')) :
undefined,
cert: DOCKER_CERT_PATH ?
Fs.readFileSync(Path.join(DOCKER_CERT_PATH, 'cert.pem')) :
undefined,
key: DOCKER_CERT_PATH ?
Fs.readFileSync(Path.join(DOCKER_CERT_PATH, 'key.pem')) :
undefined,
timeout: DOCKER_CLIENT_TIMEOUT
} }
},
watch: {
url: SDC_URL,
account: SDC_ACCOUNT,
keyId: SDC_KEY_ID
} }
}; };

File diff suppressed because it is too large Load Diff

View File

@ -38,7 +38,7 @@ exports.toDeploymentGroup = function ({ name }) {
return { return {
name, name,
slug: name, slug: name,
services: [], service_ids: [],
version_id: '', version_id: '',
history_version_ids: [] history_version_ids: []
}; };
@ -57,12 +57,15 @@ exports.fromService = function ({ service, instances, packages }) {
currentMetrics: [], currentMetrics: [],
connections: service.service_dependency_ids, connections: service.service_dependency_ids,
package: packages ? exports.fromPackage(packages) : {}, package: packages ? exports.fromPackage(packages) : {},
parent: service.parent_id || '' parent: service.parent_id || '',
active: service.active
}; };
}; };
exports.toService = function (clientService) { exports.toService = function (clientService) {
return { // wat??
return JSON.parse(JSON.stringify({
id: clientService.id,
version_hash: clientService.hash || clientService.name, version_hash: clientService.hash || clientService.name,
deployment_group_id: clientService.deploymentGroupId, deployment_group_id: clientService.deploymentGroupId,
name: clientService.name, name: clientService.name,
@ -71,8 +74,9 @@ exports.toService = function (clientService) {
instance_ids: clientService.instances ? clientService.instances.map((instance) => { return instance.id; }) : [], instance_ids: clientService.instances ? clientService.instances.map((instance) => { return instance.id; }) : [],
service_dependency_ids: clientService.connections || [], service_dependency_ids: clientService.connections || [],
package_id: clientService.package ? clientService.package.id : '', package_id: clientService.package ? clientService.package.id : '',
parent_id: clientService.parent || '' parent_id: clientService.parent || '',
}; active: clientService.ative
}));
}; };
@ -81,7 +85,7 @@ exports.toVersion = function (clientVersion) {
id: clientVersion.id, id: clientVersion.id,
created: clientVersion.created || Date.now(), created: clientVersion.created || Date.now(),
manifest_id: clientVersion.manifestId, manifest_id: clientVersion.manifestId,
service_scales: clientVersion.scales ? clientVersion.scales.map(exports.toScale) : [], service_scales: clientVersion.scale ? clientVersion.scale.map(exports.toScale) : [],
plan: exports.toPlan(clientVersion.plan || {}) plan: exports.toPlan(clientVersion.plan || {})
}; };
}; };
@ -91,7 +95,7 @@ exports.fromVersion = function (version) {
id: version.id, id: version.id,
created: version.created, created: version.created,
manifestId: version.manifest_id, manifestId: version.manifest_id,
scales: version.service_scales ? version.service_scales.map(exports.fromScale) : [], scale: version.service_scales ? version.service_scales.map(exports.fromScale) : [],
plan: exports.fromPlan(version.plan || {}) plan: exports.fromPlan(version.plan || {})
}; };
}; };

View File

@ -19,6 +19,7 @@
"docker-compose-client": "^1.0.8", "docker-compose-client": "^1.0.8",
"dockerode": "^2.5.0", "dockerode": "^2.5.0",
"hoek": "^4.1.1", "hoek": "^4.1.1",
"param-case": "^2.1.1",
"penseur": "^7.12.3", "penseur": "^7.12.3",
"vasync": "^1.6.4", "vasync": "^1.6.4",
"yamljs": "^0.2.10" "yamljs": "^0.2.10"

View File

@ -253,7 +253,7 @@ describe('versions', () => {
const clientVersion = { const clientVersion = {
deploymentGroupId: deploymentGroup.id, deploymentGroupId: deploymentGroup.id,
manifestId: manifest.id, manifestId: manifest.id,
scales: [{ scale: [{
serviceName: 'consul', serviceName: 'consul',
replicas: 3 replicas: 3
}], }],
@ -270,7 +270,7 @@ describe('versions', () => {
data.createVersion(clientVersion, (err, result) => { data.createVersion(clientVersion, (err, result) => {
expect(err).to.not.exist(); expect(err).to.not.exist();
expect(result.id).to.exist(); expect(result.id).to.exist();
expect(result.scales).to.equal(clientVersion.scales); expect(result.scale).to.equal(clientVersion.scale);
done(); done();
}); });
}); });
@ -299,7 +299,7 @@ describe('versions', () => {
const clientVersion = { const clientVersion = {
manifestId: manifest.id, manifestId: manifest.id,
deploymentGroupId: deploymentGroup.id, deploymentGroupId: deploymentGroup.id,
scales: [{ scale: [{
serviceName: 'consul', serviceName: 'consul',
replicas: 3 replicas: 3
}], }],
@ -316,7 +316,7 @@ describe('versions', () => {
data.createVersion(clientVersion, (err, result) => { data.createVersion(clientVersion, (err, result) => {
expect(err).to.not.exist(); expect(err).to.not.exist();
expect(result.id).to.exist(); expect(result.id).to.exist();
expect(result.scales).to.equal(clientVersion.scales); expect(result.scale).to.equal(clientVersion.scale);
data.getVersion({ id: result.id }, (err, retrievedVersion1) => { data.getVersion({ id: result.id }, (err, retrievedVersion1) => {
expect(err).to.not.exist(); expect(err).to.not.exist();
expect(retrievedVersion1.id).to.equal(result.id); expect(retrievedVersion1.id).to.equal(result.id);
@ -353,7 +353,7 @@ describe('versions', () => {
const clientVersion = { const clientVersion = {
manifestId: manifest.id, manifestId: manifest.id,
deploymentGroupId: deploymentGroup.id, deploymentGroupId: deploymentGroup.id,
scales: [{ scale: [{
serviceName: 'consul', serviceName: 'consul',
replicas: 3 replicas: 3
}], }],
@ -370,7 +370,7 @@ describe('versions', () => {
data.createVersion(clientVersion, (err, result) => { data.createVersion(clientVersion, (err, result) => {
expect(err).to.not.exist(); expect(err).to.not.exist();
expect(result.id).to.exist(); expect(result.id).to.exist();
expect(result.scales).to.equal(clientVersion.scales); expect(result.scale).to.equal(clientVersion.scale);
data.getVersions({ manifestId: clientVersion.manifestId }, (err, versions) => { data.getVersions({ manifestId: clientVersion.manifestId }, (err, versions) => {
expect(err).to.not.exist(); expect(err).to.not.exist();
expect(versions.length).to.equal(1); expect(versions.length).to.equal(1);
@ -401,7 +401,7 @@ describe('versions', () => {
const clientVersion = { const clientVersion = {
manifestId: manifest.id, manifestId: manifest.id,
deploymentGroupId: deploymentGroup.id, deploymentGroupId: deploymentGroup.id,
scales: [{ scale: [{
serviceName: 'consul', serviceName: 'consul',
replicas: 3 replicas: 3
}], }],
@ -695,7 +695,7 @@ describe.skip('scale()', () => {
data.scale({ id: deploymentGroupServices[0].id, replicas: 3 }, (err, version) => { data.scale({ id: deploymentGroupServices[0].id, replicas: 3 }, (err, version) => {
expect(err).to.not.exist(); expect(err).to.not.exist();
expect(version).to.exist(); expect(version).to.exist();
expect(version.scales[0].replicas).to.equal(3); expect(version.scale[0].replicas).to.equal(3);
done(); done();
}); });
}); });

View File

@ -2,6 +2,7 @@
// const Assert = require('assert'); // const Assert = require('assert');
const TritonWatch = require('triton-watch'); const TritonWatch = require('triton-watch');
const util = require('util');
const DEPLOYMENT_GROUP = 'docker:label:com.docker.compose.project'; const DEPLOYMENT_GROUP = 'docker:label:com.docker.compose.project';
@ -30,6 +31,10 @@ module.exports = class Watcher {
this._tritonWatch.on('change', (container) => { return this.onChange(container); }); this._tritonWatch.on('change', (container) => { return this.onChange(container); });
} }
poll () {
this._tritonWatch.poll();
}
getDeploymentGroupId (name, cb) { getDeploymentGroupId (name, cb) {
this._data.getDeploymentGroup({ name }, (err, deploymentGroup) => { this._data.getDeploymentGroup({ name }, (err, deploymentGroup) => {
if (err) { if (err) {
@ -40,7 +45,7 @@ module.exports = class Watcher {
}); });
} }
getServiceId ({ serviceName, deploymentGroupId }, cb) { getService ({ serviceName, deploymentGroupId }, cb) {
this._data.getServices({ name: serviceName, deploymentGroupId }, (err, services) => { this._data.getServices({ name: serviceName, deploymentGroupId }, (err, services) => {
if (err) { if (err) {
return cb(err); return cb(err);
@ -50,62 +55,87 @@ module.exports = class Watcher {
return cb(); return cb();
} }
return cb(null, services.pop().id); return cb(null, services.pop());
}); });
} }
getInstance (machineId, cb) { getInstances (service, cb) {
this._data.getInstances({ machineId }, (err, instances) => { service.instances()
if (err) { .then((instances) => { return cb(null, instances); })
return cb(err); .catch((err) => { return cb(err); });
}
if (!instances || !instances.length) {
return cb();
}
return cb(null, instances.pop());
});
} }
resolveChanges ({ machine, deploymentGroupId, serviceId, instance }) { resolveChanges ({ machine, service, instances }) {
const handleError = (err) => { // 1. if instance doesn't exist, create new
if (err) { // 2. if instance exist, update status
console.error(err);
} const handleError = (cb) => {
return (err, data) => {
if (err) {
console.error(err);
return;
}
if (cb) {
cb(err, data);
}
};
}; };
const isNew = instances
.every(({ machineId }) => { return machine.id !== machineId; });
const instance = instances
.filter(({ machineId }) => { return machine.id === machineId; })
.pop();
const create = () => { const create = () => {
return this._data.updateInstance({ const instance = {
name: machine.name, name: machine.name,
status: machine.state.toUpperCase(), status: (machine.state || '').toUpperCase(),
machineId: machine.id machineId: machine.id
}, handleError); };
console.log('-> creating instance', util.inspect(instance));
return this._data.createInstance(instance, handleError((_, instance) => {
const updatedService = {
id: service.id,
instances: instances.concat(instance)
};
console.log('-> updating service', util.inspect(updatedService));
return this._data.updateService(updatedService, handleError);
}));
}; };
const update = () => { const update = () => {
return this._data.updateInstance({ const updatedInstance = {
id: instance.id, id: instance.id,
status: machine.state.toUpperCase() status: (machine.state || '').toUpperCase()
}, handleError); };
console.log('-> updating instance', util.inspect(updatedInstance));
return this._data.updateInstance(updatedInstance, handleError);
}; };
return (!instance || !instance.id) ? return isNew ?
create() : create() :
update(); update();
} }
onChange (machine) { onChange (machine) {
if (!machine) { if (!machine) {
console.error('`change` event received without machine data'); console.error('-> `change` event received without machine data');
return; return;
} }
console.log('-> `change` event received', util.inspect(machine));
const { id, tags = [] } = machine; const { id, tags = [] } = machine;
// assert id existence // assert id existence
if (!id) { if (!id) {
console.error('`change` event received for a machine without `id`'); console.error('-> `change` event received for a machine without `id`');
return; return;
} }
@ -115,7 +145,7 @@ module.exports = class Watcher {
); );
if (!isCompose) { if (!isCompose) {
console.error(`Changed machine ${id} was not provisioned by docker-compose`); console.error(`-> Changed machine ${id} was not provisioned by docker-compose`);
return; return;
} }
@ -133,26 +163,25 @@ module.exports = class Watcher {
}; };
}; };
const getInstance = (deploymentGroupId, serviceId) => { const getInstances = (service) => {
this.getInstance(id, handleError((instance) => { this.getInstances(service, handleError((instances) => {
return this.resolveChanges({ return this.resolveChanges({
machine, machine,
deploymentGroupId, service,
serviceId, instances
instance
}); });
})); }));
}; };
// assert that service exists // assert that service exists
const assertService = (deploymentGroupId) => { const assertService = (deploymentGroupId) => {
this.getServiceId({ serviceName, deploymentGroupId }, handleError((serviceId) => { this.getService({ serviceName, deploymentGroupId }, handleError((service) => {
if (!serviceId) { if (!service) {
console.error(`Service "${serviceName}" form DeploymentGroup "${deploymentGroupName}" for machine ${id} not found`); console.error(`Service "${serviceName}" form DeploymentGroup "${deploymentGroupName}" for machine ${id} not found`);
return; return;
} }
getInstance(deploymentGroupId, serviceId); getInstances(service);
})); }));
}; };

View File

@ -10,27 +10,6 @@ const expect = Lab.expect;
it('updates instances with the current status', (done) => { it('updates instances with the current status', (done) => {
const data = {
getDeploymentGroup: (options, next) => {
expect(options.name).to.equal('test-project');
next(null, { id: 'deployment-group-id' });
},
getServices: (options, next) => {
expect(options.deploymentGroupId).to.equal('deployment-group-id');
expect(options.name).to.equal('test-service');
next(null, [{ id: 'service-id' }]);
},
getInstances: (options, next) => {
expect(options.machineId).to.equal('test-id');
next(null, [{ id: 'instance-id' }]);
},
updateInstance: (options, next) => {
expect(options.id).to.equal('instance-id');
expect(options.status).to.equal('DELETED');
done();
}
};
const machine = { const machine = {
id: 'test-id', id: 'test-id',
tags: { tags: {
@ -41,6 +20,70 @@ it('updates instances with the current status', (done) => {
state: 'deleted' state: 'deleted'
}; };
const data = {
getDeploymentGroup: (options, next) => {
expect(options.name).to.equal('test-project');
next(null, { id: 'deployment-group-id' });
},
getServices: (options, next) => {
expect(options.deploymentGroupId).to.equal('deployment-group-id');
expect(options.name).to.equal('test-service');
next(null, [{
id: 'service-id',
instances: () => {
return Promise.resolve([{
machineId: machine.id,
id: 'instance-id'
}]);
}
}]);
},
updateInstance: (options, next) => {
expect(options.id).to.equal('instance-id');
expect(options.status).to.equal('DELETED');
done();
}
};
const portalOptions = { data, url: 'url', account: 'account', keyId: 'de:e7:73:9a:aa:91:bb:3e:72:8d:cc:62:ca:58:a2:ec' };
const portalWatch = new PortalWatch(portalOptions);
portalWatch._tritonWatch.removeAllListeners('change');
portalWatch.onChange(machine);
});
it('creates new instance', (done) => {
const machine = {
id: 'test-id',
tags: {
'docker:label:com.docker.compose.project': 'test-project',
'docker:label:com.docker.compose.service': 'test-service',
'docker:label:com.docker.compose.config-hash': 'test-hash'
},
state: 'created'
};
const data = {
getDeploymentGroup: (options, next) => {
expect(options.name).to.equal('test-project');
next(null, { id: 'deployment-group-id' });
},
getServices: (options, next) => {
expect(options.deploymentGroupId).to.equal('deployment-group-id');
expect(options.name).to.equal('test-service');
next(null, [{
id: 'service-id',
instances: () => { return Promise.resolve([]); }
}]);
},
createInstance: (options, next) => {
expect(options.id).to.equal(undefined);
expect(options.status).to.equal('CREATED');
expect(options.machineId).to.equal('test-id');
done();
}
};
const portalOptions = { data, url: 'url', account: 'account', keyId: 'de:e7:73:9a:aa:91:bb:3e:72:8d:cc:62:ca:58:a2:ec' }; const portalOptions = { data, url: 'url', account: 'account', keyId: 'de:e7:73:9a:aa:91:bb:3e:72:8d:cc:62:ca:58:a2:ec' };
const portalWatch = new PortalWatch(portalOptions); const portalWatch = new PortalWatch(portalOptions);
portalWatch._tritonWatch.removeAllListeners('change'); portalWatch._tritonWatch.removeAllListeners('change');

View File

@ -502,10 +502,6 @@ ast-types@0.9.0:
version "0.9.0" version "0.9.0"
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.0.tgz#c8721c8747ae4d5b29b929e99c5317b4e8745623" resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.0.tgz#c8721c8747ae4d5b29b929e99c5317b4e8745623"
ast-types@0.9.6:
version "0.9.6"
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9"
async-each@^1.0.0: async-each@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
@ -1401,8 +1397,8 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
base64-js@^1.0.2: base64-js@^1.0.2:
version "1.2.0" version "1.2.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.0.tgz#a39992d723584811982be5e290bb6a53d86700f1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886"
bcrypt-pbkdf@^1.0.0: bcrypt-pbkdf@^1.0.0:
version "1.0.1" version "1.0.1"
@ -1770,12 +1766,12 @@ camelcase@^4.0.0, camelcase@^4.1.0:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
caniuse-db@^1.0.30000187, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: caniuse-db@^1.0.30000187, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
version "1.0.30000692" version "1.0.30000693"
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000692.tgz#3da9a99353adbcea1e142b99f60ecc6216df47a5" resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000693.tgz#8510e7a9ab04adcca23a5dcefa34df9d28c1ce20"
caniuse-lite@^1.0.30000684: caniuse-lite@^1.0.30000684:
version "1.0.30000692" version "1.0.30000693"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000692.tgz#34600fd7152352d85a47f4662a3b51b02d8b646f" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000693.tgz#c9c6298697c71fdf6cb13eefe8aa93926f2f8613"
capture-stack-trace@^1.0.0: capture-stack-trace@^1.0.0:
version "1.0.0" version "1.0.0"
@ -2023,8 +2019,8 @@ code@4.1.x, code@^4.1.0:
hoek "4.x.x" hoek "4.x.x"
codemirror@^5.18.2: codemirror@^5.18.2:
version "5.26.0" version "5.27.0"
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.26.0.tgz#bcbee86816ed123870c260461c2b5c40b68746e5" resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.27.0.tgz#0c72f70c321a7d494fd8db1976698c249c985eb3"
coleman-liau@^1.0.0: coleman-liau@^1.0.0:
version "1.0.0" version "1.0.0"
@ -2861,12 +2857,6 @@ debug-log@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f"
debug@2.2.0, debug@~2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da"
dependencies:
ms "0.7.1"
debug@2.6.7: debug@2.6.7:
version "2.6.7" version "2.6.7"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.7.tgz#92bad1f6d05bbb6bba22cca88bcd0ec894c2861e" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.7.tgz#92bad1f6d05bbb6bba22cca88bcd0ec894c2861e"
@ -2879,6 +2869,12 @@ debug@^2.1.1, debug@^2.2.0, debug@^2.6.0, debug@^2.6.3, debug@^2.6.8:
dependencies: dependencies:
ms "2.0.0" ms "2.0.0"
debug@~2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da"
dependencies:
ms "0.7.1"
debuglog@^1.0.1: debuglog@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
@ -3334,10 +3330,10 @@ eslint-import-resolver-node@^0.2.0:
resolve "^1.1.6" resolve "^1.1.6"
eslint-module-utils@^2.0.0: eslint-module-utils@^2.0.0:
version "2.0.0" version "2.1.1"
resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.0.0.tgz#a6f8c21d901358759cdc35dbac1982ae1ee58bce" resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz#abaec824177613b8a95b299639e1b6facf473449"
dependencies: dependencies:
debug "2.2.0" debug "^2.6.8"
pkg-dir "^1.0.0" pkg-dir "^1.0.0"
eslint-plugin-flowtype@^2.34.0: eslint-plugin-flowtype@^2.34.0:
@ -3356,12 +3352,12 @@ eslint-plugin-hapi@4.x.x:
no-arrowception "1.x.x" no-arrowception "1.x.x"
eslint-plugin-import@^2.3.0: eslint-plugin-import@^2.3.0:
version "2.3.0" version "2.5.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.3.0.tgz#37c801e0ada0e296cbdf20c3f393acb5b52af36b" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.5.0.tgz#293b5ea7910a901a05a47ccdd7546e611725406c"
dependencies: dependencies:
builtin-modules "^1.1.1" builtin-modules "^1.1.1"
contains-path "^0.1.0" contains-path "^0.1.0"
debug "^2.2.0" debug "^2.6.8"
doctrine "1.5.0" doctrine "1.5.0"
eslint-import-resolver-node "^0.2.0" eslint-import-resolver-node "^0.2.0"
eslint-module-utils "^2.0.0" eslint-module-utils "^2.0.0"
@ -3502,7 +3498,7 @@ esprima@^2.6.0, esprima@~2.7.1:
version "2.7.3" version "2.7.3"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
esprima@^3.1.1, esprima@~3.1.0: esprima@^3.1.1:
version "3.1.3" version "3.1.3"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
@ -3712,11 +3708,11 @@ extsprintf@1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550"
extsprintf@1.2.0, extsprintf@^1.2.0: extsprintf@1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.2.0.tgz#5ad946c22f5b32ba7f8cd7426711c6e8a3fc2529" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.2.0.tgz#5ad946c22f5b32ba7f8cd7426711c6e8a3fc2529"
extsprintf@1.3.0: extsprintf@1.3.0, extsprintf@^1.2.0:
version "1.3.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
@ -4008,8 +4004,8 @@ get-caller-file@^1.0.1:
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
get-pkg-repo@^1.0.0: get-pkg-repo@^1.0.0:
version "1.3.0" version "1.4.0"
resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-1.3.0.tgz#43c6b4c048b75dd604fc5388edecde557f6335df" resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz#c73b489c06d80cc5536c2c853f9e05232056972d"
dependencies: dependencies:
hosted-git-info "^2.1.4" hosted-git-info "^2.1.4"
meow "^3.3.0" meow "^3.3.0"
@ -4247,8 +4243,8 @@ graphql-anywhere@^3.0.0, graphql-anywhere@^3.0.1:
resolved "https://registry.yarnpkg.com/graphql-anywhere/-/graphql-anywhere-3.1.0.tgz#3ea0d8e8646b5cee68035016a9a7557c15c21e96" resolved "https://registry.yarnpkg.com/graphql-anywhere/-/graphql-anywhere-3.1.0.tgz#3ea0d8e8646b5cee68035016a9a7557c15c21e96"
graphql-tag@^2.0.0, graphql-tag@^2.4.0: graphql-tag@^2.0.0, graphql-tag@^2.4.0:
version "2.4.0" version "2.4.2"
resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.4.0.tgz#0fe137348d4db2efaf29b52ba4c1cbf84ac138cb" resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.4.2.tgz#6a63297d8522d03a2b72d26f1b239aab343840cd"
graphql@^0.10.0, graphql@^0.10.1: graphql@^0.10.0, graphql@^0.10.1:
version "0.10.3" version "0.10.3"
@ -5200,8 +5196,8 @@ jest-snapshot@^20.0.3:
pretty-format "^20.0.3" pretty-format "^20.0.3"
jest-styled-components@^3.0.2: jest-styled-components@^3.0.2:
version "3.1.1" version "3.1.2"
resolved "https://registry.yarnpkg.com/jest-styled-components/-/jest-styled-components-3.1.1.tgz#d859a73c7844ecb47204b7240c00b499502a1fc8" resolved "https://registry.yarnpkg.com/jest-styled-components/-/jest-styled-components-3.1.2.tgz#4e1a1da604824c7f31507e80c43e88a2d8d8c4c9"
dependencies: dependencies:
css "^2.2.1" css "^2.2.1"
@ -6141,7 +6137,7 @@ mooremachine@^2.0.1:
optionalDependencies: optionalDependencies:
dtrace-provider "~0.8" dtrace-provider "~0.8"
ms@0.7.1, ms@^0.7.1: ms@0.7.1:
version "0.7.1" version "0.7.1"
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098"
@ -6149,6 +6145,10 @@ ms@2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 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"
msgpack@1.0.2: msgpack@1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/msgpack/-/msgpack-1.0.2.tgz#923e2c5cffa65c8418e9b228d1124793969c429c" resolved "https://registry.yarnpkg.com/msgpack/-/msgpack-1.0.2.tgz#923e2c5cffa65c8418e9b228d1124793969c429c"
@ -7454,8 +7454,8 @@ read@1.0.7:
mute-stream "~0.0.4" mute-stream "~0.0.4"
"readable-stream@>= 1.0.2", readable-stream@^2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.6: "readable-stream@>= 1.0.2", readable-stream@^2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.6:
version "2.3.1" version "2.3.2"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.1.tgz#84e26965bb9e785535ed256e8d38e92c69f09d10" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.2.tgz#5a04df05e4f57fe3f0dc68fdd11dc5c97c7e6f4d"
dependencies: dependencies:
core-util-is "~1.0.0" core-util-is "~1.0.0"
inherits "~2.0.3" inherits "~2.0.3"
@ -7526,7 +7526,7 @@ readline2@^1.0.1:
is-fullwidth-code-point "^1.0.0" is-fullwidth-code-point "^1.0.0"
mute-stream "0.0.5" mute-stream "0.0.5"
recast@0.11.12: recast@0.11.12, recast@^0.11.5:
version "0.11.12" version "0.11.12"
resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.12.tgz#a79e4d3f82d5d72a82ee177aeaa791e793bbe5d6" resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.12.tgz#a79e4d3f82d5d72a82ee177aeaa791e793bbe5d6"
dependencies: dependencies:
@ -7535,15 +7535,6 @@ recast@0.11.12:
private "~0.1.5" private "~0.1.5"
source-map "~0.5.0" source-map "~0.5.0"
recast@^0.11.5:
version "0.11.23"
resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.23.tgz#451fd3004ab1e4df9b4e4b66376b2a21912462d3"
dependencies:
ast-types "0.9.6"
esprima "~3.1.0"
private "~0.1.5"
source-map "~0.5.0"
rechoir@^0.6.2: rechoir@^0.6.2:
version "0.6.2" version "0.6.2"
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
@ -8081,8 +8072,8 @@ rx-lite@^3.1.2:
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"
safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.1.0: safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.1.0:
version "5.1.0" version "5.1.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.0.tgz#fe4c8460397f9eaaaa58e73be46273408a45e223" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
safe-buffer@~5.0.1: safe-buffer@~5.0.1:
version "5.0.1" version "5.0.1"
@ -9228,8 +9219,8 @@ typedarray@^0.0.6, typedarray@~0.0.5:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
ua-parser-js@^0.7.9: ua-parser-js@^0.7.9:
version "0.7.12" version "0.7.13"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.12.tgz#04c81a99bdd5dc52263ea29d24c6bf8d4818a4bb" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.13.tgz#cd9dd2f86493b3f44dbeeef3780fda74c5ee14be"
uglify-js@^2.6, uglify-js@^2.8.27: uglify-js@^2.6, uglify-js@^2.8.27:
version "2.8.29" version "2.8.29"