diff --git a/Makefile b/Makefile index f59816e96a43..f35cbeceeacb 100644 --- a/Makefile +++ b/Makefile @@ -1089,7 +1089,7 @@ ui-generate: $(UI_ROOT)/distccl/bindata.go .PHONY: ui-lint ui-lint: $(YARN_INSTALLED_TARGET) $(UI_PROTOS) $(NODE_RUN) -C $(UI_ROOT) $(STYLINT) -c .stylintrc styl - $(NODE_RUN) -C $(UI_ROOT) $(TSLINT) -c tslint.json -p tsconfig.json --type-check + $(NODE_RUN) -C $(UI_ROOT) $(TSLINT) -c tslint.json -p tsconfig.json @# TODO(benesch): Invoke tslint just once when palantir/tslint#2827 is fixed. $(NODE_RUN) -C $(UI_ROOT) $(TSLINT) -c tslint.json *.js @if $(NODE_RUN) -C $(UI_ROOT) yarn list | grep phantomjs; then echo ^ forbidden UI dependency >&2; exit 1; fi diff --git a/pkg/server/server.go b/pkg/server/server.go index 587a907e73b8..8c56cfde8077 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -44,6 +44,7 @@ import ( "github.com/cockroachdb/cmux" "github.com/cockroachdb/cockroach/pkg/base" + "github.com/cockroachdb/cockroach/pkg/build" "github.com/cockroachdb/cockroach/pkg/gossip" "github.com/cockroachdb/cockroach/pkg/internal/client" "github.com/cockroachdb/cockroach/pkg/kv" @@ -1923,8 +1924,9 @@ func serveUIAssets(fileServer http.Handler, cfg Config) http.Handler { // Construct arguments for template. tmplArgs := ui.IndexHTMLArgs{ - LoginEnabled: cfg.RequireWebSession(), ExperimentalUseLogin: cfg.EnableWebSessionAuthentication, + LoginEnabled: cfg.RequireWebSession(), + Version: build.VersionPrefix(), } loggedInUser, ok := request.Context().Value(loggedInUserKey{}).(string) if ok && loggedInUser != "" { diff --git a/pkg/server/server_test.go b/pkg/server/server_test.go index f776ed4fe274..484f538734b5 100644 --- a/pkg/server/server_test.go +++ b/pkg/server/server_test.go @@ -31,6 +31,7 @@ import ( "time" "github.com/cockroachdb/cockroach/pkg/base" + "github.com/cockroachdb/cockroach/pkg/build" "github.com/cockroachdb/cockroach/pkg/config" "github.com/cockroachdb/cockroach/pkg/internal/client" "github.com/cockroachdb/cockroach/pkg/keys" @@ -988,7 +989,13 @@ func TestServeIndexHTML(t *testing.T) { t.Fatal(err) } respString := string(respBytes) - expected := fmt.Sprintf(htmlTemplate, `{"ExperimentalUseLogin":false,"LoginEnabled":false,"LoggedInUser":null}`) + expected := fmt.Sprintf( + htmlTemplate, + fmt.Sprintf( + `{"ExperimentalUseLogin":false,"LoginEnabled":false,"LoggedInUser":null,"Version":"%s"}`, + build.VersionPrefix(), + ), + ) if respString != expected { t.Fatalf("expected %s; got %s", expected, respString) } @@ -1012,8 +1019,20 @@ func TestServeIndexHTML(t *testing.T) { client http.Client json string }{ - {loggedInClient, `{"ExperimentalUseLogin":true,"LoginEnabled":true,"LoggedInUser":"authentic_user"}`}, - {loggedOutClient, `{"ExperimentalUseLogin":true,"LoginEnabled":true,"LoggedInUser":null}`}, + { + loggedInClient, + fmt.Sprintf( + `{"ExperimentalUseLogin":true,"LoginEnabled":true,"LoggedInUser":"authentic_user","Version":"%s"}`, + build.VersionPrefix(), + ), + }, + { + loggedOutClient, + fmt.Sprintf( + `{"ExperimentalUseLogin":true,"LoginEnabled":true,"LoggedInUser":null,"Version":"%s"}`, + build.VersionPrefix(), + ), + }, } for _, testCase := range cases { diff --git a/pkg/ui/package.json b/pkg/ui/package.json index 69ebcedd56e9..4f5523a5706c 100644 --- a/pkg/ui/package.json +++ b/pkg/ui/package.json @@ -102,7 +102,7 @@ "stylus-loader": "^3.0.1", "thread-loader": "^1.1.1", "ts-loader": "^2.3.4", - "tslint": "^5.1.0", + "tslint": "^5.10.0", "typescript": "^2.2.1", "url-loader": "^0.5.8", "webpack": "^3.5.6", diff --git a/pkg/ui/src/redux/analytics.ts b/pkg/ui/src/redux/analytics.ts index 4ab7c8049c1f..f20bdf4bf9d5 100644 --- a/pkg/ui/src/redux/analytics.ts +++ b/pkg/ui/src/redux/analytics.ts @@ -80,15 +80,15 @@ export class AnalyticsSync { /** * Construct a new AnalyticsSync object. - * @param analytics Underlying interface to push to the analytics service. - * @param store The redux store for the Admin UI. + * @param analyticsService Underlying interface to push to the analytics service. + * @param deprecatedStore The redux store for the Admin UI. [DEPRECATED] * @param redactions A list of redaction regular expressions, used to * scrub any potential personally-identifying information from the data * being tracked. */ constructor( - private analytics: Analytics, - private store: Store, + private analyticsService: Analytics, + private deprecatedStore: Store, private redactions: PageTrackRedaction[], ) {} @@ -147,13 +147,13 @@ export class AnalyticsSync { } // Do nothing if version information is not yet available. - const state = this.store.getState(); + const state = this.deprecatedStore.getState(); const versions = versionsSelector(state); if (_.isEmpty(versions)) { return; } - this.analytics.identify({ + this.analyticsService.identify({ userId: cluster_id, traits: { version: versions[0], @@ -170,7 +170,7 @@ export class AnalyticsSync { * to eventually retrieve this without having to request it ourselves. */ private getCluster(): ClusterResponse | null { - const state = this.store.getState(); + const state = this.deprecatedStore.getState(); // Do nothing if cluster ID has not been loaded. const cluster = state.cachedData.cluster; @@ -202,7 +202,7 @@ export class AnalyticsSync { search = "?" + params.toString(); } - this.analytics.page({ + this.analyticsService.page({ userId: userID, name: path, properties: { diff --git a/pkg/ui/src/redux/login.ts b/pkg/ui/src/redux/login.ts index e119239a0a37..bb72211c989c 100644 --- a/pkg/ui/src/redux/login.ts +++ b/pkg/ui/src/redux/login.ts @@ -5,20 +5,11 @@ import { Action } from "redux"; import { userLogin } from "src/util/api"; import { AdminUIState } from "src/redux/state"; import { cockroach } from "src/js/protos"; +import { getDataFromServer } from "src/util/dataFromServer"; + import UserLoginRequest = cockroach.server.serverpb.UserLoginRequest; -// Tell TypeScript about `window.loggedInUser`, which is set in a script -// tag in index.html, the contents of which are generated in a Go template -// server-side. -declare global { - interface Window { - dataFromServer: { - ExperimentalUseLogin: boolean; - LoginEnabled: boolean; - LoggedInUser: string; - }; - } -} +const dataFromServer = getDataFromServer(); // State for application use. @@ -94,11 +85,11 @@ class NoLoginState { export const selectLoginState = createSelector( (state: AdminUIState) => state.login, (login: LoginAPIState) => { - if (!window.dataFromServer || !window.dataFromServer.ExperimentalUseLogin) { + if (!dataFromServer.ExperimentalUseLogin) { return new NoLoginState(); } - if (!window.dataFromServer.LoginEnabled) { + if (!dataFromServer.LoginEnabled) { return new LoginDisabledState(); } @@ -117,7 +108,7 @@ export interface LoginAPIState { } const emptyLoginState: LoginAPIState = { - loggedInUser: window.dataFromServer && window.dataFromServer.LoggedInUser, + loggedInUser: dataFromServer.LoggedInUser, error: null, inProgress: false, }; diff --git a/pkg/ui/src/redux/state.ts b/pkg/ui/src/redux/state.ts index cf7286563f15..b8066125b06d 100644 --- a/pkg/ui/src/redux/state.ts +++ b/pkg/ui/src/redux/state.ts @@ -31,7 +31,7 @@ export interface AdminUIState { export function createAdminUIStore() { const sagaMiddleware = createSagaMiddleware(); - const store: Store = createStore( + const s: Store = createStore( combineReducers({ cachedData: apiReducersReducer, hover: hoverReducer, @@ -61,7 +61,7 @@ export function createAdminUIStore() { ); sagaMiddleware.run(queryMetricsSaga); - return store; + return s; } export const store = createAdminUIStore(); diff --git a/pkg/ui/src/util/api.ts b/pkg/ui/src/util/api.ts index f98eb26f4b21..d88816c86e23 100644 --- a/pkg/ui/src/util/api.ts +++ b/pkg/ui/src/util/api.ts @@ -159,7 +159,7 @@ function timeoutFetch = (req: TRequest, timeout?: moment.Duration) => Promise; +export type APIRequestFn = (req: TReq, timeout?: moment.Duration) => Promise; // propsToQueryString is a helper function that converts a set of object // properties to a query string @@ -258,7 +258,7 @@ export function getLogs(req: LogsRequestMessage, timeout?: moment.Duration): Pro } // getLiveness gets cluster liveness information from the current node. -export function getLiveness(_: LivenessRequestMessage, timeout?: moment.Duration): Promise { +export function getLiveness(_req: LivenessRequestMessage, timeout?: moment.Duration): Promise { return timeoutFetch(serverpb.LivenessResponse, `${API_PREFIX}/liveness`, null, timeout); } diff --git a/pkg/ui/src/util/dataFromServer.ts b/pkg/ui/src/util/dataFromServer.ts new file mode 100644 index 000000000000..9c522dde892a --- /dev/null +++ b/pkg/ui/src/util/dataFromServer.ts @@ -0,0 +1,19 @@ +export interface DataFromServer { + ExperimentalUseLogin: boolean; + LoginEnabled: boolean; + LoggedInUser: string; + Version: string; +} + +// Tell TypeScript about `window.dataFromServer`, which is set in a script +// tag in index.html, the contents of which are generated in a Go template +// server-side. +declare global { + interface Window { + dataFromServer: DataFromServer; + } +} + +export function getDataFromServer(): DataFromServer { + return window.dataFromServer || {}; +} diff --git a/pkg/ui/src/util/docs.ts b/pkg/ui/src/util/docs.ts index 617db50255cc..281ba1e7fda3 100644 --- a/pkg/ui/src/util/docs.ts +++ b/pkg/ui/src/util/docs.ts @@ -1,7 +1,7 @@ -// TODO(benesch): Derive this URL from build.VersionPrefix() rather than -// hardcoding it. This is harder than it sounds, since we don't want to encode -// the branch name in embedded.go. -const docsURLBase = "https://www.cockroachlabs.com/docs/v2.0"; +import { getDataFromServer } from "src/util/dataFromServer"; + +const version = getDataFromServer().Version || "stable"; +const docsURLBase = "https://www.cockroachlabs.com/docs/" + version; export default function docsURL(pageName: string): string { return `${docsURLBase}/${pageName}`; diff --git a/pkg/ui/src/views/cluster/components/linegraph/index.tsx b/pkg/ui/src/views/cluster/components/linegraph/index.tsx index 96b687dd197c..cf50d287d007 100644 --- a/pkg/ui/src/views/cluster/components/linegraph/index.tsx +++ b/pkg/ui/src/views/cluster/components/linegraph/index.tsx @@ -181,10 +181,10 @@ export class LineGraph extends React.Component { } render() { - const { title, subtitle, tooltip, data, hoverOn} = this.props; + const { title, subtitle, tooltip, data } = this.props; let hoverProps: Partial> = {}; - if (hoverOn) { + if (this.props.hoverOn) { hoverProps = { onMouseMove: this.mouseMove, onMouseLeave: this.mouseLeave, diff --git a/pkg/ui/src/views/cluster/containers/nodeGraphs/index.tsx b/pkg/ui/src/views/cluster/containers/nodeGraphs/index.tsx index 35ed3bfd388b..683a7a3db682 100644 --- a/pkg/ui/src/views/cluster/containers/nodeGraphs/index.tsx +++ b/pkg/ui/src/views/cluster/containers/nodeGraphs/index.tsx @@ -143,7 +143,7 @@ class NodeGraphs extends React.Component { } render() { - const { params, nodesSummary, hoverState, hoverOn, hoverOff } = this.props; + const { params, nodesSummary, hoverState } = this.props; const selectedDashboard = params[dashboardNameAttr]; const dashboard = _.has(dashboards, selectedDashboard) ? selectedDashboard @@ -179,6 +179,12 @@ class NodeGraphs extends React.Component { tooltipSelection, }; + const forwardParams = { + hoverOn: this.props.hoverOn, + hoverOff: this.props.hoverOff, + hoverState: this.props.hoverState, + }; + // Generate graphs for the current dashboard, wrapping each one in a // MetricsDataProvider with a unique key. const graphs = dashboards[dashboard].component(dashboardProps); @@ -187,7 +193,7 @@ class NodeGraphs extends React.Component { return (
- { React.cloneElement(graph, { hoverOn, hoverOff, hoverState }) } + { React.cloneElement(graph, forwardParams) }
); diff --git a/pkg/ui/src/views/databases/containers/databaseGrants/index.tsx b/pkg/ui/src/views/databases/containers/databaseGrants/index.tsx index db0953c69730..267a5182e77c 100644 --- a/pkg/ui/src/views/databases/containers/databaseGrants/index.tsx +++ b/pkg/ui/src/views/databases/containers/databaseGrants/index.tsx @@ -14,7 +14,7 @@ import { } from "src/redux/apiReducers"; import { - DatabaseSummaryBase, DatabaseSummaryExplicitData, databaseDetails, tableInfos, grants, + DatabaseSummaryBase, DatabaseSummaryExplicitData, databaseDetails, tableInfos, grants as selectGrants, } from "src/views/databases/containers/databaseSummary"; class DatabaseGrantsSortedTable extends SortedTable {} @@ -86,7 +86,7 @@ export default connect( tableInfos: tableInfos(state, ownProps.name), sortSetting: grantsSortSetting.selector(state), dbResponse: databaseDetails(state)[ownProps.name] && databaseDetails(state)[ownProps.name].data, - grants: grants(state, ownProps.name), + grants: selectrants(state, ownProps.name), }; }, { diff --git a/pkg/ui/src/views/databases/containers/databaseTables/index.tsx b/pkg/ui/src/views/databases/containers/databaseTables/index.tsx index d276ca3af63a..da7869b8de0c 100644 --- a/pkg/ui/src/views/databases/containers/databaseTables/index.tsx +++ b/pkg/ui/src/views/databases/containers/databaseTables/index.tsx @@ -18,7 +18,7 @@ import { Bytes } from "src/util/format"; import { TableInfo } from "src/views/databases/data/tableInfo"; import { - DatabaseSummaryBase, DatabaseSummaryExplicitData, databaseDetails, tableInfos, grants, + DatabaseSummaryBase, DatabaseSummaryExplicitData, databaseDetails, tableInfos as selectTableInfos, grants, } from "src/views/databases/containers/databaseSummary"; const databaseTablesSortSetting = new LocalSetting( @@ -124,7 +124,7 @@ class DatabaseSummaryTables extends DatabaseSummaryBase { export default connect( (state: AdminUIState, ownProps: DatabaseSummaryExplicitData) => { return { - tableInfos: tableInfos(state, ownProps.name), + tableInfos: selectTableInfos(state, ownProps.name), sortSetting: databaseTablesSortSetting.selector(state), dbResponse: databaseDetails(state)[ownProps.name] && databaseDetails(state)[ownProps.name].data, grants: grants(state, ownProps.name), diff --git a/pkg/ui/src/views/databases/containers/tableDetails/index.tsx b/pkg/ui/src/views/databases/containers/tableDetails/index.tsx index 52d2289d7823..c493c39253ee 100644 --- a/pkg/ui/src/views/databases/containers/tableDetails/index.tsx +++ b/pkg/ui/src/views/databases/containers/tableDetails/index.tsx @@ -143,7 +143,7 @@ class TableMain extends React.Component { * SELECTORS */ -function tableInfo(state: AdminUIState, props: RouterState): TableInfo { +function selectTableInfo(state: AdminUIState, props: RouterState): TableInfo { const db = props.params[databaseNameAttr]; const table = props.params[tableNameAttr]; const details = state.cachedData.tableDetails[generateTableID(db, table)]; @@ -155,7 +155,7 @@ function tableInfo(state: AdminUIState, props: RouterState): TableInfo { const tableMainConnected = connect( (state: AdminUIState, ownProps: RouterState) => { return { - tableInfo: tableInfo(state, ownProps), + tableInfo: selectTableInfo(state, ownProps), grantsSortSetting: databaseTableGrantsSortSetting.selector(state), }; }, diff --git a/pkg/ui/src/views/devtools/containers/raftMessages/index.tsx b/pkg/ui/src/views/devtools/containers/raftMessages/index.tsx index 98692ac72c99..17ca62862f30 100644 --- a/pkg/ui/src/views/devtools/containers/raftMessages/index.tsx +++ b/pkg/ui/src/views/devtools/containers/raftMessages/index.tsx @@ -6,7 +6,7 @@ import { InjectedRouter, RouterState } from "react-router"; import { createSelector } from "reselect"; import { refreshNodes, refreshLiveness } from "src/redux/apiReducers"; -import { hoverStateSelector, HoverState, hoverOn, hoverOff } from "src/redux/hover"; +import { hoverStateSelector, HoverState, hoverOn as hoverOnAction, hoverOff as hoverOffAction } from "src/redux/hover"; import { nodesSummarySelector, NodesSummary } from "src/redux/nodes"; import { AdminUIState } from "src/redux/state"; import { nodeIDAttr } from "src/util/constants"; @@ -24,8 +24,8 @@ import messagesDashboard from "./messages"; interface NodeGraphsOwnProps { refreshNodes: typeof refreshNodes; refreshLiveness: typeof refreshLiveness; - hoverOn: typeof hoverOn; - hoverOff: typeof hoverOff; + hoverOn: typeof hoverOnAction; + hoverOff: typeof hoverOffAction; nodesQueryValid: boolean; livenessQueryValid: boolean; nodesSummary: NodesSummary; @@ -176,7 +176,7 @@ function mapStateToProps(state: AdminUIState) { const actions = { refreshNodes, refreshLiveness, - hoverOn, - hoverOff, + hoverOnAction, + hoverOffAction, }; export default connect(mapStateToProps, actions)(NodeGraphs); diff --git a/pkg/ui/src/views/devtools/containers/raftRanges/index.tsx b/pkg/ui/src/views/devtools/containers/raftRanges/index.tsx index 348914152994..33c88ab92ed9 100644 --- a/pkg/ui/src/views/devtools/containers/raftRanges/index.tsx +++ b/pkg/ui/src/views/devtools/containers/raftRanges/index.tsx @@ -271,13 +271,13 @@ class RangesMain extends React.Component { */ // Base selectors to extract data from redux state. -const raftState = (state: AdminUIState): CachedDataReducerState => state.cachedData.raft; +const selectRaftState = (state: AdminUIState): CachedDataReducerState => state.cachedData.raft; // Connect the RangesMain class with our redux store. const rangesMainConnected = connect( (state: AdminUIState) => { return { - state: raftState(state), + state: selectRaftState(state), }; }, { diff --git a/pkg/ui/src/views/reports/containers/problemRanges/connectionsTable.tsx b/pkg/ui/src/views/reports/containers/problemRanges/connectionsTable.tsx index 5df09e015a63..6cb97b3a35f9 100644 --- a/pkg/ui/src/views/reports/containers/problemRanges/connectionsTable.tsx +++ b/pkg/ui/src/views/reports/containers/problemRanges/connectionsTable.tsx @@ -21,7 +21,7 @@ interface ConnectionsTableProps { const connectionTableColumns: ConnectionTableColumn[] = [ { title: "Node", - extract: (_, id) => ( + extract: (_problem, id) => ( n{id} diff --git a/pkg/ui/src/views/reports/containers/problemRanges/index.tsx b/pkg/ui/src/views/reports/containers/problemRanges/index.tsx index d9cd61ee5127..22306eb213a4 100644 --- a/pkg/ui/src/views/reports/containers/problemRanges/index.tsx +++ b/pkg/ui/src/views/reports/containers/problemRanges/index.tsx @@ -118,8 +118,8 @@ class ProblemRanges extends React.Component { const { data } = problemRanges; - const validIDs = _.keys(_.pickBy(data.problems_by_node_id, problems => { - return _.isEmpty(problems.error_message); + const validIDs = _.keys(_.pickBy(data.problems_by_node_id, d => { + return _.isEmpty(d.error_message); })); if (validIDs.length === 0) { if (_.isEmpty(this.props.params[nodeIDAttr])) { diff --git a/pkg/ui/src/views/shared/containers/metricDataProvider/index.tsx b/pkg/ui/src/views/shared/containers/metricDataProvider/index.tsx index 7312a4ad7976..0460f4865394 100644 --- a/pkg/ui/src/views/shared/containers/metricDataProvider/index.tsx +++ b/pkg/ui/src/views/shared/containers/metricDataProvider/index.tsx @@ -7,7 +7,7 @@ import moment from "moment"; import * as protos from "src/js/protos"; import { AdminUIState } from "src/redux/state"; -import { requestMetrics, MetricsQuery } from "src/redux/metrics"; +import { requestMetrics as requestMetricsAction, MetricsQuery } from "src/redux/metrics"; import { Metric, MetricProps, MetricsDataComponentProps, QueryTimeInfo, } from "src/views/shared/components/metricQuery"; @@ -69,7 +69,7 @@ function queryFromProps( interface MetricsDataProviderConnectProps { metrics: MetricsQuery; timeInfo: QueryTimeInfo; - requestMetrics: typeof requestMetrics; + requestMetrics: typeof requestMetricsAction; } /** @@ -223,7 +223,7 @@ const metricsDataProviderConnected = connect( }; }, { - requestMetrics, + requestMetricsAction, }, )(MetricsDataProvider); diff --git a/pkg/ui/ui.go b/pkg/ui/ui.go index a2515f509a9f..cf5f750431fb 100644 --- a/pkg/ui/ui.go +++ b/pkg/ui/ui.go @@ -79,6 +79,7 @@ type IndexHTMLArgs struct { ExperimentalUseLogin bool LoginEnabled bool LoggedInUser *string + Version string } func init() { diff --git a/pkg/ui/yarn.lock b/pkg/ui/yarn.lock index 9b50545210d4..f563bf3a0b77 100644 --- a/pkg/ui/yarn.lock +++ b/pkg/ui/yarn.lock @@ -336,6 +336,12 @@ ansi-styles@^3.1.0: dependencies: color-convert "^1.9.0" +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + dependencies: + color-convert "^1.9.0" + anymatch@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507" @@ -494,7 +500,7 @@ aws4@^1.2.1: version "1.6.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" -babel-code-frame@^6.11.0, babel-code-frame@^6.22.0: +babel-code-frame@^6.11.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4" dependencies: @@ -502,6 +508,14 @@ babel-code-frame@^6.11.0, babel-code-frame@^6.22.0: esutils "^2.0.2" js-tokens "^3.0.0" +babel-code-frame@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + babel-core@^6.24.0, babel-core@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.24.1.tgz#8c428564dce1e1f41fb337ec34f4c3b022b5ad83" @@ -1031,7 +1045,7 @@ backo2@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" -balanced-match@^0.4.1, balanced-match@^0.4.2: +balanced-match@^0.4.2: version "0.4.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" @@ -1133,14 +1147,7 @@ boom@2.x.x: dependencies: hoek "2.x.x" -brace-expansion@^1.0.0: - version "1.1.7" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59" - dependencies: - balanced-match "^0.4.1" - concat-map "0.0.1" - -brace-expansion@^1.1.7: +brace-expansion@^1.0.0, brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" dependencies: @@ -1251,7 +1258,7 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" -builtin-modules@^1.0.0: +builtin-modules@^1.0.0, builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" @@ -1379,6 +1386,14 @@ chalk@^2.0.1: escape-string-regexp "^1.0.5" supports-color "^4.0.0" +chalk@^2.3.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + check-error@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" @@ -1514,7 +1529,7 @@ colors@0.5.x: version "0.5.1" resolved "https://registry.yarnpkg.com/colors/-/colors-0.5.1.tgz#7d0023eaeb154e8ee9fce75dcb923d0ed1667774" -colors@^1.1.0, colors@^1.1.2, colors@~1.1.2: +colors@^1.1.0, colors@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" @@ -1547,6 +1562,10 @@ commander@2.9.0, commander@^2.9.0: dependencies: graceful-readlink ">= 1.0.0" +commander@^2.12.1: + version "2.15.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -2032,10 +2051,14 @@ diff@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" -diff@^3.1.0, diff@^3.2.0: +diff@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" +diff@^3.2.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + diffie-hellman@^5.0.0: version "5.0.2" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e" @@ -2376,6 +2399,10 @@ esprima@^2.6.0: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" +esprima@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" + esrecurse@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163" @@ -2629,12 +2656,6 @@ find-up@^2.0.0, find-up@^2.1.0: dependencies: locate-path "^2.0.0" -findup-sync@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.3.0.tgz#37930aa5d816b777c03445e1966cc6790a4c0b16" - dependencies: - glob "~5.0.0" - flatten@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" @@ -2842,7 +2863,7 @@ glob@7.0.5, glob@7.0.x: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.3, glob@^7.0.5, glob@^7.1.1: +glob@^7.0.3, glob@^7.0.5: version "7.1.1" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" dependencies: @@ -2853,7 +2874,7 @@ glob@^7.0.3, glob@^7.0.5, glob@^7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.2: +glob@^7.1.1, glob@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: @@ -2864,16 +2885,6 @@ glob@^7.1.2: once "^1.3.0" path-is-absolute "^1.0.0" -glob@~5.0.0: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - globals@^9.0.0: version "9.17.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.17.0.tgz#0c0ca696d9b9bb694d2e5470bd37777caad50286" @@ -2956,6 +2967,10 @@ has-flag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + has-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" @@ -3428,9 +3443,16 @@ js-base64@^2.1.9: version "2.1.9" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.1.9.tgz#f0e80ae039a4bd654b5f281fc93f04a914a7fcce" -js-tokens@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" +js-tokens@^3.0.0, js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + +js-yaml@^3.7.0: + version "3.11.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" js-yaml@~3.7.0: version "3.7.0" @@ -3927,19 +3949,19 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" - dependencies: - brace-expansion "^1.0.0" - -minimatch@^3.0.4: +"minimatch@2 || 3", minimatch@^3.0.2, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: brace-expansion "^1.1.7" -minimist@0.0.8, minimist@~0.0.1: +minimatch@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" + dependencies: + brace-expansion "^1.0.0" + +minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" @@ -3947,6 +3969,10 @@ minimist@1.2.0, minimist@^1.1.3, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" +minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + mississippi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-2.0.0.tgz#3442a508fafc28500486feea99409676e4ee5a6f" @@ -4273,7 +4299,7 @@ opn@^5.1.0: dependencies: is-wsl "^1.1.0" -optimist@^0.6.1, optimist@~0.6.0: +optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" dependencies: @@ -5360,8 +5386,8 @@ resolve-from@^3.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" resolve@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.2.tgz#1f0442c9e0cbb8136e87b9305f932f46c7f28235" + version "1.7.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3" dependencies: path-parse "^1.0.5" @@ -5438,11 +5464,11 @@ selfsigned@^1.9.1: dependencies: node-forge "0.6.33" -"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.3.0: +"semver@2 || 3 || 4 || 5", semver@^5.0.1: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" -semver@^5.4.1: +semver@^5.3.0, semver@^5.4.1: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" @@ -5913,6 +5939,12 @@ supports-color@^4.0.0, supports-color@^4.2.1: dependencies: has-flag "^2.0.0" +supports-color@^5.3.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + dependencies: + has-flag "^3.0.0" + svgo@^0.7.0: version "0.7.2" resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" @@ -6036,23 +6068,32 @@ ts-loader@^2.3.4: loader-utils "^1.0.2" semver "^5.0.1" -tslint@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.1.0.tgz#51a47baeeb58956fcd617bd2cf00e2ef0eea2ed9" +tslib@^1.8.0, tslib@^1.8.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.1.tgz#a5d1f0532a49221c87755cfcc89ca37197242ba7" + +tslint@^5.10.0: + version "5.10.0" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.10.0.tgz#11e26bccb88afa02dd0d9956cae3d4540b5f54c3" dependencies: babel-code-frame "^6.22.0" - colors "^1.1.2" + builtin-modules "^1.1.1" + chalk "^2.3.0" + commander "^2.12.1" diff "^3.2.0" - findup-sync "~0.3.0" glob "^7.1.1" - optimist "~0.6.0" + js-yaml "^3.7.0" + minimatch "^3.0.4" resolve "^1.3.2" semver "^5.3.0" - tsutils "^1.4.0" + tslib "^1.8.0" + tsutils "^2.12.1" -tsutils@^1.4.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-1.6.0.tgz#1fd7fac2a61369ed99cd3997f0fbb437128850f2" +tsutils@^2.12.1: + version "2.27.1" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.27.1.tgz#ab0276ac23664f36ce8fd4414daec4aebf4373ee" + dependencies: + tslib "^1.8.1" tty-browserify@0.0.0: version "0.0.0"