-
+
@@ -134,7 +139,7 @@
-
+
diff --git a/client/app/pages/queries/add-to-dashboard.js b/client/app/pages/queries/add-to-dashboard.js
index a5e720b041..8365010385 100644
--- a/client/app/pages/queries/add-to-dashboard.js
+++ b/client/app/pages/queries/add-to-dashboard.js
@@ -59,4 +59,3 @@ export default function init(ngModule) {
}
init.init = true;
-
diff --git a/client/app/pages/queries/source-view.js b/client/app/pages/queries/source-view.js
index 8aed418f15..27e57e04b2 100644
--- a/client/app/pages/queries/source-view.js
+++ b/client/app/pages/queries/source-view.js
@@ -141,4 +141,3 @@ export default function init(ngModule) {
}
init.init = true;
-
diff --git a/client/app/pages/queries/view.js b/client/app/pages/queries/view.js
index 80b7942b3f..61ed3bd234 100644
--- a/client/app/pages/queries/view.js
+++ b/client/app/pages/queries/view.js
@@ -1,6 +1,7 @@
import { pick, some, find, minBy, map, intersection, isArray, isObject } from 'lodash';
import { SCHEMA_NOT_SUPPORTED, SCHEMA_LOAD_ERROR } from '@/services/data-source';
import getTags from '@/services/getTags';
+import { policy } from '@/services/policy';
import Notifications from '@/services/notifications';
import template from './query.html';
@@ -21,7 +22,6 @@ function QueryViewCtrl(
toastr,
$uibModal,
currentUser,
- Policy,
Query,
DataSource,
Visualization,
@@ -451,14 +451,13 @@ function QueryViewCtrl(
$scope.openVisualizationEditor();
}
const intervals = clientConfig.queryRefreshIntervals;
- const allowedIntervals = Policy.getQueryRefreshIntervals();
+ const allowedIntervals = policy.getQueryRefreshIntervals();
$scope.refreshOptions = isArray(allowedIntervals) ? intersection(intervals, allowedIntervals) : intervals;
- $scope.updateQueryMetadata = changes =>
- $scope.$apply(() => {
- $scope.query = Object.assign($scope.query, changes);
- $scope.saveQuery();
- });
+ $scope.updateQueryMetadata = changes => $scope.$apply(() => {
+ $scope.query = Object.assign($scope.query, changes);
+ $scope.saveQuery();
+ });
$scope.showScheduleForm = false;
$scope.openScheduleForm = () => {
if (!$scope.canEdit || !$scope.canScheduleQuery) {
diff --git a/client/app/pages/query-snippets/edit.js b/client/app/pages/query-snippets/edit.js
index c85c1d375a..897138cc28 100644
--- a/client/app/pages/query-snippets/edit.js
+++ b/client/app/pages/query-snippets/edit.js
@@ -71,4 +71,3 @@ export default function init(ngModule) {
}
init.init = true;
-
diff --git a/client/app/pages/query-snippets/list.js b/client/app/pages/query-snippets/list.js
index 547792b423..39d087251a 100644
--- a/client/app/pages/query-snippets/list.js
+++ b/client/app/pages/query-snippets/list.js
@@ -31,4 +31,3 @@ export default function init(ngModule) {
}
init.init = true;
-
diff --git a/client/app/pages/settings/organization.js b/client/app/pages/settings/organization.js
index e826497aed..e615b6b07a 100644
--- a/client/app/pages/settings/organization.js
+++ b/client/app/pages/settings/organization.js
@@ -26,8 +26,8 @@ function OrganizationSettingsCtrl($http, toastr, clientConfig, Events) {
this.dateFormatList = clientConfig.dateFormatList;
this.googleLoginEnabled = clientConfig.googleLoginEnabled;
- this.disablePasswordLoginToggle = () =>
- (clientConfig.googleLoginEnabled || this.settings.auth_saml_enabled) === false;
+ // eslint-disable-next-line max-len
+ this.disablePasswordLoginToggle = () => (clientConfig.googleLoginEnabled || this.settings.auth_saml_enabled) === false;
}
export default function init(ngModule) {
@@ -52,4 +52,3 @@ export default function init(ngModule) {
}
init.init = true;
-
diff --git a/client/app/pages/users/list.js b/client/app/pages/users/list.js
index ffdeba3541..c40ca8c8f7 100644
--- a/client/app/pages/users/list.js
+++ b/client/app/pages/users/list.js
@@ -1,12 +1,13 @@
import { extend } from 'lodash';
+import { policy } from '@/services/policy';
import ListCtrl from '@/lib/list-ctrl';
import settingsMenu from '@/services/settingsMenu';
import template from './list.html';
class UsersListCtrl extends ListCtrl {
- constructor($scope, $location, currentUser, clientConfig, Policy, User) {
+ constructor($scope, $location, currentUser, clientConfig, User) {
super($scope, $location, currentUser, clientConfig);
- this.policy = Policy;
+ this.policy = policy;
this.enableUser = user => User.enableUser(user).then(this.update);
this.disableUser = user => User.disableUser(user).then(this.update);
this.deleteUser = user => User.deleteUser(user).then(this.update);
@@ -80,4 +81,3 @@ export default function init(ngModule) {
}
init.init = true;
-
diff --git a/client/app/pages/users/new.js b/client/app/pages/users/new.js
index 472f3255f0..f166505494 100644
--- a/client/app/pages/users/new.js
+++ b/client/app/pages/users/new.js
@@ -35,4 +35,3 @@ export default function init(ngModule) {
}
init.init = true;
-
diff --git a/client/app/pages/users/show.js b/client/app/pages/users/show.js
index 538c1a2031..f5e37e1c09 100644
--- a/client/app/pages/users/show.js
+++ b/client/app/pages/users/show.js
@@ -97,4 +97,3 @@ export default function init(ngModule) {
}
init.init = true;
-
diff --git a/client/app/services/keyboard-shortcuts.js b/client/app/services/keyboard-shortcuts.js
index 1e3b6cc2cb..1278c432fc 100644
--- a/client/app/services/keyboard-shortcuts.js
+++ b/client/app/services/keyboard-shortcuts.js
@@ -54,4 +54,3 @@ export default function init(ngModule) {
}
init.init = true;
-
diff --git a/client/app/services/ng.js b/client/app/services/ng.js
index ce59976f82..1a05e1b3b6 100644
--- a/client/app/services/ng.js
+++ b/client/app/services/ng.js
@@ -1,5 +1,7 @@
export let $http = null; // eslint-disable-line import/no-mutable-exports
export let $sanitize = null; // eslint-disable-line import/no-mutable-exports
+export let $q = null; // eslint-disable-line import/no-mutable-exports
+export let $rootScope = null; // eslint-disable-line import/no-mutable-exports
export let $uibModal = null; // eslint-disable-line import/no-mutable-exports
export let toastr = null; // eslint-disable-line import/no-mutable-exports
@@ -7,10 +9,11 @@ export default function init(ngModule) {
ngModule.run(($injector) => {
$http = $injector.get('$http');
$sanitize = $injector.get('$sanitize');
+ $q = $injector.get('$q');
+ $rootScope = $injector.get('$rootScope');
$uibModal = $injector.get('$uibModal');
toastr = $injector.get('toastr');
});
}
init.init = true;
-
diff --git a/client/app/services/organization-status.js b/client/app/services/organization-status.js
deleted file mode 100644
index 81d827e92e..0000000000
--- a/client/app/services/organization-status.js
+++ /dev/null
@@ -1,22 +0,0 @@
-export let OrganizationStatus = null; // eslint-disable-line import/no-mutable-exports
-
-function OrganizationStatusService($http) {
- this.objectCounters = {};
-
- this.refresh = () =>
- $http.get('api/organization/status').then(({ data }) => {
- this.objectCounters = data.object_counters;
- return this;
- });
-}
-
-export default function init(ngModule) {
- ngModule.service('OrganizationStatus', OrganizationStatusService);
-
- ngModule.run(($injector) => {
- OrganizationStatus = $injector.get('OrganizationStatus');
- });
-}
-
-init.init = true;
-
diff --git a/client/app/services/organizationStatus.js b/client/app/services/organizationStatus.js
new file mode 100644
index 0000000000..e4cbdcace0
--- /dev/null
+++ b/client/app/services/organizationStatus.js
@@ -0,0 +1,16 @@
+import { $http } from '@/services/ng';
+
+class OrganizationStatus {
+ constructor() {
+ this.objectCounters = {};
+ }
+
+ refresh() {
+ return $http.get('api/organization/status').then(({ data }) => {
+ this.objectCounters = data.object_counters;
+ return this;
+ });
+ }
+}
+
+export default new OrganizationStatus();
diff --git a/client/app/services/policy.js b/client/app/services/policy.js
deleted file mode 100644
index 366c06fd3e..0000000000
--- a/client/app/services/policy.js
+++ /dev/null
@@ -1,84 +0,0 @@
-import { isFunction, isArray } from 'lodash';
-
-export class Policy {
- constructor($injector) {
- this.$injector = $injector;
- }
-
- get user() {
- return this.$injector.get('currentUser');
- }
-
- get organizationStatus() {
- return this.$injector.get('OrganizationStatus');
- }
-
- refresh() {
- const $q = this.$injector.get('$q');
- return $q.resolve(this);
- }
-
- canCreateDataSource() {
- return this.user.hasPermission('admin');
- }
-
- isCreateDataSourceEnabled() {
- return this.user.hasPermission('admin');
- }
-
- canCreateDashboard() {
- return this.user.hasPermission('create_dashboard');
- }
-
- isCreateDashboardEnabled() {
- return this.user.hasPermission('create_dashboard');
- }
-
- // eslint-disable-next-line class-methods-use-this
- canCreateAlert() {
- return true;
- }
-
- canCreateUser() {
- return this.user.hasPermission('admin');
- }
-
- isCreateUserEnabled() {
- return this.user.hasPermission('admin');
- }
-
- getDashboardRefreshIntervals() {
- const clientConfig = this.$injector.get('clientConfig');
- const result = clientConfig.dashboardRefreshIntervals;
- return isArray(result) ? result : null;
- }
-
- getQueryRefreshIntervals() {
- const clientConfig = this.$injector.get('clientConfig');
- const result = clientConfig.queryRefreshIntervals;
- return isArray(result) ? result : null;
- }
-}
-
-export default function init(ngModule) {
- let appInjector = null;
-
- ngModule.run(($injector) => {
- 'ngInject';
-
- appInjector = $injector;
- });
-
- ngModule.provider('Policy', function policyProvider() {
- let PolicyClass = Policy;
-
- this.setPolicyClass = (policyClass) => {
- PolicyClass = policyClass;
- };
-
- this.$get = () => (isFunction(PolicyClass) ? new PolicyClass(appInjector) : null);
- });
-}
-
-init.init = true;
-
diff --git a/client/app/services/policy/DefaultPolicy.js b/client/app/services/policy/DefaultPolicy.js
new file mode 100644
index 0000000000..b1101addbe
--- /dev/null
+++ b/client/app/services/policy/DefaultPolicy.js
@@ -0,0 +1,49 @@
+import { isArray } from 'lodash';
+import { $q } from '@/services/ng';
+import { currentUser, clientConfig } from '@/services/auth';
+
+/* eslint-disable class-methods-use-this */
+
+export default class DefaultPolicy {
+ refresh() {
+ return $q.resolve(this);
+ }
+
+ canCreateDataSource() {
+ return currentUser.isAdmin;
+ }
+
+ isCreateDataSourceEnabled() {
+ return currentUser.isAdmin;
+ }
+
+ canCreateDashboard() {
+ return currentUser.hasPermission('create_dashboard');
+ }
+
+ isCreateDashboardEnabled() {
+ return currentUser.hasPermission('create_dashboard');
+ }
+
+ canCreateAlert() {
+ return true;
+ }
+
+ canCreateUser() {
+ return currentUser.isAdmin;
+ }
+
+ isCreateUserEnabled() {
+ return currentUser.isAdmin;
+ }
+
+ getDashboardRefreshIntervals() {
+ const result = clientConfig.dashboardRefreshIntervals;
+ return isArray(result) ? result : null;
+ }
+
+ getQueryRefreshIntervals() {
+ const result = clientConfig.queryRefreshIntervals;
+ return isArray(result) ? result : null;
+ }
+}
diff --git a/client/app/services/policy/index.js b/client/app/services/policy/index.js
new file mode 100644
index 0000000000..9a4ebd0b1d
--- /dev/null
+++ b/client/app/services/policy/index.js
@@ -0,0 +1,8 @@
+import DefaultPolicy from './DefaultPolicy';
+
+// eslint-disable-next-line import/no-mutable-exports
+export let policy = new DefaultPolicy();
+
+export function setPolicy(newPolicy) {
+ policy = newPolicy;
+}
diff --git a/client/app/services/query-result.js b/client/app/services/query-result.js
index 22fcdfe5ed..1d096d5538 100644
--- a/client/app/services/query-result.js
+++ b/client/app/services/query-result.js
@@ -237,25 +237,24 @@ function QueryResultService($resource, $timeout, $q, QueryResultError) {
}
});
- this.filteredData = this.query_result.data.rows.filter(row =>
- filters.reduce((memo, filter) => {
- if (!isArray(filter.current)) {
- filter.current = [filter.current];
- }
+ this.filteredData = this.query_result.data.rows.filter(row => filters.reduce((memo, filter) => {
+ if (!isArray(filter.current)) {
+ filter.current = [filter.current];
+ }
- return (
- memo &&
- some(filter.current, (v) => {
- const value = row[filter.name];
- if (moment.isMoment(value)) {
- return value.isSame(v);
- }
- // We compare with either the value or the String representation of the value,
- // because Select2 casts true/false to "true"/"false".
- return v === value || String(value) === v;
- })
- );
- }, true));
+ return (
+ memo &&
+ some(filter.current, (v) => {
+ const value = row[filter.name];
+ if (moment.isMoment(value)) {
+ return value.isSame(v);
+ }
+ // We compare with either the value or the String representation of the value,
+ // because Select2 casts true/false to "true"/"false".
+ return v === value || String(value) === v;
+ })
+ );
+ }, true));
} else {
this.filteredData = this.query_result.data.rows;
}
diff --git a/client/app/services/query-snippet.js b/client/app/services/query-snippet.js
index 0d4bb7f1f2..19ca698eaf 100644
--- a/client/app/services/query-snippet.js
+++ b/client/app/services/query-snippet.js
@@ -27,4 +27,3 @@ export default function init(ngModule) {
}
init.init = true;
-
diff --git a/client/app/services/query.js b/client/app/services/query.js
index 57ece987dd..740e339b21 100644
--- a/client/app/services/query.js
+++ b/client/app/services/query.js
@@ -145,6 +145,7 @@ class Parameter {
get ngModel() {
return this.normalizedValue;
}
+
set ngModel(value) {
this.setValue(value);
}
diff --git a/client/app/services/user.js b/client/app/services/user.js
index 0c46877e9b..201b568b2b 100644
--- a/client/app/services/user.js
+++ b/client/app/services/user.js
@@ -126,4 +126,3 @@ export default function init(ngModule) {
}
init.init = true;
-
diff --git a/client/app/services/widget.js b/client/app/services/widget.js
index 822af3dbeb..9bd4221e96 100644
--- a/client/app/services/widget.js
+++ b/client/app/services/widget.js
@@ -194,7 +194,7 @@ function WidgetFactory($http, $location, Query, Visualization, dashboardGridOpti
const result = param.clone();
result.title = mapping.title || param.title;
result.locals = [param];
- result.urlPrefix = `w${this.id}_`;
+ result.urlPrefix = `p_w${this.id}_`;
if (mapping.type === WidgetService.MappingType.StaticValue) {
result.setValue(mapping.value);
} else {
@@ -253,4 +253,3 @@ export default function init(ngModule) {
}
init.init = true;
-
diff --git a/client/app/visualizations/box-plot/index.js b/client/app/visualizations/box-plot/index.js
index 99afd7775c..59c266929a 100644
--- a/client/app/visualizations/box-plot/index.js
+++ b/client/app/visualizations/box-plot/index.js
@@ -192,4 +192,3 @@ export default function init(ngModule) {
}
init.init = true;
-
diff --git a/client/app/visualizations/chart/index.js b/client/app/visualizations/chart/index.js
index ab2f26a301..4343bfce95 100644
--- a/client/app/visualizations/chart/index.js
+++ b/client/app/visualizations/chart/index.js
@@ -231,8 +231,7 @@ function ChartEditor(ColorPalette, clientConfig) {
scope.form = {
yAxisColumns: [],
- seriesList: sortBy(keys(scope.options.seriesOptions), name =>
- scope.options.seriesOptions[name].zIndex),
+ seriesList: sortBy(keys(scope.options.seriesOptions), name => scope.options.seriesOptions[name].zIndex),
valuesList: keys(scope.options.valuesOptions),
};
@@ -370,4 +369,3 @@ export default function init(ngModule) {
}
init.init = true;
-
diff --git a/client/app/visualizations/chart/plotly/index.js b/client/app/visualizations/chart/plotly/index.js
index 43b18a1143..c2e7172e42 100644
--- a/client/app/visualizations/chart/plotly/index.js
+++ b/client/app/visualizations/chart/plotly/index.js
@@ -140,4 +140,3 @@ export default function init(ngModule) {
}
init.init = true;
-
diff --git a/client/app/visualizations/choropleth/index.js b/client/app/visualizations/choropleth/index.js
index 54c2cfa2e1..ff45d47e59 100644
--- a/client/app/visualizations/choropleth/index.js
+++ b/client/app/visualizations/choropleth/index.js
@@ -311,4 +311,3 @@ export default function init(ngModule) {
}
init.init = true;
-
diff --git a/client/app/visualizations/cohort/index.js b/client/app/visualizations/cohort/index.js
index f92c2ad167..25bf3e23c5 100644
--- a/client/app/visualizations/cohort/index.js
+++ b/client/app/visualizations/cohort/index.js
@@ -236,4 +236,3 @@ export default function init(ngModule) {
}
init.init = true;
-
diff --git a/client/app/visualizations/map/index.js b/client/app/visualizations/map/index.js
index d1eaa23f07..e7b799bfe8 100644
--- a/client/app/visualizations/map/index.js
+++ b/client/app/visualizations/map/index.js
@@ -309,4 +309,3 @@ export default function init(ngModule) {
}
init.init = true;
-
diff --git a/client/app/visualizations/sankey/index.js b/client/app/visualizations/sankey/index.js
index b2c59cacdc..6ca87ccbc3 100644
--- a/client/app/visualizations/sankey/index.js
+++ b/client/app/visualizations/sankey/index.js
@@ -120,10 +120,7 @@ function createSankey(element, data) {
const color = d3.scale.category20();
data = graph(data);
- data.nodes = _.map(data.nodes, d =>
- _.extend(d, {
- color: color(d.name.replace(/ .*/, '')),
- }));
+ data.nodes = _.map(data.nodes, d => _.extend(d, { color: color(d.name.replace(/ .*/, '')) }));
// append the svg canvas to the page
const svg = d3
diff --git a/cypress/cypress.js b/cypress/cypress.js
index 3363b437e1..0dda6e4cff 100644
--- a/cypress/cypress.js
+++ b/cypress/cypress.js
@@ -36,7 +36,10 @@ function runCypressCI() {
if (process.env.PERCY_TOKEN_ENCODED) {
process.env.PERCY_TOKEN = atob(`${process.env.PERCY_TOKEN_ENCODED}`);
}
- execSync('docker-compose run cypress ./node_modules/.bin/percy exec -- ./node_modules/.bin/cypress run --browser chrome', { stdio: 'inherit' });
+ execSync(
+ 'docker-compose run cypress ./node_modules/.bin/percy exec -- ./node_modules/.bin/cypress run --browser chrome',
+ { stdio: 'inherit' },
+ );
}
const command = process.argv[2] || 'all';
diff --git a/package-lock.json b/package-lock.json
index d44c23c8f8..0d806d44d3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -626,21 +626,10 @@
}
},
"acorn-jsx": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
- "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
- "dev": true,
- "requires": {
- "acorn": "^3.0.4"
- },
- "dependencies": {
- "acorn": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
- "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
- "dev": true
- }
- }
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz",
+ "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==",
+ "dev": true
},
"acorn-walk": {
"version": "6.1.0",
@@ -673,15 +662,29 @@
}
},
"ajv": {
- "version": "5.2.3",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.2.3.tgz",
- "integrity": "sha1-wG9Zh3jETGsWGrr+NGa4GtGBTtI=",
+ "version": "6.7.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz",
+ "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==",
"dev": true,
"requires": {
- "co": "^4.6.0",
- "fast-deep-equal": "^1.0.0",
- "json-schema-traverse": "^0.3.0",
- "json-stable-stringify": "^1.0.1"
+ "fast-deep-equal": "^2.0.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "dependencies": {
+ "fast-deep-equal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ }
}
},
"ajv-errors": {
@@ -691,9 +694,9 @@
"dev": true
},
"ajv-keywords": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.0.tgz",
- "integrity": "sha1-opbhf3v658HOT34N5T0pyzIWLfA=",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz",
+ "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=",
"dev": true
},
"align-text": {
@@ -975,14 +978,6 @@
"requires": {
"ast-types-flow": "0.0.7",
"commander": "^2.11.0"
- },
- "dependencies": {
- "commander": {
- "version": "2.16.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.16.0.tgz",
- "integrity": "sha512-sVXqklSaotK9at437sFlFpyOcJonxe0yST/AG9DkQKUdIE6IqGIMv4SfAQSKaJbSdVEJYItASCrBiVQHq1HQew==",
- "dev": true
- }
}
},
"arr-diff": {
@@ -1283,9 +1278,9 @@
"optional": true
},
"axobject-query": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.1.tgz",
- "integrity": "sha1-Bd+nBa2orZ25k/polvItOVsLCgc=",
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz",
+ "integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==",
"dev": true,
"requires": {
"ast-types-flow": "0.0.7"
@@ -4547,21 +4542,6 @@
"resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
"integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM="
},
- "del": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
- "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
- "dev": true,
- "requires": {
- "globby": "^5.0.0",
- "is-path-cwd": "^1.0.0",
- "is-path-in-cwd": "^1.0.0",
- "object-assign": "^4.0.1",
- "pify": "^2.0.0",
- "pinkie-promise": "^2.0.0",
- "rimraf": "^2.2.8"
- }
- },
"delaunay-triangulate": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/delaunay-triangulate/-/delaunay-triangulate-1.1.6.tgz",
@@ -4712,14 +4692,6 @@
"dev": true,
"requires": {
"esutils": "^2.0.2"
- },
- "dependencies": {
- "esutils": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
- "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
- "dev": true
- }
}
},
"dom-align": {
@@ -5261,123 +5233,115 @@
}
},
"eslint": {
- "version": "4.19.1",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz",
- "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==",
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.3.0.tgz",
+ "integrity": "sha512-N/tCqlMKkyNvAvLu+zI9AqDasnSLt00K+Hu8kdsERliC9jYEc8ck12XtjvOXrBKu8fK6RrBcN9bat6Xk++9jAg==",
"dev": true,
"requires": {
- "ajv": "^5.3.0",
- "babel-code-frame": "^6.22.0",
+ "ajv": "^6.5.0",
+ "babel-code-frame": "^6.26.0",
"chalk": "^2.1.0",
- "concat-stream": "^1.6.0",
- "cross-spawn": "^5.1.0",
+ "cross-spawn": "^6.0.5",
"debug": "^3.1.0",
"doctrine": "^2.1.0",
- "eslint-scope": "^3.7.1",
+ "eslint-scope": "^4.0.0",
+ "eslint-utils": "^1.3.1",
"eslint-visitor-keys": "^1.0.0",
- "espree": "^3.5.4",
- "esquery": "^1.0.0",
+ "espree": "^4.0.0",
+ "esquery": "^1.0.1",
"esutils": "^2.0.2",
"file-entry-cache": "^2.0.0",
"functional-red-black-tree": "^1.0.1",
"glob": "^7.1.2",
- "globals": "^11.0.1",
- "ignore": "^3.3.3",
+ "globals": "^11.7.0",
+ "ignore": "^4.0.2",
"imurmurhash": "^0.1.4",
- "inquirer": "^3.0.6",
- "is-resolvable": "^1.0.0",
- "js-yaml": "^3.9.1",
+ "inquirer": "^5.2.0",
+ "is-resolvable": "^1.1.0",
+ "js-yaml": "^3.11.0",
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.3.0",
- "lodash": "^4.17.4",
- "minimatch": "^3.0.2",
+ "lodash": "^4.17.5",
+ "minimatch": "^3.0.4",
"mkdirp": "^0.5.1",
"natural-compare": "^1.4.0",
"optionator": "^0.8.2",
"path-is-inside": "^1.0.2",
"pluralize": "^7.0.0",
"progress": "^2.0.0",
- "regexpp": "^1.0.1",
+ "regexpp": "^2.0.0",
"require-uncached": "^1.0.3",
- "semver": "^5.3.0",
+ "semver": "^5.5.0",
+ "string.prototype.matchall": "^2.0.0",
"strip-ansi": "^4.0.0",
- "strip-json-comments": "~2.0.1",
- "table": "4.0.2",
- "text-table": "~0.2.0"
+ "strip-json-comments": "^2.0.1",
+ "table": "^4.0.3",
+ "text-table": "^0.2.0"
},
"dependencies": {
- "ajv": {
- "version": "5.5.2",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
- "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
- "dev": true,
- "requires": {
- "co": "^4.6.0",
- "fast-deep-equal": "^1.0.0",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.3.0"
- }
- },
"ansi-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
"dev": true
},
- "ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
"dev": true,
"requires": {
- "color-convert": "^1.9.0"
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
}
},
- "chalk": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
- "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
+ "eslint-scope": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz",
+ "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==",
"dev": true,
"requires": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
+ "esrecurse": "^4.1.0",
+ "estraverse": "^4.1.1"
}
},
"esprima": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
- "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==",
- "dev": true
- },
- "esutils": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
- "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"dev": true
},
"globals": {
- "version": "11.7.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz",
- "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==",
+ "version": "11.10.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.10.0.tgz",
+ "integrity": "sha512-0GZF1RiPKU97IHUO5TORo9w1PwrH/NBPl+fS7oMLdaTRiYmYbwK4NWoZWrAdd0/abG9R2BU+OiwyQpTpE6pdfQ==",
"dev": true
},
- "has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "ignore": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
"dev": true
},
"js-yaml": {
- "version": "3.12.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
- "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
+ "version": "3.12.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz",
+ "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==",
"dev": true,
"requires": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
}
},
+ "semver": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
+ "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
+ "dev": true
+ },
"strip-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
@@ -5386,34 +5350,29 @@
"requires": {
"ansi-regex": "^3.0.0"
}
- },
- "supports-color": {
- "version": "5.4.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
- "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
- "dev": true,
- "requires": {
- "has-flag": "^3.0.0"
- }
}
}
},
"eslint-config-airbnb": {
- "version": "16.1.0",
- "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-16.1.0.tgz",
- "integrity": "sha512-zLyOhVWhzB/jwbz7IPSbkUuj7X2ox4PHXTcZkEmDqTvd0baJmJyuxlFPDlZOE/Y5bC+HQRaEkT3FoHo9wIdRiw==",
+ "version": "17.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-17.1.0.tgz",
+ "integrity": "sha512-R9jw28hFfEQnpPau01NO5K/JWMGLi6aymiF6RsnMURjTk+MqZKllCqGK/0tOvHkPi/NWSSOU2Ced/GX++YxLnw==",
"dev": true,
"requires": {
- "eslint-config-airbnb-base": "^12.1.0"
+ "eslint-config-airbnb-base": "^13.1.0",
+ "object.assign": "^4.1.0",
+ "object.entries": "^1.0.4"
},
"dependencies": {
"eslint-config-airbnb-base": {
- "version": "12.1.0",
- "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-12.1.0.tgz",
- "integrity": "sha512-/vjm0Px5ZCpmJqnjIzcFb9TKZrKWz0gnuG/7Gfkt0Db1ELJR51xkZth+t14rYdqWgX836XbuxtArbIHlVhbLBA==",
+ "version": "13.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-13.1.0.tgz",
+ "integrity": "sha512-XWwQtf3U3zIoKO1BbHh6aUhJZQweOwSt4c2JrPDg9FP3Ltv3+YfEv7jIDB8275tVnO/qOHbfuYg3kzw6Je7uWw==",
"dev": true,
"requires": {
- "eslint-restricted-globals": "^0.1.1"
+ "eslint-restricted-globals": "^0.1.1",
+ "object.assign": "^4.1.0",
+ "object.entries": "^1.0.4"
}
}
}
@@ -5428,13 +5387,13 @@
}
},
"eslint-import-resolver-node": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.1.tgz",
- "integrity": "sha512-yUtXS15gIcij68NmXmP9Ni77AQuCN0itXbCc/jWd8C6/yKZaSNXicpC8cgvjnxVdmfsosIXrjpzFq7GcDryb6A==",
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz",
+ "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==",
"dev": true,
"requires": {
- "debug": "^2.6.8",
- "resolve": "^1.2.0"
+ "debug": "^2.6.9",
+ "resolve": "^1.5.0"
},
"dependencies": {
"debug": {
@@ -5445,6 +5404,21 @@
"requires": {
"ms": "2.0.0"
}
+ },
+ "path-parse": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz",
+ "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==",
+ "dev": true,
+ "requires": {
+ "path-parse": "^1.0.6"
+ }
}
}
},
@@ -5587,9 +5561,9 @@
}
},
"eslint-module-utils": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz",
- "integrity": "sha512-jDI/X5l/6D1rRD/3T43q8Qgbls2nq5km5KSqiwlyUbGo5+04fXhMKdCPhjwbqAa6HXWaMxj8Q4hQDIh7IadJQw==",
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz",
+ "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=",
"dev": true,
"requires": {
"debug": "^2.6.8",
@@ -5653,21 +5627,21 @@
}
},
"eslint-plugin-import": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.7.0.tgz",
- "integrity": "sha512-HGYmpU9f/zJaQiKNQOVfHUh2oLWW3STBrCgH0sHTX1xtsxYlH1zjLh8FlQGEIdZSdTbUMaV36WaZ6ImXkenGxQ==",
+ "version": "2.14.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz",
+ "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==",
"dev": true,
"requires": {
- "builtin-modules": "^1.1.1",
"contains-path": "^0.1.0",
"debug": "^2.6.8",
"doctrine": "1.5.0",
"eslint-import-resolver-node": "^0.3.1",
- "eslint-module-utils": "^2.1.1",
+ "eslint-module-utils": "^2.2.0",
"has": "^1.0.1",
- "lodash.cond": "^4.3.0",
+ "lodash": "^4.17.4",
"minimatch": "^3.0.3",
- "read-pkg-up": "^2.0.0"
+ "read-pkg-up": "^2.0.0",
+ "resolve": "^1.6.0"
},
"dependencies": {
"debug": {
@@ -5689,17 +5663,26 @@
"isarray": "^1.0.0"
}
},
- "esutils": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
- "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
- "dev": true
- },
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
"dev": true
+ },
+ "path-parse": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz",
+ "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==",
+ "dev": true,
+ "requires": {
+ "path-parse": "^1.0.6"
+ }
}
}
},
@@ -5710,9 +5693,9 @@
"dev": true
},
"eslint-plugin-jsx-a11y": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.1.0.tgz",
- "integrity": "sha512-hnhf28u7Z9zlh7Y56tETrwnPeBvXgcqlP7ntHvZsWQs/n/p/vPnfNMNFWTqJAFcbd8PrDEifX1NRGHsjnUmqMw==",
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.1.2.tgz",
+ "integrity": "sha512-7gSSmwb3A+fQwtw0arguwMdOdzmKUgnUcbSNlo+GjKLAQFuC2EZxWqG9XHRI8VscBJD5a8raz3RuxQNFW+XJbw==",
"dev": true,
"requires": {
"aria-query": "^3.0.0",
@@ -5737,15 +5720,18 @@
}
},
"eslint-plugin-react": {
- "version": "7.10.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.10.0.tgz",
- "integrity": "sha512-18rzWn4AtbSUxFKKM7aCVcj5LXOhOKdwBino3KKWy4psxfPW0YtIbE8WNRDUdyHFL50BeLb6qFd4vpvNYyp7hw==",
+ "version": "7.12.3",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.12.3.tgz",
+ "integrity": "sha512-WTIA3cS8OzkPeCi4KWuPmjR33lgG9r9Y/7RmnLTRw08MZKgAfnK/n3BO4X0S67MPkVLazdfCNT/XWqcDu4BLTA==",
"dev": true,
"requires": {
+ "array-includes": "^3.0.3",
"doctrine": "^2.1.0",
"has": "^1.0.3",
"jsx-ast-utils": "^2.0.1",
- "prop-types": "^15.6.2"
+ "object.fromentries": "^2.0.0",
+ "prop-types": "^15.6.2",
+ "resolve": "^1.9.0"
},
"dependencies": {
"has": {
@@ -5757,6 +5743,12 @@
"function-bind": "^1.1.1"
}
},
+ "path-parse": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+ "dev": true
+ },
"prop-types": {
"version": "15.6.2",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz",
@@ -5766,6 +5758,15 @@
"loose-envify": "^1.3.1",
"object-assign": "^4.1.1"
}
+ },
+ "resolve": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz",
+ "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==",
+ "dev": true,
+ "requires": {
+ "path-parse": "^1.0.6"
+ }
}
}
},
@@ -5785,6 +5786,12 @@
"estraverse": "^4.1.1"
}
},
+ "eslint-utils": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz",
+ "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==",
+ "dev": true
+ },
"eslint-visitor-keys": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
@@ -5792,19 +5799,20 @@
"dev": true
},
"espree": {
- "version": "3.5.4",
- "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
- "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-4.1.0.tgz",
+ "integrity": "sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w==",
"dev": true,
"requires": {
- "acorn": "^5.5.0",
- "acorn-jsx": "^3.0.0"
+ "acorn": "^6.0.2",
+ "acorn-jsx": "^5.0.0",
+ "eslint-visitor-keys": "^1.0.0"
},
"dependencies": {
"acorn": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz",
- "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==",
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.5.tgz",
+ "integrity": "sha512-i33Zgp3XWtmZBMNvCr4azvOFeWVw1Rk6p3hfi3LUDvIFraOMywb1kAtrbi+med14m4Xfpqm3zRZMT+c0FNE7kg==",
"dev": true
}
}
@@ -6522,14 +6530,14 @@
}
},
"flat-cache": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz",
- "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=",
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz",
+ "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==",
"dev": true,
"requires": {
"circular-json": "^0.3.1",
- "del": "^2.0.2",
"graceful-fs": "^4.1.2",
+ "rimraf": "~2.6.2",
"write": "^0.2.1"
}
},
@@ -6806,11 +6814,13 @@
},
"balanced-match": {
"version": "1.0.0",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
+ "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -6827,7 +6837,8 @@
},
"concat-map": {
"version": "0.0.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"console-control-strings": {
"version": "1.1.0",
@@ -6956,6 +6967,7 @@
"minimatch": {
"version": "3.0.4",
"bundled": true,
+ "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -7055,7 +7067,8 @@
},
"number-is-nan": {
"version": "1.0.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"object-assign": {
"version": "4.1.1",
@@ -7798,20 +7811,6 @@
"integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
"dev": true
},
- "globby": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
- "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
- "dev": true,
- "requires": {
- "array-union": "^1.0.1",
- "arrify": "^1.0.0",
- "glob": "^7.0.3",
- "object-assign": "^4.0.1",
- "pify": "^2.0.0",
- "pinkie-promise": "^2.0.0"
- }
- },
"glsl-face-normal": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/glsl-face-normal/-/glsl-face-normal-1.0.2.tgz",
@@ -8799,22 +8798,21 @@
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"inquirer": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
- "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==",
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz",
+ "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==",
"dev": true,
"requires": {
"ansi-escapes": "^3.0.0",
"chalk": "^2.0.0",
"cli-cursor": "^2.1.0",
"cli-width": "^2.0.0",
- "external-editor": "^2.0.4",
+ "external-editor": "^2.1.0",
"figures": "^2.0.0",
"lodash": "^4.3.0",
"mute-stream": "0.0.7",
"run-async": "^2.2.0",
- "rx-lite": "^4.0.8",
- "rx-lite-aggregates": "^4.0.8",
+ "rxjs": "^5.5.2",
"string-width": "^2.1.0",
"strip-ansi": "^4.0.0",
"through": "^2.3.6"
@@ -8826,32 +8824,6 @@
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
"dev": true
},
- "ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "requires": {
- "color-convert": "^1.9.0"
- }
- },
- "chalk": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
- "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
- "dev": true,
- "requires": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- }
- },
- "has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
- "dev": true
- },
"strip-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
@@ -8860,15 +8832,6 @@
"requires": {
"ansi-regex": "^3.0.0"
}
- },
- "supports-color": {
- "version": "5.4.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
- "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
- "dev": true,
- "requires": {
- "has-flag": "^3.0.0"
- }
}
}
},
@@ -10549,6 +10512,7 @@
"resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
"integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
"dev": true,
+ "optional": true,
"requires": {
"jsonify": "~0.0.0"
}
@@ -10598,7 +10562,8 @@
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
"integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"jsprim": {
"version": "1.4.1",
@@ -11041,12 +11006,6 @@
"integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=",
"dev": true
},
- "lodash.cond": {
- "version": "4.5.2",
- "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz",
- "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=",
- "dev": true
- },
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@@ -12592,6 +12551,77 @@
}
}
},
+ "object.fromentries": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.0.tgz",
+ "integrity": "sha512-9iLiI6H083uiqUuvzyY6qrlmc/Gz8hLQFOcb/Ri/0xXFkSNS3ctV+CbE6yM2+AnkYfOB3dGjdzC0wrMLIhQICA==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "es-abstract": "^1.11.0",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.1"
+ },
+ "dependencies": {
+ "es-abstract": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
+ "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
+ "dev": true,
+ "requires": {
+ "es-to-primitive": "^1.2.0",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "is-callable": "^1.1.4",
+ "is-regex": "^1.0.4",
+ "object-keys": "^1.0.12"
+ },
+ "dependencies": {
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ }
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
+ "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
+ "dev": true,
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "is-callable": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
+ "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
+ "dev": true
+ },
+ "is-symbol": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
+ "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.0"
+ }
+ },
+ "object-keys": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz",
+ "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==",
+ "dev": true
+ }
+ }
+ },
"object.getownpropertydescriptors": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
@@ -14114,9 +14144,9 @@
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
},
"progress": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz",
- "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
"dev": true
},
"promise": {
@@ -15320,10 +15350,19 @@
}
}
},
+ "regexp.prototype.flags": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz",
+ "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2"
+ }
+ },
"regexpp": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz",
- "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
+ "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
"dev": true
},
"regexpu-core": {
@@ -15897,19 +15936,13 @@
"resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
"integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q="
},
- "rx-lite": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz",
- "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=",
- "dev": true
- },
- "rx-lite-aggregates": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz",
- "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=",
+ "rxjs": {
+ "version": "5.5.12",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz",
+ "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==",
"dev": true,
"requires": {
- "rx-lite": "*"
+ "symbol-observable": "1.0.1"
}
},
"safe-buffer": {
@@ -17099,6 +17132,76 @@
}
}
},
+ "string.prototype.matchall": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-2.0.0.tgz",
+ "integrity": "sha512-WoZ+B2ypng1dp4iFLF2kmZlwwlE19gmjgKuhL1FJfDgCREWb3ye3SDVHSzLH6bxfnvYmkCxbzkmWcQZHA4P//Q==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "es-abstract": "^1.10.0",
+ "function-bind": "^1.1.1",
+ "has-symbols": "^1.0.0",
+ "regexp.prototype.flags": "^1.2.0"
+ },
+ "dependencies": {
+ "es-abstract": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
+ "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
+ "dev": true,
+ "requires": {
+ "es-to-primitive": "^1.2.0",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "is-callable": "^1.1.4",
+ "is-regex": "^1.0.4",
+ "object-keys": "^1.0.12"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
+ "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
+ "dev": true,
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "is-callable": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
+ "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
+ "dev": true
+ },
+ "is-symbol": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
+ "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.0"
+ }
+ },
+ "object-keys": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz",
+ "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==",
+ "dev": true
+ }
+ }
+ },
"string.prototype.trim": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz",
@@ -17248,6 +17351,12 @@
}
}
},
+ "symbol-observable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz",
+ "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=",
+ "dev": true
+ },
"symbol-tree": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz",
@@ -17255,54 +17364,17 @@
"dev": true
},
"table": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz",
- "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==",
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz",
+ "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==",
"dev": true,
"requires": {
- "ajv": "^5.2.3",
- "ajv-keywords": "^2.1.0",
+ "ajv": "^6.0.1",
+ "ajv-keywords": "^3.0.0",
"chalk": "^2.1.0",
"lodash": "^4.17.4",
"slice-ansi": "1.0.0",
"string-width": "^2.1.1"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "requires": {
- "color-convert": "^1.9.0"
- }
- },
- "chalk": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
- "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
- "dev": true,
- "requires": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- }
- },
- "has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
- "dev": true
- },
- "supports-color": {
- "version": "5.4.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
- "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
- "dev": true,
- "requires": {
- "has-flag": "^3.0.0"
- }
- }
}
},
"tapable": {
diff --git a/package.json b/package.json
index 8bbcaa21f6..14fb2e7278 100644
--- a/package.json
+++ b/package.json
@@ -11,9 +11,10 @@
"watch": "webpack --watch --progress --colors -d",
"analyze": "npm run clean && BUNDLE_ANALYZER=on webpack",
"analyze:build": "npm run clean && NODE_ENV=production BUNDLE_ANALYZER=on webpack",
+ "lint": "eslint --config ./client/.eslintrc.js --ext .js --ext .jsx ./client/app",
"test": "TZ=Asia/Jerusalem jest",
"test:watch": "jest --watch",
- "cypress:install": "npm install --no-save cypress @percy/cypress",
+ "cypress:install": "npm install --no-save cypress@^3.1.5 @percy/cypress@^0.2.3",
"cypress": "node cypress/cypress.js"
},
"repository": {
@@ -50,6 +51,7 @@
"bootstrap": "^3.3.7",
"brace": "^0.11.0",
"chroma-js": "^1.3.6",
+ "classnames": "^2.2.6",
"core-js": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz",
"cornelius": "git+https://github.com/restorando/cornelius.git",
"d3": "^3.5.17",
@@ -98,16 +100,16 @@
"enzyme": "^3.8.0",
"enzyme-adapter-react-16": "^1.7.1",
"enzyme-to-json": "^3.3.5",
- "eslint": "^4.19.1",
- "eslint-config-airbnb": "^16.1.0",
+ "eslint": "^5.3.0",
+ "eslint-config-airbnb": "^17.1.0",
"eslint-config-airbnb-base": "^12.0.1",
"eslint-import-resolver-webpack": "^0.8.3",
"eslint-loader": "^2.1.1",
"eslint-plugin-cypress": "^2.0.1",
- "eslint-plugin-import": "^2.7.0",
+ "eslint-plugin-import": "^2.14.0",
"eslint-plugin-jest": "^21.25.1",
- "eslint-plugin-jsx-a11y": "^6.0.3",
- "eslint-plugin-react": "^7.7.0",
+ "eslint-plugin-jsx-a11y": "^6.1.2",
+ "eslint-plugin-react": "^7.12.3",
"file-loader": "^2.0.0",
"html-webpack-plugin": "^3.2.0",
"identity-obj-proxy": "^3.0.0",
diff --git a/redash/handlers/query_results.py b/redash/handlers/query_results.py
index 575f576653..45be31301f 100644
--- a/redash/handlers/query_results.py
+++ b/redash/handlers/query_results.py
@@ -10,7 +10,7 @@
require_permission, view_only)
from redash.tasks import QueryTask
from redash.tasks.queries import enqueue_query
-from redash.utils import (collect_parameters_from_request, gen_query_hash, json_dumps, utcnow)
+from redash.utils import (collect_parameters_from_request, gen_query_hash, json_dumps, json_loads, utcnow)
from redash.utils.parameterized_query import ParameterizedQuery
@@ -64,7 +64,7 @@ def run_query_sync(data_source, parameter_values, query_text, max_age=0):
return None
-def run_query(data_source, parameter_values, query_text, query_id, max_age=0):
+def run_query(data_source, parameter_values, query_text, query_id, max_age=0, parameter_schema=None):
if data_source.paused:
if data_source.pause_reason:
message = '{} is paused ({}). Please try later.'.format(data_source.name, data_source.pause_reason)
@@ -73,7 +73,7 @@ def run_query(data_source, parameter_values, query_text, query_id, max_age=0):
return error_response(message)
- query = ParameterizedQuery(query_text).apply(parameter_values)
+ query = ParameterizedQuery(query_text, parameter_schema).apply(parameter_values)
if query.missing_params:
return error_response(u'Missing parameter value for: {}'.format(u", ".join(query.missing_params)))
@@ -154,6 +154,23 @@ def options(self, query_id=None, query_result_id=None, filetype='json'):
return make_response("", 200, headers)
+ def _fetch_rows(self, query_id):
+ query = models.Query.get_by_id_and_org(query_id, self.current_org)
+ require_access(query.data_source.groups, self.current_user, view_only)
+
+ query_result = models.QueryResult.get_by_id_and_org(query.latest_query_data_id, self.current_org)
+
+ return json_loads(query_result.data)["rows"]
+
+ def _convert_queries_to_enums(self, definition):
+ if definition["type"] == "query":
+ definition["type"] = "enum"
+
+ rows = self._fetch_rows(definition.pop("queryId"))
+ definition["enumOptions"] = [row.get('value', row.get(row.keys()[0])) for row in rows if row]
+
+ return definition
+
@require_permission('execute_query')
def post(self, query_id):
"""
@@ -171,11 +188,13 @@ def post(self, query_id):
max_age = int(params.get('max_age', 0))
query = get_object_or_404(models.Query.get_by_id_and_org, query_id, self.current_org)
+ parameter_schema = map(self._convert_queries_to_enums,
+ query.options.get("parameters", []))
if not has_access(query.data_source.groups, self.current_user, not_view_only):
return {'job': {'status': 4, 'error': 'You do not have permission to run queries with this data source.'}}, 403
else:
- return run_query(query.data_source, parameters, query.query_text, query_id, max_age)
+ return run_query(query.data_source, parameters, query.query_text, query_id, max_age, parameter_schema=parameter_schema)
@require_permission('view_query')
def get(self, query_id=None, query_result_id=None, filetype='json'):
@@ -204,6 +223,7 @@ def get(self, query_id=None, query_result_id=None, filetype='json'):
max_age = int(request.args.get('maxAge', 0))
query_result = None
+ query = None
if query_result_id:
query_result = get_object_or_404(models.QueryResult.get_by_id_and_org, query_result_id, self.current_org)
@@ -257,6 +277,16 @@ def get(self, query_id=None, query_result_id=None, filetype='json'):
if should_cache:
response.headers.add_header('Cache-Control', 'private,max-age=%d' % ONE_YEAR)
+ str_date = query_result.retrieved_at.strftime("%Y_%m_%d")
+ str_id = None
+ if query is not None:
+ str_id = str(query.id)
+ else:
+ str_id = str(query_result.id)
+ filename = "{}_{}.{}".format(str_id, str_date, filetype,)
+
+ response.headers.add_header("Content-Disposition", 'attachment; filename="{}"'.format(filename,))
+
return response
else:
diff --git a/redash/query_runner/big_query.py b/redash/query_runner/big_query.py
index 274f63da8a..6ed63021b5 100644
--- a/redash/query_runner/big_query.py
+++ b/redash/query_runner/big_query.py
@@ -235,7 +235,7 @@ def _get_query_result(self, jobs, query):
def _get_columns_schema(self, table_data):
columns = []
- for column in table_data['schema']['fields']:
+ for column in table_data.get('schema', {}).get('fields', []):
columns.extend(self._get_columns_schema_column(column))
project_id = self._get_project_id()
diff --git a/redash/query_runner/clickhouse.py b/redash/query_runner/clickhouse.py
index a51328531a..8a07b3634a 100644
--- a/redash/query_runner/clickhouse.py
+++ b/redash/query_runner/clickhouse.py
@@ -68,13 +68,13 @@ def _get_tables(self, schema):
def _send_query(self, data, stream=False):
r = requests.post(
- self.configuration['url'],
+ self.configuration.get('url', "http://127.0.0.1:8123"),
data=data.encode("utf-8"),
stream=stream,
timeout=self.configuration.get('timeout', 30),
params={
- 'user': self.configuration['user'],
- 'password': self.configuration['password'],
+ 'user': self.configuration.get('user', "default"),
+ 'password': self.configuration.get('password', ""),
'database': self.configuration['dbname']
}
)
diff --git a/redash/query_runner/yandex_metrica.py b/redash/query_runner/yandex_metrica.py
index 814b1b8662..82f47d8565 100644
--- a/redash/query_runner/yandex_metrica.py
+++ b/redash/query_runner/yandex_metrica.py
@@ -115,7 +115,11 @@ def test_connection(self):
def _send_query(self, path='stat/v1/data', **kwargs):
token = kwargs.pop('oauth_token', self.configuration['token'])
- r = requests.get('{0}/{1}'.format(self.host, path), params=dict(oauth_token=token, **kwargs))
+ r = requests.get(
+ '{0}/{1}'.format(self.host, path),
+ headers={'Authorization': 'OAuth {}'.format(token)},
+ params=kwargs
+ )
if r.status_code != 200:
raise Exception(r.text)
return r.json()
diff --git a/redash/utils/parameterized_query.py b/redash/utils/parameterized_query.py
index 4f9a873518..c1ec2d38bd 100644
--- a/redash/utils/parameterized_query.py
+++ b/redash/utils/parameterized_query.py
@@ -1,7 +1,8 @@
import pystache
+from numbers import Number
from redash.utils import mustache_render
from funcy import distinct
-
+from dateutil.parser import parse
def _collect_key_names(nodes):
keys = []
@@ -33,17 +34,60 @@ def _parameter_names(parameter_values):
return names
+def _is_date(string):
+ try:
+ parse(string)
+ return True
+ except ValueError:
+ return False
+
+
+def _is_date_range(obj):
+ try:
+ return _is_date(obj["start"]) and _is_date(obj["end"])
+ except (KeyError, TypeError):
+ return False
+
+
class ParameterizedQuery(object):
- def __init__(self, template):
+ def __init__(self, template, schema=None):
+ self.schema = schema or []
self.template = template
self.query = template
self.parameters = {}
def apply(self, parameters):
- self.parameters.update(parameters)
- self.query = mustache_render(self.template, self.parameters)
+ invalid_parameter_names = [key for (key, value) in parameters.iteritems() if not self._valid(key, value)]
+ if invalid_parameter_names:
+ raise InvalidParameterError(invalid_parameter_names)
+ else:
+ self.parameters.update(parameters)
+ self.query = mustache_render(self.template, self.parameters)
+
return self
+ def _valid(self, name, value):
+ definition = next((definition for definition in self.schema if definition["name"] == name), None)
+
+ if not definition:
+ return True
+
+ validators = {
+ "text": lambda value: isinstance(value, basestring),
+ "number": lambda value: isinstance(value, Number),
+ "enum": lambda value: value in definition["enumOptions"],
+ "date": _is_date,
+ "datetime-local": _is_date,
+ "datetime-with-seconds": _is_date,
+ "date-range": _is_date_range,
+ "datetime-range": _is_date_range,
+ "datetime-range-with-seconds": _is_date_range,
+ }
+
+ validate = validators.get(definition["type"], lambda x: False)
+
+ return validate(value)
+
@property
def missing_params(self):
query_parameters = set(_collect_query_parameters(self.template))
@@ -52,3 +96,9 @@ def missing_params(self):
@property
def text(self):
return self.query
+
+
+class InvalidParameterError(Exception):
+ def __init__(self, parameters):
+ message = u"The following parameter values are incompatible with their type definitions: {}".format(", ".join(parameters))
+ super(InvalidParameterError, self).__init__(message)
diff --git a/requirements.txt b/requirements.txt
index c078f4cdff..f2dab0eabd 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -10,6 +10,8 @@ Flask-Admin==1.5.2
Flask-RESTful==0.3.5
Flask-Login==0.4.0
Flask-OAuthLib==0.9.5
+# pin this until https://github.com/lepture/flask-oauthlib/pull/388 is released
+requests-oauthlib>=0.6.2,<1.2.0
Flask-SQLAlchemy==2.3.2
Flask-Migrate==2.0.1
flask-mail==0.9.1
@@ -19,7 +21,7 @@ passlib==1.6.2
aniso8601==1.1.0
blinker==1.3
psycopg2==2.7.3.2
-python-dateutil==2.7.3
+python-dateutil==2.7.5
pytz==2016.7
PyYAML==3.12
redis==3.0.1
diff --git a/requirements_all_ds.txt b/requirements_all_ds.txt
index c2af9ebd7a..47fc62a206 100644
--- a/requirements_all_ds.txt
+++ b/requirements_all_ds.txt
@@ -11,7 +11,8 @@ td-client==0.8.0
pymssql==2.1.3
dql==0.5.24
dynamo3==0.4.7
-botocore==1.10.2
+boto3==1.9.85
+botocore==1.12.85
sasl>=0.1.3
thrift>=0.8.0
thrift_sasl>=0.1.0
diff --git a/requirements_dev.txt b/requirements_dev.txt
index 85dba64f27..d0332fb2c1 100644
--- a/requirements_dev.txt
+++ b/requirements_dev.txt
@@ -6,5 +6,5 @@ mock==2.0.0
# PyMongo and Athena dependencies are needed for some of the unit tests:
# (this is not perfect and we should resolve this in a different way)
pymongo[tls,srv]==3.6.1
-botocore==1.10.2
+botocore==1.12.85
PyAthena>=1.0.0
diff --git a/tests/utils/test_parameterized_query.py b/tests/utils/test_parameterized_query.py
index e076dfae11..c63acc96d4 100644
--- a/tests/utils/test_parameterized_query.py
+++ b/tests/utils/test_parameterized_query.py
@@ -1,6 +1,7 @@
from unittest import TestCase
+import pytest
-from redash.utils.parameterized_query import ParameterizedQuery
+from redash.utils.parameterized_query import ParameterizedQuery, InvalidParameterError
class TestParameterizedQuery(TestCase):
@@ -41,3 +42,92 @@ def test_handles_objects(self):
}
})
self.assertEqual(set([]), query.missing_params)
+
+ def test_raises_on_invalid_text_parameters(self):
+ schema = [{"name": "bar", "type": "text"}]
+ query = ParameterizedQuery("foo", schema)
+
+ with pytest.raises(InvalidParameterError):
+ query.apply({"bar": 7})
+
+ def test_validates_text_parameters(self):
+ schema = [{"name": "bar", "type": "text"}]
+ query = ParameterizedQuery("foo {{bar}}", schema)
+
+ query.apply({"bar": u"baz"})
+
+ self.assertEquals("foo baz", query.text)
+
+ def test_raises_on_invalid_number_parameters(self):
+ schema = [{"name": "bar", "type": "number"}]
+ query = ParameterizedQuery("foo", schema)
+
+ with pytest.raises(InvalidParameterError):
+ query.apply({"bar": "baz"})
+
+ def test_validates_number_parameters(self):
+ schema = [{"name": "bar", "type": "number"}]
+ query = ParameterizedQuery("foo {{bar}}", schema)
+
+ query.apply({"bar": 7})
+
+ self.assertEquals("foo 7", query.text)
+
+ def test_raises_on_invalid_date_parameters(self):
+ schema = [{"name": "bar", "type": "date"}]
+ query = ParameterizedQuery("foo", schema)
+
+ with pytest.raises(InvalidParameterError):
+ query.apply({"bar": "baz"})
+
+ def test_validates_date_parameters(self):
+ schema = [{"name": "bar", "type": "date"}]
+ query = ParameterizedQuery("foo {{bar}}", schema)
+
+ query.apply({"bar": "2000-01-01 12:00:00"})
+
+ self.assertEquals("foo 2000-01-01 12:00:00", query.text)
+
+ def test_raises_on_invalid_enum_parameters(self):
+ schema = [{"name": "bar", "type": "enum", "enumOptions": ["baz", "qux"]}]
+ query = ParameterizedQuery("foo", schema)
+
+ with pytest.raises(InvalidParameterError):
+ query.apply({"bar": 7})
+
+ def test_raises_on_unlisted_enum_value_parameters(self):
+ schema = [{"name": "bar", "type": "enum", "enumOptions": ["baz", "qux"]}]
+ query = ParameterizedQuery("foo", schema)
+
+ with pytest.raises(InvalidParameterError):
+ query.apply({"bar": "shlomo"})
+
+ def test_validates_enum_parameters(self):
+ schema = [{"name": "bar", "type": "enum", "enumOptions": ["baz", "qux"]}]
+ query = ParameterizedQuery("foo {{bar}}", schema)
+
+ query.apply({"bar": "baz"})
+
+ self.assertEquals("foo baz", query.text)
+
+ def test_raises_on_invalid_date_range_parameters(self):
+ schema = [{"name": "bar", "type": "date-range"}]
+ query = ParameterizedQuery("foo", schema)
+
+ with pytest.raises(InvalidParameterError):
+ query.apply({"bar": "baz"})
+
+ def test_validates_date_range_parameters(self):
+ schema = [{"name": "bar", "type": "date-range"}]
+ query = ParameterizedQuery("foo {{bar.start}} {{bar.end}}", schema)
+
+ query.apply({"bar": {"start": "2000-01-01 12:00:00", "end": "2000-12-31 12:00:00"}})
+
+ self.assertEquals("foo 2000-01-01 12:00:00 2000-12-31 12:00:00", query.text)
+
+ def test_raises_on_unexpected_param_types(self):
+ schema = [{"name": "bar", "type": "burrito"}]
+ query = ParameterizedQuery("foo", schema)
+
+ with pytest.raises(InvalidParameterError):
+ query.apply({"bar": "baz"})